17 KiB
Dashboard Entity
The Dashboard entity represents collections of visualizations and reports in BI tools (e.g., Looker, Tableau, PowerBI). This guide covers comprehensive dashboard operations in SDK V2.
Creating a Dashboard
Minimal Dashboard
Only tool and id are required:
Dashboard dashboard = Dashboard.builder()
.tool("looker")
.id("my_sales_dashboard")
.build();
With Metadata
Add title and description at construction:
Dashboard dashboard = Dashboard.builder()
.tool("tableau")
.id("executive_dashboard")
.title("Executive KPI Dashboard")
.description("Real-time executive dashboard showing key business metrics")
.build();
With Custom Properties
Include custom properties in builder:
Map<String, String> props = new HashMap<>();
props.put("team", "business-intelligence");
props.put("refresh_schedule", "hourly");
Dashboard dashboard = Dashboard.builder()
.tool("powerbi")
.id("sales_dashboard")
.title("Sales Performance")
.customProperties(props)
.build();
URN Construction
Dashboard URNs follow the pattern:
urn:li:dashboard:({tool},{id})
Automatic URN creation:
Dashboard dashboard = Dashboard.builder()
.tool("looker")
.id("regional_sales")
.build();
DashboardUrn urn = dashboard.getDashboardUrn();
// urn:li:dashboard:(looker,regional_sales)
Supported BI Tools
Common tool identifiers:
looker- Lookertableau- Tableaupowerbi- Power BIsuperset- Apache Supersetmetabase- Metabaseredash- Redashmode- Mode Analyticsquicksight- Amazon QuickSightthoughtspot- ThoughtSpot
Tags
Adding Tags
// Simple tag name (auto-prefixed)
dashboard.addTag("executive");
// Creates: urn:li:tag:executive
// Full tag URN
dashboard.addTag("urn:li:tag:production");
Removing Tags
dashboard.removeTag("executive");
dashboard.removeTag("urn:li:tag:production");
Tag Chaining
dashboard.addTag("executive")
.addTag("real-time")
.addTag("kpi");
Owners
Adding Owners
import com.linkedin.common.OwnershipType;
// Business owner
dashboard.addOwner(
"urn:li:corpuser:john_doe",
OwnershipType.BUSINESS_OWNER
);
// Technical owner
dashboard.addOwner(
"urn:li:corpuser:bi_team",
OwnershipType.TECHNICAL_OWNER
);
// Data steward
dashboard.addOwner(
"urn:li:corpuser:governance",
OwnershipType.DATA_STEWARD
);
Removing Owners
dashboard.removeOwner("urn:li:corpuser:john_doe");
Owner Types
Available ownership types:
BUSINESS_OWNER- Business stakeholderTECHNICAL_OWNER- Maintains the technical implementationDATA_STEWARD- Manages data quality and complianceDATAOWNER- Generic data ownerDEVELOPER- Software developerPRODUCER- Dashboard producer/creatorCONSUMER- Dashboard consumerSTAKEHOLDER- Other stakeholder
Glossary Terms
Adding Terms
dashboard.addTerm("urn:li:glossaryTerm:ExecutiveMetrics");
dashboard.addTerm("urn:li:glossaryTerm:BusinessIntelligence");
Removing Terms
dashboard.removeTerm("urn:li:glossaryTerm:ExecutiveMetrics");
Term Chaining
dashboard.addTerm("urn:li:glossaryTerm:KeyPerformanceIndicator")
.addTerm("urn:li:glossaryTerm:SalesMetrics")
.addTerm("urn:li:glossaryTerm:RealTimeData");
Domain
Setting Domain
dashboard.setDomain("urn:li:domain:Sales");
Removing Domain
// Remove a specific domain
dashboard.removeDomain("urn:li:domain:Sales");
// Or clear all domains
dashboard.clearDomains();
Custom Properties
Adding Individual Properties
dashboard.addCustomProperty("team", "sales-operations");
dashboard.addCustomProperty("refresh_schedule", "hourly");
dashboard.addCustomProperty("data_source", "snowflake");
Setting All Properties
Replace all custom properties:
Map<String, String> properties = new HashMap<>();
properties.put("team", "business-intelligence");
properties.put("refresh_schedule", "real-time");
properties.put("access_level", "executive");
dashboard.setCustomProperties(properties);
Removing Properties
dashboard.removeCustomProperty("refresh_schedule");
Reading Dashboard Metadata
Get Title
String title = dashboard.getTitle();
Get Description
String description = dashboard.getDescription();
Lineage Operations
Dashboard lineage represents the data sources (datasets) that feed into the dashboard. This creates upstream lineage relationships from the dashboard to its source datasets.
Adding Input Datasets
Add datasets one at a time:
// Using DatasetUrn
DatasetUrn dataset = DatasetUrn.createFromString(
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)"
);
dashboard.addInputDataset(dataset);
// Using string URN
dashboard.addInputDataset(
"urn:li:dataset:(urn:li:dataPlatform:bigquery,marketing.campaigns,PROD)"
);
Setting Input Datasets
Replace all input datasets at once:
List<DatasetUrn> datasets = Arrays.asList(
DatasetUrn.createFromString(
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)"
),
DatasetUrn.createFromString(
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.customers,PROD)"
)
);
dashboard.setInputDatasets(datasets);
Removing Input Datasets
// Using DatasetUrn
DatasetUrn dataset = DatasetUrn.createFromString(
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)"
);
dashboard.removeInputDataset(dataset);
// Using string URN
dashboard.removeInputDataset(
"urn:li:dataset:(urn:li:dataPlatform:bigquery,marketing.campaigns,PROD)"
);
Getting Input Datasets
Retrieve all input datasets:
List<DatasetUrn> inputDatasets = dashboard.getInputDatasets();
for (DatasetUrn dataset : inputDatasets) {
System.out.println("Dataset: " + dataset);
}
Lineage Chaining
dashboard.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)")
.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.customers,PROD)")
.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:salesforce,Account,PROD)");
Chart Relationships
Chart relationships represent the visualizations embedded in a dashboard. This creates "Contains" relationships between the dashboard and its charts.
Adding Charts
Add charts one at a time:
// Using ChartUrn
ChartUrn chart = new ChartUrn("tableau", "revenue_chart");
dashboard.addChart(chart);
// Using string URN
dashboard.addChart("urn:li:chart:(looker,sales_performance_chart)");
Setting Charts
Replace all charts at once:
List<ChartUrn> charts = Arrays.asList(
new ChartUrn("tableau", "revenue_chart"),
new ChartUrn("tableau", "customer_satisfaction_chart"),
new ChartUrn("tableau", "regional_breakdown_chart")
);
dashboard.setCharts(charts);
Removing Charts
// Using ChartUrn
ChartUrn chart = new ChartUrn("tableau", "revenue_chart");
dashboard.removeChart(chart);
// Using string URN
dashboard.removeChart("urn:li:chart:(looker,sales_performance_chart)");
Getting Charts
Retrieve all charts:
List<ChartUrn> charts = dashboard.getCharts();
for (ChartUrn chart : charts) {
System.out.println("Chart: " + chart);
}
Chart Chaining
dashboard.addChart(new ChartUrn("looker", "revenue_chart"))
.addChart(new ChartUrn("looker", "customer_chart"))
.addChart(new ChartUrn("looker", "product_chart"));
Dashboard-Specific Properties
Dashboard URL
Set a direct link to the dashboard in its native BI tool:
// Set dashboard URL
dashboard.setDashboardUrl("https://tableau.company.com/views/sales-dashboard");
// Get dashboard URL
String url = dashboard.getDashboardUrl();
Last Refreshed
Track when the dashboard data was last updated:
// Set last refreshed timestamp (milliseconds since epoch)
long currentTime = System.currentTimeMillis();
dashboard.setLastRefreshed(currentTime);
// Get last refreshed timestamp
Long lastRefreshed = dashboard.getLastRefreshed();
if (lastRefreshed != null) {
System.out.println("Last refreshed at: " + new Date(lastRefreshed));
}
Combined Dashboard Properties
dashboard.setDashboardUrl("https://looker.company.com/dashboards/executive")
.setLastRefreshed(System.currentTimeMillis());
Complete Example
import datahub.client.v2.DataHubClientV2;
import datahub.client.v2.entity.Dashboard;
import com.linkedin.common.OwnershipType;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
public class DashboardExample {
public static void main(String[] args) {
// Create client
DataHubClientV2 client = DataHubClientV2.builder()
.server("http://localhost:8080")
.build();
try {
// Build dashboard with all metadata
Dashboard dashboard = Dashboard.builder()
.tool("looker")
.id("sales_performance_dashboard")
.title("Sales Performance Dashboard")
.description("Executive dashboard showing key sales metrics and regional performance")
.build();
// Add tags
dashboard.addTag("executive")
.addTag("sales")
.addTag("production");
// Add owners
dashboard.addOwner("urn:li:corpuser:sales_team", OwnershipType.BUSINESS_OWNER)
.addOwner("urn:li:corpuser:bi_team", OwnershipType.TECHNICAL_OWNER);
// Add glossary terms
dashboard.addTerm("urn:li:glossaryTerm:SalesMetrics")
.addTerm("urn:li:glossaryTerm:ExecutiveDashboard");
// Set domain
dashboard.setDomain("urn:li:domain:Sales");
// Add custom properties
dashboard.addCustomProperty("team", "sales-operations")
.addCustomProperty("refresh_schedule", "hourly")
.addCustomProperty("data_source", "snowflake");
// Upsert to DataHub
client.entities().upsert(dashboard);
System.out.println("Successfully created dashboard: " + dashboard.getUrn());
} catch (IOException | ExecutionException | InterruptedException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Updating Existing Dashboards
Load and Modify
// Load existing dashboard
DashboardUrn urn = new DashboardUrn("looker", "my_dashboard");
Dashboard dashboard = client.entities().get(urn);
// Add new metadata (creates patches)
dashboard.addTag("new-tag")
.addOwner("urn:li:corpuser:new_owner", OwnershipType.TECHNICAL_OWNER);
// Apply patches
client.entities().update(dashboard);
Incremental Updates
// Just add what you need
dashboard.addTag("real-time");
client.entities().update(dashboard);
// Later, add more
dashboard.addCustomProperty("updated_at", String.valueOf(System.currentTimeMillis()));
client.entities().update(dashboard);
Builder Options Reference
| Method | Required | Description |
|---|---|---|
tool(String) |
✅ Yes | BI tool identifier (e.g., "looker", "tableau") |
id(String) |
✅ Yes | Dashboard identifier within the tool |
title(String) |
No | Dashboard title |
description(String) |
No | Dashboard description |
customProperties(Map) |
No | Map of custom key-value properties |
Patch-Based Operations
Dashboard uses patch-based updates for metadata operations. All methods like addTag(), addOwner(), etc. create patches that are accumulated until upsert() or update() is called.
Benefits:
- Efficient: Multiple operations batched into fewer API calls
- Atomic: All changes succeed or fail together
- Incremental: Only specified fields are modified, others remain unchanged
Example:
Dashboard dashboard = Dashboard.builder()
.tool("tableau")
.id("sales_dashboard")
.build();
// These create patches (no API calls yet)
dashboard.addTag("production");
dashboard.addOwner("urn:li:corpuser:owner", OwnershipType.BUSINESS_OWNER);
dashboard.setDomain("urn:li:domain:Sales");
// Single API call emits all patches
client.entities().upsert(dashboard);
Common Patterns
Creating Multiple Dashboards
List<String> dashboardIds = Arrays.asList("dashboard1", "dashboard2", "dashboard3");
for (String dashboardId : dashboardIds) {
Dashboard dashboard = Dashboard.builder()
.tool("looker")
.id(dashboardId)
.title("Dashboard " + dashboardId)
.build();
dashboard.addTag("auto-generated")
.addCustomProperty("created_by", "sync_job");
client.entities().upsert(dashboard);
}
Batch Metadata Addition
Dashboard dashboard = Dashboard.builder()
.tool("tableau")
.id("executive_dashboard")
.build();
List<String> tags = Arrays.asList("executive", "kpi", "real-time", "production");
tags.forEach(dashboard::addTag);
client.entities().upsert(dashboard); // Emits all tags in one call
Conditional Metadata
if (isExecutiveDashboard(dashboard)) {
dashboard.addTag("executive")
.addTerm("urn:li:glossaryTerm:ExecutiveMetrics");
}
if (requiresGovernance(dashboard)) {
dashboard.addOwner("urn:li:corpuser:governance_team", OwnershipType.DATA_STEWARD);
}
Dashboard with Full Lineage Context
// Create dashboard with rich metadata
Dashboard dashboard = Dashboard.builder()
.tool("looker")
.id("customer_360_dashboard")
.title("Customer 360 Dashboard")
.description("Comprehensive customer analytics dashboard")
.build();
// Add business context
dashboard.addTerm("urn:li:glossaryTerm:CustomerAnalytics")
.addTerm("urn:li:glossaryTerm:BusinessIntelligence")
.setDomain("urn:li:domain:Customer");
// Add input datasets for lineage
dashboard.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,customer.profile,PROD)")
.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:salesforce,Account,PROD)")
.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:zendesk,Tickets,PROD)");
// Add embedded charts
dashboard.addChart(new ChartUrn("looker", "customer_segmentation_chart"))
.addChart(new ChartUrn("looker", "lifetime_value_chart"))
.addChart(new ChartUrn("looker", "support_tickets_chart"));
// Add operational metadata
dashboard.addCustomProperty("data_sources", "snowflake,salesforce,zendesk")
.addCustomProperty("refresh_schedule", "every_15_minutes")
.addCustomProperty("sla_tier", "tier1")
.addCustomProperty("business_criticality", "high");
// Set dashboard properties
dashboard.setDashboardUrl("https://looker.company.com/dashboards/customer-360")
.setLastRefreshed(System.currentTimeMillis());
// Add ownership and governance
dashboard.addOwner("urn:li:corpuser:product_team", OwnershipType.BUSINESS_OWNER)
.addOwner("urn:li:corpuser:bi_team", OwnershipType.TECHNICAL_OWNER)
.addTag("production")
.addTag("customer-facing");
client.entities().upsert(dashboard);
Comparison with Chart Entity
Dashboard and Chart are similar but serve different purposes:
| Feature | Dashboard | Chart |
|---|---|---|
| Purpose | Collection of visualizations | Single visualization |
| URN Pattern | (tool,id) |
(tool,id) |
| Patch Operations | ✅ Full support | ✅ Full support |
| Common Use Cases | Executive dashboards, reports | Individual graphs, charts |
Next Steps
- Chart Entity Guide - Working with chart entities
- Dataset Entity Guide - Working with dataset entities
- Patch Operations - Deep dive into patches
- Migration Guide - Upgrading from V1
Examples
Basic Dashboard Creation
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/DashboardCreateExample.java show_path_as_comment }}
Comprehensive Dashboard with Metadata
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/DashboardFullExample.java show_path_as_comment }}
Dashboard with Lineage and Relationships
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/DashboardLineageExample.java show_path_as_comment }}