You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by qi...@apache.org on 2023/04/30 14:24:13 UTC

[skywalking-grafana-plugins] branch main updated (7d35f8e -> 548f163)

This is an automated email from the ASF dual-hosted git repository.

qiuxiafan pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-grafana-plugins.git


    from 7d35f8e  feat: query call metrics
     new c19259a  feat: update metrics
     new 92f5454  feat: add details
     new 548f163  refactor: update types

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/datasource.ts | 125 ++++++++++++++++++++++++++++++++++++++++++++++--------
 src/types.ts      |  18 ++++++++
 2 files changed, 125 insertions(+), 18 deletions(-)


[skywalking-grafana-plugins] 01/03: feat: update metrics

Posted by qi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

qiuxiafan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-grafana-plugins.git

commit c19259acfd1e16a251a3f8ef9553671c52058e38
Author: Fine0830 <fa...@gmail.com>
AuthorDate: Sun Apr 30 21:39:52 2023 +0800

    feat: update metrics
---
 src/datasource.ts | 83 +++++++++++++++++++++++++++++++++++++++++++++----------
 src/types.ts      | 17 ++++++++++++
 2 files changed, 86 insertions(+), 14 deletions(-)

diff --git a/src/datasource.ts b/src/datasource.ts
index 670d42e..2b6f5d2 100644
--- a/src/datasource.ts
+++ b/src/datasource.ts
@@ -12,7 +12,7 @@ import dayjs from "dayjs";
 import timezone from "dayjs/plugin/timezone";
 import utc from "dayjs/plugin/utc";
 
-import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY, DurationTime, MetricData } from './types';
+import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY, DurationTime, MetricData, Call, Node } from './types';
 import {Fragments, RoutePath, TimeType } from "./constant";
 
 export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
@@ -69,22 +69,24 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
         }
       }
 
-      const ids = serviceObj ? [serviceObj.id] : services.map((d: any) => d.id);
       // fetch topology data from api
       const res = await this.doRequest(t);
-
+      const {nodes, calls} = this.setTopologyData({nodes: res.data.topology.nodes || [],  calls: res.data.topology.calls || []});
+      const idsS = calls.filter((i: Call) => i.detectPoints.includes("SERVER")).map((b: Call) => b.id);
+      const idsC = calls.filter((i: Call) => i.detectPoints.includes("CLIENT")).map((b: Call) => b.id);
+      const ids = nodes.map((d: Node) => d.id);
       // fetch topology metrics from api
