mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-19 14:08:38 +00:00
544 lines
15 KiB
Markdown
544 lines
15 KiB
Markdown
|
|
# Chart Entity
|
||
|
|
|
||
|
|
The Chart entity represents visualizations and reports in BI tools (e.g., Looker, Tableau, Superset). This guide covers chart operations in SDK V2.
|
||
|
|
|
||
|
|
## Creating a Chart
|
||
|
|
|
||
|
|
### Minimal Chart
|
||
|
|
|
||
|
|
Only tool and id are required:
|
||
|
|
|
||
|
|
```java
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("looker")
|
||
|
|
.id("my_sales_chart")
|
||
|
|
.build();
|
||
|
|
```
|
||
|
|
|
||
|
|
### With Metadata
|
||
|
|
|
||
|
|
Add title, description, and custom properties:
|
||
|
|
|
||
|
|
```java
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("tableau")
|
||
|
|
.id("sales_dashboard_chart_1")
|
||
|
|
.title("Sales Performance by Region")
|
||
|
|
.description("Monthly sales broken down by geographic region")
|
||
|
|
.build();
|
||
|
|
```
|
||
|
|
|
||
|
|
### With Custom Properties
|
||
|
|
|
||
|
|
```java
|
||
|
|
Map<String, String> properties = new HashMap<>();
|
||
|
|
properties.put("dashboard", "executive_dashboard");
|
||
|
|
properties.put("refresh_schedule", "hourly");
|
||
|
|
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("looker")
|
||
|
|
.id("revenue_chart")
|
||
|
|
.title("Revenue Trends")
|
||
|
|
.customProperties(properties)
|
||
|
|
.build();
|
||
|
|
```
|
||
|
|
|
||
|
|
## URN Construction
|
||
|
|
|
||
|
|
Chart URNs follow the pattern:
|
||
|
|
|
||
|
|
```
|
||
|
|
urn:li:chart:({tool},{id})
|
||
|
|
```
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
|
||
|
|
```java
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("looker")
|
||
|
|
.id("my_chart")
|
||
|
|
.build();
|
||
|
|
|
||
|
|
ChartUrn urn = chart.getChartUrn();
|
||
|
|
// urn:li:chart:(looker,my_chart)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Supported BI Tools
|
||
|
|
|
||
|
|
Common tool identifiers:
|
||
|
|
|
||
|
|
- `looker` - Looker
|
||
|
|
- `tableau` - Tableau
|
||
|
|
- `superset` - Apache Superset
|
||
|
|
- `powerbi` - Power BI
|
||
|
|
- `metabase` - Metabase
|
||
|
|
- `redash` - Redash
|
||
|
|
- `mode` - Mode Analytics
|
||
|
|
|
||
|
|
## Chart Operations
|
||
|
|
|
||
|
|
### Adding Tags
|
||
|
|
|
||
|
|
Add tags to categorize and classify your charts:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Simple tag (automatically adds "urn:li:tag:" prefix)
|
||
|
|
chart.addTag("pii");
|
||
|
|
chart.addTag("financial");
|
||
|
|
|
||
|
|
// Or use full URN
|
||
|
|
chart.addTag("urn:li:tag:production");
|
||
|
|
```
|
||
|
|
|
||
|
|
### Managing Owners
|
||
|
|
|
||
|
|
Add owners with different ownership types:
|
||
|
|
|
||
|
|
```java
|
||
|
|
import com.linkedin.common.OwnershipType;
|
||
|
|
|
||
|
|
// Add technical owner
|
||
|
|
chart.addOwner("urn:li:corpuser:data_team", OwnershipType.TECHNICAL_OWNER);
|
||
|
|
|
||
|
|
// Add business owner
|
||
|
|
chart.addOwner("urn:li:corpuser:sales_team", OwnershipType.BUSINESS_OWNER);
|
||
|
|
|
||
|
|
// Add data steward
|
||
|
|
chart.addOwner("urn:li:corpuser:compliance_team", OwnershipType.DATA_STEWARD);
|
||
|
|
|
||
|
|
// Remove an owner
|
||
|
|
chart.removeOwner("urn:li:corpuser:old_owner");
|
||
|
|
```
|
||
|
|
|
||
|
|
### Adding Glossary Terms
|
||
|
|
|
||
|
|
Link charts to business glossary terms:
|
||
|
|
|
||
|
|
```java
|
||
|
|
chart.addTerm("urn:li:glossaryTerm:SalesMetrics");
|
||
|
|
chart.addTerm("urn:li:glossaryTerm:QuarterlyReporting");
|
||
|
|
|
||
|
|
// Remove a term
|
||
|
|
chart.removeTerm("urn:li:glossaryTerm:OldTerm");
|
||
|
|
```
|
||
|
|
|
||
|
|
### Setting Domain
|
||
|
|
|
||
|
|
Organize charts into domains:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Set domain
|
||
|
|
chart.setDomain("urn:li:domain:Sales");
|
||
|
|
|
||
|
|
// Remove domain
|
||
|
|
chart.setDomain(null);
|
||
|
|
// or
|
||
|
|
chart.removeDomain();
|
||
|
|
```
|
||
|
|
|
||
|
|
### Setting Description and Title
|
||
|
|
|
||
|
|
Update chart description and title using patch-based updates:
|
||
|
|
|
||
|
|
```java
|
||
|
|
chart.setDescription("Updated chart description");
|
||
|
|
chart.setTitle("New Chart Title");
|
||
|
|
```
|
||
|
|
|
||
|
|
### Managing Custom Properties
|
||
|
|
|
||
|
|
Add, update, or remove custom properties:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Add individual properties
|
||
|
|
chart.addCustomProperty("refresh_schedule", "hourly");
|
||
|
|
chart.addCustomProperty("chart_type", "bar");
|
||
|
|
|
||
|
|
// Set all properties at once (replaces existing)
|
||
|
|
Map<String, String> props = new HashMap<>();
|
||
|
|
props.put("dashboard_url", "https://dashboard.example.com");
|
||
|
|
props.put("author", "data_team");
|
||
|
|
chart.setCustomProperties(props);
|
||
|
|
|
||
|
|
// Remove a property
|
||
|
|
chart.removeCustomProperty("old_property");
|
||
|
|
```
|
||
|
|
|
||
|
|
## Lineage Operations
|
||
|
|
|
||
|
|
Chart lineage defines the data flow relationships between charts and the datasets they consume. This is essential for impact analysis, data governance, and understanding data dependencies.
|
||
|
|
|
||
|
|
### Setting Input Datasets
|
||
|
|
|
||
|
|
Define which datasets a chart consumes:
|
||
|
|
|
||
|
|
```java
|
||
|
|
import com.linkedin.common.urn.DatasetUrn;
|
||
|
|
import java.util.Arrays;
|
||
|
|
|
||
|
|
// Create dataset URNs
|
||
|
|
DatasetUrn salesDataset = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.transactions,PROD)");
|
||
|
|
DatasetUrn customerDataset = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.customers,PROD)");
|
||
|
|
|
||
|
|
// Set all input datasets at once (replaces existing)
|
||
|
|
chart.setInputDatasets(Arrays.asList(salesDataset, customerDataset));
|
||
|
|
```
|
||
|
|
|
||
|
|
### Adding Individual Input Datasets
|
||
|
|
|
||
|
|
Add input datasets incrementally:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Add datasets one at a time
|
||
|
|
chart.addInputDataset(salesDataset);
|
||
|
|
chart.addInputDataset(customerDataset);
|
||
|
|
|
||
|
|
// This pattern is useful when:
|
||
|
|
// - Building lineage incrementally
|
||
|
|
// - Discovering datasets during chart analysis
|
||
|
|
// - Adding new data sources to existing chart
|
||
|
|
```
|
||
|
|
|
||
|
|
### Removing Input Datasets
|
||
|
|
|
||
|
|
Remove datasets that are no longer consumed:
|
||
|
|
|
||
|
|
```java
|
||
|
|
DatasetUrn legacyDataset = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:postgres,legacy.old_table,PROD)");
|
||
|
|
|
||
|
|
// Remove specific dataset from lineage
|
||
|
|
chart.removeInputDataset(legacyDataset);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Retrieving Input Datasets
|
||
|
|
|
||
|
|
Get the list of datasets a chart consumes:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Load chart from DataHub
|
||
|
|
ChartUrn chartUrn = new ChartUrn("looker", "my_chart");
|
||
|
|
Chart chart = client.entities().get(chartUrn);
|
||
|
|
|
||
|
|
// Get all input datasets
|
||
|
|
List<DatasetUrn> inputDatasets = chart.getInputDatasets();
|
||
|
|
System.out.println("Chart consumes " + inputDatasets.size() + " datasets:");
|
||
|
|
for (DatasetUrn dataset : inputDatasets) {
|
||
|
|
System.out.println(" - " + dataset);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Complete Lineage Example
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Create chart with comprehensive lineage
|
||
|
|
Chart salesChart = Chart.builder()
|
||
|
|
.tool("tableau")
|
||
|
|
.id("sales_dashboard_chart")
|
||
|
|
.title("Sales Performance")
|
||
|
|
.build();
|
||
|
|
|
||
|
|
// Define input datasets
|
||
|
|
DatasetUrn transactions = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.transactions,PROD)");
|
||
|
|
DatasetUrn customers = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.customers,PROD)");
|
||
|
|
DatasetUrn products = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.products,PROD)");
|
||
|
|
|
||
|
|
// Set lineage
|
||
|
|
salesChart.setInputDatasets(Arrays.asList(transactions, customers, products));
|
||
|
|
|
||
|
|
// Add metadata
|
||
|
|
salesChart.addTag("sales")
|
||
|
|
.addOwner("urn:li:corpuser:data_team", OwnershipType.TECHNICAL_OWNER)
|
||
|
|
.setDomain("urn:li:domain:Sales");
|
||
|
|
|
||
|
|
// Save to DataHub
|
||
|
|
client.entities().upsert(salesChart);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Chart-Specific Properties
|
||
|
|
|
||
|
|
Charts have several specialized properties beyond basic metadata:
|
||
|
|
|
||
|
|
### Chart Type
|
||
|
|
|
||
|
|
Set the visualization type:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Available types: BAR, LINE, PIE, TABLE, TEXT, BOXPLOT, AREA, SCATTER
|
||
|
|
chart.setChartType("BAR");
|
||
|
|
|
||
|
|
// Get chart type
|
||
|
|
String chartType = chart.getChartType();
|
||
|
|
```
|
||
|
|
|
||
|
|
### Access Level
|
||
|
|
|
||
|
|
Control chart visibility:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Available levels: PUBLIC, PRIVATE
|
||
|
|
chart.setAccess("PUBLIC");
|
||
|
|
|
||
|
|
// Get access level
|
||
|
|
String access = chart.getAccess();
|
||
|
|
```
|
||
|
|
|
||
|
|
### External and Chart URLs
|
||
|
|
|
||
|
|
Set URLs for accessing the chart:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// External URL - link to view chart in source BI tool
|
||
|
|
chart.setExternalUrl("https://looker.company.com/dashboards/123");
|
||
|
|
|
||
|
|
// Chart URL - direct URL to chart (may be different from external URL)
|
||
|
|
chart.setChartUrl("https://looker.company.com/embed/charts/456");
|
||
|
|
|
||
|
|
// Get URLs
|
||
|
|
String externalUrl = chart.getExternalUrl();
|
||
|
|
String chartUrl = chart.getChartUrl();
|
||
|
|
```
|
||
|
|
|
||
|
|
### Last Refreshed Timestamp
|
||
|
|
|
||
|
|
Track when chart data was last updated:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Set timestamp (milliseconds since epoch)
|
||
|
|
long currentTime = System.currentTimeMillis();
|
||
|
|
chart.setLastRefreshed(currentTime);
|
||
|
|
|
||
|
|
// Or use a specific time
|
||
|
|
long specificTime = Instant.parse("2025-10-29T10:00:00Z").toEpochMilli();
|
||
|
|
chart.setLastRefreshed(specificTime);
|
||
|
|
|
||
|
|
// Get last refreshed time
|
||
|
|
Long lastRefreshed = chart.getLastRefreshed();
|
||
|
|
if (lastRefreshed != null) {
|
||
|
|
Instant refreshTime = Instant.ofEpochMilli(lastRefreshed);
|
||
|
|
System.out.println("Last refreshed: " + refreshTime);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Complete Properties Example
|
||
|
|
|
||
|
|
```java
|
||
|
|
import java.time.Instant;
|
||
|
|
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("looker")
|
||
|
|
.id("sales_performance")
|
||
|
|
.title("Sales Performance Dashboard")
|
||
|
|
.build();
|
||
|
|
|
||
|
|
// Set all chart-specific properties
|
||
|
|
chart.setChartType("BAR")
|
||
|
|
.setAccess("PUBLIC")
|
||
|
|
.setExternalUrl("https://looker.company.com/dashboards/sales")
|
||
|
|
.setChartUrl("https://looker.company.com/embed/charts/sales_performance")
|
||
|
|
.setLastRefreshed(System.currentTimeMillis());
|
||
|
|
|
||
|
|
// Set lineage
|
||
|
|
DatasetUrn salesDataset = DatasetUrn.createFromString(
|
||
|
|
"urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.transactions,PROD)");
|
||
|
|
chart.addInputDataset(salesDataset);
|
||
|
|
|
||
|
|
// Add metadata
|
||
|
|
chart.addTag("sales")
|
||
|
|
.setDomain("urn:li:domain:Sales");
|
||
|
|
|
||
|
|
client.entities().upsert(chart);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Complete Example
|
||
|
|
|
||
|
|
Here's a comprehensive example showing all chart operations:
|
||
|
|
|
||
|
|
```java
|
||
|
|
import com.linkedin.common.OwnershipType;
|
||
|
|
import datahub.client.v2.DataHubClientV2;
|
||
|
|
import datahub.client.v2.entity.Chart;
|
||
|
|
import java.io.IOException;
|
||
|
|
import java.util.concurrent.ExecutionException;
|
||
|
|
|
||
|
|
public class ChartExample {
|
||
|
|
public static void main(String[] args)
|
||
|
|
throws IOException, ExecutionException, InterruptedException {
|
||
|
|
// Create client
|
||
|
|
DataHubClientV2 client = DataHubClientV2.builder()
|
||
|
|
.server("http://localhost:8080")
|
||
|
|
.build();
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Create chart with basic metadata
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("looker")
|
||
|
|
.id("regional_sales_chart")
|
||
|
|
.title("Regional Sales Performance")
|
||
|
|
.description("Quarterly sales broken down by region and product category")
|
||
|
|
.build();
|
||
|
|
|
||
|
|
// Add tags for categorization
|
||
|
|
chart.addTag("sales")
|
||
|
|
.addTag("executive")
|
||
|
|
.addTag("quarterly-review");
|
||
|
|
|
||
|
|
// Add owners
|
||
|
|
chart.addOwner("urn:li:corpuser:sales_team", OwnershipType.TECHNICAL_OWNER)
|
||
|
|
.addOwner("urn:li:corpuser:bi_team", OwnershipType.DATA_STEWARD);
|
||
|
|
|
||
|
|
// Add glossary terms
|
||
|
|
chart.addTerm("urn:li:glossaryTerm:SalesMetrics")
|
||
|
|
.addTerm("urn:li:glossaryTerm:QuarterlyReporting");
|
||
|
|
|
||
|
|
// Set domain
|
||
|
|
chart.setDomain("urn:li:domain:Sales");
|
||
|
|
|
||
|
|
// Add custom properties
|
||
|
|
chart.addCustomProperty("dashboard", "executive_overview")
|
||
|
|
.addCustomProperty("chart_type", "bar")
|
||
|
|
.addCustomProperty("data_source", "snowflake")
|
||
|
|
.addCustomProperty("refresh_schedule", "hourly");
|
||
|
|
|
||
|
|
// Upsert to DataHub (emits all accumulated patches)
|
||
|
|
client.entities().upsert(chart);
|
||
|
|
|
||
|
|
System.out.println("Successfully created chart: " + chart.getUrn());
|
||
|
|
System.out.println("Total patches: " + chart.getPendingPatches().size());
|
||
|
|
|
||
|
|
} finally {
|
||
|
|
client.close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Builder Options Reference
|
||
|
|
|
||
|
|
| Method | Required | Description |
|
||
|
|
| ----------------------- | -------- | ---------------------------------------------- |
|
||
|
|
| `tool(String)` | ✅ Yes | BI tool identifier (e.g., "looker", "tableau") |
|
||
|
|
| `id(String)` | ✅ Yes | Chart identifier within the tool |
|
||
|
|
| `title(String)` | No | Chart title |
|
||
|
|
| `description(String)` | No | Chart description |
|
||
|
|
| `customProperties(Map)` | No | Map of custom key-value properties |
|
||
|
|
|
||
|
|
## Patch-Based Operations
|
||
|
|
|
||
|
|
Chart entities now support patch-based operations similar to Dataset. All mutations (addTag, addOwner, etc.) create patch MCPs that accumulate until save(). This enables:
|
||
|
|
|
||
|
|
- **Efficient batching**: Multiple operations in a single network call
|
||
|
|
- **Incremental updates**: Only modified fields are sent to the server
|
||
|
|
- **Fluent chaining**: Build complex metadata in a readable way
|
||
|
|
|
||
|
|
Available patch operations:
|
||
|
|
|
||
|
|
| Operation | Description |
|
||
|
|
| ----------------------------------- | ---------------------------------- |
|
||
|
|
| `addTag(String)` | Add a tag to the chart |
|
||
|
|
| `removeTag(String)` | Remove a tag from the chart |
|
||
|
|
| `addOwner(String, OwnershipType)` | Add an owner with ownership type |
|
||
|
|
| `removeOwner(String)` | Remove an owner from the chart |
|
||
|
|
| `addTerm(String)` | Add a glossary term to the chart |
|
||
|
|
| `removeTerm(String)` | Remove a glossary term |
|
||
|
|
| `setDomain(String)` | Set the domain for the chart |
|
||
|
|
| `removeDomain()` | Remove the domain from the chart |
|
||
|
|
| `setDescription(String)` | Update chart description |
|
||
|
|
| `setTitle(String)` | Update chart title |
|
||
|
|
| `addCustomProperty(String, String)` | Add or update a custom property |
|
||
|
|
| `removeCustomProperty(String)` | Remove a custom property |
|
||
|
|
| `setCustomProperties(Map)` | Replace all custom properties |
|
||
|
|
| `setInputDatasets(List)` | Set input datasets (lineage) |
|
||
|
|
| `addInputDataset(DatasetUrn)` | Add an input dataset (lineage) |
|
||
|
|
| `removeInputDataset(DatasetUrn)` | Remove an input dataset (lineage) |
|
||
|
|
| `setExternalUrl(String)` | Set external URL for the chart |
|
||
|
|
| `setChartUrl(String)` | Set chart URL |
|
||
|
|
| `setLastRefreshed(long)` | Set last refreshed timestamp |
|
||
|
|
| `setChartType(String)` | Set chart type (BAR, LINE, etc.) |
|
||
|
|
| `setAccess(String)` | Set access level (PUBLIC, PRIVATE) |
|
||
|
|
|
||
|
|
See [Patch Operations Guide](./patch-operations.md) for more details on how patch-based updates work.
|
||
|
|
|
||
|
|
## Common Patterns
|
||
|
|
|
||
|
|
### Creating Multiple Charts
|
||
|
|
|
||
|
|
```java
|
||
|
|
List<String> chartIds = Arrays.asList("chart1", "chart2", "chart3");
|
||
|
|
|
||
|
|
for (String chartId : chartIds) {
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("looker")
|
||
|
|
.id(chartId)
|
||
|
|
.title("Chart " + chartId)
|
||
|
|
.build();
|
||
|
|
|
||
|
|
client.entities().upsert(chart);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Linking Charts to Dashboards
|
||
|
|
|
||
|
|
Use custom properties to track relationships:
|
||
|
|
|
||
|
|
```java
|
||
|
|
Chart chart = Chart.builder()
|
||
|
|
.tool("tableau")
|
||
|
|
.id("sales_chart")
|
||
|
|
.build();
|
||
|
|
|
||
|
|
Map<String, String> props = new HashMap<>();
|
||
|
|
props.put("dashboard_id", "executive_dashboard");
|
||
|
|
props.put("position", "top_left");
|
||
|
|
|
||
|
|
chart.setCustomProperties(props);
|
||
|
|
client.entities().upsert(chart);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Updating Charts
|
||
|
|
|
||
|
|
### Load and Modify
|
||
|
|
|
||
|
|
```java
|
||
|
|
// Load existing chart
|
||
|
|
ChartUrn urn = new ChartUrn("looker", "my_chart");
|
||
|
|
Chart chart = client.entities().get(urn);
|
||
|
|
|
||
|
|
// Modify
|
||
|
|
chart.setDescription("Updated description");
|
||
|
|
|
||
|
|
// Save changes
|
||
|
|
client.entities().update(chart);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Next Steps
|
||
|
|
|
||
|
|
- **[Dataset Entity Guide](./dataset-entity.md)** - Comprehensive dataset operations
|
||
|
|
- **[Entities Overview](./entities-overview.md)** - Common patterns across entities
|
||
|
|
- **[Patch Operations](./patch-operations.md)** - Understanding incremental updates
|
||
|
|
|
||
|
|
## Examples
|
||
|
|
|
||
|
|
### Basic Chart Creation
|
||
|
|
|
||
|
|
```java
|
||
|
|
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/ChartCreateExample.java show_path_as_comment }}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Comprehensive Chart with Metadata and Lineage
|
||
|
|
|
||
|
|
```java
|
||
|
|
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/ChartFullExample.java show_path_as_comment }}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Chart Lineage Operations
|
||
|
|
|
||
|
|
```java
|
||
|
|
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/ChartLineageExample.java show_path_as_comment }}
|
||
|
|
```
|