You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ap...@apache.org on 2019/01/31 18:59:13 UTC
[incubator-pinot] branch master updated: [TE] rootcause - callgraph
gui (#3769)
This is an automated email from the ASF dual-hosted git repository.
apucher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 0f4bf85 [TE] rootcause - callgraph gui (#3769)
0f4bf85 is described below
commit 0f4bf857f6df8a707cc9899c22298a2c6d23b126
Author: Alexander Pucher <ap...@linkedin.com>
AuthorDate: Thu Jan 31 10:59:08 2019 -0800
[TE] rootcause - callgraph gui (#3769)
Adds an additional CallGraph tab to the RCA UI that provides bare-bones visualization of call graph analysis results. This call graph UI integrates directly with data sets and metrics that support page_key and fabric/datacenter filters. The UI does not support time series visualization and selection toggling yet.
---
.../rootcause-callgraph-table/component.js | 137 +++++++++++++++++++++
.../rootcause-callgraph-table/template.hbs | 33 +++++
.../pods/partials/rootcause/callgraph/template.hbs | 10 ++
.../app/pods/rootcause/controller.js | 35 +++++-
.../app/pods/rootcause/template.hbs | 5 +
.../services/rootcause-callgraph-cache/service.js | 106 ++++++++++++++++
.../app/shared/callgraphTableColumns.js | 28 +++++
thirdeye/thirdeye-frontend/app/styles/app.scss | 1 +
.../app/styles/components/metrics-table.scss | 7 ++
.../app/styles/components/rootcause-callgraph.scss | 7 ++
thirdeye/thirdeye-frontend/app/utils/rca-utils.js | 37 +++++-
11 files changed, 396 insertions(+), 10 deletions(-)
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-callgraph-table/component.js b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-callgraph-table/component.js
new file mode 100644
index 0000000..0eb8995
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-callgraph-table/component.js
@@ -0,0 +1,137 @@
+import { computed, getProperties, set } from '@ember/object';
+import Component from '@ember/component';
+import {
+ toFilters
+} from 'thirdeye-frontend/utils/rca-utils';
+import {
+ humanizeChange,
+ humanizeFloat
+} from 'thirdeye-frontend/utils/utils';
+import CALLGRAPH_TABLE_COLUMNS from 'thirdeye-frontend/shared/callgraphTableColumns';
+import _ from 'lodash';
+
+export default Component.extend({
+ classNames: ['rootcause-metrics'],
+
+ /**
+ * Columns for dimensions table
+ * @type {Array}
+ */
+ callgraphTableColumns: CALLGRAPH_TABLE_COLUMNS,
+
+ //
+ // external properties
+ //
+
+ /**
+ * Primary metric
+ * @type {string}
+ */
+ metricUrn: null,
+
+ /**
+ * Edges cache
+ * @type {object}
+ */
+ edges: null,
+
+ //
+ // internal properties
+ //
+
+ /**
+ * Tracks presence of callgraph edges
+ * @type {boolean}
+ */
+ hasEdges: computed('edges', function () {
+ const { edges } = getProperties(this, 'edges');
+ return !_.isEmpty(edges);
+ }),
+
+ /**
+ * Fabrics analyzed
+ * @type {array}
+ */
+ fabrics: computed('metricUrn', function () {
+ const { metricUrn } = getProperties(this, 'metricUrn');
+ if (_.isEmpty(metricUrn)) { return []; }
+
+ const fabrics = toFilters(metricUrn).filter(t => t[0] === 'data_center').map(t => t[2]);
+ if (_.isEmpty(fabrics)) { return ['all']; }
+
+ return fabrics;
+ }),
+
+ /**
+ * Page keys analyzed
+ * @type {array}
+ */
+ pageKeys: computed('metricUrn', function () {
+ const { metricUrn } = getProperties(this, 'metricUrn');
+ if (_.isEmpty(metricUrn)) { return []; }
+
+ const pageKeys = toFilters(metricUrn).filter(t => t[0] === 'page_key').map(t => t[2]);
+
+ return pageKeys;
+ }),
+
+ /**
+ * Tracks presence of page keys
+ * @type {boolean}
+ */
+ hasPageKeys: computed('pageKeys', function () {
+ const { pageKeys } = getProperties(this, 'pageKeys');
+ return !_.isEmpty(pageKeys);
+ }),
+
+ /**
+ * Data for metrics table
+ * @type {Array}
+ */
+ callgraphTableData: computed('edges', function() {
+ const { edges } = getProperties(this, 'edges');
+
+ if (_.isEmpty(edges)) { return []; }
+
+ return Object.keys(edges).map(edge =>
+ toFilters(edge).reduce((agg, t) => { agg[t[0]] = this._parse(t[2]); return agg; }, {}));
+ }),
+
+ /**
+ * Keeps track of items that are selected in the table
+ * @type {Array}
+ */
+ preselectedItems: computed({
+ get () {
+ return [];
+ },
+ set () {
+ // ignore
+ }
+ }),
+
+ /**
+ * Parse values heuristically as string or float
+ * @private
+ */
+ _parse(value) {
+ const f = parseFloat(value);
+ if (!Number.isNaN(f)) {
+ if (f >= 100) {
+ return Math.round(f);
+ }
+ return (f / 1000.0).toFixed(3);
+ }
+ return value;
+ },
+
+ actions: {
+ /**
+ * Triggered on cell selection, ignored.
+ * @param {Object} e
+ */
+ displayDataChanged (e) {
+ // ignore
+ }
+ }
+});
diff --git a/thirdeye/thirdeye-frontend/app/pods/components/rootcause-callgraph-table/template.hbs b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-callgraph-table/template.hbs
new file mode 100644
index 0000000..cdc951a
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/components/rootcause-callgraph-table/template.hbs
@@ -0,0 +1,33 @@
+
+{{#if hasPageKeys}}
+ <ul class="list-unstyled">
+ <li><span class="rootcause-callgraph-label">Page Keys: </span>{{pageKeys}}</li>
+ <li><span class="rootcause-callgraph-label">Fabrics: </span>{{fabrics}}</li>
+ </ul>
+
+ {{#if hasEdges}}
+ <div class="rootcause-callgraph-table">
+ {{update-table
+ data=callgraphTableData
+ columns=callgraphTableColumns
+ preselectedItems=preselectedItems
+ showColumnsDropdown=false
+ showGlobalFilter=false
+ }}
+ </div>
+
+ {{else}}
+ <div class="rootcause-alert alert alert-warning fade in">
+ No call graph data available for the selected page keys and time range.
+ You may need to expand the investigation period.
+ </div>
+
+ {{/if}}
+
+{{else}}
+ <div class="rootcause-alert alert alert-warning fade in">
+ Call Graph analysis requires at least one active page key filter.
+ Please select a metric with a page key support, and select a page key filter to generate the report.
+ </div>
+
+{{/if}}
\ No newline at end of file
diff --git a/thirdeye/thirdeye-frontend/app/pods/partials/rootcause/callgraph/template.hbs b/thirdeye/thirdeye-frontend/app/pods/partials/rootcause/callgraph/template.hbs
new file mode 100644
index 0000000..136a395
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/partials/rootcause/callgraph/template.hbs
@@ -0,0 +1,10 @@
+{{#if isLoadingCallgraph}}
+ <div class="spinner-wrapper spinner-wrapper--card">
+ {{ember-spinner}}
+ </div>
+{{/if}}
+
+{{rootcause-callgraph-table
+ edges=edges
+ metricUrn=metricUrn
+}}
diff --git a/thirdeye/thirdeye-frontend/app/pods/rootcause/controller.js b/thirdeye/thirdeye-frontend/app/pods/rootcause/controller.js
index f8ebeee..531a3af 100644
--- a/thirdeye/thirdeye-frontend/app/pods/rootcause/controller.js
+++ b/thirdeye/thirdeye-frontend/app/pods/rootcause/controller.js
@@ -25,6 +25,7 @@ const ROOTCAUSE_TAB_DIMENSIONS = 'dimensions';
const ROOTCAUSE_TAB_METRICS = 'metrics';
const ROOTCAUSE_TAB_EVENTS = 'events';
const ROOTCAUSE_TAB_TREND = 'trend';
+const ROOTCAUSE_TAB_CALLGRAPH = 'callgraph';
const ROOTCAUSE_SETUP_MODE_CONTEXT = "context";
const ROOTCAUSE_SETUP_MODE_SELECTED = "selected";
@@ -39,6 +40,7 @@ const ROOTCAUSE_SERVICE_TIMESERIES = 'timeseries';
const ROOTCAUSE_SERVICE_AGGREGATES = 'aggregates';
const ROOTCAUSE_SERVICE_BREAKDOWNS = 'breakdowns';
const ROOTCAUSE_SERVICE_ANOMALY_FUNCTIONS = 'anomalyFunctions';
+const ROOTCAUSE_SERVICE_CALLGRAPH = 'callgraph';
const ROOTCAUSE_SERVICE_ALL = 'all';
const ROOTCAUSE_SESSION_TIMER_INTERVAL = 300000;
@@ -98,6 +100,8 @@ export default Controller.extend({
anomalyFunctionService: service('services/rootcause-anomalyfunction-cache'),
+ callgraphService: service('services/rootcause-callgraph-cache'),
+
//
// user details
//
@@ -297,6 +301,9 @@ export default Controller.extend({
*
* anomalyfunctions: anomaly function baselines for display in chart
* (typically displayed in timeseries chart)
+ *
+ * callgraph: service call graph edges as ranked by the backend
+ * (typically displayed in call graph table)
*/
_contextObserver: observer(
'context',
@@ -305,8 +312,8 @@ export default Controller.extend({
'sizeMetricUrns',
'activeTab',
function () {
- const { context, selectedUrns, sizeMetricUrns, entitiesService, timeseriesService, aggregatesService, breakdownsService, scoresService, anomalyFunctionService, activeTab, setupMode } =
- getProperties(this, 'context', 'selectedUrns', 'sizeMetricUrns', 'entitiesService', 'timeseriesService', 'aggregatesService', 'breakdownsService', 'scoresService', 'anomalyFunctionService', 'activeTab', 'setupMode');
+ const { context, selectedUrns, sizeMetricUrns, entitiesService, timeseriesService, aggregatesService, breakdownsService, scoresService, anomalyFunctionService, callgraphService, activeTab, setupMode } =
+ getProperties(this, 'context', 'selectedUrns', 'sizeMetricUrns', 'entitiesService', 'timeseriesService', 'aggregatesService', 'breakdownsService', 'scoresService', 'anomalyFunctionService', 'callgraphService', 'activeTab', 'setupMode');
if (!context || !selectedUrns) {
return;
}
@@ -389,6 +396,13 @@ export default Controller.extend({
.map(urn => [].concat(anomalyOffsets.map(offset => toOffsetUrn(urn, offset))))
.reduce((agg, l) => agg.concat(l), []);
+ //
+ // call graph
+ //
+ if (activeTab === ROOTCAUSE_SERVICE_CALLGRAPH) {
+ callgraphService.request(context, [...context.urns]);
+ }
+
aggregatesService.request(context, new Set([...offsetUrns, ...anomalyOffsetUrns]));
}
@@ -485,6 +499,12 @@ export default Controller.extend({
scores: reads('scoresService.scores'),
/**
+ * Subscribed callgraph edges cache
+ * @type {object}
+ */
+ edges: reads('callgraphService.edges'),
+
+ /**
* Primary metric urn for rootcause search
* @type {string}
*/
@@ -611,6 +631,8 @@ export default Controller.extend({
isLoadingMetricData: or('isLoadingAggregates', 'isLoadingScores'),
+ isLoadingCallgraph: gt('callgraphService.pending.size', 0),
+
loadingFrameworks: reads('entitiesService.pending'),
//
@@ -1161,8 +1183,8 @@ export default Controller.extend({
* Clears error logs of data services and/or route
*/
clearErrors(type) {
- const { entitiesService, timeseriesService, aggregatesService, breakdownsService, anomalyFunctionService } =
- getProperties(this, 'entitiesService', 'timeseriesService', 'aggregatesService', 'breakdownsService', 'anomalyFunctionService');
+ const { entitiesService, timeseriesService, aggregatesService, breakdownsService, anomalyFunctionService, callgraphService } =
+ getProperties(this, 'entitiesService', 'timeseriesService', 'aggregatesService', 'breakdownsService', 'anomalyFunctionService', 'callgraphService');
switch(type) {
case ROOTCAUSE_SERVICE_ENTITIES:
@@ -1185,6 +1207,10 @@ export default Controller.extend({
anomalyFunctionService.clearErrors();
break;
+ case ROOTCAUSE_SERVICE_CALLGRAPH:
+ callgraphService.clearErrors();
+ break;
+
case ROOTCAUSE_SERVICE_ROUTE:
setProperties(this, { routeErrors: new Set() });
break;
@@ -1195,6 +1221,7 @@ export default Controller.extend({
aggregatesService.clearErrors();
breakdownsService.clearErrors();
anomalyFunctionService.clearErrors();
+ callgraphService.clearErrors();
break;
}
diff --git a/thirdeye/thirdeye-frontend/app/pods/rootcause/template.hbs b/thirdeye/thirdeye-frontend/app/pods/rootcause/template.hbs
index 3b984a1..4842585 100644
--- a/thirdeye/thirdeye-frontend/app/pods/rootcause/template.hbs
+++ b/thirdeye/thirdeye-frontend/app/pods/rootcause/template.hbs
@@ -174,6 +174,7 @@
{{#tablist.tab name="dimensions"}}Dimensions{{/tablist.tab}}
{{#tablist.tab name="events"}}Events{{/tablist.tab}}
{{#tablist.tab name="trend"}}Trend{{/tablist.tab}}
+ {{#tablist.tab name="callgraph"}}CallGraph{{/tablist.tab}}
{{/tabs.tablist}}
{{!-- metrics --}}
{{#tabs.tabpanel name="metrics"}}
@@ -191,6 +192,10 @@
{{#tabs.tabpanel name="trend"}}
{{partial 'partials/rootcause/trend'}}
{{/tabs.tabpanel}}
+ {{!-- callgraph --}}
+ {{#tabs.tabpanel name="callgraph"}}
+ {{partial 'partials/rootcause/callgraph'}}
+ {{/tabs.tabpanel}}
{{/shared/common-tabs}}
</div>
</div>
diff --git a/thirdeye/thirdeye-frontend/app/pods/services/rootcause-callgraph-cache/service.js b/thirdeye/thirdeye-frontend/app/pods/services/rootcause-callgraph-cache/service.js
new file mode 100644
index 0000000..18d0b87
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/pods/services/rootcause-callgraph-cache/service.js
@@ -0,0 +1,106 @@
+import Service from '@ember/service';
+import { inject as service } from '@ember/service';
+import {
+ trimTimeRanges,
+ filterPrefix,
+ toBaselineRange,
+ toDimensionsUrn
+} from 'thirdeye-frontend/utils/rca-utils';
+import { checkStatus } from 'thirdeye-frontend/utils/utils';
+import _ from 'lodash';
+
+const ROOTCAUSE_CALLGRAPH_ENDPOINT = '/rootcause/query';
+const ROOTCAUSE_CALLGRAPH_PRIORITY = 15;
+
+export default Service.extend({
+ edges: null, // {}
+
+ context: null, // {}
+
+ pending: null, // Set
+
+ errors: null, // Set({ urn, error })
+
+ fetcher: service('services/rootcause-fetcher'),
+
+ init() {
+ this._super(...arguments);
+ this.setProperties({ edges: {}, context: {}, pending: new Set(), errors: new Set() });
+ },
+
+ clearErrors() {
+ this.setProperties({ errors: new Set() });
+ },
+
+ request(requestContext, urns) {
+ const { context } = this.getProperties('context');
+
+ const metrics = [...urns].filter(urn => urn.startsWith('thirdeye:metric:'));
+
+ if(_.isEqual(context, requestContext)) {
+ return;
+ }
+
+ // new analysis range: evict all, reload
+ this.get('fetcher').resetPrefix(ROOTCAUSE_CALLGRAPH_ENDPOINT);
+ this.setProperties({ context: _.cloneDeep(requestContext), edges: {}, pending: new Set(metrics) });
+
+ if (_.isEmpty(metrics)) {
+ return;
+ }
+
+ // call graph properties
+ const fetcher = this.get('fetcher');
+
+ const dimensionsUrns = [...metrics].map(toDimensionsUrn);
+
+ // TODO generalize replacement
+ const dimensionsUrnsModified = dimensionsUrns
+ .map(urn => urn.replace(/:data_center/, ':callee_fabric'))
+ .map(urn => urn.replace(/:fabric/, ':callee_fabric'))
+ .map(urn => urn.replace(/:service/, ':callee_container'))
+ .map(urn => urn.replace(/:data_center/, ':callee_fabric'));
+
+ const url = this._makeUrl('callgraph', requestContext, dimensionsUrnsModified);
+ fetcher.fetch(url, ROOTCAUSE_CALLGRAPH_PRIORITY)
+ .then(checkStatus)
+ .then(res => this._complete(requestContext, res))
+ .catch(error => this._handleError(urns, error));
+ },
+
+ _complete(requestContext, incoming) {
+ const { context } = this.getProperties('context');
+
+ if (!_.isEqual(context, requestContext)) {
+ return;
+ }
+
+ const edges = incoming.reduce((agg, e) => { agg[e.urn] = e; return agg; }, {});
+
+ this.setProperties({ edges, pending: new Set() });
+ },
+
+ _makeUrl(framework, context, urns) {
+ const urnString = filterPrefix(urns, 'thirdeye:dimensions:').join(',');
+ const ranges = trimTimeRanges(context.anomalyRange, context.analysisRange);
+
+ const baselineRange = toBaselineRange(ranges.anomalyRange, context.compareMode);
+ return `${ROOTCAUSE_CALLGRAPH_ENDPOINT}?framework=${framework}` +
+ `&anomalyStart=${ranges.anomalyRange[0]}&anomalyEnd=${ranges.anomalyRange[1]}` +
+ `&baselineStart=${baselineRange[0]}&baselineEnd=${baselineRange[1]}` +
+ `&analysisStart=${ranges.analysisRange[0]}&analysisEnd=${ranges.analysisRange[1]}` +
+ `&urns=${urnString}`;
+ },
+
+ _handleError(urns, error) {
+ const { errors, pending } = this.getProperties('errors', 'pending');
+
+ const newError = urns;
+ const newErrors = new Set([...errors, newError]);
+
+ const newPending = new Set(pending);
+ [...urns].forEach(urn => newPending.delete(urn));
+
+ this.setProperties({ errors: newErrors, pending: newPending });
+ }
+});
diff --git a/thirdeye/thirdeye-frontend/app/shared/callgraphTableColumns.js b/thirdeye/thirdeye-frontend/app/shared/callgraphTableColumns.js
new file mode 100644
index 0000000..dcb0d9f
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/shared/callgraphTableColumns.js
@@ -0,0 +1,28 @@
+// rootcause dimensions table columns
+export default [
+ {
+ propertyName: 'callee_container',
+ title: 'Container',
+ className: 'metrics-table__column metrics-table__column--text'
+ }, {
+ propertyName: 'callee_fabric',
+ title: 'Fabric',
+ className: 'metrics-table__column metrics-table__column--text'
+ }, {
+ propertyName: 'callee_api',
+ title: 'API',
+ className: 'metrics-table__column metrics-table__column--text'
+ }, {
+ propertyName: 'currCount',
+ title: 'Traffic',
+ disableFiltering: true,
+ className: 'metrics-table__column metrics-table__column--small'
+ }, {
+ propertyName: 'diffAverage',
+ title: 'Change in Avg. Latency',
+ disableFiltering: true,
+ className: 'metrics-table__column metrics-table__column--small',
+ sortDirection: 'desc',
+ sortPrecedence: 0
+ }
+];
diff --git a/thirdeye/thirdeye-frontend/app/styles/app.scss b/thirdeye/thirdeye-frontend/app/styles/app.scss
index fd476c3..59940ab 100644
--- a/thirdeye/thirdeye-frontend/app/styles/app.scss
+++ b/thirdeye/thirdeye-frontend/app/styles/app.scss
@@ -56,6 +56,7 @@ body {
@import 'components/rootcause-chart';
@import 'components/rootcause-trend';
@import 'components/rootcause-dimensions';
+@import 'components/rootcause-callgraph';
@import 'components/alert-report-modal';
@import 'components/te-radio';
@import 'components/metrics-table';
diff --git a/thirdeye/thirdeye-frontend/app/styles/components/metrics-table.scss b/thirdeye/thirdeye-frontend/app/styles/components/metrics-table.scss
index 9680796..a98cdf2 100644
--- a/thirdeye/thirdeye-frontend/app/styles/components/metrics-table.scss
+++ b/thirdeye/thirdeye-frontend/app/styles/components/metrics-table.scss
@@ -1,6 +1,7 @@
.metrics-table {
&__column {
vertical-align: middle !important; // override ember-models-table
+
&--checkbox {
width: 24px;
}
@@ -10,8 +11,14 @@
text-align: right;
}
+ &--text {
+ width: 80px;
+ text-align: left;
+ }
+
&--large {
min-width: 200px;
+ text-align: left;
}
}
diff --git a/thirdeye/thirdeye-frontend/app/styles/components/rootcause-callgraph.scss b/thirdeye/thirdeye-frontend/app/styles/components/rootcause-callgraph.scss
new file mode 100644
index 0000000..0a320e6
--- /dev/null
+++ b/thirdeye/thirdeye-frontend/app/styles/components/rootcause-callgraph.scss
@@ -0,0 +1,7 @@
+.rootcause-callgraph-label {
+ font-weight: bold;
+}
+
+.rootcause-callgraph-table {
+ margin-top: 16px;
+}
diff --git a/thirdeye/thirdeye-frontend/app/utils/rca-utils.js b/thirdeye/thirdeye-frontend/app/utils/rca-utils.js
index 4c2103c..e96493b 100644
--- a/thirdeye/thirdeye-frontend/app/utils/rca-utils.js
+++ b/thirdeye/thirdeye-frontend/app/utils/rca-utils.js
@@ -111,6 +111,12 @@ export function stripTail(urn) {
if (urn.startsWith('frontend:anomalyfunction:')) {
return _.slice(parts, 0, 3).join(':');
}
+ if (urn.startsWith('thirdeye:dimensions:')) {
+ return _.slice(parts, 0, 2).join(':');
+ }
+ if (urn.startsWith('thirdeye:callgraph:')) {
+ return _.slice(parts, 0, 2).join(':');
+ }
return urn;
}
@@ -124,13 +130,19 @@ export function stripTail(urn) {
export function extractTail(urn) {
const parts = urn.split(':');
if (urn.startsWith('thirdeye:metric:')) {
- return _.slice(parts, 3);
+ return _.slice(parts, 3).filter(p => !_.isEmpty(p));
}
if (urn.startsWith('frontend:metric:')) {
- return _.slice(parts, 4);
+ return _.slice(parts, 4).filter(p => !_.isEmpty(p));
}
if (urn.startsWith('frontend:anomalyfunction:')) {
- return _.slice(parts, 3);
+ return _.slice(parts, 3).filter(p => !_.isEmpty(p));
+ }
+ if (urn.startsWith('thirdeye:dimensions:')) {
+ return _.slice(parts, 2).filter(p => !_.isEmpty(p));
+ }
+ if (urn.startsWith('thirdeye:callgraph:')) {
+ return _.slice(parts, 2).filter(p => !_.isEmpty(p));
}
return [];
}
@@ -190,6 +202,17 @@ export function toBaselineUrn(urn) {
}
/**
+ * Converts any metric urn to its dimensions equivalent
+ * Example: 'thirdeye:metric:123:country=IT' returns 'thirdeye:dimensions:country=IT'
+ *
+ * @param {string} urn metric urn
+ * @returns {string} dimensions urn
+ */
+export function toDimensionsUrn(urn) {
+ return appendTail('thirdeye:dimensions:', extractTail(urn));
+}
+
+/**
* Converts any metric urn to its frontend metric-reference equivalent, with an user-specified offset.
*
* @param {string} urn metric urn
@@ -336,7 +359,7 @@ function metricUrnHelper(prefix, urn) {
const tail = makeUrnTail(parts, 3);
return `${prefix}${parts[2]}${tail}`;
}
- throw new Error(`Requires metric urn, but found ${urn}`);
+ throw new Error(`Requires supported urn, but found ${urn}`);
}
/**
@@ -467,12 +490,13 @@ export function toAbsoluteRange(urn, currentRange, baselineCompareMode) {
export function toFilters(urns) {
const flatten = (agg, l) => agg.concat(l);
const dimensionFilters = filterPrefix(urns, 'thirdeye:dimension:').map(urn => _.slice(urn.split(':').map(decodeURIComponent), 2, 4).insertAt(1, '='));
-
+ const dimensionsFilters = filterPrefix(urns, 'thirdeye:dimensions:').map(extractTail).map(enc => enc.map(tup => splitFilterFragment(decodeURIComponent(tup)))).reduce(flatten, []);
const metricFilters = filterPrefix(urns, 'thirdeye:metric:').map(extractTail).map(enc => enc.map(tup => splitFilterFragment(decodeURIComponent(tup)))).reduce(flatten, []);
const frontendMetricFilters = filterPrefix(urns, 'frontend:metric:').map(extractTail).map(enc => enc.map(tup => splitFilterFragment(decodeURIComponent(tup)))).reduce(flatten, []);
const anomalyFunctionFilters = filterPrefix(urns, 'frontend:anomalyfunction:').map(extractTail).map(enc => enc.map(tup => splitFilterFragment(decodeURIComponent(tup)))).reduce(flatten, []);
+ const callgraphFilters = filterPrefix(urns, 'thirdeye:callgraph:').map(extractTail).map(enc => enc.map(tup => splitFilterFragment(decodeURIComponent(tup)))).reduce(flatten, []);
- return [...new Set([...dimensionFilters, ...metricFilters, ...frontendMetricFilters, ...anomalyFunctionFilters])].sort();
+ return [...new Set([...dimensionFilters, ...dimensionsFilters, ...metricFilters, ...frontendMetricFilters, ...anomalyFunctionFilters, ...callgraphFilters])].sort();
}
/**
@@ -729,6 +753,7 @@ export default {
toMetricUrn,
toOffsetUrn,
toAbsoluteUrn,
+ toDimensionsUrn,
stripTail,
extractTail,
appendTail,
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org