-      if (nodeMetrics) {
-        await this.parseMetrics(nodeMetrics, ids, duration);
-      }
-      if (edgeServerMetrics) {
-        await this.parseMetrics(edgeServerMetrics, ids, duration);
-      }
-      if (edgeClientMetrics) {
-        await this.parseMetrics(edgeClientMetrics, ids, duration);
-      }
-      const nodes = res.data.topology.nodes || [];
-      const calls = res.data.topology.calls || [];
+      const nodeMetricsResp = nodeMetrics ? await this.parseMetrics(nodeMetrics, ids, duration) : null;
+      const edgeServerMetricsResp = edgeServerMetrics && idsS.length ? await this.parseMetrics(edgeServerMetrics, idsS, duration) : null;
+      const edgeClientMetricsResp = edgeClientMetrics && idsC.length ? await this.parseMetrics(edgeClientMetrics, idsC, duration) : null;
+      const topology = this.setTopologyMetrics({
+        nodes,
+        calls,
+        nodeMetrics: nodeMetricsResp ? nodeMetricsResp.data : undefined,
+        edgeServerMetrics: edgeServerMetricsResp ? edgeServerMetricsResp.data : undefined,
+        edgeClientMetrics: edgeClientMetricsResp ? edgeClientMetricsResp.data : undefined,
+      });
+      console.log(topology);
       const nodeFrame =  new MutableDataFrame({
         name: 'Nodes',
         refId: target.refId,
@@ -142,6 +144,59 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
     return metricJson;
   }
 
+  setTopologyData(params: {nodes: Node[], calls: Call[]}) {
+    const obj = {} as Record<string, any>;
+      const nodes = (params.nodes || []).reduce((prev: Node[], next: Node) => {
+        if (!obj[next.id]) {
+          obj[next.id] = true;
+          prev.push(next);
+        }
+        return prev;
+      }, []);
+      const calls = (params.calls || []).reduce((prev: Call[], next: Call) => {
+        if (!obj[next.id]) {
+          obj[next.id] = true;
+          prev.push(next);
+        }
+        return prev;
+      }, []);
+      return {nodes, calls}
+  }
+
+  setTopologyMetrics(params: {nodes: Node[], calls: Call[], nodeMetrics: Record<string, any>, edgeServerMetrics: Record<string, any>, edgeClientMetrics: Record<string, any>}) {
+    const obj = {} as Record<string, any>;
+      const nodes = (params.nodes || []).reduce((prev: Record<string, any>, next: Record<string, any>) => {
+        if (!obj[next.id]) {
+          obj[next.id] = true;
+          if (params.nodeMetrics) {
+            for (const k of Object.keys(params.nodeMetrics)) {
+              const m = (params.nodeMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
+              next[`detail__${k}`] = m.value;
+            }
+          }
+          prev.push(next);
+        }
+        return prev;
+      }, []);
+      const calls = (params.calls || []).reduce((prev: any[], next: any) => {
+        if (!obj[next.id]) {
+          obj[next.id] = true;
+          for (const k of Object.keys(params.edgeServerMetrics)) {
+            const m = (params.edgeServerMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
+            next[`detail__${k}`] = m.value;
+          }
+          for (const k of Object.keys(params.edgeClientMetrics)) {
+            const m = (params.edgeClientMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
+            next[`detail__${k}`] = m.value;
+          }
+          next.value = next.value || 1;
+          prev.push(next);
+        }
+        return prev;
+      }, []);
+      return {nodes, calls}
+  }
+
   queryTopologyMetrics(metrics: string[], ids: string[], duration: DurationTime) {
     const conditions: { [key: string]: unknown } = {
       duration,
diff --git a/src/types.ts b/src/types.ts
index d1583c3..bea3f8c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -36,3 +36,20 @@ export type MetricData = {
   label: string;
   calculation: string;
 }
+
+export type Call = {
+  source: string;
+  target: string;
+  id: string;
+  detectPoints: string[];
+  type?: string;
+  sourceComponents: string[];
+  targetComponents: string[];
+}
+export type Node = {
+  id: string;
+  name: string;
+  type: string;
+  isReal: boolean;
+  serviceName?: string;
+}


[skywalking-grafana-plugins] 03/03: refactor: update types

Posted by qi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

qiuxiafan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-grafana-plugins.git

commit 548f163995b7af09a3e75c2b69f53482e1465a9a
Author: Fine0830 <fa...@gmail.com>
AuthorDate: Sun Apr 30 22:23:59 2023 +0800

    refactor: update types
---
 src/datasource.ts | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/src/datasource.ts b/src/datasource.ts
index 0aa5955..69e2dd7 100644
--- a/src/datasource.ts
+++ b/src/datasource.ts
@@ -12,7 +12,16 @@ import dayjs from "dayjs";
 import timezone from "dayjs/plugin/timezone";
 import utc from "dayjs/plugin/utc";
 
-import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY, DurationTime, MetricData, Call, Node, Recordable } from './types';
+import {
+  MyQuery,
+  MyDataSourceOptions,
+  DEFAULT_QUERY,
+  DurationTime,
+  MetricData,
+  Call,
+  Node,
+  Recordable
+} from './types';
 import {Fragments, RoutePath, TimeType } from "./constant";
 
 export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
@@ -47,7 +56,10 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
       const edgeServerMetrics = getTemplateSrv().replace(query.edgeServerMetrics, options.scopedVars);
       const edgeClientMetrics = getTemplateSrv().replace(query.edgeClientMetrics, options.scopedVars);
       let services = [];
-      let t: any = {
+      let t: {
+        query: string;
+        variables: Recordable;
+      } = {
         query: Fragments.globalTopology,
         variables: {duration},
       };
@@ -130,7 +142,7 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
     return Promise.all(promises).then(data => ({ data: data[0] }));
   }
 
-  async doRequest(params?: Record<string, any>) {
+  async doRequest(params?: Recordable) {
     // Do the request on proxy; the server will replace url + routePath with the url
     // defined in plugin.json
     const result = getBackendSrv().post(`${this.URL}${RoutePath}`, params, {headers: {
@@ -156,7 +168,7 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
     if (!(params.nodes.length && params.calls.length)) {
       return {nodes: [], calls: []}
     }
-    const obj = {} as Record<string, any>;
+    const obj = {} as Recordable;
       const nodes = (params.nodes || []).reduce((prev: Node[], next: Node) => {
         if (!obj[next.id]) {
           obj[next.id] = true;


[skywalking-grafana-plugins] 02/03: feat: add details

Posted by qi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

qiuxiafan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-grafana-plugins.git

commit 92f5454fa1bc37fe1f40e93916bb4e70871f6707
Author: Fine0830 <fa...@gmail.com>
AuthorDate: Sun Apr 30 22:19:48 2023 +0800

    feat: add details
---
 src/datasource.ts | 90 ++++++++++++++++++++++++++++++++++---------------------
 src/types.ts      | 17 ++++++-----
 2 files changed, 65 insertions(+), 42 deletions(-)

diff --git a/src/datasource.ts b/src/datasource.ts
index 2b6f5d2..0aa5955 100644
--- a/src/datasource.ts
+++ b/src/datasource.ts
@@ -12,7 +12,7 @@ import dayjs from "dayjs";
 import timezone from "dayjs/plugin/timezone";
 import utc from "dayjs/plugin/utc";
 
-import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY, DurationTime, MetricData, Call, Node } from './types';
+import { MyQuery, MyDataSourceOptions, DEFAULT_QUERY, DurationTime, MetricData, Call, Node, Recordable } from './types';
 import {Fragments, RoutePath, TimeType } from "./constant";
 
 export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
@@ -86,6 +86,11 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
         edgeServerMetrics: edgeServerMetricsResp ? edgeServerMetricsResp.data : undefined,
         edgeClientMetrics: edgeClientMetricsResp ? edgeClientMetricsResp.data : undefined,
       });
+      const {nodeFieldTypes, edgeServerFieldTypes, edgeClientFieldTypes} = this.setFieldTypes({
+        nodeMetrics: nodeMetricsResp ? nodeMetricsResp.data : undefined,
+        edgeServerMetrics: edgeServerMetricsResp ? edgeServerMetricsResp.data : undefined,
+        edgeClientMetrics: edgeClientMetricsResp ? edgeClientMetricsResp.data : undefined,
+      });
       console.log(topology);
       const nodeFrame =  new MutableDataFrame({
         name: 'Nodes',
@@ -93,6 +98,7 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
         fields: [
           { name: 'id', type: FieldType.string },
           { name: 'title', type: FieldType.string },
+          ...nodeFieldTypes
         ],
         meta: {
           preferredVisualisationType: 'nodeGraph',
@@ -105,16 +111,18 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
           { name: 'id', type: FieldType.string },
           { name: 'source', type: FieldType.string },
           { name: 'target', type: FieldType.string },
+          ...edgeServerFieldTypes,
+          ...edgeClientFieldTypes,
         ],
         meta: {
           preferredVisualisationType: 'nodeGraph',
         }
       });
       for (const node of nodes) {
-        nodeFrame.add({id: node.id, title: node.name});
+        nodeFrame.add({...node, title: node.name});
       }
       for (const call of calls) {
-        edgeFrame.add({id: call.id, target: call.target, source: call.source});
+        edgeFrame.add(call);
       }
       return [nodeFrame, edgeFrame];
     });
@@ -145,6 +153,9 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
   }
 
   setTopologyData(params: {nodes: Node[], calls: Call[]}) {
+    if (!(params.nodes.length && params.calls.length)) {
+      return {nodes: [], calls: []}
+    }
     const obj = {} as Record<string, any>;
       const nodes = (params.nodes || []).reduce((prev: Node[], next: Node) => {
         if (!obj[next.id]) {
@@ -163,37 +174,48 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
       return {nodes, calls}
   }
 
-  setTopologyMetrics(params: {nodes: Node[], calls: Call[], nodeMetrics: Record<string, any>, edgeServerMetrics: Record<string, any>, edgeClientMetrics: Record<string, any>}) {
-    const obj = {} as Record<string, any>;
-      const nodes = (params.nodes || []).reduce((prev: Record<string, any>, next: Record<string, any>) => {
-        if (!obj[next.id]) {
-          obj[next.id] = true;
-          if (params.nodeMetrics) {
-            for (const k of Object.keys(params.nodeMetrics)) {
-              const m = (params.nodeMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
-              next[`detail__${k}`] = m.value;
-            }
-          }
-          prev.push(next);
-        }
-        return prev;
-      }, []);
-      const calls = (params.calls || []).reduce((prev: any[], next: any) => {
-        if (!obj[next.id]) {
-          obj[next.id] = true;
-          for (const k of Object.keys(params.edgeServerMetrics)) {
-            const m = (params.edgeServerMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
-            next[`detail__${k}`] = m.value;
-          }
-          for (const k of Object.keys(params.edgeClientMetrics)) {
-            const m = (params.edgeClientMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
-            next[`detail__${k}`] = m.value;
-          }
-          next.value = next.value || 1;
-          prev.push(next);
-        }
-        return prev;
-      }, []);
+  setFieldTypes(params: {nodeMetrics: Recordable, edgeServerMetrics: Recordable, edgeClientMetrics: Recordable}) {
+    const nodeMetrics = params.nodeMetrics || {};
+    const edgeServerMetrics = params.edgeServerMetrics || {};
+    const edgeClientMetrics = params.edgeClientMetrics || {};
+    const nodeFieldTypes = this.getTypes(nodeMetrics);
+    const edgeServerFieldTypes = this.getTypes(edgeServerMetrics);
+    const edgeClientFieldTypes = this.getTypes(edgeClientMetrics);
+
+    return {nodeFieldTypes, edgeServerFieldTypes, edgeClientFieldTypes};
+  }
+
+  getTypes(metrics: Recordable) {
+    const types = Object.keys(metrics).map((k: string) => {
+      return { name: `detail__${k}`, type: FieldType.number };
+    });
+
+    return types;
+  }
+
+  setTopologyMetrics(params: {nodes: Node[], calls: Call[], nodeMetrics: Recordable, edgeServerMetrics: Recordable, edgeClientMetrics: Recordable}) {
+    const nodeMetrics = params.nodeMetrics || {};
+    const edgeServerMetrics = params.edgeServerMetrics || {};
+    const edgeClientMetrics = params.edgeClientMetrics || {};
+    const nodes = params.nodes.map((next: Node) => {
+      for (const k of Object.keys(nodeMetrics)) {
+        const m = (nodeMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
+        next[`detail__${k}`] = m.value;
+      }
+      return next;
+    })
+    const calls = params.calls.map((next: Call) => {
+      for (const k of Object.keys(edgeServerMetrics)) {
+        const m = (edgeServerMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
+        next[`detail__${k}`] = m.value;
+      }
+      for (const k of Object.keys(edgeClientMetrics)) {
+        const m = (edgeClientMetrics[k].values).find((v: {id: string}) => v.id === next.id) || {value: NaN};
+        next[`detail__${k}`] = m.value;
+      }
+      return next;
+    })
+    
       return {nodes, calls}
   }
 
diff --git a/src/types.ts b/src/types.ts
index bea3f8c..c770c08 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -37,7 +37,15 @@ export type MetricData = {
   calculation: string;
 }
 
-export type Call = {
+export type Recordable = Record<string, any>;
+export interface Node extends Recordable {
+  id: string;
+  name: string;
+  type: string;
+  isReal: boolean;
+  serviceName?: string;
+}
+export interface Call extends Recordable {
   source: string;
   target: string;
   id: string;
@@ -46,10 +54,3 @@ export type Call = {
   sourceComponents: string[];
   targetComponents: string[];
 }
-export type Node = {
-  id: string;
-  name: string;
-  type: string;
-  isReal: boolean;
-  serviceName?: string;
-}