Compare commits

..

3 Commits

Author SHA1 Message Date
sam
26dea47a55 Make the ASN View origin-AS selector a free-text input
asn_num was a fixed custom variable; converting it to a textbox lets an
operator look up any origin AS and see all of its RIB prefixes, upstreams,
and downstreams.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:22:21 -07:00
sam
9d74940614 Fix ExaBGP OOM, add container health checks and resource monitoring
RCA: the exabgp container was OOM-killed — its 512m mem_limit was far too
small for the full-table feature (900K route objects in memory). Raises the
limit to a parameterized 6g default (EXABGP_MEM_LIMIT).

Adds Docker healthchecks to 14 services (port/HTTP probes) so unhealthy
containers are visible. Adds a Telegraf docker input that collects per-
container CPU/memory/IO into InfluxDB, plus a "Stack Resources" dashboard —
so resource pressure is caught before it causes an OOM crash. telegraf runs
with an overridden entrypoint so it keeps root and can read the docker socket.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:03:52 -07:00
sam
482c0cdc01 Add ipv6 unicast to ExaBGP neighbor family
The IOS-XR routers negotiate IPv6 unicast capability, but the generated
exabgp.conf declared only ipv4 unicast — producing repeated "route family
(ipv6/unicast) is not configured" errors that crashed ExaBGP. Declaring
ipv6 unicast on the neighbor matches the routers' capabilities and stops
the crash-restart cycle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:40:32 -07:00
6 changed files with 298 additions and 31 deletions

View File

@ -24,6 +24,8 @@ OBMP_COOKIE_DOMAIN=example.com
PSQL_MEM_LIMIT=6g PSQL_MEM_LIMIT=6g
PSQL_APP_MEM_LIMIT=4g PSQL_APP_MEM_LIMIT=4g
KAFKA_MEM_LIMIT=4g KAFKA_MEM_LIMIT=4g
# ExaBGP — the full-table feature holds up to 900K route objects in memory.
EXABGP_MEM_LIMIT=6g
# gNMI streaming telemetry (telegraf, test profile). GNMI_ADDRESSES is a # gNMI streaming telemetry (telegraf, test profile). GNMI_ADDRESSES is a
# quoted, comma-separated host:port list — add a router here once gNMI/grpc # quoted, comma-separated host:port list — add a router here once gNMI/grpc

View File

