feat: set link metrics

This commit is contained in:
Qiuxia Fan 2022-02-14 17:41:04 +08:00
parent 72080f7bd5
commit cc01598ae2
7 changed files with 101 additions and 70 deletions

View File

@ -117,37 +117,7 @@ export const InstanceTopology = {
} }
`, `,
}; };
export const TopoMetric = {
variable: "$ids: [ID!]!",
query: `
sla: getValues(metric: {
name: "service_sla"
ids: $ids
}, duration: $duration) {
values {
id
value
}
}
nodeCpm: getValues(metric: {
name: "service_cpm"
ids: $ids
}, duration: $duration) {
values {
id
value
}
}
nodeLatency: getValues(metric: {
name: "service_resp_time"
ids: $ids
}, duration: $duration) {
values {
id
value
}
}`,
};
export const TopoServiceMetric = { export const TopoServiceMetric = {
variable: "$idsS: [ID!]!", variable: "$idsS: [ID!]!",
query: ` query: `

View File

@ -19,22 +19,9 @@ import {
EndpointTopology, EndpointTopology,
ServiceTopology, ServiceTopology,
GlobalTopology, GlobalTopology,
TopoMetric,
TopoServiceMetric,
TopoClientMetric,
} from "../fragments/topology"; } from "../fragments/topology";
export const getGlobalTopology = `query queryData(${GlobalTopology.variable}) {${GlobalTopology.query}}`; export const getGlobalTopology = `query queryData(${GlobalTopology.variable}) {${GlobalTopology.query}}`;
export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`; export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`;
export const getServiceTopology = `query queryData(${ServiceTopology.variable}) {${ServiceTopology.query}}`; export const getServiceTopology = `query queryData(${ServiceTopology.variable}) {${ServiceTopology.query}}`;
export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`; export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`;
export const queryTopoInfo = `query queryTopoInfo(
${GlobalTopology.variable},
${TopoMetric.variable},
${TopoServiceMetric.variable},
${TopoClientMetric.variable})
{
${TopoMetric.query},
${TopoServiceMetric.query},
${TopoClientMetric.query}
}`;

View File

@ -258,7 +258,7 @@ export function usePodsSource(
}); });
return data; return data;
} }
export function useQueryNodesMetrics(metrics: string[], ids: string[]) { export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const conditions: { [key: string]: unknown } = { const conditions: { [key: string]: unknown } = {
duration: appStore.durationTime, duration: appStore.durationTime,

View File

@ -29,6 +29,8 @@ interface TopologyState {
calls: Call[]; calls: Call[];
nodes: Node[]; nodes: Node[];
nodeMetrics: { id: string; value: unknown }[]; nodeMetrics: { id: string; value: unknown }[];
linkServerMetrics: { id: string; value: unknown }[];
linkClientMetrics: { id: string; value: unknown }[];
} }
export const topologyStore = defineStore({ export const topologyStore = defineStore({
@ -39,6 +41,8 @@ export const topologyStore = defineStore({
node: null, node: null,
call: null, call: null,
nodeMetrics: [], nodeMetrics: [],
linkServerMetrics: [],
linkClientMetrics: [],
}), }),
actions: { actions: {
setNode(node: Node) { setNode(node: Node) {
@ -119,6 +123,30 @@ export const topologyStore = defineStore({
this.nodeMetrics = res.data.data; this.nodeMetrics = res.data.data;
return res.data; return res.data;
}, },
async getCallServerMetrics(param: {
queryStr: string;
conditions: { [key: string]: unknown };
}) {
const res: AxiosResponse = await query(param);
if (res.data.errors) {
return res.data;
}
this.linkServerMetrics = res.data.data;
return res.data;
},
async getCallClientMetrics(param: {
queryStr: string;
conditions: { [key: string]: unknown };
}) {
const res: AxiosResponse = await query(param);
if (res.data.errors) {
return res.data;
}
this.linkClientMetrics = res.data.data;
return res.data;
},
}, },
}); });

View File

@ -43,8 +43,8 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, watch, reactive } from "vue"; import { ref, onMounted, onBeforeUnmount, reactive } from "vue";
import { useI18n } from "vue-i18n"; // import { useI18n } from "vue-i18n";
import * as d3 from "d3"; import * as d3 from "d3";
import d3tip from "d3-tip"; import d3tip from "d3-tip";
import zoom from "./utils/zoom"; import zoom from "./utils/zoom";
@ -61,7 +61,7 @@ import { ElMessage } from "element-plus";
import Settings from "./Settings.vue"; import Settings from "./Settings.vue";
/*global Nullable */ /*global Nullable */
const { t } = useI18n(); // const { t } = useI18n();
const topologyStore = useTopologyStore(); const topologyStore = useTopologyStore();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const height = ref<number>(document.body.clientHeight - 90); const height = ref<number>(document.body.clientHeight - 90);
@ -227,18 +227,29 @@ function update() {
anchor.value.enter(), anchor.value.enter(),
{ {
handleLinkClick: handleLinkClick, handleLinkClick: handleLinkClick,
$tip: (data: Call) => tipHtml: (data: Call) => {
` const linkClientMetrics: string[] = settings.value.linkClientMetrics;
<div class="mb-5"><span class="grey">${t("cpm")}: </span>${ const linkServerMetrics: string[] = settings.value.linkServerMetrics;
data.cpm const htmlServer = linkServerMetrics.map((m) => {
}</div> const metric = topologyStore.linkServerMetrics[m].values.filter(
<div class="mb-5"><span class="grey">${t("latency")}: </span>${ (val: { id: string; value: unknown }) => val.id === data.id
data.latency )[0];
}</div> if (metric) {
<div><span class="grey">${t( return ` <div class="mb-5"><span class="grey">${m}: </span>${metric.value}</div>`;
"detectPoint" }
)}: </span>${data.detectPoints.join(" | ")}</div> });
`, const htmlClient = linkClientMetrics.map((m) => {
const metric = topologyStore.linkClientMetrics[m].values.filter(
(val: { id: string; value: unknown }) => val.id === data.id
)[0];
if (metric) {
return ` <div class="mb-5"><span class="grey">${m}: </span>${metric.value}</div>`;
}
});
const html = [...htmlServer, ...htmlClient].join(" ");
return html;
},
}, },
tip.value tip.value
).merge(anchor.value); ).merge(anchor.value);

