Skip to content

Commit 7a03ddf

Browse files
Merge branch 'master' into feature/cus-3546-fix-tableau-authentication
2 parents 2e9ce71 + 09a9b6e commit 7a03ddf

17 files changed

+1050
-135
lines changed

datahub-graphql-core/src/main/resources/entity.graphql

+193-3
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,16 @@ type Query {
262262
Fetch all Business Attributes
263263
"""
264264
listBusinessAttributes(input: ListBusinessAttributesInput!): ListBusinessAttributesResult
265+
266+
"""
267+
Fetch a Data Process Instance by primary key (urn)
268+
"""
269+
dataProcessInstance(urn: String!): DataProcessInstance
270+
271+
265272
}
266273

274+
267275
"""
268276
An ERModelRelationship is a high-level abstraction that dictates what datasets fields are erModelRelationshiped.
269277
"""
@@ -9832,15 +9840,45 @@ type MLModelGroup implements EntityWithRelationships & Entity & BrowsableEntity
98329840
privileges: EntityPrivileges
98339841
}
98349842

9843+
"""
9844+
Properties describing a group of related ML models
9845+
"""
98359846
type MLModelGroupProperties {
9847+
"""
9848+
Display name of the model group
9849+
"""
9850+
name: String
98369851

9852+
"""
9853+
Detailed description of the model group's purpose and contents
9854+
"""
98379855
description: String
98389856

9839-
createdAt: Long
9857+
"""
9858+
When this model group was created
9859+
"""
9860+
created: AuditStamp
98409861

9862+
"""
9863+
When this model group was last modified
9864+
"""
9865+
lastModified: AuditStamp
9866+
9867+
"""
9868+
Version identifier for this model group
9869+
"""
98419870
version: VersionTag
98429871

9872+
"""
9873+
Custom key-value properties for the model group
9874+
"""
98439875
customProperties: [CustomPropertiesEntry!]
9876+
9877+
"""
9878+
Deprecated creation timestamp
9879+
@deprecated Use the 'created' field instead
9880+
"""
9881+
createdAt: Long @deprecated(reason: "Use `created` instead")
98449882
}
98459883

98469884
"""
@@ -9990,40 +10028,103 @@ description: String
999010028
}
999110029

999210030
type MLMetric {
10031+
"""
10032+
Name of the metric (e.g. accuracy, precision, recall)
10033+
"""
999310034
name: String
999410035

10036+
"""
10037+
Description of what this metric measures
10038+
"""
999510039
description: String
999610040

10041+
"""
10042+
The computed value of the metric
10043+
"""
999710044
value: String
999810045

10046+
"""
10047+
Timestamp when this metric was recorded
10048+
"""
999910049
createdAt: Long
1000010050
}
1000110051

1000210052
type MLModelProperties {
10053+
"""
10054+
The display name of the model used in the UI
10055+
"""
10056+
name: String!
1000310057

10058+
"""
10059+
Detailed description of the model's purpose and characteristics
10060+
"""
1000410061
description: String
1000510062

10006-
date: Long
10063+
"""
10064+
When the model was last modified
10065+
"""
10066+
lastModified: AuditStamp
1000710067

10068+
"""
10069+
Version identifier for this model
10070+
"""
1000810071
version: String
1000910072

10073+
"""
10074+
The type/category of ML model (e.g. classification, regression)
10075+
"""
1001010076
type: String
1001110077

10078+
"""
10079+
Mapping of hyperparameter configurations
10080+
"""
1001210081
hyperParameters: HyperParameterMap
1001310082

10014-
hyperParams: [MLHyperParam]
10083+
"""
10084+
List of hyperparameter settings used to train this model
10085+
"""
10086+
hyperParams: [MLHyperParam]
1001510087

10088+
"""
10089+
Performance metrics from model training
10090+
"""
1001610091
trainingMetrics: [MLMetric]
1001710092

10093+
"""
10094+
Names of ML features used by this model
10095+
"""
1001810096
mlFeatures: [String!]
1001910097

10098+
"""
10099+
Tags for categorizing and searching models
10100+
"""
1002010101
tags: [String!]
1002110102

10103+
"""
10104+
Model groups this model belongs to
10105+
"""
1002210106
groups: [MLModelGroup]
1002310107

10108+
"""
10109+
Additional custom properties specific to this model
10110+
"""
1002410111
customProperties: [CustomPropertiesEntry!]
1002510112

10113+
"""
10114+
URL to view this model in external system
10115+
"""
1002610116
externalUrl: String
10117+
10118+
"""
10119+
When this model was created
10120+
"""
10121+
created: AuditStamp
10122+
10123+
"""
10124+
Deprecated timestamp for model creation
10125+
@deprecated Use 'created' field instead
10126+
"""
10127+
date: Long @deprecated(reason: "Use `created` instead")
1002710128
}
1002810129