@ -17,6 +17,12 @@ services:
zookeeper: zookeeper:
restart: unless-stopped restart: unless-stopped
container_name: obmp-zookeeper container_name: obmp-zookeeper
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/2181'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
image: confluentinc/cp-zookeeper:7.1.1 image: confluentinc/cp-zookeeper:7.1.1
mem_limit: 1g mem_limit: 1g
volumes: volumes:
@ -29,6 +35,12 @@ services:
kafka: kafka:
restart: unless-stopped restart: unless-stopped
container_name: obmp-kafka container_name: obmp-kafka
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/9092'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 90s
image: confluentinc/cp-kafka:7.1.1 image: confluentinc/cp-kafka:7.1.1
# Raise KAFKA_MEM_LIMIT for production (full-table initial dumps are bursty). # Raise KAFKA_MEM_LIMIT for production (full-table initial dumps are bursty).
mem_limit: ${KAFKA_MEM_LIMIT:-4g} mem_limit: ${KAFKA_MEM_LIMIT:-4g}
@ -87,6 +99,12 @@ services:
grafana: grafana:
restart: unless-stopped restart: unless-stopped
container_name: obmp-grafana container_name: obmp-grafana
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/api/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
image: grafana/grafana:9.1.7 image: grafana/grafana:9.1.7
mem_limit: 1g mem_limit: 1g
ports: ports:
@ -128,6 +146,12 @@ services:
psql: psql:
restart: unless-stopped restart: unless-stopped
container_name: obmp-psql container_name: obmp-psql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U openbmp -d openbmp"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
image: openbmp/postgres:2.2.1 image: openbmp/postgres:2.2.1
# Raise PSQL_MEM_LIMIT for production (see docs/production-sizing.md). # Raise PSQL_MEM_LIMIT for production (see docs/production-sizing.md).
mem_limit: ${PSQL_MEM_LIMIT:-6g} mem_limit: ${PSQL_MEM_LIMIT:-6g}
@ -153,6 +177,12 @@ services:
collector: collector:
restart: unless-stopped restart: unless-stopped
container_name: obmp-collector container_name: obmp-collector
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/5000'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
image: openbmp/collector:2.2.3 image: openbmp/collector:2.2.3
mem_limit: 2g mem_limit: 2g
sysctls: sysctls:
@ -169,6 +199,8 @@ services:
psql-app: psql-app:
restart: unless-stopped restart: unless-stopped
container_name: obmp-psql-app container_name: obmp-psql-app
# No healthcheck — the consumer exposes no health port; Docker's
# restart-on-exit covers process death.
image: openbmp/psql-app:2.2.2 image: openbmp/psql-app:2.2.2
# mem_limit must exceed the MEM (JVM heap) env below. Raise both for # mem_limit must exceed the MEM (JVM heap) env below. Raise both for
# production — see docs/production-sizing.md. # production — see docs/production-sizing.md.
@ -216,8 +248,16 @@ services:
exabgp: exabgp:
restart: unless-stopped restart: unless-stopped
container_name: obmp-exabgp container_name: obmp-exabgp
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/5050'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
profiles: ["test"] profiles: ["test"]
mem_limit: 512m # The full-table feature generates up to 900K route objects in memory;
# 512m OOM-killed it. Raise EXABGP_MEM_LIMIT in .env for larger tables.
mem_limit: ${EXABGP_MEM_LIMIT:-6g}
build: build:
context: ./exabgp context: ./exabgp
dockerfile: Dockerfile dockerfile: Dockerfile
@ -241,6 +281,12 @@ services:
exabgp-ui: exabgp-ui:
restart: unless-stopped restart: unless-stopped
container_name: obmp-exabgp-ui container_name: obmp-exabgp-ui
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:5001/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
profiles: ["test"] profiles: ["test"]
mem_limit: 256m mem_limit: 256m
build: build:
@ -255,6 +301,12 @@ services:
influxdb: influxdb:
restart: unless-stopped restart: unless-stopped
container_name: obmp-influxdb container_name: obmp-influxdb
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8086/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
profiles: ["test"] profiles: ["test"]
image: influxdb:2.7 image: influxdb:2.7
mem_limit: 2g mem_limit: 2g
@ -280,6 +332,13 @@ services:
context: ./telegraf context: ./telegraf
dockerfile: Dockerfile dockerfile: Dockerfile
network_mode: host network_mode: host
# Run telegraf as root and override the image entrypoint (which otherwise
# drops back to the telegraf user) so [[inputs.docker]] can read the
# Docker daemon socket for container resource metrics.
user: root
entrypoint: ["telegraf"]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on: depends_on:
- influxdb - influxdb
environment: environment:
@ -295,6 +354,12 @@ services:
traffic-gen: traffic-gen:
restart: unless-stopped restart: unless-stopped
container_name: obmp-traffic-gen container_name: obmp-traffic-gen
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/5051'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
profiles: ["test"] profiles: ["test"]
mem_limit: 1g mem_limit: 1g
build: build:
@ -312,6 +377,12 @@ services:
traffic-gen-ui: traffic-gen-ui:
restart: unless-stopped restart: unless-stopped
container_name: obmp-traffic-gen-ui container_name: obmp-traffic-gen-ui
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:5002/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
profiles: ["test"] profiles: ["test"]
mem_limit: 256m mem_limit: 256m
build: build:
@ -323,6 +394,12 @@ services:
traffic-gen-responder: traffic-gen-responder:
restart: unless-stopped restart: unless-stopped
container_name: obmp-traffic-gen-responder container_name: obmp-traffic-gen-responder
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/5053'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
profiles: ["test"] profiles: ["test"]
mem_limit: 1g mem_limit: 1g
build: build:
@ -345,6 +422,12 @@ services:
whois: whois:
restart: unless-stopped restart: unless-stopped
container_name: obmp-whois container_name: obmp-whois
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/43'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
image: openbmp/whois:2.2.0 image: openbmp/whois:2.2.0
mem_limit: 1g mem_limit: 1g
sysctls: sysctls:
@ -378,6 +461,12 @@ services:
portal: portal:
restart: unless-stopped restart: unless-stopped
container_name: obmp-portal container_name: obmp-portal
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:80/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
profiles: ["auth"] profiles: ["auth"]
mem_limit: 128m mem_limit: 128m
image: nginx:alpine image: nginx:alpine

View File

