@platform-x/hep-observability
v1.0.2
Published
Platform-X shared OpenTelemetry metrics instrumentation for Node services (HTTP RED, GraphQL, dependency USE, runtime).
Keywords
Readme
@platform-x/hep-observability
Shared OpenTelemetry metrics instrumentation for the Platform-X Node fleet — HTTP RED, GraphQL operation labeling, dependency (USE) metrics, and Node runtime metrics — exported via OTLP to the OpenTelemetry Collector (→ Prometheus/Mimir → Grafana).
Install
npm install @platform-x/hep-observabilityPeer deps: @opentelemetry/api (required), express (optional, for the middleware).
Adopt in a service (~15 lines)
// src/server.ts — top, right AFTER the existing elastic-apm-node .start({...}) block
import { initTelemetry } from '@platform-x/hep-observability';
initTelemetry(); // reads OTEL_SERVICE_NAME / OTEL_EXPORTER_OTLP_ENDPOINT / NODE_ENV// where the Express app is built — mount FIRST, before auth/cache middleware
import { httpMetricsMiddleware, makeAllowlist } from '@platform-x/hep-observability';
app.use(httpMetricsMiddleware({
graphqlPath: '/v1/publish/gateway', // omit for pure-REST services
knownSites: makeAllowlist(KNOWN_TENANTS), // bound sitename cardinality
}));// where ApolloServer is constructed (GraphQL services)
import { apolloMetricsPlugin, makeAllowlist } from '@platform-x/hep-observability';
new ApolloServer({
/* ... */
plugins: [ /* ...existing */ apolloMetricsPlugin({ knownOperations: makeAllowlist(ROOT_FIELDS) }) ],
});// wrap DAO/driver calls at the data-access layer
import { instrumentDependency, registerPoolGauge } from '@platform-x/hep-observability';
await instrumentDependency('mongo', 'roles.findOne', () => Roles.findOne(filter));
registerPoolGauge('mongo', () => ({ in_use: pool.used, idle: pool.available, waiting: pool.pending }));// service-specific business metrics build on the shared meter
import { getMeter } from '@platform-x/hep-observability';
const authAttempts = getMeter().createCounter('gateway_auth_attempts');Kubernetes env
env:
- { name: OTEL_SERVICE_NAME, value: "cx-delivery-gateway" } # the fleet `service` dimension
- { name: OTEL_EXPORTER_OTLP_ENDPOINT, value: "http://otel-collector.monitoring:4317" }Metrics emitted
| Metric | Type | Key labels |
|---|---|---|
| platx_http_requests_total | counter | service, transport, method, route, operation, status_code, sitename |
| platx_http_request_duration_seconds | histogram | service, transport, route, operation, sitename |
| platx_http_inflight_requests | up-down counter | service, sitename |
| platx_http_errors_total | counter | service, route, operation, type, sitename |
| platx_graphql_resolution_total | counter | service, operation, field, outcome |
| platx_dependency_request_duration_seconds | histogram | service, dependency, operation, outcome |
| platx_dependency_pool_connections | gauge | service, dependency, state |
| nodejs_* / v8js_* (runtime) | — | service |
* service comes from the service.name resource attribute (OTEL_SERVICE_NAME), attached by the
Collector — not a per-instrument label. Counter _total / histogram unit suffixes are added by the
Prometheus-format exporter (so name instruments without them).
Scripts
npm run build # rimraf dist && tsc → dist/
npm test # jest
npm run lint # eslintPublishing
Set NPM_TOKEN in your environment / CI, then npm publish. .npmrc reads the token from that env var
— never commit a token.
