Skip to content

Commit 2a014de

Browse files
committed
feat: implement graph for the listener
1 parent 26e335f commit 2a014de

File tree

11 files changed

+204
-58
lines changed

11 files changed

+204
-58
lines changed

src/components/Graph.vue

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,57 @@
11
<script >
2-
import { onMounted, onUnmounted } from '@vue/runtime-core';
3-
import { clusters, config_dump, listeners } from '../libs/envoy';
42
import { defineComponent, ref } from 'vue';
3+
import { onMounted, onUnmounted } from '@vue/runtime-core';
4+
import { config_dump, useConfigRelationship } from '../libs/envoy';
55
import { useSankey } from '../libs/echarts';
66
export default defineComponent({
7-
setup() {
7+
props: {
8+
modelValue: Object,
9+
close: Function,
10+
},
11+
setup(props) {
812
const sankey = useSankey();
9-
onMounted(() => {
10-
config_dump().then((data) => {
11-
sankey.build("container", data);
13+
onMounted(async () => {
14+
console.log(112233, props.modelValue);
15+
const cfg = props.modelValue;
16+
const cd = await config_dump(true)
17+
const rdata = useConfigRelationship(cfg, cd);
18+
console.log(2233, rdata);
19+
20+
let tMap = {}
21+
rdata.forEach(el => {
22+
tMap[el.target] = 1;
23+
tMap[el.source] = 1;
1224
});
13-
14-
listeners().then(console.log);
15-
clusters().then(console.log);
25+
console.log(12311, tMap);
26+
let data = Object.keys(tMap).map(key => { return { name: key } })
27+
console.log(12311, data);
28+
29+
sankey.build("container", { data: data, links: rdata });
1630
});
1731
1832
onUnmounted(() => {
19-
// echart.dispose;
33+
sankey.dispose();
2034
});
2135
22-
const handleChange = (e) => {
23-
console.log(e);
24-
};
36+
const drawerVisible = ref(true)
37+
const onClose = () => {
38+
drawerVisible.value = false
39+
props.close()
40+
}
2541
2642
return {
27-
search: ref({}),
28-
listeners: ref([]),
29-
clusters: ref([]),
30-
handleChange,
43+
drawerVisible,
44+
onClose
3145
};
3246
},
3347
});
3448
3549
</script>
3650

3751
<template>
38-
<div style="height: 100%">
39-
<a-form layout="inline" :model="search">
40-
<a-form-item label="Listener">
41-
<a-select ref="select" style="width: 120px" v-model:value="search.listener" :options="listeners">
42-
</a-select>
43-
</a-form-item>
44-
<a-form-item label="Cluster">
45-
<a-select ref="select" style="width: 120px" v-model:value="search.cluster" :options="clusters">
46-
</a-select>
47-
</a-form-item>
48-
<a-form-item>
49-
<a-button type="primary">Search</a-button>
50-
</a-form-item>
51-
</a-form>
52-
52+
<a-drawer title="Graph" size="large" :visible="drawerVisible" @close="onClose" width="950" destroyOnClose>
5353
<div id="container" style="height: 100%"></div>
54-
</div>
54+
</a-drawer>
5555
</template>
5656

5757
<style>

src/components/JSONViewer.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ export default {
66
JsonViewer,
77
},
88
props: {
9-
jsondata: Object
9+
modelValue: Object,
10+
close: Function,
1011
},
1112
setup(props) {
1213
const drawerVisible = ref(true)
1314
const onClose = () => {
1415
drawerVisible.value = false
16+
props.close()
1517
}
1618
17-
console.log(112233, props.jsondata);
19+
console.log(112233, props.modelValue);
1820
return {
1921
drawerVisible,
2022
onClose
@@ -24,8 +26,8 @@ export default {
2426
</script>
2527

2628
<template>
27-
<a-drawer title="JSONViewer" size="large" :visible="drawerVisible" @close="onClose" width="950">
28-
<json-viewer :value="jsondata" :expand-depth="5" copyable sort></json-viewer>
29+
<a-drawer title="JSONViewer" size="large" :visible="drawerVisible" @close="onClose" width="950" destroyOnClose>
30+
<json-viewer :value="modelValue" :expand-depth="5" copyable sort></json-viewer>
2931
</a-drawer>
3032
</template>
3133

src/libs/drawer/index.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
import { createApp } from 'vue'
1+
import { createApp, onUnmounted } from 'vue'
22
import Antd from 'ant-design-vue';
33
import 'ant-design-vue/dist/antd.css';
44

55
// options为组件的props
66
export const openDrawer = function (component, options) {
77
console.log(options);
8-
let existEl = document.getElementById('component')
9-
if (existEl) {
10-
document.body.removeChild(existEl);
11-
}
128

139
let el = document.createElement('div')
1410
el.setAttribute('id', 'component')
15-
document.body.appendChild(el)
11+
options['close'] = () => {
12+
console.log('closed');
13+
document.body.removeChild(el)
14+
}
1615

16+
document.body.appendChild(el)
1717
const app = createApp(component, options)
1818
app.use(Antd);
19-
app.mount("#component")
19+
app.mount(el)
2020
}

src/libs/echarts/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { build } from "./sankey"
1+
import { build, dispose } from "./sankey"
22

33
export const useSankey = () => {
44
return {
55
build,
6+
dispose
67
}
78
}

src/libs/echarts/sankey.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ const buildSankeyLinks = (raw_data) => {
3737
export const build = (domid, data) => {
3838
var dom = document.getElementById(domid);
3939
var chart = echarts.init(dom);
40-
var app = {};
4140
var option;
4241

4342
console.log(data);
@@ -50,11 +49,13 @@ export const build = (domid, data) => {
5049
trigger: 'item',
5150
triggerOn: 'mousemove'
5251
},
52+
// animation: false,
5353
series: [
5454
{
5555
type: 'sankey',
56-
data: buildSankeyData(data),
57-
links: buildSankeyLinks(data),
56+
// orient: 'vertical',
57+
data: data.data,
58+
links: data.links,
5859
emphasis: {
5960
focus: 'adjacency'
6061
},
@@ -117,4 +118,8 @@ export const build = (domid, data) => {
117118
//自适应大小
118119
chart.resize();
119120
};
121+
}
122+
123+
export const dispose = () => {
124+
echarts.dispose()
120125
}

src/libs/envoy/index.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,44 @@ export const endpointConfigs = async () => {
7272
return configs
7373
}
7474

75+
export class Configs {
76+
configs;
77+
constructor(configs) {
78+
this.configs = configs
79+
}
80+
getBootstrapConfig() {
81+
return this.configs.find(d => d["@type"].endsWith("BootstrapConfigDump")).bootstrap
82+
}
83+
getListenerConfigs() {
84+
const lcd = this.configs.find(d => d["@type"].endsWith("ListenersConfigDump"))
85+
const configs = [];
86+
lcd.static_listeners.forEach(ln => { configs.push(ln.listener) })
87+
lcd.dynamic_listeners.forEach(item => { configs.push(item.active_state.listener) })
88+
return configs
89+
}
90+
getRouteConfigs() {
91+
const rcd = this.configs.find(d => d["@type"].endsWith("v3.RoutesConfigDump"))
92+
const configs = [];
93+
rcd.static_route_configs.forEach(item => { configs.push(item.route_config) })
94+
rcd.dynamic_route_configs.forEach(item => { configs.push(item.route_config) })
95+
return configs
96+
}
97+
getClusterConfigs() {
98+
const ccd = this.configs.find(d => d["@type"].endsWith("v3.ClustersConfigDump"))
99+
const configs = [];
100+
ccd.static_clusters.forEach(item => { configs.push(item.cluster) })
101+
ccd.dynamic_active_clusters.forEach(item => { configs.push(item.cluster) })
102+
return configs
103+
}
104+
getEndpointConfigs() {
105+
const ecd = this.configs.find(d => d["@type"].endsWith("v3.EndpointsConfigDump"))
106+
const configs = [];
107+
ecd.static_endpoint_configs.forEach(item => { configs.push(item.endpoint_config) })
108+
ecd.dynamic_endpoint_configs.forEach(item => { configs.push(item.endpoint_config) })
109+
return configs
110+
}
111+
}
112+
75113
export const listeners = async () => {
76114
return (await axios.get('/listeners?format=json')).data.listener_statuses;
77115
}
@@ -83,4 +121,6 @@ export const clusterStatuses = async () => {
83121
export const buildEndpointName = (endpoint) => {
84122
const addr = endpoint.address;
85123
return addr.socket_address ? `${addr.socket_address.address}:${addr.socket_address.port_value}` : addr.pipe.path
86-
}
124+
}
125+
126+
export * from "./relation";

src/libs/envoy/relation.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { Configs } from ".";
2+
3+
const typeGetters = {
4+
"type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy": (obj) => {
5+
return { type: "cluster", value: obj.cluster };
6+
},
7+
"type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager": (obj) => {
8+
return { type: "route", value: obj.rds?.route_config_name || 'Inline Route' };
9+
}
10+
}
11+
12+
const typeHandlers = {
13+
'type.googleapis.com/envoy.config.listener.v3.Listener': (config, config_dump) => {
14+
let chains = [];
15+
if (config.default_filter_chain) {
16+
chains.push(config.default_filter_chain)
17+
}
18+
chains.push(...config.filter_chains)
19+
console.log(chains);
20+
21+
const result = []
22+
chains.forEach(chain => {
23+
console.log(chain);
24+
chain.filters.forEach(async filter => {
25+
const fType = filter.typed_config["@type"]
26+
console.log(fType);
27+
if (!typeGetters[fType]) return
28+
29+
const target = typeGetters[fType](filter.typed_config)
30+
const links = useConfigRelationship(findTargetConfig(target, config_dump), config_dump)
31+
result.push(...links)
32+
33+
result.push({ source: `listener: ${config.name}`, target: `${target.type}: ${target.value}`, value: 1 })
34+
})
35+
})
36+
return result
37+
},
38+
'type.googleapis.com/envoy.config.route.v3.RouteConfiguration': (config, config_dump) => {
39+
const result = []
40+
config.virtual_hosts.forEach(vh => {
41+
vh.routes.forEach(route => {
42+
const target = route.route.cluster
43+
// console.log(target);
44+
const links = useConfigRelationship(findTargetConfig({ type: 'cluster', value: target }, config_dump), config_dump)
45+
result.push(...links)
46+
47+
result.push({ source: `route: ${config.name}`, target: `cluster: ${target}`, value: 1 })
48+
})
49+
})
50+
return result
51+
},
52+
'type.googleapis.com/envoy.config.cluster.v3.Cluster': (config, config_dump) => {
53+
if (config.type == 'EDS') {
54+
return useConfigRelationship(findTargetConfig({ type: 'endpoint', value: config.eds_cluster_config.service_name }, config_dump), config_dump)
55+
}
56+
57+
return []
58+
},
59+
'type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment': (config, config_dump) => {
60+
const result = []
61+
config.endpoints?.forEach(endpoint => {
62+
endpoint.lb_endpoints.forEach(lb_endpoint => {
63+
const target = lb_endpoint.endpoint.address.socket_address.address
64+
result.push({ source: `cluster: ${config.cluster_name}`, target: `endpoint: ${target}`, value: 1 })
65+
})
66+
}
67+
)
68+
return result
69+
}
70+
}
71+
72+
export const findTargetConfig = (target, config_dump) => {
73+
const configTool = new Configs(config_dump);
74+
if (target.type === 'route') {
75+
return configTool.getRouteConfigs().find(c => c.name === target.value)
76+
}
77+
78+
if (target.type === 'cluster') {
79+
return configTool.getClusterConfigs().find(c => c.name === target.value)
80+
}
81+
82+
if (target.type === 'endpoint') {
83+
return configTool.getEndpointConfigs().find(c => c.cluster_name === target.value)
84+
}
85+
}
86+
87+
export const useConfigRelationship = (cfg, config_dump) => {
88+
const type = cfg["@type"];
89+
console.log(type, cfg, config_dump);
90+
if (!typeHandlers[type]) return []
91+
const links = typeHandlers[type](cfg, config_dump)
92+
console.log(links);
93+
return links;
94+
}

src/views/Clusters.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default defineComponent({
4646
4747
const openJSONDrawer = (row) => {
4848
openDrawer(JSONViewer, {
49-
jsondata: row
49+
modelValue: row
5050
})
5151
}
5252

src/views/Endpoints.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default defineComponent({
1616
1717
const openJSONDrawer = (row) => {
1818
openDrawer(JSONViewer, {
19-
jsondata: row
19+
modelValue: row
2020
})
2121
}
2222

0 commit comments

Comments
 (0)