@ -52,6 +52,7 @@ neighbor ${p_ip} {
family { family {
ipv4 unicast; ipv4 unicast;
ipv6 unicast;
} }
api { api {

View File

@ -0,0 +1,78 @@
{
"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": "Per-container CPU, memory, and I/O for the OpenBMP stack — collected by the Telegraf docker input. Watch memory % to catch a container approaching its mem_limit before it OOM-crashes.",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
"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": "influxdb","uid": "obmp_influxdb"},
"description": "Memory usage as a percentage of each container's mem_limit. Sustained values near 100% precede an OOM kill.",
"fieldConfig": {
"defaults": {"color": {"mode": "palette-classic"},"custom": {"axisPlacement": "auto","drawStyle": "line","fillOpacity": 10,"lineInterpolation": "smooth","lineWidth": 1,"pointSize": 5,"showPoints": "never","spanNulls": false,"stacking": {"group": "A","mode": "none"}},"unit": "percent","min": 0,"thresholds": {"mode": "absolute","steps": [{"color": "green","value": null},{"color": "orange","value": 80},{"color": "red","value": 95}]}},
"overrides": []
},
"gridPos": {"h": 9,"w": 12,"x": 0,"y": 0},
"id": 1,
"options": {"legend": {"calcs": ["max"],"displayMode": "table","placement": "right","showLegend": true},"tooltip": {"mode": "multi","sort": "desc"}},
"targets": [{"datasource": {"type": "influxdb","uid": "obmp_influxdb"},"query": "from(bucket: \"telemetry\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r._measurement == \"docker_container_mem\" and r._field == \"usage_percent\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> keep(columns: [\"_time\", \"_value\", \"container_name\"])\n |> group(columns: [\"container_name\"])","refId": "A"}],
"title": "Container Memory %",
"type": "timeseries"
},
{
"datasource": {"type": "influxdb","uid": "obmp_influxdb"},
"description": "CPU usage per container (cpu-total). Can exceed 100% — that is multiple cores.",
"fieldConfig": {
"defaults": {"color": {"mode": "palette-classic"},"custom": {"axisPlacement": "auto","drawStyle": "line","fillOpacity": 10,"lineInterpolation": "smooth","lineWidth": 1,"pointSize": 5,"showPoints": "never","spanNulls": false,"stacking": {"group": "A","mode": "none"}},"unit": "percent","min": 0},
"overrides": []
},
"gridPos": {"h": 9,"w": 12,"x": 12,"y": 0},
"id": 2,
"options": {"legend": {"calcs": ["max"],"displayMode": "table","placement": "right","showLegend": true},"tooltip": {"mode": "multi","sort": "desc"}},
"targets": [{"datasource": {"type": "influxdb","uid": "obmp_influxdb"},"query": "from(bucket: \"telemetry\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r._measurement == \"docker_container_cpu\" and r._field == \"usage_percent\" and r.cpu == \"cpu-total\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> keep(columns: [\"_time\", \"_value\", \"container_name\"])\n |> group(columns: [\"container_name\"])","refId": "A"}],
"title": "Container CPU %",
"type": "timeseries"
},
{
"datasource": {"type": "influxdb","uid": "obmp_influxdb"},
"description": "Absolute memory usage per container.",
"fieldConfig": {
"defaults": {"color": {"mode": "palette-classic"},"custom": {"axisPlacement": "auto","drawStyle": "line","fillOpacity": 10,"lineInterpolation": "smooth","lineWidth": 1,"pointSize": 5,"showPoints": "never","spanNulls": false,"stacking": {"group": "A","mode": "none"}},"unit": "bytes","min": 0},
"overrides": []
},
"gridPos": {"h": 9,"w": 12,"x": 0,"y": 9},
"id": 3,
"options": {"legend": {"calcs": ["max"],"displayMode": "table","placement": "right","showLegend": true},"tooltip": {"mode": "multi","sort": "desc"}},
"targets": [{"datasource": {"type": "influxdb","uid": "obmp_influxdb"},"query": "from(bucket: \"telemetry\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r._measurement == \"docker_container_mem\" and r._field == \"usage\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> keep(columns: [\"_time\", \"_value\", \"container_name\"])\n |> group(columns: [\"container_name\"])","refId": "A"}],
"title": "Container Memory Usage",
"type": "timeseries"
},
{
"datasource": {"type": "influxdb","uid": "obmp_influxdb"},
"description": "Current memory pressure per container. Anything in orange/red is close to its mem_limit.",
"fieldConfig": {
"defaults": {"custom": {"align": "auto","displayMode": "auto"},"unit": "percent"},
"overrides": [{"matcher": {"id": "byName","options": "Memory %"},"properties": [{"id": "custom.displayMode","value": "gradient-gauge"},{"id": "max","value": 100},{"id": "thresholds","value": {"mode": "absolute","steps": [{"color": "green","value": null},{"color": "orange","value": 80},{"color": "red","value": 95}]}}]}]
},
"gridPos": {"h": 9,"w": 12,"x": 12,"y": 9},
"id": 4,
"options": {"showHeader": true,"sortBy": [{"desc": true,"displayName": "Memory %"}]},
"targets": [{"datasource": {"type": "influxdb","uid": "obmp_influxdb"},"query": "from(bucket: \"telemetry\")\n |> range(start: -5m)\n |> filter(fn: (r) => r._measurement == \"docker_container_mem\" and r._field == \"usage_percent\")\n |> last()\n |> keep(columns: [\"container_name\", \"_value\"])\n |> group()\n |> rename(columns: {_value: \"Memory %\", container_name: \"Container\"})\n |> sort(columns: [\"Memory %\"], desc: true)","refId": "A"}],
"title": "Current Memory % by Container",
"type": "table"
}
],
"refresh": "30s",
"schemaVersion": 36,
"style": "dark",
"tags": ["obmp", "obmp-nav", "telemetry", "resources"],
"time": {"from": "now-1h","to": "now"},
"timepicker": {},
"timezone": "browser",
"title": "Stack Resources",
"uid": "obmp-stack-resources",
"version": 1
}

