From f47dffb2eac7163894630d131e76670c2618f9f6 Mon Sep 17 00:00:00 2001 From: Gordon Smith Date: Thu, 4 Jul 2024 09:44:10 +0100 Subject: [PATCH] HPCC-32185 Prevent metrics timeline from making a duplicate WUDetails call Signed-off-by: Gordon Smith --- esp/src/src-react/components/Metrics.tsx | 45 +++++---------------- esp/src/src/Timings.ts | 50 +++++++++++++++++++++++- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/esp/src/src-react/components/Metrics.tsx b/esp/src/src-react/components/Metrics.tsx index ee05e3055e3..8ef04ccb5cc 100644 --- a/esp/src/src-react/components/Metrics.tsx +++ b/esp/src/src-react/components/Metrics.tsx @@ -9,7 +9,7 @@ import { WorkunitsServiceEx, IScope, splitMetric } from "@hpcc-js/comms"; import { DBStore, Table } from "@hpcc-js/dgrid"; import { compare, scopedLogger } from "@hpcc-js/util"; import nlsHPCC from "src/nlsHPCC"; -import { WUTimelinePatched } from "src/Timings"; +import { WUTimelineNoFetch } from "src/Timings"; import * as Utility from "src/Utility"; import { FetchStatus, useMetricsOptions, useWUQueryMetrics, MetricsOptions as MetricsOptionsT } from "../hooks/metrics"; import { HolyGrail } from "../layouts/HolyGrail"; @@ -200,40 +200,10 @@ export const Metrics: React.FunctionComponent = ({ }, [parentUrl, selection]); // Timeline --- - const timeline = useConst(() => new WUTimelinePatched() + const timeline = useConst(() => new WUTimelineNoFetch() .maxZoom(Number.MAX_SAFE_INTEGER) - .baseUrl("") - .request({ - ScopeFilter: { - MaxDepth: 3, - ScopeTypes: [] - }, - NestedFilter: { - Depth: 0, - ScopeTypes: [] - }, - PropertiesToReturn: { - AllProperties: false, - AllStatistics: true, - AllHints: false, - Properties: ["WhenStarted", "TimeElapsed", "TimeLocalExecute"] - }, - ScopeOptions: { - IncludeId: true, - IncludeScope: true, - IncludeScopeType: true - }, - PropertyOptions: { - IncludeName: true, - IncludeRawValue: true, - IncludeFormatted: true, - IncludeMeasure: true, - IncludeCreator: true, - IncludeCreatorType: false - } - }) .on("click", (row, col, sel) => { - setTimelineFilter(sel ? row[7].ScopeName : ""); + setTimelineFilter(sel ? row[7].__hpcc_id : ""); if (sel) { setSelectedMetricsSource("scopesTable"); pushUrl(`${parentUrl}/${row[7].Id}`); @@ -242,8 +212,11 @@ export const Metrics: React.FunctionComponent = ({ ); React.useEffect(() => { - timeline.wuid(wuid); - }, [timeline, wuid]); + timeline + .scopes(metrics) + .lazyRender() + ; + }, [metrics, timeline]); // Scopes Table --- const [scopeFilter, setScopeFilter] = React.useState(""); @@ -427,7 +400,7 @@ export const Metrics: React.FunctionComponent = ({ if (fetchStatus === FetchStatus.STARTED) { return nlsHPCC.FetchingData; } else if (!isLayoutComplete) { - return `${nlsHPCC.PerformingLayout} (${dot.split("\n").length})`; + return `${nlsHPCC.PerformingLayout}(${dot.split("\n").length})`; } else if (!isRenderComplete) { return nlsHPCC.RenderSVG; } diff --git a/esp/src/src/Timings.ts b/esp/src/src/Timings.ts index c7db66385e5..3aa90c8894e 100644 --- a/esp/src/src/Timings.ts +++ b/esp/src/src/Timings.ts @@ -1,6 +1,6 @@ import { Column } from "@hpcc-js/chart"; import { ascending as d3Ascending, max as d3Max, scaleLinear as d3ScaleLinear, select as d3Select } from "@hpcc-js/common"; -import { Workunit } from "@hpcc-js/comms"; +import { IScope, Workunit } from "@hpcc-js/comms"; import { WUTimeline } from "@hpcc-js/eclwatch"; import { ChartPanel } from "@hpcc-js/layout"; @@ -39,7 +39,9 @@ export class WUTimelinePatched extends WUTimeline { ; this._gantt["_series_idx"] = -1; this.strokeWidth(0); - this.tooltipHTML(d => ""); + this.tooltipHTML(d => { + return d[7].__hpcc_id; + }); } data(): any; @@ -59,6 +61,50 @@ export class WUTimelinePatched extends WUTimeline { } } +export class WUTimelineNoFetch extends WUTimelinePatched { + + constructor() { + super(); + } + + protected _scopes: IScope[] = []; + scopes(): IScope[]; + scopes(_: IScope[]): this; + scopes(_?: IScope[]): IScope[] | this { + if (arguments.length === 0) return this._scopes; + this._scopes = _; + return this; + } + + fetchScopes() { + const data = this._scopes.filter(scope => { + if (!scope.__hpcc_id) { + scope.__hpcc_id = scope.name; + } + return scope.id && + scope.WhenStarted && (scope.WhenFinished || scope.TimeElapsed) && + scope.type !== "activity"; + }).map((scope: IScope) => { + let whenFinished = scope.WhenFinished; + if (!whenFinished) { + const d = new Date(scope.WhenStarted); + d.setMilliseconds(d.getMilliseconds() + scope.TimeElapsed * 1000); + whenFinished = d.toISOString(); + } + return [ + scope.id, + scope.WhenStarted, + whenFinished, + null, + this._palette(scope.type), + scope.name.split("::").join(":").split(":").slice(0, 1), + scope + ]; + }); + this.data(data); + } +} + export class Timings { private wu: Workunit;