mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-07-18 13:25:25 +00:00
feat: set link metrics
This commit is contained in:
parent
72080f7bd5
commit
cc01598ae2
@ -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: `
|
||||||
|
@ -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}
|
|
||||||
}`;
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user