From 734e3e54d88b2662ca487959afd0f9d286836406 Mon Sep 17 00:00:00 2001 From: JamieDeMaria Date: Tue, 15 Apr 2025 13:58:57 -0400 Subject: [PATCH 1/4] freshness ui --- .../dagster-ui/packages/ui-core/client.json | 2 +- .../src/asset-data/AssetHealthDataProvider.tsx | 7 +++++++ .../types/AssetHealthDataProvider.types.ts | 15 ++++++++++++++- .../ui-core/src/assets/AssetHealthSummary.tsx | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/js_modules/dagster-ui/packages/ui-core/client.json b/js_modules/dagster-ui/packages/ui-core/client.json index c6ad0a84fb33f..0c841fd616518 100644 --- a/js_modules/dagster-ui/packages/ui-core/client.json +++ b/js_modules/dagster-ui/packages/ui-core/client.json @@ -3,7 +3,7 @@ "LogTelemetryMutation": "b7bec91d7a5e9e8fb3ad41bb5b7fa1eb1e067c530a8f4cd52a76fde6475462c3", "AssetGraphLiveQuery": "9f875017c08597b0fa017a17fa40813c255d13e3f92eb98992772f4c8ae42e52", "AssetsFreshnessInfoQuery": "1049ac5edde1a0f5c16dd8342020c30db8603477f6d7760712c5784a71bdbc01", - "AssetHealthQuery": "564cb745963722748aeaac66dc433a44e8b6091ef60812a0bb7ec44c3fae5b1c", + "AssetHealthQuery": "79029e5084496e14147e615fa7cf65f4f61d71add7ac519720e1911fbe0bdbc2", "AssetStaleStatusDataQuery": "0168440bb72ae79664e8ba33f41a85f99398d0838b0baaa611b16a4dbb15b004", "AssetGraphSidebarQuery": "724ef0733b9b187ffd012e40c02c3b3a5e32967dbcae46e2024b15dfd5bf0271", "AssetLiveRunLogsSubscription": "d3ae8fb8b8500d37715da27d84b0840e19a175f27f6e62cc859473345a20f64d", diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-data/AssetHealthDataProvider.tsx b/js_modules/dagster-ui/packages/ui-core/src/asset-data/AssetHealthDataProvider.tsx index 420ef72391017..b3e37340bb7ff 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-data/AssetHealthDataProvider.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-data/AssetHealthDataProvider.tsx @@ -82,6 +82,9 @@ export const ASSETS_HEALTH_INFO_QUERY = gql` ...AssetHealthCheckUnknownMetaFragment } freshnessStatus + freshnessStatusMetadata { + ...AssetHealthFreshnessMetaFragment + } } } @@ -114,6 +117,10 @@ export const ASSETS_HEALTH_INFO_QUERY = gql` numNotExecutedChecks totalNumChecks } + + fragment AssetHealthFreshnessMetaFragment on AssetHealthFreshnessMeta { + lastMaterializedTimestamp + } `; // For tests diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-data/types/AssetHealthDataProvider.types.ts b/js_modules/dagster-ui/packages/ui-core/src/asset-data/types/AssetHealthDataProvider.types.ts index 504980659b002..e03b327f81977 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-data/types/AssetHealthDataProvider.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-data/types/AssetHealthDataProvider.types.ts @@ -49,6 +49,10 @@ export type AssetHealthQuery = { totalNumChecks: number; } | null; + freshnessStatusMetadata: { + __typename: 'AssetHealthFreshnessMeta'; + lastMaterializedTimestamp: number | null; + } | null; } | null; }>; }; @@ -93,6 +97,10 @@ export type AssetHealthFragment = { totalNumChecks: number; } | null; + freshnessStatusMetadata: { + __typename: 'AssetHealthFreshnessMeta'; + lastMaterializedTimestamp: number | null; + } | null; } | null; }; @@ -132,4 +140,9 @@ export type AssetHealthCheckUnknownMetaFragment = { totalNumChecks: number; }; -export const AssetHealthQueryVersion = '564cb745963722748aeaac66dc433a44e8b6091ef60812a0bb7ec44c3fae5b1c'; +export type AssetHealthFreshnessMetaFragment = { + __typename: 'AssetHealthFreshnessMeta'; + lastMaterializedTimestamp: number | null; +}; + +export const AssetHealthQueryVersion = '79029e5084496e14147e615fa7cf65f4f61d71add7ac519720e1911fbe0bdbc2'; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx index fbea440e20234..99e78c408b78c 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx @@ -26,6 +26,7 @@ import { AssetHealthMaterializationDegradedNotPartitionedMetaFragment, AssetHealthMaterializationDegradedPartitionedMetaFragment, AssetHealthMaterializationWarningPartitionedMetaFragment, + AssetHealthFreshnessMetaFragment, } from '../asset-data/types/AssetHealthDataProvider.types'; import {AssetHealthStatus} from '../graphql/types'; import {numberFormatter} from '../ui/formatters'; @@ -85,6 +86,11 @@ export const AssetHealthSummary = React.memo( assetKey={key} text="Has no freshness violations" status={health?.freshnessStatus} + explanation={ + !health || health?.freshnessStatus === AssetHealthStatus.NOT_APPLICABLE + ? 'No freshness policy defined' + : undefined + } /> ); + case 'AssetHealthFreshnessMeta': + if (metadata.lastMaterializedTimestamp === null) { + return No materializations; + } + return ( + + Last materialized at {new Date(metadata.lastMaterializedTimestamp).toLocaleString()} + + ); case undefined: return null; default: From e7180508a2f206c13ad3c4cf860e19762c5d71ca Mon Sep 17 00:00:00 2001 From: JamieDeMaria Date: Wed, 16 Apr 2025 12:40:50 -0400 Subject: [PATCH 2/4] change helper text --- .../ui-core/src/assets/AssetHealthSummary.tsx | 6 +++++- .../dagster-test/dagster_test/toys/asset_health.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx index 99e78c408b78c..c41ffcc103105 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx @@ -14,6 +14,8 @@ import { } from '@dagster-io/ui-components'; import React, {useMemo} from 'react'; import {Link} from 'react-router-dom'; +import dayjs from 'dayjs'; + import {asAssetKeyInput} from './asInput'; import {assetDetailsPathForKey} from './assetDetailsPathForKey'; @@ -86,6 +88,7 @@ export const AssetHealthSummary = React.memo( assetKey={key} text="Has no freshness violations" status={health?.freshnessStatus} + metadata={health?.freshnessStatusMetadata} explanation={ !health || health?.freshnessStatus === AssetHealthStatus.NOT_APPLICABLE ? 'No freshness policy defined' @@ -247,9 +250,10 @@ const Criteria = React.memo( if (metadata.lastMaterializedTimestamp === null) { return No materializations; } + return ( - Last materialized at {new Date(metadata.lastMaterializedTimestamp).toLocaleString()} + Last materialized {dayjs(Number(metadata.lastMaterializedTimestamp)).fromNow()} ago ); case undefined: diff --git a/python_modules/dagster-test/dagster_test/toys/asset_health.py b/python_modules/dagster-test/dagster_test/toys/asset_health.py index f04ce6766ccb5..1f835141856d0 100644 --- a/python_modules/dagster-test/dagster_test/toys/asset_health.py +++ b/python_modules/dagster-test/dagster_test/toys/asset_health.py @@ -1,4 +1,7 @@ +from datetime import timedelta + import dagster as dg +from dagster._core.definitions.freshness import InternalFreshnessPolicy from dagster._time import get_current_timestamp @@ -117,6 +120,14 @@ def observable_source_asset_random_execution_error(context): return dg.DataVersion("5") +@dg.asset( + internal_freshness_policy=InternalFreshnessPolicy.time_window( + fail_window=timedelta(minutes=5), warn_window=timedelta(minutes=1) + ) +) +def asset_with_freshness_and_warning(): + return 1 + def get_assets_and_checks(): return [ @@ -136,4 +147,5 @@ def get_assets_and_checks(): observable_source_asset_always_observes, observable_source_asset_execution_error, observable_source_asset_random_execution_error, + asset_with_freshness_and_warning, ] From aeafb6b98cb8c07e0c1270715d0eb2f35ccb9de3 Mon Sep 17 00:00:00 2001 From: Marco Salazar Date: Wed, 16 Apr 2025 14:21:33 -0400 Subject: [PATCH 3/4] fix --- .../packages/ui-core/src/assets/AssetHealthSummary.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx index c41ffcc103105..e51de755cdbb0 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetHealthSummary.tsx @@ -12,10 +12,9 @@ import { Tag, ifPlural, } from '@dagster-io/ui-components'; +import dayjs from 'dayjs'; import React, {useMemo} from 'react'; import {Link} from 'react-router-dom'; -import dayjs from 'dayjs'; - import {asAssetKeyInput} from './asInput'; import {assetDetailsPathForKey} from './assetDetailsPathForKey'; @@ -25,10 +24,10 @@ import { AssetHealthCheckDegradedMetaFragment, AssetHealthCheckUnknownMetaFragment, AssetHealthCheckWarningMetaFragment, + AssetHealthFreshnessMetaFragment, AssetHealthMaterializationDegradedNotPartitionedMetaFragment, AssetHealthMaterializationDegradedPartitionedMetaFragment, AssetHealthMaterializationWarningPartitionedMetaFragment, - AssetHealthFreshnessMetaFragment, } from '../asset-data/types/AssetHealthDataProvider.types'; import {AssetHealthStatus} from '../graphql/types'; import {numberFormatter} from '../ui/formatters'; @@ -253,7 +252,8 @@ const Criteria = React.memo( return ( - Last materialized {dayjs(Number(metadata.lastMaterializedTimestamp)).fromNow()} ago + Last materialized {dayjs(Number(metadata.lastMaterializedTimestamp * 1000)).fromNow()}{' '} + ago ); case undefined: From 187a8b7ee54423beba54261d775aaf4db6199351 Mon Sep 17 00:00:00 2001 From: JamieDeMaria Date: Wed, 16 Apr 2025 15:18:29 -0400 Subject: [PATCH 4/4] format after merge --- python_modules/dagster-test/dagster_test/toys/asset_health.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python_modules/dagster-test/dagster_test/toys/asset_health.py b/python_modules/dagster-test/dagster_test/toys/asset_health.py index 1f835141856d0..aaa1480549440 100644 --- a/python_modules/dagster-test/dagster_test/toys/asset_health.py +++ b/python_modules/dagster-test/dagster_test/toys/asset_health.py @@ -120,6 +120,7 @@ def observable_source_asset_random_execution_error(context): return dg.DataVersion("5") + @dg.asset( internal_freshness_policy=InternalFreshnessPolicy.time_window( fail_window=timedelta(minutes=5), warn_window=timedelta(minutes=1)