View File

@ -27,7 +27,17 @@
"id": null, "id": null,
"iteration": 1654876929746, "iteration": 1654876929746,
"links": [ "links": [
{"asDropdown": true,"icon": "external link","includeVars": true,"keepTime": true,"tags": ["obmp-nav"],"title": "OBMP Dashboards","type": "dashboards"} {
"asDropdown": true,
"icon": "external link",
"includeVars": true,
"keepTime": true,
"tags": [
"obmp-nav"
],
"title": "OBMP Dashboards",
"type": "dashboards"
}
], ],
"liveNow": false, "liveNow": false,
"panels": [ "panels": [
@ -39,8 +49,16 @@
"description": "IPv4 vs IPv6 prefix count advertised by this ASN.", "description": "IPv4 vs IPv6 prefix count advertised by this ASN.",
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
"color": {"mode": "palette-classic"}, "color": {
"custom": {"hideFrom": {"legend": false,"tooltip": false,"viz": false}}, "mode": "palette-classic"
},
"custom": {
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
}
},
"decimals": 0, "decimals": 0,
"mappings": [], "mappings": [],
"unit": "none" "unit": "none"
@ -56,23 +74,48 @@
"id": 6, "id": 6,
"links": [], "links": [],
"options": { "options": {
"displayLabels": ["value"], "displayLabels": [
"legend": {"calcs": [],"displayMode": "table","placement": "bottom","values": ["value","percent"]}, "value"
],
"legend": {
"calcs": [],
"displayMode": "table",
"placement": "bottom",
"values": [
"value",
"percent"
]
},
"pieType": "pie", "pieType": "pie",
"reduceOptions": {"calcs": ["lastNotNull"],"fields": "","values": false}, "reduceOptions": {
"tooltip": {"mode": "single","sort": "none"} "calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
}, },
"pluginVersion": "9.1.7", "pluginVersion": "9.1.7",
"targets": [ "targets": [
{ {
"datasource": {"type": "postgres","uid": "obmp_postgres"}, "datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"alias": "", "alias": "",
"format": "time_series", "format": "time_series",
"rawSql": "SELECT\n max(timestamp) as time,\n count(*) as \"ipv4\"\nFROM\n global_ip_rib\nWHERE\n recv_origin_as = [[asn_num]]\n and family(prefix) = 4\nGROUP BY prefix\n", "rawSql": "SELECT\n max(timestamp) as time,\n count(*) as \"ipv4\"\nFROM\n global_ip_rib\nWHERE\n recv_origin_as = [[asn_num]]\n and family(prefix) = 4\nGROUP BY prefix\n",
"refId": "A" "refId": "A"
}, },
{ {
"datasource": {"type": "postgres","uid": "obmp_postgres"}, "datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"alias": "", "alias": "",
"format": "time_series", "format": "time_series",
"rawSql": "SELECT\n max(timestamp) as time,\n count(*) as \"ipv6\"\nFROM\n global_ip_rib\nWHERE\n recv_origin_as = [[asn_num]]\n and family(prefix) = 6\nGROUP BY prefix\n", "rawSql": "SELECT\n max(timestamp) as time,\n count(*) as \"ipv6\"\nFROM\n global_ip_rib\nWHERE\n recv_origin_as = [[asn_num]]\n and family(prefix) = 6\nGROUP BY prefix\n",
@ -186,8 +229,39 @@
"description": "IPv4/IPv6 prefixes originated by this ASN over time, with RPKI/IRR coverage (from stats_ip_origins).", "description": "IPv4/IPv6 prefixes originated by this ASN over time, with RPKI/IRR coverage (from stats_ip_origins).",
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {
"color": {"mode": "palette-classic"}, "color": {
"custom": {"axisCenteredZero": false,"axisColorMode": "text","axisLabel": "","axisPlacement": "auto","barAlignment": 0,"drawStyle": "line","fillOpacity": 10,"gradientMode": "none","hideFrom": {"legend": false,"tooltip": false,"viz": false},"lineInterpolation": "linear","lineWidth": 1,"pointSize": 5,"scaleDistribution": {"type": "linear"},"showPoints": "auto","spanNulls": false,"stacking": {"group": "A","mode": "none"},"thresholdsStyle": {"mode": "off"}}, "mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 0, "decimals": 0,
"mappings": [], "mappings": [],
"unit": "none" "unit": "none"
@ -203,13 +277,28 @@
"id": 14, "id": 14,
"links": [], "links": [],
"options": { "options": {
"legend": {"calcs": ["min","max","mean"],"displayMode": "table","placement": "right","showLegend": true}, "legend": {
"tooltip": {"mode": "multi","sort": "none"} "calcs": [
"min",
"max",
"mean"
],
"displayMode": "table",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "none"
}
}, },
"pluginVersion": "9.1.7", "pluginVersion": "9.1.7",
"targets": [ "targets": [
{ {
"datasource": {"type": "postgres","uid": "obmp_postgres"}, "datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"alias": "", "alias": "",
"format": "time_series", "format": "time_series",
"rawSql": "SELECT\n $__time(interval_time),\n v4_prefixes,v6_prefixes,v4_with_rpki,v6_with_rpki,v4_with_irr,v6_with_irr\nFROM\n stats_ip_origins\nWHERE\n $__timeFilter(interval_time) and asn = [[asn_num]]\nORDER BY interval_time asc\n", "rawSql": "SELECT\n $__time(interval_time),\n v4_prefixes,v6_prefixes,v4_with_rpki,v6_with_rpki,v4_with_irr,v6_with_irr\nFROM\n stats_ip_origins\nWHERE\n $__timeFilter(interval_time) and asn = [[asn_num]]\nORDER BY interval_time asc\n",
@ -941,27 +1030,24 @@
"templating": { "templating": {
"list": [ "list": [
{ {
"current": {
"selected": false,
"text": "714",
"value": "714"
},
"hide": 0,
"includeAll": false,
"label": "ASN",
"multi": false,
"name": "asn_num", "name": "asn_num",
"type": "textbox",
"label": "Origin AS",
"description": "Enter an origin AS number \u2014 every panel shows that AS's prefixes, upstreams, and downstreams from the BMP RIB.",
"query": "13335",
"current": {
"text": "13335",
"value": "13335"
},
"options": [ "options": [
{ {
"selected": true, "text": "13335",
"text": "109", "value": "13335",
"value": "109" "selected": true
} }
], ],
"query": "109", "hide": 0,
"queryValue": "714", "skipUrlSync": false
"skipUrlSync": false,
"type": "custom"
} }
] ]
}, },

View File

@ -53,6 +53,17 @@
subscription_mode = "sample" subscription_mode = "sample"
sample_interval = "30s" sample_interval = "30s"
## Docker container resource metrics — CPU, memory (incl. limit + %), network,
## and block IO for every obmp-* container. Surfaces resource pressure (e.g. a
## container approaching its mem_limit) before it OOM-crashes.
[[inputs.docker]]
endpoint = "unix:///var/run/docker.sock"
gather_services = false
container_name_include = ["obmp-*"]
perdevice = false
total = true
timeout = "10s"
############################################################################### ###############################################################################
# OUTPUT PLUGINS # # OUTPUT PLUGINS #
############################################################################### ###############################################################################