71 lines
6.4 KiB
JSON
71 lines
6.4 KiB
JSON
|
|
{
|
||
|
|
"annotations": {"list": [{"builtIn": 1,"datasource": {"type": "datasource","uid": "grafana"},"enable": true,"hide": true,"iconColor": "rgba(0, 211, 255, 1)","name": "Annotations & Alerts","type": "dashboard"}]},
|
||
|
|
"description": "AS adjacency graph derived from consecutive AS pairs in observed AS_PATHs. Edge label = how many times that adjacency appears in a 200k-route sample. Raise 'Min occurrences' to thin the graph; set 'Focus AS' to a 1-hop view around one AS. Manual refresh — the query explodes ~200k AS_PATH arrays.",
|
||
|
|
"editable": true,
|
||
|
|
"fiscalYearStartMonth": 0,
|
||
|
|
"graphTooltip": 0,
|
||
|
|
"id": null,
|
||
|
|
"links": [{"asDropdown": true,"icon": "external link","includeVars": true,"keepTime": true,"tags": ["obmp-nav"],"title": "OBMP Dashboards","type": "dashboards"}],
|
||
|
|
"liveNow": false,
|
||
|
|
"panels": [
|
||
|
|
{
|
||
|
|
"datasource": {"type": "postgres","uid": "obmp_postgres"},
|
||
|
|
"description": "Each node is an AS (enriched from info_asn whois data); each edge is an adjacency seen in the AS_PATH sample. Edge label is the occurrence count.",
|
||
|
|
"fieldConfig": {"defaults": {},"overrides": []},
|
||
|
|
"gridPos": {"h": 24,"w": 24,"x": 0,"y": 0},
|
||
|
|
"id": 1,
|
||
|
|
"options": {"nodes": {"mainStatUnit": "","secondaryStatUnit": ""}},
|
||
|
|
"targets": [
|
||
|
|
{
|
||
|
|
"datasource": {"type": "postgres","uid": "obmp_postgres"},
|
||
|
|
"format": "table",
|
||
|
|
"rawSql": "WITH sample AS (SELECT as_path FROM base_attrs WHERE as_path_count >= 2 LIMIT 200000),\npairs AS (\n SELECT a.asn AS src, b.asn AS dst\n FROM sample ba\n CROSS JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY a(asn,ord)\n JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY b(asn,ord) ON b.ord = a.ord + 1\n WHERE a.asn <> b.asn\n),\nedges AS (\n SELECT LEAST(src,dst) AS x, GREATEST(src,dst) AS y, COUNT(*) AS occ\n FROM pairs GROUP BY 1,2 HAVING COUNT(*) >= $min_occ ORDER BY occ DESC LIMIT 300\n),\nfedges AS (\n SELECT * FROM edges\n WHERE '$focus_as' = '' OR x::text = '$focus_as' OR y::text = '$focus_as'\n),\nnlist AS (SELECT x AS asn FROM fedges UNION SELECT y FROM fedges),\ndeg AS (SELECT asn, COUNT(*) AS d FROM (SELECT x AS asn FROM fedges UNION ALL SELECT y FROM fedges) z GROUP BY asn)\nSELECT n.asn::text AS id,\n COALESCE(NULLIF(ia.as_name,''),'AS'||n.asn) AS title,\n 'AS ' || n.asn AS mainstat,\n COALESCE(NULLIF(ia.country,''),'?') || ' · ' || dg.d::text || ' links' AS secondarystat,\n COALESCE(NULLIF(ia.org_name,''),'—') AS detail__org,\n COALESCE(NULLIF(ia.country,''),'—') AS detail__country,\n dg.d::text AS detail__degree\nFROM nlist n\nLEFT JOIN info_asn ia ON ia.asn = n.asn\nLEFT JOIN deg dg ON dg.asn = n.asn\nORDER BY dg.d DESC",
|
||
|
|
"refId": "nodes"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"datasource": {"type": "postgres","uid": "obmp_postgres"},
|
||
|
|
"format": "table",
|
||
|
|
"rawSql": "WITH sample AS (SELECT as_path FROM base_attrs WHERE as_path_count >= 2 LIMIT 200000),\npairs AS (\n SELECT a.asn AS src, b.asn AS dst\n FROM sample ba\n CROSS JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY a(asn,ord)\n JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY b(asn,ord) ON b.ord = a.ord + 1\n WHERE a.asn <> b.asn\n),\nedges AS (\n SELECT LEAST(src,dst) AS x, GREATEST(src,dst) AS y, COUNT(*) AS occ\n FROM pairs GROUP BY 1,2 HAVING COUNT(*) >= $min_occ ORDER BY occ DESC LIMIT 300\n)\nSELECT x::text || '-' || y::text AS id,\n x::text AS source, y::text AS target,\n occ AS mainstat,\n occ::text || ' paths' AS detail__occurrences\nFROM edges\nWHERE '$focus_as' = '' OR x::text = '$focus_as' OR y::text = '$focus_as'",
|
||
|
|
"refId": "edges"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"title": "AS Adjacency Graph",
|
||
|
|
"type": "nodeGraph"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"datasource": {"type": "postgres","uid": "obmp_postgres"},
|
||
|
|
"description": "The strongest AS adjacencies in the sample, with whois names for both endpoints.",
|
||
|
|
"fieldConfig": {"defaults": {"custom": {"align": "auto","displayMode": "auto"}},"overrides": [{"matcher": {"id": "byName","options": "Occurrences"},"properties": [{"id": "custom.displayMode","value": "gradient-gauge"},{"id": "color","value": {"mode": "continuous-BlPu"}}]}]},
|
||
|
|
"gridPos": {"h": 10,"w": 24,"x": 0,"y": 24},
|
||
|
|
"id": 2,
|
||
|
|
"options": {"showHeader": true,"sortBy": [{"desc": true,"displayName": "Occurrences"}]},
|
||
|
|
"targets": [
|
||
|
|
{
|
||
|
|
"datasource": {"type": "postgres","uid": "obmp_postgres"},
|
||
|
|
"format": "table",
|
||
|
|
"rawSql": "WITH sample AS (SELECT as_path FROM base_attrs WHERE as_path_count >= 2 LIMIT 200000),\npairs AS (\n SELECT a.asn AS src, b.asn AS dst\n FROM sample ba\n CROSS JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY a(asn,ord)\n JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY b(asn,ord) ON b.ord = a.ord + 1\n WHERE a.asn <> b.asn\n),\nedges AS (\n SELECT LEAST(src,dst) AS x, GREATEST(src,dst) AS y, COUNT(*) AS occ\n FROM pairs GROUP BY 1,2 HAVING COUNT(*) >= $min_occ ORDER BY occ DESC LIMIT 300\n)\nSELECT e.x AS \"AS A\",\n COALESCE(NULLIF(ax.as_name,''),'—') AS \"Name A\",\n e.y AS \"AS B\",\n COALESCE(NULLIF(ay.as_name,''),'—') AS \"Name B\",\n e.occ AS \"Occurrences\"\nFROM edges e\nLEFT JOIN info_asn ax ON ax.asn = e.x\nLEFT JOIN info_asn ay ON ay.asn = e.y\nWHERE '$focus_as' = '' OR e.x::text = '$focus_as' OR e.y::text = '$focus_as'\nORDER BY e.occ DESC",
|
||
|
|
"refId": "A"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"title": "Top AS Adjacencies",
|
||
|
|
"type": "table"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"schemaVersion": 36,
|
||
|
|
"style": "dark",
|
||
|
|
"tags": ["obmp", "obmp-nav", "obmp-maps", "asn"],
|
||
|
|
"templating": {
|
||
|
|
"list": [
|
||
|
|
{"name": "min_occ","type": "custom","label": "Min occurrences","description": "Only draw adjacencies seen at least this many times in the 200k-route sample. Raise it to thin a cluttered graph.","query": "5,20,100,500","current": {"text": "20","value": "20"},"options": [{"text": "5","value": "5","selected": false},{"text": "20","value": "20","selected": true},{"text": "100","value": "100","selected": false},{"text": "500","value": "500","selected": false}],"hide": 0},
|
||
|
|
{"name": "focus_as","type": "textbox","label": "Focus AS","description": "Optional. Enter an ASN to show only adjacencies touching that AS (1-hop view). Leave blank for the full graph.","query": "","current": {"text": "","value": ""},"options": [{"text": "","value": "","selected": true}],"hide": 0}
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"time": {"from": "now-6h","to": "now"},
|
||
|
|
"timepicker": {},
|
||
|
|
"timezone": "",
|
||
|
|
"title": "AS Relationship Map",
|
||
|
|
"uid": "as-rel-map",
|
||
|
|
"version": 1,
|
||
|
|
"weekStart": ""
|
||
|
|
}
|