refactor: update metrics
diff --git a/src/datasource.ts b/src/datasource.ts
index 42a5af7..42f7e02 100644
--- a/src/datasource.ts
+++ b/src/datasource.ts
@@ -6,7 +6,8 @@
DataSourceInstanceSettings,
MutableDataFrame,
FieldType,
- // FieldColorModeId,
+ ArrayVector,
+ NodeGraphDataFrameFieldNames,
} from '@grafana/data';
import { getBackendSrv, getTemplateSrv } from '@grafana/runtime';
import dayjs from "dayjs";
@@ -53,10 +54,10 @@
const promises = options.targets.map(async (target) => {
const query = defaults(target, DEFAULT_QUERY);
const layer = getTemplateSrv().replace(query.layer, options.scopedVars);
- if (!layer) {
+ const serviceName = getTemplateSrv().replace(query.service, options.scopedVars);
+ if (!layer && !serviceName) {
return [];
}
- const serviceName = getTemplateSrv().replace(query.service, options.scopedVars);
const nodeMetricsStr = getTemplateSrv().replace(query.nodeMetrics, options.scopedVars);
const nodeMetrics = nodeMetricsStr ? this.parseMetrics(nodeMetricsStr) : [];
const edgeMetricsStr = getTemplateSrv().replace(query.edgeMetrics, options.scopedVars);
@@ -106,25 +107,16 @@
const edgeMetricsResp: any = (edgeServerMetricsResp || edgeClientMetricsResp) ? {
data: {...edgeServerMetricsResp.data, ...edgeClientMetricsResp.data}
} : null;
- const topology = this.setTopologyMetrics({
+ const fieldTypes = this.setFieldTypes({
nodes,
calls,
nodeMetrics: nodeMetricsResp ? {...nodeMetricsResp, config: nodeMetrics} : undefined,
edgeMetrics: edgeMetricsResp ? {...edgeMetricsResp, config: edgeMetrics} : undefined,
});
- const {nodeFieldTypes, edgeFieldTypes} = this.setFieldTypes({
- nodeMetrics: nodeMetricsResp ? {...nodeMetricsResp, config: nodeMetrics} : undefined,
- edgeMetrics: edgeMetricsResp ? {...edgeMetricsResp, config: edgeMetrics} : undefined,
- });
- console.log(topology);
const nodeFrame = new MutableDataFrame({
name: 'Nodes',
refId: target.refId,
- fields: [
- { name: 'id', type: FieldType.string },
- { name: 'title', type: FieldType.string },
- ...nodeFieldTypes
- ],
+ fields: fieldTypes.nodeFieldTypes,
meta: {
preferredVisualisationType: 'nodeGraph',
}
@@ -132,22 +124,12 @@
const edgeFrame = new MutableDataFrame({
name: 'Edges',
refId: target.refId,
- fields: [
- { name: 'id', type: FieldType.string },
- { name: 'source', type: FieldType.string },
- { name: 'target', type: FieldType.string },
- ...edgeFieldTypes,
- ],
+ fields: fieldTypes.edgeFieldTypes,
meta: {
preferredVisualisationType: 'nodeGraph',
}
});
- for (const node of topology.nodes) {
- nodeFrame.add({...node, title: node.name});
- }
- for (const call of topology.calls) {
- edgeFrame.add(call);
- }
+
return [nodeFrame, edgeFrame];
});
@@ -203,67 +185,108 @@
return {nodes, calls}
}
- setFieldTypes(params: {nodeMetrics: Recordable, edgeMetrics: Recordable}) {
+ setFieldTypes(params: {nodes: Node[], calls: Call[], nodeMetrics: Recordable, edgeMetrics: Recordable}) {
const nodeMetrics = params.nodeMetrics || {config: [], data: {}};
const edgeMetrics = params.edgeMetrics || {config: [], data: {}};
- const nodeFieldTypes = this.getTypes(nodeMetrics);
- const edgeFieldTypes = this.getTypes(edgeMetrics);
+ if (!(params.nodes && params.calls)) {
+ return {nodeFieldTypes: [], edgeFieldTypes: []};;
+ }
+ const nodeFieldTypes = this.getNodeTypes(params.nodes || [], nodeMetrics);
+ const edgeFieldTypes = this.getEdgeTypes(params.calls || [], edgeMetrics);
return {nodeFieldTypes, edgeFieldTypes};
}
- getTypes(metrics: Recordable) {
- const types = Object.keys(metrics.data).map((k: string, index: number) => {
+ getNodeTypes(nodes: Node[], metrics: Recordable) {
+ const idField = { name: NodeGraphDataFrameFieldNames.id, type: FieldType.string, values: new ArrayVector(), config: {}};
+ const titleField = { name: NodeGraphDataFrameFieldNames.title, type: FieldType.string, values: new ArrayVector(), config: {}};
+ const mainStatField = { name: NodeGraphDataFrameFieldNames.mainStat, type: FieldType.number, values: new ArrayVector(), config: {}};
+ const secondaryStatField = { name: NodeGraphDataFrameFieldNames.secondaryStat, type: FieldType.number, values: new ArrayVector(), config: {}};
+ const detailsFields: any = [];
+ for (const [index, k] of Object.keys(metrics.data).entries()) {
const c = metrics.config.find((d: MetricData) => d.name === k) || {};
const config = {displayName: c.label, unit: c.unit};
if (index === 0) {
- return { name: 'mainstat', type: FieldType.number, config};
+ mainStatField.config = config;
+ } else if (index === 1) {
+ secondaryStatField.config = config;
+ } else {
+ detailsFields.push({
+ name: `${NodeGraphDataFrameFieldNames.detail}${k}`,
+ type: FieldType.number,
+ values: new ArrayVector(),
+ config: {displayName: `${c.label || k } ${c.unit || ''}`}
+ });
}
- if (index === 1) {
- return { name: 'secondarystat', type: FieldType.number, config};
+ }
+ for (const node of nodes) {
+ idField.values.add(node.id || '');
+ titleField.values.add(node.name);
+ for (let i = 0; i < metrics.config.length; i++) {
+ const item = metrics.config[i];
+ const m = (metrics.data[item.name].values).find((v: {id: string}) => v.id === node.id) || {isEmptyValue: true};
+ const value = m.isEmptyValue ? NaN : this.expression(Number(m.value), item.calculation);
+ if(i > 1) {
+ detailsFields[i - 2]?.values.add(Number(value));
+ } else {
+ if (i === 0) {
+ mainStatField.values.add(Number(value));
+ }
+ if (i === 1) {
+ secondaryStatField.values.add(Number(value));
+ }
+ }
}
+ }
- return { name: `detail__${k}`, type: FieldType.number, config: {displayName: c.label || k, unit: c.unit} };
- });
-
- return types;
+ return [idField, titleField, mainStatField, secondaryStatField, ...detailsFields];
}
- setTopologyMetrics(params: {nodes: Node[], calls: Call[], nodeMetrics: Recordable, edgeMetrics: Recordable}) {
- const nodeMetrics = params.nodeMetrics || {config: [], data: {}};
- const edgeMetrics = params.edgeMetrics || {config: [], data: {}};
- const nodes = params.nodes.map((next: Node) => {
- for (const [index, k] of Object.keys(nodeMetrics.data).entries()) {
- const c = nodeMetrics.config.find((d: MetricData) => d.name === k) || {};
- const m = (nodeMetrics.data[k].values).find((v: {id: string}) => v.id === next.id) || {isEmptyValue: true};
- const value = m.isEmptyValue ? NaN : this.expression(Number(m.value), c.calculation);
- if (index === 0) {
- next.mainstat = value;
- } else if (index === 1) {
- next.secondarystat = value;
- } else {
- next[`detail__${k}`] = value;
- }
+ getEdgeTypes(calls: Call[], metrics: Recordable) {
+ const idField = { name: NodeGraphDataFrameFieldNames.id, type: FieldType.string, values: new ArrayVector(), config: {}};
+ const targetField = { name: NodeGraphDataFrameFieldNames.target, type: FieldType.string, values: new ArrayVector(), config: {}};
+ const sourceField = { name: NodeGraphDataFrameFieldNames.source, type: FieldType.string, values: new ArrayVector(), config: {}};
+ const mainStatField = { name: NodeGraphDataFrameFieldNames.mainStat, type: FieldType.number, values: new ArrayVector(), config: {}};
+ const secondaryStatField = { name: NodeGraphDataFrameFieldNames.secondaryStat, type: FieldType.number, values: new ArrayVector(), config: {}};
+ const detailsFields: any = [];
+ for (const [index, k] of Object.keys(metrics.data).entries()) {
+ const c = metrics.config.find((d: MetricData) => d.name === k) || {};
+ const config = {displayName: c.label, unit: c.unit};
+ if (index === 0) {
+ mainStatField.config = config;
}
- return next;
- })
- const calls = params.calls.map((next: Call) => {
- for (const [index, k] of Object.keys(edgeMetrics.data).entries()) {
- const c = edgeMetrics.config.find((d: MetricData) => d.name === k) || {};
- const m = (edgeMetrics.data[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
- const value = m.isEmptyValue ? NaN : this.expression(Number(m.value), c.calculation);
- if (index === 0) {
- next.mainstat = value;
- } else if (index === 1) {
- next.secondarystat = value;
- } else {
- next[`detail__${k}`] = value;
- }
+ else if (index === 1) {
+ secondaryStatField.config = config;
+ } else {
+ detailsFields.push({
+ name: `${NodeGraphDataFrameFieldNames.detail}${k}`,
+ type: FieldType.number,
+ values: new ArrayVector(),
+ config: {displayName: `${c.label || k } ${c.unit || ''}`}
+ });
}
- return next;
- })
+ }
- return {nodes, calls}
+ for (const call of calls) {
+ idField.values.add(call.id);
+ targetField.values.add(call.target);
+ sourceField.values.add(call.source);
+ for (let i = 0; i < metrics.config.length; i++) {
+ const item = metrics.config[i];
+ const m = (metrics.data[item.name].values).find((v: {id: string}) => v.id === call.id) || {isEmptyValue: true};
+ const value = m.isEmptyValue ? NaN : this.expression(Number(m.value), item.calculation);
+
+ if (i === 0) {
+ mainStatField.values.add(Number(value));
+ } else if (i === 1) {
+ secondaryStatField.values.add(Number(value));
+ } else {
+ detailsFields[i - 2]?.values.add(Number(value));
+ }
+ }
+ }
+
+ return [idField, targetField, sourceField, mainStatField, secondaryStatField, ...detailsFields];
}
expression(val: number, calculation: string): number | string {