-
Notifications
You must be signed in to change notification settings - Fork 9
feat: OpenTelemetry logs, metrics, and tracing #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tim-hm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is excellent 🙌
tim-hm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Add OpenTelemetry packages to production dependencies and configure external bundling. This enables automatic instrumentation for metrics, traces, and logs with dual export modes (OTLP push and Prometheus scrape).
Add OTEL_METRICS_EXPORT_INTERVAL_MS environment variable to control how frequently metrics are exported. Defaults to 60000ms (1 minute), can be set lower for local testing.
Add OpenTelemetry Collector with debug exporter for local testing. Replace Jaeger with simpler debug-to-stdout approach. Configure faster metrics export interval (10s) for local development.
Add Proxy-based bridge that emits Pino logs to both stdout and OpenTelemetry LoggerProvider when otel feature flag is enabled. Maintains backward compatibility with stdout-only logging.
Add initializeMetricsOnly() for metrics-only mode (PrometheusExporter serves /metrics endpoint) and initializeOtel() for full mode (OTLP push only). Both use OpenTelemetry APIs with automatic HTTP instrumentation, providing DRY metric definitions. - metrics flag: serves metrics on :9091/metrics for scraping - otel flag: pushes metrics/traces/logs to OTLP, no /metrics endpoint
Remove getMetrics() function and metrics server logic. Metrics are now handled entirely by OpenTelemetry providers (PrometheusExporter for scraping or OTLP for push), not Hono routers.
Automatic trace instrumentation via @opentelemetry/auto-instrumentations-node handles HTTP request tracing and metrics.
Update main.ts to initialize correct observability mode based on feature flags: - metrics flag only: initializeMetricsOnly() for Prometheus scraping - otel flag: initializeOtel() for full OTLP push (metrics/traces/logs) Add proper shutdown handlers for both modes.
Document new metrics/otel feature flag behavior, remove Jaeger references, add OTEL_METRICS_EXPORT_INTERVAL_MS configuration, and clarify when /metrics endpoint is available.
Create build-deps target that builds workspace dependencies and make check, test, and build targets depend on it. These workspace packages must be built before type checking and testing can succeed
Replaces ATTR_DEPLOYMENT_ENVIRONMENT with ATTR_DEPLOYMENT_ENVIRONMENT_NAME to align with current OpenTelemetry semantic conventions. The deprecated attribute set 'deployment.environment', while the new one correctly sets 'deployment.environment.name'.
Replace custom shouldEmitTelemetry() function with standard OpenTelemetry OTEL_SDK_DISABLED environment variable. This provides better separation of concerns: deployment environment name is now purely a resource attribute, while OTEL_SDK_DISABLED controls emission.
The 'metrics' and 'otel' feature flags are now mutually exclusive. The server will exit with a clear error message if both are enabled, preventing misconfiguration and forcing explicit choice of observability mode.
Replace String(value) with JSON.stringify(value) for complex objects in the Pino-to-OTel logger bridge to prevent "[object Object]" in logs. Added try-catch to gracefully handle circular references by falling back to String(value).
HTTP request logs were inconsistent with the rest of the codebase,
passing only attributes without a message string. This resulted in
empty OTLP body fields. All other logs use the standard Pino pattern
of log.method({ attrs }, "message"). Now HTTP logs follow the same
pattern with messages like "GET /health 200".
…figuration - Add envDetector and processDetector to merge resource attributes from environment - Make createOtelResource, initializeOtel, and initializeMetricsOnly async to support detection - Update main.ts to await async OpenTelemetry initialization functions - Document OTEL_RESOURCE_ATTRIBUTES usage and precedence rules Enables dynamic resource attribute configuration per OpenTelemetry standards: OTEL_RESOURCE_ATTRIBUTES=service.instance.id=nildb-r5nw Environment variables take precedence over programmatically set values, allowing deployment-specific attributes to override defaults without code changes.
Integrate @opentelemetry/instrumentation-runtime-node and @opentelemetry/host-metrics to provide comprehensive metrics for: - Node.js runtime metrics (heap usage, RSS, GC, event loop lag) - System metrics (CPU, memory, network) Both metrics-only and full OTEL modes now include these metrics, enabling better visibility into Node.js performance and resource usage.
Replace auto-instrumentation HTTP metrics with custom Hono middleware that records http.server.duration with http.route attribute for endpoint-level observability. - Add metrics.middleware.ts with semantic conventions v1.28.0 - Disable @opentelemetry/instrumentation-http to prevent double counting - Integrate middleware early in stack for complete request coverage
tim-hm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work 🙌
Summary
Implements unified observability using OpenTelemetry with two modes:
metricsflag: Serves metrics on:9091/metricsfor Prometheus scrapingotelflag: Pushes metrics, traces, and logs to OTLP endpointKey Changes
@hono/prometheuswith OpenTelemetry for single canonical metric definitions across both modes. NOTE: Metrics format changes (metric names, labels follow OpenTelemetry semantic conventions)otelenabledConfiguration
New environment variables (all optional):
OTEL_ENDPOINT- OTLP endpoint URL (default:http://localhost)OTEL_SERVICE_NAME- Service name (default:nildb)OTEL_TEAM_NAME- Team name (default:nildb)OTEL_DEPLOYMENT_ENV- Environment (default:local)OTEL_METRICS_EXPORT_INTERVAL_MS- Export interval in ms (default:60000)Local Testing
The local stack now includes an OTel Collector with debug exporter: