如何在Grafana中基于源-目标节点表格数据绘制网络图?
实现Grafana网络图的可行方案
当然可以实现!针对你这种source-target结构的边数据,有两种常用的方案,我一个个给你拆解:
方案一:使用Grafana内置的Network Graph面板
这是最直接的方式,不需要额外写代码,只要配置数据源和面板参数就行:
准备数据源查询
确保你的数据源(不管是MySQL、PostgreSQL、InfluxDB还是其他)能返回包含source和target字段的结果集。比如用SQL的话,直接查询你的表:SELECT source, target FROM your_table_name;添加Network Graph面板
在Grafana仪表盘里点击「Add panel」,选择「Network Graph」类型。配置面板数据映射
- 切换到「Data」标签页,确保你的查询已经加载出source和target数据。
- 切换到「Panel」标签页:
- 在「Nodes」区域,设置「ID field」为
source(面板会自动识别所有出现的source和target作为节点集合)。 - 在「Edges」区域,设置「Source field」为
source,「Target field」为target。
- 在「Nodes」区域,设置「ID field」为
自定义样式(可选)
你可以调整节点大小、颜色,连线的粗细、颜色,还可以开启交互功能(比如点击节点高亮关联边),这些都在「Panel」标签页的「Options」里设置。
方案二:用自定义HTML/JavaScript面板(适合复杂需求)
如果内置的Network Graph满足不了你的定制化需求(比如特殊布局、动画效果),可以用Grafana的Text面板结合D3.js来实现:
添加Text面板
点击「Add panel」,选择「Text」类型,然后在面板编辑界面切换到「HTML」模式。编写D3.js代码
下面是一个简单的示例,你可以直接替换数据部分,后续再对接Grafana数据源获取实时数据:<div id="network-graph" style="width: 100%; height: 600px;"></div> <script src="https://d3js.org/d3.v7.min.js"></script> <script> // 替换成你的source-target数据 const edgeData = [ {source: "00", target: "21"}, {source: "00", target: "23"}, {source: "00", target: "28"}, {source: "01", target: "21"}, {source: "02", target: "21"}, {source: "02", target: "22"}, {source: "02", target: "23"}, ]; // 提取所有独立节点 const nodes = Array.from(new Set(edgeData.flatMap(d => [d.source, d.target]))).map(id => ({id})); // 创建SVG绘图容器 const width = document.getElementById("network-graph").clientWidth; const height = 600; const svg = d3.select("#network-graph") .append("svg") .attr("width", width) .attr("height", height); // 配置力导向布局(自动计算节点位置) const simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(edgeData).id(d => d.id).distance(100)) .force("charge", d3.forceManyBody().strength(-300)) .force("center", d3.forceCenter(width / 2, height / 2)); // 绘制节点间的连线 const links = svg.append("g") .selectAll("line") .data(edgeData) .enter().append("line") .attr("stroke", "#ccc") .attr("stroke-width", 2); // 绘制节点圆圈 const nodeElements = svg.append("g") .selectAll("circle") .data(nodes) .enter().append("circle") .attr("r", 15) .attr("fill", "#4287f5") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); // 添加节点悬浮提示 nodeElements.append("title") .text(d => d.id); // 实时更新布局位置 simulation.on("tick", () => { links .attr("x1", d => d.source.x) .attr("y1", d => d.source.y) .attr("x2", d => d.target.x) .attr("y2", d => d.target.y); nodeElements .attr("cx", d => d.x) .attr("cy", d => d.y); }); // 节点拖拽交互函数 function dragstarted(event, d) { if (!event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(event, d) { d.fx = event.x; d.fy = event.y; } function dragended(event, d) { if (!event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } </script>对接实时数据源(可选)
如果要从Grafana数据源获取动态数据,可以用Grafana的getDataSource()方法发起查询,不过需要注意权限和数据格式转换,具体可以参考Grafana的自定义面板API说明。
注意事项
- 如果你的数据量很大(上千条边),内置的Network Graph性能会更稳定,自定义D3方案可能需要优化布局算法来提升流畅度。
- 若需要给节点添加分组、名称等额外属性,可以通过额外的查询获取节点元数据,再合并到节点集合中,方便做样式区分。
内容的提问来源于stack exchange,提问作者Tomas
相关产品推荐
相关产品推荐

