Looker Integration
Looker is Google Cloud's enterprise business intelligence platform. Olytix Core provides native Looker integration by generating LookML from your semantic layer, enabling you to publish cubes as Looker views, explores, and models while maintaining a single source of truth.
Integration Methods
| Method | Features | Best For |
|---|---|---|
| LookML Publishing | Native views, explores, joins | Full semantic layer sync |
| REST API | Custom data connector | Flexible integration |
| CLI Tools | Automated deployment | CI/CD pipelines |
Prerequisites
- Looker instance with API access enabled
- Looker API credentials (client ID and client secret)
- Olytix Core project with defined cubes
- Git repository for LookML project (if using production deployment)
Configuration
Enable Looker Integration
Configure Looker settings in your environment or configuration file:
# Environment variables
export OLYTIX_LOOKER__BASE_URL=https://your-instance.looker.com
export OLYTIX_LOOKER__CLIENT_ID=your_client_id
export OLYTIX_LOOKER__CLIENT_SECRET=your_client_secret
export OLYTIX_LOOKER__PROJECT_NAME=olytix_semantic_layer
Or via configuration file:
# olytix-core_project.yml
looker:
base_url: https://your-instance.looker.com
client_id: ${LOOKER_CLIENT_ID}
client_secret: ${LOOKER_CLIENT_SECRET}
project_name: olytix_semantic_layer
git_branch: main
Authentication Options
API Key Authentication (Recommended)
looker:
base_url: https://your-instance.looker.com
auth_method: api_key
client_id: ${LOOKER_CLIENT_ID}
client_secret: ${LOOKER_CLIENT_SECRET}
OAuth Authentication
looker:
base_url: https://your-instance.looker.com
auth_method: oauth
client_id: ${LOOKER_OAUTH_CLIENT_ID}
client_secret: ${LOOKER_OAUTH_CLIENT_SECRET}
LookML Generation
Olytix Core generates complete LookML from your semantic layer definitions.
Cube to View Mapping
| Olytix Core Concept | LookML Equivalent |
|---|---|
| Cube | View |
| Dimension | dimension |
| Time Dimension | dimension_group (type: time) |
| Measure | measure |
| Join | join (in explore) |
| Segment | sql_always_where (filtered explore) |
Example Mapping
Olytix Core cube definition:
# cubes/orders.yml
cubes:
- name: orders
sql_table: analytics.fct_orders
dimensions:
- name: order_id
type: number
primary_key: true
- name: region
type: string
sql: region_code
- name: order_date
type: time
sql: created_at
granularities: [day, week, month, quarter, year]
measures:
- name: total_revenue
type: sum
sql: total_amount
format: currency
- name: order_count
type: count
description: "Number of orders"
- name: average_order_value
type: number
sql: "${total_revenue} / NULLIF(${order_count}, 0)"
joins:
- name: customers
sql: "${orders.customer_id} = ${customers.customer_id}"
type: left
relationship: many_to_one
Generated LookML view:
# orders.view.lkml
view: orders {
sql_table_name: analytics.fct_orders ;;
# Primary Key
dimension: order_id {
primary_key: yes
type: number
sql: ${TABLE}.order_id ;;
}
# Dimensions
dimension: region {
type: string
sql: ${TABLE}.region_code ;;
}
# Time Dimension Group
dimension_group: order_date {
type: time
timeframes: [raw, date, week, month, quarter, year]
sql: ${TABLE}.created_at ;;
}
# Measures
measure: total_revenue {
type: sum
sql: ${TABLE}.total_amount ;;
value_format_name: usd
}
measure: order_count {
type: count
description: "Number of orders"
}
measure: average_order_value {
type: number
sql: ${total_revenue} / NULLIF(${order_count}, 0) ;;
}
}
Generated LookML explore:
# semantic_model.model.lkml
connection: "your_connection"
include: "*.view.lkml"
explore: orders {
label: "Orders"
join: customers {
type: left_outer
sql_on: ${orders.customer_id} = ${customers.customer_id} ;;
relationship: many_to_one
}
}
Publishing Cubes
Using the API
Publish a Single Cube
curl -X POST "https://your-olytix-server/api/v1/looker/cubes/orders/publish" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"cube_name": "orders",
"project_name": "olytix_semantic_layer",
"connection_name": "bigquery_prod",
"model_name": "semantic_model",
"include_time_intelligence": true,
"validate_before_deploy": true,
"deploy_to_production": false
}'
Response:
{
"status": "completed",
"cube_name": "orders",
"project_name": "olytix_semantic_layer",
"model_name": "semantic_model",
"view_file": "orders.view.lkml",
"dimensions_created": 3,
"measures_created": 3,
"dimension_groups_created": 1,
"joins_created": 1,
"validation_passed": true,
"duration_ms": 1523
}
Publish Entire Semantic Layer
curl -X POST "https://your-olytix-server/api/v1/looker/semantic-layer/publish" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"project_name": "olytix_semantic_layer",
"connection_name": "bigquery_prod",
"model_name": "semantic_model",
"include_cross_cube_joins": true,
"include_time_intelligence": true,
"validate_before_deploy": true,
"deploy_to_production": false
}'
Response:
{
"status": "completed",
"project_name": "olytix_semantic_layer",
"model_name": "semantic_model",
"cubes_published": ["orders", "customers", "products"],
"views_created": ["orders.view.lkml", "customers.view.lkml", "products.view.lkml"],
"explores_created": ["orders", "customers", "products"],
"total_dimensions": 15,
"total_measures": 12,
"total_joins": 5,
"cross_cube_joins": 2,
"validation_passed": true
}
Using the CLI
Publish a Single Cube
olytix-core looker publish orders \
--project olytix_semantic_layer \
--connection bigquery_prod \
--model semantic_model \
--include-time-intelligence
Publish All Cubes
olytix-core looker semantic-layer-publish \
--project olytix_semantic_layer \
--connection bigquery_prod \
--include-cross-cube-joins
Preview Without Deploying (Dry Run)
olytix-core looker preview orders \
--connection bigquery_prod
Validate Before Publishing
olytix-core looker validate orders
Time Intelligence
Olytix Core automatically generates time intelligence measures for LookML.
Supported Time Calculations
| Calculation | LookML Output |
|---|---|
| YTD (Year to Date) | Filtered measure with year filter |
| MTD (Month to Date) | Filtered measure with month filter |
| QTD (Quarter to Date) | Filtered measure with quarter filter |
| Rolling 7 Days | Window function with date offset |
| Rolling 30 Days | Window function with date offset |
| YoY Growth | Period comparison calculation |
| MoM Growth | Period comparison calculation |
Example Time Intelligence Output
# Time intelligence measures for orders
measure: total_revenue_ytd {
type: sum
sql: ${TABLE}.total_amount ;;
filters: [order_date_year: "this year"]
label: "Revenue YTD"
}
measure: total_revenue_mtd {
type: sum
sql: ${TABLE}.total_amount ;;
filters: [order_date_month: "this month"]
label: "Revenue MTD"
}
measure: total_revenue_prior_year {
type: sum
sql: ${TABLE}.total_amount ;;
filters: [order_date_year: "1 year ago"]
label: "Revenue Prior Year"
}
measure: total_revenue_yoy_growth {
type: number
sql: (${total_revenue} - ${total_revenue_prior_year}) / NULLIF(${total_revenue_prior_year}, 0) ;;
value_format_name: percent_2
label: "Revenue YoY Growth"
}
Join Mapping
Olytix Core maps cube joins to LookML join definitions with correct types and cardinalities.
Join Type Mapping
| Olytix Core | LookML |
|---|---|
| left | left_outer |
| right | right_outer |
| inner | inner |
| full | full_outer |
| cross | cross |
Relationship Mapping
| Olytix Core | LookML |
|---|---|
| one_to_one | one_to_one |
| many_to_one | many_to_one |
| one_to_many | one_to_many |
| many_to_many | many_to_many |
Cross-Cube Joins
When publishing multiple cubes, Olytix Core automatically generates cross-cube joins:
explore: orders {
join: customers {
type: left_outer
sql_on: ${orders.customer_id} = ${customers.customer_id} ;;
relationship: many_to_one
}
join: products {
type: left_outer
sql_on: ${orders.product_id} = ${products.product_id} ;;
relationship: many_to_one
}
}
Validation
Pre-Publish Validation
Olytix Core validates cubes before publishing:
olytix-core looker validate orders
Validation Results for 'orders':
✓ Cube has required sql_table or sql
✓ All dimensions have valid types
✓ All measures have valid aggregation types
✓ Join SQL syntax is valid
✓ Primary key dimension exists
Warnings:
⚠ Dimension 'internal_notes' marked as hidden
Result: VALID
Looker-Side Validation
When validate_before_deploy is enabled, Olytix Core validates the generated LookML against Looker's validator:
{
"validate_before_deploy": true
}
Validation errors are returned in the response:
{
"status": "failed",
"validation_passed": false,
"validation_errors": [
"View 'orders' references undefined connection 'invalid_connection'"
]
}
Deployment Modes
Development Mode
Deploy to dev mode for testing (default):
olytix-core looker publish orders \
--project olytix_semantic_layer \
--connection bigquery_prod
Production Deployment
Deploy directly to production:
olytix-core looker publish orders \
--project olytix_semantic_layer \
--connection bigquery_prod \
--deploy-to-production
Production deployment commits changes to the Git repository. Ensure your changes are reviewed before deploying.
Re-Publishing Behavior
When re-publishing cubes, Olytix Core preserves compatibility with existing Looks and dashboards:
What Gets Updated
- Dimension and measure definitions
- Join relationships
- SQL table references
- Descriptions and labels
What Is Preserved
- View names (unless explicitly changed)
- Explore names
- Custom LookML extensions in separate files
Safe Update Strategy
- Dry Run First: Preview changes without deploying
olytix-core looker preview orders --connection bigquery_prod
- Validate: Check for breaking changes
olytix-core looker validate orders
- Deploy to Dev: Test in development mode
olytix-core looker publish orders --project my_project --connection bigquery_prod
- Deploy to Production: After validation
olytix-core looker publish orders --project my_project --connection bigquery_prod --deploy-to-production
API Endpoints
Cube Endpoints
| Endpoint | Method | Description |
|---|---|---|
/looker/cubes/{cube_name}/publish | POST | Publish a cube to Looker |
/looker/cubes/{cube_name}/validate | POST | Validate a cube for Looker |
/looker/cubes/{cube_name}/preview-lookml | POST | Preview generated LookML |
/looker/cubes/{cube_name}/info | GET | Get cube information |
/looker/cubes | GET | List all publishable cubes |
Semantic Layer Endpoints
| Endpoint | Method | Description |
|---|---|---|
/looker/semantic-layer/publish | POST | Publish entire semantic layer |
/looker/semantic-layer/validate | POST | Validate semantic layer |
/looker/semantic-layer/preview-lookml | POST | Preview all generated LookML |
/looker/semantic-layer/info | GET | Get semantic layer information |
CLI Commands
# Publish a single cube
olytix-core looker publish <cube_name> [options]
# Publish semantic layer
olytix-core looker semantic-layer-publish [options]
# Validate a cube
olytix-core looker validate <cube_name>
# Preview LookML
olytix-core looker preview <cube_name> [options]
# Get semantic layer info
olytix-core looker info
CLI Options
| Option | Description |
|---|---|
--project | Looker project name |
--connection | Database connection name |
--model | LookML model name (default: semantic_model) |
--include-time-intelligence | Include YTD, MTD measures |
--include-cross-cube-joins | Include joins between cubes |
--overwrite | Overwrite existing files |
--dry-run | Preview without deploying |
--deploy-to-production | Deploy to production |
--output | Output directory for previews |
--format | Output format (json, yaml, lookml) |
Troubleshooting
Connection Failed
Error: Unable to connect to Looker API
Solutions:
- Verify Looker base URL is correct
- Check API credentials are valid
- Ensure network connectivity to Looker
- Verify SSL certificate is valid