mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-06 08:09:24 +00:00
fix: use edge-specific metrics in service graph tree view
- Calculate tree node metrics from edges instead of global node totals - Add Connections field to tooltips - Reposition labels (left for horizontal, top for vertical) Fixes bidirectional edges showing incorrect request counts.
This commit is contained in:
@@ -232,7 +232,8 @@ export const convertServiceGraphToTree = (
|
||||
const globalVisited = new Set<string>();
|
||||
|
||||
// Helper to build tree recursively
|
||||
const buildTree = (nodeId: string, visited = new Set<string>()): any => {
|
||||
// incomingEdge: the edge that led to this node (for direction-aware metrics)
|
||||
const buildTree = (nodeId: string, visited = new Set<string>(), incomingEdge: any = null): any => {
|
||||
if (visited.has(nodeId)) return null; // Prevent cycles
|
||||
visited.add(nodeId);
|
||||
globalVisited.add(nodeId);
|
||||
@@ -242,14 +243,29 @@ export const convertServiceGraphToTree = (
|
||||
|
||||
const outgoingEdges = edgesMap.get(nodeId) || [];
|
||||
const children = outgoingEdges
|
||||
.map((edge: any) => buildTree(edge.to, new Set(visited)))
|
||||
.map((edge: any) => buildTree(edge.to, new Set(visited), edge))
|
||||
.filter((child: any) => child !== null);
|
||||
|
||||
// Calculate node metrics - use node's own request count, not just outgoing edges
|
||||
// This ensures leaf nodes show their actual traffic instead of 0
|
||||
const totalRequests = node.requests || 0;
|
||||
const failedRequests = node.errors || 0;
|
||||
const errorRate = node.error_rate || 0;
|
||||
// Calculate node metrics - direction-aware based on tree position
|
||||
let totalRequests: number;
|
||||
let failedRequests: number;
|
||||
let errorRate: number;
|
||||
|
||||
if (incomingEdge) {
|
||||
// Child node: use the incoming edge's metrics (traffic via this specific edge)
|
||||
totalRequests = incomingEdge.total_requests ?? 0;
|
||||
failedRequests = incomingEdge.failed_requests ?? 0;
|
||||
errorRate = incomingEdge.error_rate ?? 0;
|
||||
} else {
|
||||
// Root node: sum of all outgoing edges (traffic flowing from this node)
|
||||
totalRequests = outgoingEdges.reduce((sum: number, edge: any) => sum + (edge.total_requests ?? 0), 0);
|
||||
failedRequests = outgoingEdges.reduce((sum: number, edge: any) => sum + (edge.failed_requests ?? 0), 0);
|
||||
errorRate = totalRequests > 0 ? (failedRequests / totalRequests) * 100 : 0;
|
||||
}
|
||||
|
||||
// Calculate connections count (incoming + outgoing edges)
|
||||
const incomingEdges = incomingEdgesMap.get(nodeId) || [];
|
||||
const connectionCount = incomingEdges.length + outgoingEdges.length;
|
||||
|
||||
// Determine node color based on error rate
|
||||
let nodeColor = "#4CAF50"; // Green for healthy
|
||||
@@ -268,7 +284,7 @@ export const convertServiceGraphToTree = (
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: layoutType === 'vertical' ? 'bottom' : 'right',
|
||||
position: layoutType === 'vertical' ? 'top' : 'left',
|
||||
formatter: (params: any) => {
|
||||
return `${params.name}\n${formatNumber(totalRequests)} req`;
|
||||
},
|
||||
@@ -279,7 +295,8 @@ export const convertServiceGraphToTree = (
|
||||
<strong>${params.name}</strong><br/>
|
||||
Requests: ${formatNumber(totalRequests)}<br/>
|
||||
Errors: ${failedRequests}<br/>
|
||||
Error Rate: ${errorRate.toFixed(2)}%
|
||||
Error Rate: ${errorRate.toFixed(2)}%<br/>
|
||||
Connections: ${connectionCount}
|
||||
`;
|
||||
},
|
||||
},
|
||||
@@ -358,16 +375,16 @@ export const convertServiceGraphToTree = (
|
||||
symbol: 'circle',
|
||||
symbolSize: 20,
|
||||
label: {
|
||||
position: layoutType === 'vertical' ? 'bottom' : 'right',
|
||||
verticalAlign: layoutType === 'vertical' ? 'top' : 'middle',
|
||||
position: layoutType === 'vertical' ? 'top' : 'left',
|
||||
verticalAlign: layoutType === 'vertical' ? 'bottom' : 'middle',
|
||||
distance: 15,
|
||||
fontSize: 12,
|
||||
rotate: 0, // Keep text horizontal, no rotation
|
||||
},
|
||||
leaves: {
|
||||
label: {
|
||||
position: layoutType === 'vertical' ? 'bottom' : 'right',
|
||||
verticalAlign: layoutType === 'vertical' ? 'top' : 'middle',
|
||||
position: layoutType === 'vertical' ? 'top' : 'left',
|
||||
verticalAlign: layoutType === 'vertical' ? 'bottom' : 'middle',
|
||||
distance: 15,
|
||||
rotate: 0, // Keep text horizontal, no rotation
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user