1002910130
type MLFeatureProperties {
@@ -12804,3 +12905,92 @@ type CronSchedule {
1280412905
"""
1280512906
timezone: String!
1280612907
}
12908+
12909+
12910+
"""
12911+
Properties describing a data process instance's execution metadata
12912+
"""
12913+
type DataProcessInstanceProperties {
12914+
"""
12915+
The display name of this process instance
12916+
"""
12917+
name: String!
12918+
12919+
"""
12920+
URL to view this process instance in the external system
12921+
"""
12922+
externalUrl: String
12923+
12924+
"""
12925+
When this process instance was created
12926+
"""
12927+
created: AuditStamp
12928+
12929+
"""
12930+
Additional custom properties specific to this process instance
12931+
"""
12932+
customProperties: [CustomPropertiesEntry!]
12933+
}
12934+
12935+
"""
12936+
Properties specific to an ML model training run instance
12937+
"""
12938+
type MLTrainingRunProperties {
12939+
"""
12940+
Unique identifier for this training run
12941+
"""
12942+
id: String
12943+
12944+
"""
12945+
List of URLs to access training run outputs (e.g. model artifacts, logs)
12946+
"""
12947+
outputUrls: [String]
12948+
12949+
"""
12950+
Hyperparameters used in this training run
12951+
"""
12952+
hyperParams: [MLHyperParam]
12953+
12954+
"""
12955+
Performance metrics recorded during this training run
12956+
"""
12957+
trainingMetrics: [MLMetric]
12958+
}
12959+
12960+
extend type DataProcessInstance {
12961+
12962+
"""
12963+
Additional read only properties associated with the Data Job
12964+
"""
12965+
properties: DataProcessInstanceProperties
12966+
12967+
"""
12968+
The specific instance of the data platform that this entity belongs to
12969+
"""
12970+
dataPlatformInstance: DataPlatformInstance
12971+
12972+
"""
12973+
Sub Types that this entity implements
12974+
"""
12975+
subTypes: SubTypes
12976+
12977+
"""
12978+
The parent container in which the entity resides
12979+
"""
12980+
container: Container
12981+
12982+
"""
12983+
Standardized platform urn where the data process instance is defined
12984+
"""
12985+
platform: DataPlatform!
12986+
12987+
"""
12988+
Recursively get the lineage of containers for this entity
12989+
"""
12990+
parentContainers: ParentContainersResult
12991+
12992+
"""
12993+
Additional properties when subtype is Training Run
12994+
"""
12995+
mlTrainingRunProperties: MLTrainingRunProperties
12996+
}

metadata-ingestion/src/datahub/ingestion/source/looker/looker_common.py

+9
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,15 @@ class LookerDashboardSourceReport(StaleEntityRemovalSourceReport):
14081408
dashboards_with_activity: LossySet[str] = dataclasses_field(
14091409
default_factory=LossySet
14101410
)
1411+
1412+
# Entities that don't seem to exist, so we don't emit usage aspects for them despite having usage data
1413+
dashboards_skipped_for_usage: LossySet[str] = dataclasses_field(
1414+
default_factory=LossySet
1415+
)
1416+
charts_skipped_for_usage: LossySet[str] = dataclasses_field(
1417+
default_factory=LossySet
1418+
)
1419+
14111420
stage_latency: List[StageLatency] = dataclasses_field(default_factory=list)
14121421
_looker_explore_registry: Optional[LookerExploreRegistry] = None
14131422
total_explores: int = 0

metadata-ingestion/src/datahub/ingestion/source/looker/looker_source.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
ViewField,
6969
ViewFieldType,
7070
gen_model_key,
71+
get_urn_looker_element_id,
7172
)
7273
from datahub.ingestion.source.looker.looker_config import LookerDashboardSourceConfig
7374
from datahub.ingestion.source.looker.looker_lib_wrapper import LookerAPI
@@ -165,6 +166,9 @@ def __init__(self, config: LookerDashboardSourceConfig, ctx: PipelineContext):
165166
# Required, as we do not ingest all folders but only those that have dashboards/looks
166167
self.processed_folders: List[str] = []
167168

169+
# Keep track of ingested chart urns, to omit usage for non-ingested entities
170+
self.chart_urns: Set[str] = set()
171+
168172
@staticmethod
169173
def test_connection(config_dict: dict) -> TestConnectionReport:
170174
test_report = TestConnectionReport()
@@ -642,6 +646,7 @@ def _make_chart_metadata_events(
642646
chart_urn = self._make_chart_urn(
643647
element_id=dashboard_element.get_urn_element_id()
644648
)
649+
self.chart_urns.add(chart_urn)
645650
chart_snapshot = ChartSnapshot(
646651
urn=chart_urn,
647652
aspects=[Status(removed=False)],
@@ -1380,7 +1385,9 @@ def _get_folder_and_ancestors_workunits(
13801385
yield from self._emit_folder_as_container(folder)
13811386

13821387
def extract_usage_stat(
1383-
self, looker_dashboards: List[looker_usage.LookerDashboardForUsage]
1388+
self,
1389+
looker_dashboards: List[looker_usage.LookerDashboardForUsage],
1390+
ingested_chart_urns: Set[str],
13841391
) -> List[MetadataChangeProposalWrapper]:
13851392
looks: List[looker_usage.LookerChartForUsage] = []
13861393
# filter out look from all dashboard
@@ -1391,6 +1398,15 @@ def extract_usage_stat(
13911398

13921399
# dedup looks
13931400
looks = list({str(look.id): look for look in looks}.values())
1401+
filtered_looks = []
1402+
for look in looks:
1403+
if not look.id:
1404+
continue
1405+
chart_urn = self._make_chart_urn(get_urn_looker_element_id(look.id))
1406+
if chart_urn in ingested_chart_urns:
1407+
filtered_looks.append(look)
1408+
else:
1409+
self.reporter.charts_skipped_for_usage.add(look.id)
13941410

13951411
# Keep stat generators to generate entity stat aspect later
13961412
stat_generator_config: looker_usage.StatGeneratorConfig = (
@@ -1414,7 +1430,7 @@ def extract_usage_stat(
14141430
stat_generator_config,
14151431
self.reporter,
14161432
self._make_chart_urn,
1417-
looks,
1433+
filtered_looks,
14181434
)
14191435

14201436
mcps: List[MetadataChangeProposalWrapper] = []
@@ -1669,7 +1685,7 @@ def get_workunits_internal(self) -> Iterable[MetadataWorkUnit]:
16691685
if self.source_config.extract_usage_history:
16701686
self.reporter.report_stage_start("usage_extraction")
16711687
usage_mcps: List[MetadataChangeProposalWrapper] = self.extract_usage_stat(
1672-
looker_dashboards_for_usage
1688+
looker_dashboards_for_usage, self.chart_urns
16731689
)
16741690
for usage_mcp in usage_mcps:
16751691
yield usage_mcp.as_workunit()

0 commit comments

Comments
 (0)