View File

@ -27,11 +27,21 @@ limitations under the License. -->
<Selector <Selector
class="inputs" class="inputs"
:multiple="true" :multiple="true"
:value="states.linkMetrics" :value="states.linkServerMetrics"
:options="states.linkMetricList" :options="states.linkMetricList"
size="small" size="small"
placeholder="Select metrics" placeholder="Select metrics"
@change="changeLinkMetrics" @change="changeLinkServerMetrics"
/>
<div class="label">{{ t("linkMetrics") }}</div>
<Selector
class="inputs"
:multiple="true"
:value="states.linkClientMetrics"
:options="states.linkMetricList"
size="small"
placeholder="Select metrics"
@change="changeLinkClientMetrics"
/> />
</div> </div>
<div class="node-settings"> <div class="node-settings">
@ -80,7 +90,7 @@ import { useTopologyStore } from "@/store/modules/topology";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { MetricCatalog } from "../../data"; import { MetricCatalog } from "../../data";
import { Option } from "@/types/app"; import { Option } from "@/types/app";
import { useQueryNodesMetrics } from "@/hooks/useProcessor"; import { useQueryTopologyMetrics } from "@/hooks/useProcessor";
import { Node, Call } from "@/types/topology"; import { Node, Call } from "@/types/topology";
/*global defineEmits */ /*global defineEmits */
@ -93,7 +103,8 @@ const states = reactive<{
nodeDashboard: string; nodeDashboard: string;
instanceDashboard: string; instanceDashboard: string;
endpointDashboard: string; endpointDashboard: string;
linkMetrics: string[]; linkServerMetrics: string[];
linkClientMetrics: string[];
nodeMetrics: string[]; nodeMetrics: string[];
nodeMetricList: Option[]; nodeMetricList: Option[];
linkMetricList: Option[]; linkMetricList: Option[];
@ -102,7 +113,8 @@ const states = reactive<{
nodeDashboard: "", nodeDashboard: "",
instanceDashboard: "", instanceDashboard: "",
endpointDashboard: "", endpointDashboard: "",
linkMetrics: [], linkServerMetrics: [],
linkClientMetrics: [],
nodeMetrics: [], nodeMetrics: [],
nodeMetricList: [], nodeMetricList: [],
linkMetricList: [], linkMetricList: [],
@ -130,20 +142,43 @@ function updateSettings() {
nodeDashboard: states.nodeDashboard, nodeDashboard: states.nodeDashboard,
endpointDashboard: states.endpointDashboard, endpointDashboard: states.endpointDashboard,
instanceDashboard: states.instanceDashboard, instanceDashboard: states.instanceDashboard,
linkMetrics: states.linkMetrics, linkServerMetrics: states.linkServerMetrics,
linkClientMetrics: states.linkClientMetrics,
nodeMetrics: states.nodeMetrics, nodeMetrics: states.nodeMetrics,
}); });
} }
async function changeLinkMetrics(options: Option[]) { async function changeLinkServerMetrics(options: Option[]) {
states.linkMetrics = options.map((d: Option) => d.value); states.linkServerMetrics = options.map((d: Option) => d.value);
updateSettings(); updateSettings();
const idsS = topologyStore.calls
.filter((i: Call) => i.detectPoints.includes("SERVER"))
.map((b: Call) => b.id);
const param = await useQueryTopologyMetrics(states.linkServerMetrics, idsS);
const res = await topologyStore.getCallServerMetrics(param);
if (res.errors) {
ElMessage.error(res.errors);
}
}
async function changeLinkClientMetrics(options: Option[]) {
states.linkClientMetrics = options.map((d: Option) => d.value);
updateSettings();
const idsC = topologyStore.calls
.filter((i: Call) => i.detectPoints.includes("CLIENT"))
.map((b: Call) => b.id);
const param = await useQueryTopologyMetrics(states.linkClientMetrics, idsC);
const res = await topologyStore.getCallClientMetrics(param);
if (res.errors) {
ElMessage.error(res.errors);
}
} }
async function changeNodeMetrics(options: Option[]) { async function changeNodeMetrics(options: Option[]) {
states.nodeMetrics = options.map((d: Option) => d.value); states.nodeMetrics = options.map((d: Option) => d.value);
updateSettings(); updateSettings();
const ids = topologyStore.nodes.map((d: Node) => d.id); const ids = topologyStore.nodes.map((d: Node) => d.id);
const param = await useQueryNodesMetrics(states.nodeMetrics, ids); const param = await useQueryTopologyMetrics(states.nodeMetrics, ids);
const res = await topologyStore.getNodeMetrics(param); const res = await topologyStore.getNodeMetrics(param);
if (res.errors) { if (res.errors) {

View File

@ -30,7 +30,7 @@ export const anchorElement = (graph: any, funcs: any, tip: any) => {
.attr("r", 5) .attr("r", 5)
.attr("fill", "#217EF25f") .attr("fill", "#217EF25f")
.on("mouseover", function (event: unknown, d: unknown) { .on("mouseover", function (event: unknown, d: unknown) {
tip.html(funcs.$tip).show(d, this); tip.html(funcs.tipHtml).show(d, this);
}) })
.on("mouseout", function () { .on("mouseout", function () {
tip.hide(this); tip.hide(this);