infra/home/cluster/tmobile-exporter/configmap.yaml
Graham McIntire 8466e4590f
tmobile-exporter: switch to stock json_exporter + nginx sidecar
Replaces the vendored Go exporter with two pre-built upstream images:
- quay.io/prometheuscommunity/json-exporter:v0.7.0 maps the gateway JSON
  into prometheus metrics via JSONPath. The G4AR keys signal blocks as
  "5g" / "4g" (digit-prefixed), which the k8s client-go JSONPath dialect
  only reaches via bracket-with-single-quote notation.
- nginxinc/nginx-unprivileged:1.27-alpine-slim sidecar rewrites
  GET /metrics → GET /probe?module=tmhi&target=http://192.168.12.1/...
  so the existing kubernetes-services scrape job picks it up over the
  apiserver proxy with no Prometheus-side config changes.

Avoiding caddy here: its binary carries cap_net_bind_service file caps,
which the kernel refuses to exec under no_new_privs as a non-root user.

Dashboard "Gateway up" panel now reads up{service="tmobile-exporter"}
(Prometheus's built-in scrape-success gauge) since json_exporter's
/probe endpoint does not emit probe_success.
2026-05-10 17:57:13 -05:00

102 lines
3.7 KiB
YAML

apiVersion: v1
kind: ConfigMap
metadata:
name: tmobile-exporter-config
namespace: monitoring
data:
# nginx reverse-proxies /metrics to json_exporter's /probe endpoint with the
# gateway target baked in, so the existing Prometheus kubernetes-services
# scrape job picks this up via a normal /metrics path annotation.
nginx.conf: |
worker_processes 1;
pid /tmp/nginx.pid;
error_log /dev/stderr warn;
events { worker_connections 64; }
http {
access_log off;
client_body_temp_path /tmp/nginx-client 1 2;
proxy_temp_path /tmp/nginx-proxy 1 2;
fastcgi_temp_path /tmp/nginx-fcgi 1 2;
uwsgi_temp_path /tmp/nginx-uwsgi 1 2;
scgi_temp_path /tmp/nginx-scgi 1 2;
server {
listen 9099;
location = /healthz { return 200 "ok\n"; }
location = /metrics {
proxy_pass http://127.0.0.1:7979/probe?module=tmhi&target=http://192.168.12.1/TMI/v1/gateway?get=all;
}
location / { return 404; }
}
}
# json_exporter mapping for the G4AR's /TMI/v1/gateway?get=all response.
# JSONPath uses k8s client-go dialect, which requires bracket+single-quote
# notation for digit-prefixed keys (.signal['5g']). YAML single-quoted
# strings escape literal single quotes by doubling them.
# allow_missing_key keeps the scrape clean when blocks are absent (the
# G4AR omits the 4g block entirely on 5G-only deployments).
json-exporter.yml: |
modules:
tmhi:
metrics:
- name: tmobile_gateway_uptime_seconds
path: '{ .time.upTime }'
help: Gateway uptime in seconds.
- name: tmobile_gateway
type: object
path: '{ .device }'
help: Static gateway metadata; value is always 1.
labels:
serial: '{ .serial }'
manufacturer: '{ .manufacturer }'
model: '{ .model }'
name: '{ .name }'
hardware_version: '{ .hardwareVersion }'
software_version: '{ .softwareVersion }'
mac: '{ .macId }'
values:
info: 1
- name: tmobile_gateway_rsrp
path: '{ .signal[''5g''].rsrp }'
allow_missing_key: true
help: Reference Signal Received Power (dBm).
labels:
type: "5g"
band: '{ .signal[''5g''].bands[0] }'
- name: tmobile_gateway_rsrq
path: '{ .signal[''5g''].rsrq }'
allow_missing_key: true
help: Reference Signal Received Quality (dB).
labels:
type: "5g"
band: '{ .signal[''5g''].bands[0] }'
- name: tmobile_gateway_rssi
path: '{ .signal[''5g''].rssi }'
allow_missing_key: true
help: Received Signal Strength Indicator (dBm).
labels:
type: "5g"
band: '{ .signal[''5g''].bands[0] }'
- name: tmobile_gateway_snr
path: '{ .signal[''5g''].sinr }'
allow_missing_key: true
help: Signal-to-noise ratio (dB).
labels:
type: "5g"
band: '{ .signal[''5g''].bands[0] }'
- name: tmobile_gateway_bars
path: '{ .signal[''5g''].bars }'
allow_missing_key: true
help: Signal strength in bars (0-5).
labels:
type: "5g"
band: '{ .signal[''5g''].bands[0] }'
- name: tmobile_gateway_channel_id
path: '{ .signal[''5g''].cid }'
allow_missing_key: true
help: Cellular channel ID.
labels:
type: "5g"
band: '{ .signal[''5g''].bands[0] }'