Browse Source

HPCC-17840 Normalize data for stats chart

Allow charting different metrics on a single chart.

Signed-off-by: Gordon Smith <gordonjsmith@gmail.com>
Gordon Smith 6 năm trước cách đây
mục cha
commit
6ad4ed4118

+ 1 - 1
esp/src/eclwatch/GraphsWidget.js

@@ -284,7 +284,7 @@ define([
                 var title = row.Name;
                 var delayWidget = "GraphTree7Widget";
                 var delayProps = {
-                    _owner: this,
+                    _hostPage: this,
                     forceJS: true
                 };
                 if (params && params.SubGraphId) {

+ 1 - 1
esp/src/eclwatch/TimingPageWidget.js

@@ -269,7 +269,7 @@ define([
                         closable: true,
                         delayWidget: "GraphTree7Widget",
                         delayProps: {
-                            _owner: this
+                            _hostPage: this
                         },
                         params: {
                             Wuid: this.wu.Wuid,

+ 9 - 2
esp/src/eclwatch/dojoConfig.js

@@ -24,8 +24,15 @@ function getConfig(env) {
             "templates": baseUrl + "/eclwatch/templates",
             "ecl": baseUrl + "/eclwatch/ecl",
             "css": baseUrl + "/loader/css",
-            "d3-array": baseUrl + "/node_modules/d3-array/build/d3-array",
-            "d3-selection": baseUrl + "/node_modules/d3-selection/build/d3-selection",
+            "d3-array": baseUrl + "/node_modules/d3-array/build/d3-array" + hpccMin,
+            "d3-collection": baseUrl + "/node_modules/d3-collection/build/d3-collection" + hpccMin,
+            "d3-color": baseUrl + "/node_modules/d3-color/build/d3-color" + hpccMin,
+            "d3-format": baseUrl + "/node_modules/d3-format/build/d3-format" + hpccMin,
+            "d3-interpolate": baseUrl + "/node_modules/d3-interpolate/build/d3-interpolate" + hpccMin,
+            "d3-scale": baseUrl + "/node_modules/d3-scale/build/d3-scale" + hpccMin,
+            "d3-selection": baseUrl + "/node_modules/d3-selection/build/d3-selection" + hpccMin,
+            "d3-time": baseUrl + "/node_modules/d3-time/build/d3-time" + hpccMin,
+            "d3-time-format": baseUrl + "/node_modules/d3-time-format/build/d3-time-format" + hpccMin,
             "@hpcc-js/api": baseUrl + "/node_modules/@hpcc-js/api/dist/index" + hpccMin,
             "@hpcc-js/chart": baseUrl + "/node_modules/@hpcc-js/chart/dist/index" + hpccMin,
             "@hpcc-js/common": baseUrl + "/node_modules/@hpcc-js/common/dist/index" + hpccMin,

+ 2 - 2
esp/src/eclwatch/templates/TimingPageWidget.html

@@ -33,8 +33,8 @@
                         <div id="${id}Grid" style="padding: 0px; border:0px; border-color:none">
                         </div>
                     </div>
-                    <div id="${id}TimingTab2" style="padding: 0px; border:0px; border-color:none" data-dojo-props='title:"${i18n.Chart}"' data-dojo-type="dijit.layout.ContentPane">
-                        <div id="${id}Chart" style="width:100%;height:100%">
+                    <div id="${id}TimingTab2" style="padding: 0px; border:0px; border-color:none" data-dojo-props='title:"${i18n.Chart}",iconClass:"iconChart"' data-dojo-type="dijit.layout.ContentPane">
+                        <div id="${id}Chart" style="width:100%;height:100%;overflow: hidden;">
                         </div>
                     </div>
                 </div>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 103 - 797
esp/src/package-lock.json


+ 8 - 6
esp/src/package.json

@@ -32,19 +32,21 @@
   "dependencies": {},
   "devDependencies": {
     "@types/dojo": "1.9.40",
-    "@hpcc-js/chart": "0.8.11",
-    "@hpcc-js/comms": "0.4.15",
-    "@hpcc-js/eclwatch": "0.2.21",
-    "@hpcc-js/map": "0.3.21",
-    "@hpcc-js/other": "0.5.14",
-    "@hpcc-js/tree": "0.1.16",
+    "@hpcc-js/chart": "2.1.0",
+    "@hpcc-js/comms": "2.0.1",
+    "@hpcc-js/eclwatch": "2.0.1",
+    "@hpcc-js/map": "2.0.1",
+    "@hpcc-js/other": "2.1.0",
+    "@hpcc-js/tree": "2.0.1",
     "clipboard": "1.7.1",
     "codemirror": "5.31.0",
     "copy-webpack-plugin": "4.5.2",
     "cpx": "1.5.0",
     "crossfilter2": "1.4.3",
     "css-loader": "1.0.0",
+    "d3-array": "1.2.1",
     "dijit": "1.13.0",
+    "d3-scale": "1.0.6",
     "dojo": "1.13.0",
     "dojo-themes": "1.13.0",
     "dojo-util": "1.13.0",

+ 22 - 18
esp/src/src/GraphTree7Widget.ts

@@ -69,7 +69,7 @@ export class GraphTree7Widget {
     targetQuery: any;
     queryId: any;
 
-    _owner;
+    _hostPage;
     wuid = "";
     graphName = "";
     subgraphsGrid = null;
@@ -390,9 +390,11 @@ export class GraphTree7Widget {
 
     formatColumns(columns) {
         columns.forEach((column: any) => {
-            column.formatter = function (cell, row) {
-                const retVal = (row.__formatted && row.__formatted[`${column.field}`]) ? row.__formatted[`${column.field}`] : cell;
-                return retVal !== undefined ? retVal : "";
+            if (column.formatter === undefined) {
+                column.formatter = function (cell, row) {
+                    const retVal = (row.__formatted && row.__formatted[`${column.field}`]) ? row.__formatted[`${column.field}`] : cell;
+                    return retVal !== undefined ? retVal : "";
+                }
             }
         })
     }
@@ -404,7 +406,7 @@ export class GraphTree7Widget {
         const context = this;
         this.subgraphsGrid.on(".dgrid-row-url:click", function (evt) {
             var row = context.subgraphsGrid.row(evt).data;
-            context._owner.openGraph(context.graphName, row.Id);
+            context._hostPage.openGraph(context.graphName, row.Id);
         });
 
         this._initItemGrid(this.subgraphsGrid);
@@ -419,7 +421,7 @@ export class GraphTree7Widget {
             {
                 label: this.i18n.ID, field: "Id", width: 54,
                 formatter: function (_id, row) {
-                    return "<img src='" + img + "'/>&nbsp;" + (context._owner ? "<a href='#" + _id + "' class='dgrid-row-url'>" + _id + "</a>" : _id);
+                    return "<img src='" + img + "'/>&nbsp;" + (context._hostPage ? "<a href='#" + _id + "' class='dgrid-row-url'>" + _id + "</a>" : _id);
                 }
             }
         ];
@@ -489,18 +491,20 @@ export class GraphTree7Widget {
                 scopeItem = scopeItem.parent;
             }
             const w = this._gc.item(itemID);
-            if (refresh) {
-                this._graph
-                    .data(this._gc.graphData(), true)   //  Force re-render 
-                    .render(w => {
-                        setTimeout(() => {
-                            this._graph
-                                .centerOnItem(w)
-                                ;
-                        }, 1000);
-                    });
-            } else {
-                this._graph.centerOnItem(w);
+            if (w) {
+                if (refresh) {
+                    this._graph
+                        .data(this._gc.graphData(), true)   //  Force re-render 
+                        .render(w => {
+                            setTimeout(() => {
+                                this._graph
+                                    .centerOnItem(w)
+                                    ;
+                            }, 1000);
+                        });
+                } else {
+                    this._graph.centerOnItem(w);
+                }
             }
         }
     }

+ 51 - 7
esp/src/src/Timings.ts

@@ -1,11 +1,24 @@
 import { Workunit } from "@hpcc-js/comms";
 import * as hpccCommon from "@hpcc-js/common";
 import { WUTimeline } from "@hpcc-js/eclwatch";
+import { ChartPanel } from "@hpcc-js/layout";
 import { Column } from "@hpcc-js/chart";
-import { ascending as d3Ascending } from "d3-array";
+import { ascending as d3Ascending, max as d3Max } from "d3-array";
+import { scaleLinear as d3ScaleLinear } from "d3-scale";
 
 const d3Select = (hpccCommon as any).select;
 
+class TimingColumn extends Column {
+
+    layerEnter(host, element, duration) {
+        super.layerEnter(host, element, duration);
+        this.tooltipHTML(d => {
+            const lparam = d.origRow[d.origRow.length - 1];
+            return d.column + ":  " + lparam["__" + d.column];
+        });
+    }
+}
+
 export class Timings {
     private wu: Workunit;
 
@@ -46,9 +59,18 @@ export class Timings {
         })
         ;
 
-    private chart = new Column()
+    private chart = new TimingColumn()
         .yAxisDomainLow(0 as any)
         .yAxisTickFormat("s")
+        .yAxisHidden(true)
+        ;
+    private chartPanel = new ChartPanel()
+        .dataButtonVisible(false)
+        .downloadButtonVisible(false)
+        .legendButtonVisible(false)
+        .legendVisible(true)
+        .titleOverlay(true)
+        .widget(this.chart)
         ;
 
     private metricsSelect;
@@ -58,7 +80,9 @@ export class Timings {
         this.timeline
             .target(timelineTarget)
             .wuid(wuid)
-        this.chart
+            ;
+        delete (this.timeline as any).__prop_tickFormat;
+        this.chartPanel
             .target(chartTarget)
             ;
         this.metricsSelect = d3Select(`#${metricsSelectTarget}`);
@@ -261,17 +285,37 @@ export class Timings {
                 ;
             options.exit().remove();
 
-            this.chart
+            const filteredData = data.filter((row, i) => row.name !== this._scopeFilter);
+            const normalizedData = this.normalize(filteredData);
+
+            this.chartPanel
                 .columns(["id", ...this._metricSelectValue])
-                .data(data.filter((row, i) => row.name !== this._scopeFilter).map((row, i) => {
-                    return [row.id, ...this._metricSelectValue.map(metric => row[metric])];
+                .data(normalizedData.map((row, i) => {
+                    return [row.id, ...this._metricSelectValue.map(metric => row[metric]), row];
                 }))
+                .lazyRender()
                 ;
 
             return [this._metricSelectValue, data];
         });
     }
 
+    normalize(data) {
+        const normalizedData = data.map(row => {
+            return {
+                ...row
+            };
+        });
+        this._metricSelectValue.forEach(metric => {
+            var max = d3Max(data.map(row => row[metric]));
+            var scale = d3ScaleLinear().domain([0, max]).range([0, 100]);
+            normalizedData.forEach(row => {
+                row[metric] = scale(row[metric]);
+            });
+        });
+        return normalizedData;
+    }
+
     resizeTimeline() {
         this.timeline
             .resize()
@@ -280,7 +324,7 @@ export class Timings {
     }
 
     resizeChart() {
-        this.chart
+        this.chartPanel
             .resize()
             .lazyRender()
             ;

+ 8 - 6
esp/src/src/WUScopeController.ts

@@ -619,9 +619,9 @@ export class WUScopeController {
         return retVal;
     }
 
-    scopeItem(_: string): ScopeSubgraph | ScopeVertex | ScopeEdge {
+    scopeItem(_: string): ScopeSubgraph | ScopeVertex | ScopeEdge | undefined {
         const widget = this.item(_);
-        return this.rItem(widget);
+        return widget ? this.rItem(widget) : undefined;
     }
 
     item(_: string): Subgraph | VertexType | Edge {
@@ -761,10 +761,12 @@ export class WUScopeController {
 
     calcGraphTooltip(id: string, findText?: string) {
         const item = this.scopeItem(id);
-        const scope = item._;
-        const parentScope = item.parent._;
-        if (scope) {
-            return this.calcTooltip(scope, parentScope, findText);
+        if (item) {
+            const scope = item._;
+            const parentScope = item.parent._;
+            if (scope) {
+                return this.calcTooltip(scope, parentScope, findText);
+            }
         }
         return "";
     }