Skip to content

Commit 1a5903b

Browse files
Entleinclaude
andcommitted
fix(dx_evidence_graph): node identity = pod→service→IP, so empty-pod peers don't collapse
Edges whose peer is not a pod (k8s API server, external/IP endpoints, consulted sockets) carry an empty requestor_pod/responder_pod. The Graph widget keyed on *_pod alone, so EVERY such edge collapsed into one bogus "" node — visually merging unrelated peers (the API server, every distinct remote IP) into one. Coalesce node identity to pod, else service, else IP (the same idiom net_flow_graph uses: px.select(src=='', src_ip, src)) and point the adjacencyList from/to at the coalesced columns. Now each distinct peer is its own node. Validated live (px run, forensic_db): control-plane → k8s-apiserver; the 5 consulted sockets → 5 distinct IPs (10.43.143.34, 10.42.0.1, ::1, 127.0.0.1, 10.42.0.43) instead of one merged node. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent b7d915c commit 1a5903b

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

src/pxl_scripts/px/dx_evidence_graph/dx_evidence_graph.pxl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,19 @@ import px
1919

2020
def dx_attack_graph(start_time: str, clickhouse_dsn: str, table: str):
2121
df = px.DataFrame(table, clickhouse_dsn=clickhouse_dsn, start_time=start_time)
22-
return df[['requestor_pod', 'responder_pod',
22+
# Node identity: pod, else service, else IP. Edges whose peer is an IP or a
23+
# non-pod entity (the k8s API server, an external endpoint, a consulted
24+
# socket) have an empty *_pod; keying the graph on *_pod alone collapses ALL
25+
# of them into one bogus "" node. Coalesce so each distinct peer is its own
26+
# node — same idiom Pixie's net_flow_graph uses (px.select(src=='', src_ip, src)).
27+
df.requestor = px.select(df.requestor_pod == '',
28+
px.select(df.requestor_service == '', df.requestor_ip, df.requestor_service),
29+
df.requestor_pod)
30+
df.responder = px.select(df.responder_pod == '',
31+
px.select(df.responder_service == '', df.responder_ip, df.responder_service),
32+
df.responder_pod)
33+
return df[['requestor', 'responder',
34+
'requestor_pod', 'responder_pod',
2335
'requestor_service', 'responder_service',
2436
'requestor_ip', 'responder_ip',
2537
'weight', 'max_severity', 'confidence',

src/pxl_scripts/px/dx_evidence_graph/vis.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"displaySpec": {
4141
"@type": "types.px.dev/px.vispb.Graph",
4242
"adjacencyList": {
43-
"fromColumn": "requestor_pod",
44-
"toColumn": "responder_pod"
43+
"fromColumn": "requestor",
44+
"toColumn": "responder"
4545
},
4646
"edgeWeightColumn": "weight",
4747
"edgeColorColumn": "max_severity",

0 commit comments

Comments
 (0)