mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-16 14:47:04 -05:00
[GH-ISSUE #1429] [Feature Request] Implement OpenTelemetry Metrics in Pangolin #8671
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @marcschaeferger on GitHub (Sep 7, 2025).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/1429
Originally assigned to: @marcschaeferger on GitHub.
Add OpenTelemetry-based observability to Pangolin
Summary / Goal
Instrument Pangolin with OpenTelemetry Metrics (OTel) following CNCF / industry best practices so that:
_seconds,_bytes), and low‑cardinality labels are enforced./metricsendpoint for Prometheus scraping (Prometheus exporter) and example OTel Collector config for production pipelines.Why OpenTelemetry (OTel)
Requirements & Constraints
/metricsendpoint in Prometheus exposition format via the OTel Prometheus exporter._seconds,_bytes) and counters use_total.site_id,resource_id). Do not use per‑request unique values as labels.prometheusremotewriteusage.Recommended Pangolin Metrics (TypeScript implementation)
Use snake_case names and include units/
_totalsuffixes where applicable.pangolin_site_active_sitessite_id,regionpangolin_site_onlinesite_id,transportpangolin_site_bandwidth_bytes_totalsite_id,direction,protocolpangolin_site_uptime_seconds_totalsite_idpangolin_site_connection_drops_totalsite_idpangolin_site_handshake_latency_secondssite_id,transportpangolin_resource_requests_totalsite_id,resource_id,backend,method,statuspangolin_resource_request_duration_secondssite_id,resource_id,backend,methodpangolin_resource_active_connectionssite_id,resource_id,protocolpangolin_resource_errors_totalsite_id,resource_id,backend,error_typepangolin_resource_bandwidth_bytes_totalsite_id,resource_id,directionpangolin_tunnel_upsite_id,transportpangolin_tunnel_reconnects_totalsite_id,transport,reasonpangolin_tunnel_latency_secondssite_id,transportpangolin_tunnel_bytes_totalsite_id,transport,directionpangolin_wg_handshake_totalsite_id,resultpangolin_backend_health_statusbackend,site_idpangolin_backend_connection_errors_totalbackend,site_id,error_typepangolin_backend_response_size_bytesbackend,site_idpangolin_auth_requests_totalsite_id,auth_method,resultpangolin_auth_request_duration_secondsauth_method,resultpangolin_auth_active_userssite_id,auth_methodpangolin_auth_failure_reasons_totalsite_id,reason,auth_methodpangolin_token_issued_totalsite_id,auth_methodpangolin_token_revoked_totalreasonpangolin_token_refresh_totalsite_id,resultpangolin_ui_requests_totalendpoint,method,statuspangolin_ui_active_sessionspangolin_config_reloads_totalresultpangolin_restart_count_totalpangolin_background_jobs_totaljob_type,statuspangolin_certificates_expiry_dayssite_id,resource_idLabel guidelines: prefer
site_id/resource_id. Avoid per‑request unique labels (user IDs, full URLs). Use enums and stable identifiers.Implementation Plan
Dependencies (example packages)
@opentelemetry/api@opentelemetry/sdk-metrics(or current stable metrics SDK)@opentelemetry/exporter-prometheus@opentelemetry/exporter-metrics-otlp-http(or OTLP exporter variant)@opentelemetry/instrumentation-http@opentelemetry/instrumentation-express, Next.js instrumentation patterns)Central metrics module
src/metrics/(orserver/metrics/) that:/metrics(or mounts to existing server route).metricsobject with helper functions:inc(name, labels),observe(name, value, labels),setGauge(name, value, labels)— mapped to pre-registered instruments.shutdown()to flush metrics.Instrumentation approach
@opentelemetry/instrumentation-httpplus manual wrapper to label proxied requests withsite_id,resource_id,backend, etc.Histograms & buckets
Exporter configuration (runtime)
PANGOLIN_METRICS_PROMETHEUS_ENABLED=truePANGOLIN_METRICS_OTLP_ENABLED=falseOTEL_EXPORTER_OTLP_ENDPOINT(when OTLP enabled)OTEL_EXPORTER_OTLP_PROTOCOL(http/protobuf or grpc)OTEL_SERVICE_NAME=pangolinOTEL_RESOURCE_ATTRIBUTES(e.g.,service.instance.id=...)OTEL_METRIC_EXPORT_INTERVAL(ms)Local testing
docker-compose.metrics.ymlwith:/metricsor Collector)Collector example
example collector.yamldemonstrating:site_id,resource_id)Documentation
observability.md:Testing & validation
/metrics, verify metrics names, units, labels and histogram buckets./metricsoutput in the PR.References & Best Practices
Practical walkthroughs & blog posts
@miloschwartz commented on GitHub (Sep 27, 2025):
Thanks, converting this to a discussion thread so others can upvote and participate!