Package Exports
- @vtex/diagnostics-nodejs
- @vtex/diagnostics-nodejs/dist/config/index.d.ts
- @vtex/diagnostics-nodejs/dist/config/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/config/index.js
- @vtex/diagnostics-nodejs/dist/config/index.js.map
- @vtex/diagnostics-nodejs/dist/config/manager.d.ts
- @vtex/diagnostics-nodejs/dist/config/manager.d.ts.map
- @vtex/diagnostics-nodejs/dist/config/manager.js
- @vtex/diagnostics-nodejs/dist/config/manager.js.map
- @vtex/diagnostics-nodejs/dist/config/providers/file.d.ts
- @vtex/diagnostics-nodejs/dist/config/providers/file.d.ts.map
- @vtex/diagnostics-nodejs/dist/config/providers/file.js
- @vtex/diagnostics-nodejs/dist/config/providers/file.js.map
- @vtex/diagnostics-nodejs/dist/config/providers/s3.d.ts
- @vtex/diagnostics-nodejs/dist/config/providers/s3.d.ts.map
- @vtex/diagnostics-nodejs/dist/config/providers/s3.js
- @vtex/diagnostics-nodejs/dist/config/providers/s3.js.map
- @vtex/diagnostics-nodejs/dist/discovery/index.d.ts
- @vtex/diagnostics-nodejs/dist/discovery/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/discovery/index.js
- @vtex/diagnostics-nodejs/dist/discovery/index.js.map
- @vtex/diagnostics-nodejs/dist/discovery/resource-discovery.d.ts
- @vtex/diagnostics-nodejs/dist/discovery/resource-discovery.d.ts.map
- @vtex/diagnostics-nodejs/dist/discovery/resource-discovery.js
- @vtex/diagnostics-nodejs/dist/discovery/resource-discovery.js.map
- @vtex/diagnostics-nodejs/dist/exporters/index.d.ts
- @vtex/diagnostics-nodejs/dist/exporters/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/exporters/index.js
- @vtex/diagnostics-nodejs/dist/exporters/index.js.map
- @vtex/diagnostics-nodejs/dist/exporters/interface.d.ts
- @vtex/diagnostics-nodejs/dist/exporters/interface.d.ts.map
- @vtex/diagnostics-nodejs/dist/exporters/interface.js
- @vtex/diagnostics-nodejs/dist/exporters/interface.js.map
- @vtex/diagnostics-nodejs/dist/exporters/otlp.d.ts
- @vtex/diagnostics-nodejs/dist/exporters/otlp.d.ts.map
- @vtex/diagnostics-nodejs/dist/exporters/otlp.js
- @vtex/diagnostics-nodejs/dist/exporters/otlp.js.map
- @vtex/diagnostics-nodejs/dist/exporters/stdout.d.ts
- @vtex/diagnostics-nodejs/dist/exporters/stdout.d.ts.map
- @vtex/diagnostics-nodejs/dist/exporters/stdout.js
- @vtex/diagnostics-nodejs/dist/exporters/stdout.js.map
- @vtex/diagnostics-nodejs/dist/index.d.ts
- @vtex/diagnostics-nodejs/dist/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/index.js
- @vtex/diagnostics-nodejs/dist/index.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/index.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/index.js
- @vtex/diagnostics-nodejs/dist/instrumentation/index.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/core.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/core.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/core.js
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/core.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/express.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/express.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/express.js
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/express.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/fastify.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/fastify.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/fastify.js
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/fastify.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/index.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/index.js
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/index.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/koa.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/koa.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/koa.js
- @vtex/diagnostics-nodejs/dist/instrumentation/middlewares/koa.js.map
- @vtex/diagnostics-nodejs/dist/instrumentation/propagation/index.d.ts
- @vtex/diagnostics-nodejs/dist/instrumentation/propagation/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/instrumentation/propagation/index.js
- @vtex/diagnostics-nodejs/dist/instrumentation/propagation/index.js.map
- @vtex/diagnostics-nodejs/dist/logs/client.d.ts
- @vtex/diagnostics-nodejs/dist/logs/client.d.ts.map
- @vtex/diagnostics-nodejs/dist/logs/client.js
- @vtex/diagnostics-nodejs/dist/logs/client.js.map
- @vtex/diagnostics-nodejs/dist/logs/index.d.ts
- @vtex/diagnostics-nodejs/dist/logs/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/logs/index.js
- @vtex/diagnostics-nodejs/dist/logs/index.js.map
- @vtex/diagnostics-nodejs/dist/metrics/client.d.ts
- @vtex/diagnostics-nodejs/dist/metrics/client.d.ts.map
- @vtex/diagnostics-nodejs/dist/metrics/client.js
- @vtex/diagnostics-nodejs/dist/metrics/client.js.map
- @vtex/diagnostics-nodejs/dist/metrics/counter.d.ts
- @vtex/diagnostics-nodejs/dist/metrics/counter.d.ts.map
- @vtex/diagnostics-nodejs/dist/metrics/counter.js
- @vtex/diagnostics-nodejs/dist/metrics/counter.js.map
- @vtex/diagnostics-nodejs/dist/metrics/gauge.d.ts
- @vtex/diagnostics-nodejs/dist/metrics/gauge.d.ts.map
- @vtex/diagnostics-nodejs/dist/metrics/gauge.js
- @vtex/diagnostics-nodejs/dist/metrics/gauge.js.map
- @vtex/diagnostics-nodejs/dist/metrics/histogram.d.ts
- @vtex/diagnostics-nodejs/dist/metrics/histogram.d.ts.map
- @vtex/diagnostics-nodejs/dist/metrics/histogram.js
- @vtex/diagnostics-nodejs/dist/metrics/histogram.js.map
- @vtex/diagnostics-nodejs/dist/metrics/index.d.ts
- @vtex/diagnostics-nodejs/dist/metrics/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/metrics/index.js
- @vtex/diagnostics-nodejs/dist/metrics/index.js.map
- @vtex/diagnostics-nodejs/dist/metrics/options.d.ts
- @vtex/diagnostics-nodejs/dist/metrics/options.d.ts.map
- @vtex/diagnostics-nodejs/dist/metrics/options.js
- @vtex/diagnostics-nodejs/dist/metrics/options.js.map
- @vtex/diagnostics-nodejs/dist/processors/index.d.ts
- @vtex/diagnostics-nodejs/dist/processors/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/processors/index.js
- @vtex/diagnostics-nodejs/dist/processors/index.js.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/constants.d.ts
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/constants.d.ts.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/constants.js
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/constants.js.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/index.d.ts
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/index.js
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/index.js.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/log-processor.d.ts
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/log-processor.d.ts.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/log-processor.js
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/log-processor.js.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/span-processor.d.ts
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/span-processor.d.ts.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/span-processor.js
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/span-processor.js.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/utils.d.ts
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/utils.d.ts.map
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/utils.js
- @vtex/diagnostics-nodejs/dist/processors/vtexattrs/utils.js.map
- @vtex/diagnostics-nodejs/dist/providers/account/configurable.d.ts
- @vtex/diagnostics-nodejs/dist/providers/account/configurable.d.ts.map
- @vtex/diagnostics-nodejs/dist/providers/account/configurable.js
- @vtex/diagnostics-nodejs/dist/providers/account/configurable.js.map
- @vtex/diagnostics-nodejs/dist/providers/account/file-source.d.ts
- @vtex/diagnostics-nodejs/dist/providers/account/file-source.d.ts.map
- @vtex/diagnostics-nodejs/dist/providers/account/file-source.js
- @vtex/diagnostics-nodejs/dist/providers/account/file-source.js.map
- @vtex/diagnostics-nodejs/dist/providers/account/index.d.ts
- @vtex/diagnostics-nodejs/dist/providers/account/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/providers/account/index.js
- @vtex/diagnostics-nodejs/dist/providers/account/index.js.map
- @vtex/diagnostics-nodejs/dist/providers/account/provider.d.ts
- @vtex/diagnostics-nodejs/dist/providers/account/provider.d.ts.map
- @vtex/diagnostics-nodejs/dist/providers/account/provider.js
- @vtex/diagnostics-nodejs/dist/providers/account/provider.js.map
- @vtex/diagnostics-nodejs/dist/providers/account/static.d.ts
- @vtex/diagnostics-nodejs/dist/providers/account/static.d.ts.map
- @vtex/diagnostics-nodejs/dist/providers/account/static.js
- @vtex/diagnostics-nodejs/dist/providers/account/static.js.map
- @vtex/diagnostics-nodejs/dist/providers/index.d.ts
- @vtex/diagnostics-nodejs/dist/providers/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/providers/index.js
- @vtex/diagnostics-nodejs/dist/providers/index.js.map
- @vtex/diagnostics-nodejs/dist/samplers/index.d.ts
- @vtex/diagnostics-nodejs/dist/samplers/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/samplers/index.js
- @vtex/diagnostics-nodejs/dist/samplers/index.js.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/composed.d.ts
- @vtex/diagnostics-nodejs/dist/samplers/traces/composed.d.ts.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/composed.js
- @vtex/diagnostics-nodejs/dist/samplers/traces/composed.js.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/configurable.d.ts
- @vtex/diagnostics-nodejs/dist/samplers/traces/configurable.d.ts.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/configurable.js
- @vtex/diagnostics-nodejs/dist/samplers/traces/configurable.js.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/debug.d.ts
- @vtex/diagnostics-nodejs/dist/samplers/traces/debug.d.ts.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/debug.js
- @vtex/diagnostics-nodejs/dist/samplers/traces/debug.js.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/index.d.ts
- @vtex/diagnostics-nodejs/dist/samplers/traces/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/index.js
- @vtex/diagnostics-nodejs/dist/samplers/traces/index.js.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/metadata.d.ts
- @vtex/diagnostics-nodejs/dist/samplers/traces/metadata.d.ts.map
- @vtex/diagnostics-nodejs/dist/samplers/traces/metadata.js
- @vtex/diagnostics-nodejs/dist/samplers/traces/metadata.js.map
- @vtex/diagnostics-nodejs/dist/telemetry/client.d.ts
- @vtex/diagnostics-nodejs/dist/telemetry/client.d.ts.map
- @vtex/diagnostics-nodejs/dist/telemetry/client.js
- @vtex/diagnostics-nodejs/dist/telemetry/client.js.map
- @vtex/diagnostics-nodejs/dist/telemetry/index.d.ts
- @vtex/diagnostics-nodejs/dist/telemetry/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/telemetry/index.js
- @vtex/diagnostics-nodejs/dist/telemetry/index.js.map
- @vtex/diagnostics-nodejs/dist/traces/baggage.d.ts
- @vtex/diagnostics-nodejs/dist/traces/baggage.d.ts.map
- @vtex/diagnostics-nodejs/dist/traces/baggage.js
- @vtex/diagnostics-nodejs/dist/traces/baggage.js.map
- @vtex/diagnostics-nodejs/dist/traces/client.d.ts
- @vtex/diagnostics-nodejs/dist/traces/client.d.ts.map
- @vtex/diagnostics-nodejs/dist/traces/client.js
- @vtex/diagnostics-nodejs/dist/traces/client.js.map
- @vtex/diagnostics-nodejs/dist/traces/config.d.ts
- @vtex/diagnostics-nodejs/dist/traces/config.d.ts.map
- @vtex/diagnostics-nodejs/dist/traces/config.js
- @vtex/diagnostics-nodejs/dist/traces/config.js.map
- @vtex/diagnostics-nodejs/dist/traces/index.d.ts
- @vtex/diagnostics-nodejs/dist/traces/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/traces/index.js
- @vtex/diagnostics-nodejs/dist/traces/index.js.map
- @vtex/diagnostics-nodejs/dist/traces/span.d.ts
- @vtex/diagnostics-nodejs/dist/traces/span.d.ts.map
- @vtex/diagnostics-nodejs/dist/traces/span.js
- @vtex/diagnostics-nodejs/dist/traces/span.js.map
- @vtex/diagnostics-nodejs/dist/traces/tracer.d.ts
- @vtex/diagnostics-nodejs/dist/traces/tracer.d.ts.map
- @vtex/diagnostics-nodejs/dist/traces/tracer.js
- @vtex/diagnostics-nodejs/dist/traces/tracer.js.map
- @vtex/diagnostics-nodejs/dist/types/config.d.ts
- @vtex/diagnostics-nodejs/dist/types/config.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/config.js
- @vtex/diagnostics-nodejs/dist/types/config.js.map
- @vtex/diagnostics-nodejs/dist/types/exporters.d.ts
- @vtex/diagnostics-nodejs/dist/types/exporters.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/exporters.js
- @vtex/diagnostics-nodejs/dist/types/exporters.js.map
- @vtex/diagnostics-nodejs/dist/types/index.d.ts
- @vtex/diagnostics-nodejs/dist/types/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/index.js
- @vtex/diagnostics-nodejs/dist/types/index.js.map
- @vtex/diagnostics-nodejs/dist/types/logs.d.ts
- @vtex/diagnostics-nodejs/dist/types/logs.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/logs.js
- @vtex/diagnostics-nodejs/dist/types/logs.js.map
- @vtex/diagnostics-nodejs/dist/types/metrics.d.ts
- @vtex/diagnostics-nodejs/dist/types/metrics.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/metrics.js
- @vtex/diagnostics-nodejs/dist/types/metrics.js.map
- @vtex/diagnostics-nodejs/dist/types/sampling.d.ts
- @vtex/diagnostics-nodejs/dist/types/sampling.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/sampling.js
- @vtex/diagnostics-nodejs/dist/types/sampling.js.map
- @vtex/diagnostics-nodejs/dist/types/telemetry.d.ts
- @vtex/diagnostics-nodejs/dist/types/telemetry.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/telemetry.js
- @vtex/diagnostics-nodejs/dist/types/telemetry.js.map
- @vtex/diagnostics-nodejs/dist/types/traces.d.ts
- @vtex/diagnostics-nodejs/dist/types/traces.d.ts.map
- @vtex/diagnostics-nodejs/dist/types/traces.js
- @vtex/diagnostics-nodejs/dist/types/traces.js.map
- @vtex/diagnostics-nodejs/dist/utils/index.d.ts
- @vtex/diagnostics-nodejs/dist/utils/index.d.ts.map
- @vtex/diagnostics-nodejs/dist/utils/index.js
- @vtex/diagnostics-nodejs/dist/utils/index.js.map
- @vtex/diagnostics-nodejs/dist/utils/utils.d.ts
- @vtex/diagnostics-nodejs/dist/utils/utils.d.ts.map
- @vtex/diagnostics-nodejs/dist/utils/utils.js
- @vtex/diagnostics-nodejs/dist/utils/utils.js.map
Readme
OpenTelemetry Diagnostics Library for Node.js
A comprehensive Node.js library that simplifies telemetry collection using OpenTelemetry, providing unified interfaces for metrics, logs, and traces with advanced sampling, hot-reload configuration, and easy-to-use instrumentation setups for popular frameworks.
Features
✅ Unified Telemetry: Metrics, logs, and traces in one library
✅ Auto-Instrumentation: Express, Fastify, Koa, NestJS support
✅ Advanced Sampling: Rule-based, parent-based, debug override, hot-reload
✅ Remote Configuration: File-based, S3, with live reload and polling
✅ Configuration Override: Runtime config updates and hot-swapping
✅ Resource Discovery: Automatic cloud and Kubernetes detection
✅ Context Propagation: Baggage and trace context across services
✅ Custom Processors: VTEX-specific attribute enrichment
✅ Distributed Resampling: Override parent sampling decisions
✅ gRPC Export: High-performance OTLP export
Installation
npm install @vtex/diagnostics-nodejsQuick Start
import { NewTelemetryClient, Instrumentation } from '@vtex/diagnostics-nodejs';
async function main() {
// 1. Define your instrumentations
const instrumentations = Instrumentation.CommonInstrumentations.express();
// 2. Initialize telemetry client BEFORE importing frameworks
const telemetryClient = await NewTelemetryClient(
'my-app-id', // Application ID
'my-client-instance', // Client instance name
'my-service-name' // Service name
);
// 3. Create telemetry clients
const tracesClient = await telemetryClient.newTracesClient({
setGlobalProvider: true,
});
const metricsClient = await telemetryClient.newMetricsClient();
const logsClient = await telemetryClient.newLogsClient();
// 4. Register the instrumentations. This activates them.
telemetryClient.registerInstrumentations(instrumentations);
// 5. NOW import your frameworks
const express = require('express');
const app = express();
// Your app is automatically instrumented!
app.get('/api/users', (req, res) => {
logsClient.info('Users endpoint called', { userId: req.query.id });
res.json({ users: [] });
});
app.listen(3000);
}
main().catch(console.error);Remote Configuration Management
File-Based Configuration with Hot Reload
const telemetryClient = await NewTelemetryClient(
'my-app-id',
'my-client',
'my-service',
{
config: {
configPath: './config/telemetry.json',
enableHotReload: true, // Enable live reload
pollIntervalMs: 15000 // Check for changes every 15s
}
}
);
// Config changes are automatically applied without restart!
// Watch logs for: "🔄 Hot reloading sampling configuration..."S3-Based Remote Configuration
const telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
config: {
s3Config: {
bucket: 'my-telemetry-configs',
key: 'environments/prod/my-service.json',
region: 'us-east-1'
},
pollIntervalMs: 30000, // Poll S3 every 30s
enableHotReload: true
}
}
);
// Centralized config management:
// 1. Update config in S3
// 2. All instances pick up changes automatically
// 3. No service restarts requiredConfiguration Override at Runtime
// The ConfigManager is an internal component and not exposed via a public `getConfigManager()` method.
// Configuration updates are handled automatically via file/S3 polling when `enableHotReload` is true.
// The `onConfigChange` functionality would require implementing a custom configuration provider.
console.log('Configuration from file/S3 will be hot-reloaded automatically if enabled.');Environment-Specific Configuration
// Base configuration
const telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
config: {
configPath: `./config/${process.env.NODE_ENV || 'development'}.json`,
enableHotReload: process.env.NODE_ENV !== 'production'
},
// Override config based on environment
environment: process.env.DEPLOYMENT_ENV,
region: process.env.AWS_REGION,
// Additional runtime attributes
additionalAttrs: {
'deployment.version': process.env.GIT_SHA,
'deployment.timestamp': new Date().toISOString()
}
}
);Using Configuration Files
const telemetryClient = await NewTelemetryClient(
'my-app',
'my-client',
'my-service',
{
config: {
configPath: './config/telemetry.json',
enableHotReload: true,
pollIntervalMs: 15000
}
}
);Configuration Override Examples
// Development: High sampling for debugging
// config/development.json
{
"traces": {
"sampling": {
"defaultRate": 1.0,
"rules": [
{
"name": "debug_everything",
"sampleRate": 1.0,
"conditions": []
}
]
}
}
}
```json
// Production: Selective sampling
// config/production.json
{
"traces": {
"sampling": {
"defaultRate": 0.01,
"rules": [
{
"name": "critical_endpoints",
"sampleRate": 1.0,
"conditions": [
{
"attribute": "http.target",
"operator": "Regex",
"value": "^/api/(checkout|payment|auth)"
}
]
},
{
"name": "error_traces",
"sampleRate": 1.0,
"conditions": [
{
"attribute": "http.status_code",
"operator": "GreaterThanEqual",
"value": "400"
}
]
}
]
}
}
}Live Configuration Updates
// Monitor configuration changes in real-time
const telemetryClient = await NewTelemetryClient('app', 'client', 'service', {
config: { enableHotReload: true }
});
// Define instrumentations
const instrumentations = Instrumentation.CommonInstrumentations.autoDetect();
// Initialize clients
const tracesClient = await telemetryClient.newTracesClient();
// Register instrumentations
telemetryClient.registerInstrumentations(instrumentations);
// Example: Change sampling rules via file edit
// 1. Edit config/telemetry.json
// 2. Change defaultRate from 0.1 to 0.5
// 3. Save file
// 4. Library automatically detects change
// 5. New sampling rules applied within seconds
// 6. See logs: "🔄 Hot reloading sampling configuration..."
console.log('Config will auto-reload from file changes...');Conditional Configuration Loading
async function createTelemetryClient() {
const isProd = process.env.NODE_ENV === 'production';
const isK8s = !!process.env.KUBERNETES_SERVICE_HOST;
const config = {
config: {
// Production: Use S3 remote config
...(isProd && {
s3Config: {
bucket: 'prod-telemetry-configs',
key: `services/${process.env.SERVICE_NAME}/config.json`,
region: process.env.AWS_REGION
}
}),
// Development: Use local file
...(!isProd && {
configPath: './config/dev.json'
}),
enableHotReload: true,
pollIntervalMs: isProd ? 60000 : 15000 // Slower polling in prod
},
// Kubernetes-specific attributes
...(isK8s && {
additionalAttrs: {
'k8s.namespace': process.env.KUBERNETES_NAMESPACE,
'k8s.pod': process.env.HOSTNAME,
'k8s.node': process.env.NODE_NAME
}
}),
disableCloudDetect: !isProd,
debug: !isProd
};
return await NewTelemetryClient('app', 'client', 'service', config);
}Global vs Service-Specific Configuration
// Hierarchical configuration override
const baseConfig = {
"globalResourceAttributes": {
"service.namespace": "ecommerce",
"deployment.environment": "production"
},
"traces": {
"exporters": {
"mode": "otlp",
"otlp": { "endpoint": "otel-collector:4317" }
},
"sampling": {
"parentBased": true,
"defaultRate": 0.05
}
}
};
```json
// Service-specific overrides
const serviceOverrides = {
"user-service": {
"traces": {
"sampling": {
"defaultRate": 0.1,
"rules": [
{
"name": "auth_endpoints",
"sampleRate": 1.0,
"conditions": [
{ "attribute": "http.target", "operator": "StartsWith", "value": "/auth" }
]
}
]
}
}
},
"payment-service": {
"traces": {
"sampling": {
"defaultRate": 1.0,
"parentBased": false
}
}
},
"inventory-service": {
"traces": {
"sampling": {
"parentBased": false,
"defaultRate": 0.01,
"rules": [
{
"name": "resample_checkout_flow",
"sampleRate": 1.0,
"conditions": [
{ "attribute": "http.target", "operator": "Contains", "value": "checkout" }
]
}
]
}
}
}
};
```json
{
"environment": "production",
"globalResourceAttributes": {
"service.namespace": "ecommerce",
"deployment.environment": "prod"
},
"traces": {
"exporters": {
"mode": "otlp",
"otlp": { "endpoint": "otel-collector:4317" }
},
"sampling": {
"parentBased": true,
"defaultRate": 0.1,
"rules": [
{
"name": "sample_critical_endpoints",
"sampleRate": 1.0,
"conditions": [
{
"attribute": "http.target",
"operator": "StartsWith",
"value": "/api/checkout"
}
]
},
{
"name": "debug_override",
"sampleRate": 1.0,
"conditions": [
{
"attribute": "debug",
"operator": "Equals",
"value": "true"
}
]
}
]
}
}
}Advanced Sampling
Rule-Based Sampling
Control sampling with flexible rules that support hot-reload:
// Configuration supports multiple operators and conditions
{
"sampling": {
"parentBased": true,
"defaultRate": 0.05,
"rules": [
{
"name": "high_priority_routes",
"sampleRate": 1.0,
"conditions": [
{
"attribute": "http.method",
"operator": "Equals",
"value": "POST"
},
{
"attribute": "http.target",
"operator": "Regex",
"value": "^/api/(orders|payments)"
}
]
}
]
}
}Resampling in Distributed Traces
Override parent sampling decisions in specific services:
// Service A: parentBased: true (follows upstream decisions)
// Service B: parentBased: false (makes independent decisions)
{
"sampling": {
"parentBased": false,
"rules": [
{
"name": "force_sample_inventory_operations",
"sampleRate": 1.0,
"conditions": [...]
}
]
}
}Debug Sampling
Force sampling with debug flags:
# Always samples when debug is present
curl "http://api/users?debug=true"
curl -H "debug: true" http://api/usersSupported Sampling Operators
Equals,NotEqualsContains,StartsWith,EndsWithIn,NotIn(arrays)RegexGreaterThan,LessThan,GreaterThanEqual,LessThanEqual
Instrumentation
Framework Support
// Choose your framework bundle
const instrumentations = {
express: Instrumentation.CommonInstrumentations.express(),
fastify: Instrumentation.CommonInstrumentations.fastify(),
koa: Instrumentation.CommonInstrumentations.koa(),
nestjs: Instrumentation.CommonInstrumentations.nestjs(),
minimal: Instrumentation.CommonInstrumentations.minimal(), // HTTP only
autoDetect: Instrumentation.CommonInstrumentations.autoDetect()
};Adding Database & External Service Tracing
import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb';
import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';
import { NewTelemetryClient, Instrumentation } from '@vtex/diagnostics-nodejs';
async function setup() {
// 1. Create a list of all desired instrumentations
const myInstrumentations = [
...Instrumentation.CommonInstrumentations.express(),
new MongoDBInstrumentation(),
new RedisInstrumentation(),
// Add any other OpenTelemetry community instrumentation
];
// 2. Initialize the client
const telemetryClient = await NewTelemetryClient('app-id', 'client-name', 'service-name');
await telemetryClient.newTracesClient(); // and other clients
// 3. Register all instrumentations
telemetryClient.registerInstrumentations(myInstrumentations);
}Context Propagation & Baggage
Adding Baggage
import { Traces } from '@vtex/diagnostics-nodejs';
app.get('/api/users', (req, res) => {
// Add baggage items that propagate to downstream services
Traces.addBaggage({
'user.id': req.user.id,
'request.priority': 'high',
'trace.source': 'web-app'
});
// Single baggage item
Traces.setBaggage('operation.type', 'user-lookup');
// Retrieve baggage
const baggage = Traces.getActiveBaggage();
console.log('Current baggage:', baggage);
});Middleware for Context Propagation
import { Instrumentation } from '@vtex/diagnostics-nodejs';
// Express
app.use(Instrumentation.Middlewares.ContextMiddlewares.Express.ContextPropagationMiddleware());
// Fastify
fastify.register(Instrumentation.Middlewares.ContextMiddlewares.Fastify.createContextPlugin());
// Koa
app.use(Instrumentation.Middlewares.ContextMiddlewares.Koa.ContextPropagationMiddleware());Manual Tracing
Creating Custom Spans
const span = tracesClient.startSpan('database-migration', {
attributes: { 'migration.version': '1.2.0' },
kind: SpanKind.INTERNAL
});
try {
span.setAttributes({
'migration.tables': ['users', 'orders'],
'migration.duration_estimate': '5min'
});
span.addEvent('migration-started', { timestamp: Date.now() });
// Your operation
await runMigration();
span.addEvent('migration-completed');
} catch (error) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
throw error;
} finally {
span.end();
}Trace Context Injection/Extraction
// Inject trace context into HTTP headers
const headers = {};
tracesClient.inject(headers);
console.log(headers); // { traceparent: "00-...", tracestate: "..." }
// Extract trace context from incoming headers
const context = tracesClient.extract(req.headers);
context.execute(() => {
// Code executed within the extracted trace context
logsClient.info('Processing with extracted context');
});Metrics
Counter Metrics
import { Metrics } from '@vtex/diagnostics-nodejs';
const httpRequestsCounter = metricsClient.createCounter(
'http_requests_total',
{
description: 'Total HTTP requests processed',
unit: '1'
}
);
// Increment counter
httpRequestsCounter.increment({ method: 'GET', status: '200' });
httpRequestsCounter.add(5, { method: 'POST', status: '201' });Histogram Metrics
const responseTimeHistogram = metricsClient.createHistogram(
'http_response_time_seconds',
{
description: 'HTTP response time distribution',
unit: 's',
boundaries: [0.01, 0.05, 0.1, 0.5, 1, 5, 10]
}
);
responseTimeHistogram.record(0.145, { route: '/api/users', method: 'GET' });Gauge Metrics
const activeConnectionsGauge = metricsClient.createGauge(
'active_connections',
{ description: 'Current active database connections' }
);
activeConnectionsGauge.set(42);
activeConnectionsGauge.add(5); // Increment by 5
activeConnectionsGauge.subtract(2); // Decrement by 2Structured Logging
Log Levels & Attributes
// Structured logging with attributes
logsClient.info('User login successful', {
'user.id': '12345',
'login.method': 'oauth',
'client.ip': req.ip,
'vtex.search_index': 'user_events' // Custom attributes
});
logsClient.warn('Rate limit approaching', {
'rate_limit.current': 95,
'rate_limit.max': 100,
'time_window': '1min'
});
logsClient.error('Database query failed', {
'query.table': 'users',
'query.duration_ms': 5000,
'error.type': 'timeout'
});Log Correlation with Traces
Logs automatically include trace context when created within an active span:
const span = tracesClient.startSpan('process-order');
// Logs will automatically include trace and span IDs
logsClient.info('Processing order', { orderId: '12345' });
span.end();Resource Discovery
Automatic Attribute Detection
const telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
// Environment variable mappings
envMappings: [
{ envVar: 'REGION', attributeName: 'cloud.region' },
{ envVar: 'VERSION', attributeName: 'service.version' }
],
// Additional static attributes
additionalAttrs: {
'service.team': 'platform',
'service.tier': 'critical'
},
// Cloud detection
disableCloudDetect: false, // Auto-detect AWS/GCP/Azure
disableK8sDetect: false, // Auto-detect Kubernetes
// Environment and region
environment: 'production',
region: 'us-east-1'
}
);Custom Attributes from Files
// Read attributes from JSON file
{
"customAttributesFile": "./custom-attributes.json"
}
```json
// custom-attributes.json
{
"environmentVariables": {
"POD_NAME": "k8s.pod.name",
"NODE_NAME": "k8s.node.name"
},
"attributes": {
"service.owner": "platform-team",
"cost.center": "engineering"
}
}Export Configuration
OTLP gRPC Export
// Local development (insecure)
const tracesClient = await telemetryClient.newTracesClient({
exporter: CreateExporter(
CreateTracesExporterConfig({
endpoint: 'localhost:4317',
compression: 'gzip',
timeoutSeconds: 30
}),
'otlp'
)
});
```javascript
// Production (secure)
const tracesClient = await telemetryClient.newTracesClient({
exporter: CreateExporter(
CreateTracesExporterConfig({
endpoint: 'otel-collector.company.com:443',
compression: 'gzip',
insecure: false
}),
'otlp'
)
});Console Export (Development)
const tracesClient = await telemetryClient.newTracesClient({
exporter: CreateExporter(
CreateTracesExporterConfig({ endpoint: 'stdout' }),
'stdout'
)
});Advanced Configuration
Configuration Providers
// File Provider (local development)
import { ConfigManager, FileConfigProvider } from '@vtex/diagnostics-nodejs';
const configManager = new ConfigManager('my-app', 'my-service', {
configPath: './config/telemetry.json',
enableHotReload: true
});
```javascript
// S3 Provider (production)
import { S3ConfigProvider } from '@vtex/diagnostics-nodejs';
const s3Provider = new S3ConfigProvider(
'telemetry-configs-bucket',
'services/my-service/config.json',
'us-east-1',
30000 // Poll interval
);
```javascript
// Custom provider implementation
class CustomConfigProvider {
async load() {
// Fetch from your custom source (API, database, etc.)
return {
traces: {
sampling: {
defaultRate: await this.getSamplingRateFromAPI()
}
}
};
}
onChange(callback) {
// Subscribe to config changes
this.webhookSubscriber.on('config-changed', callback);
}
}Environment Variable Mappings
const telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
// Map environment variables to resource attributes
envMappings: [
{ envVar: 'REGION', attributeName: 'cloud.region' },
{ envVar: 'VERSION', attributeName: 'service.version' },
{ envVar: 'TEAM', attributeName: 'service.team' },
{ envVar: 'POD_NAME', attributeName: 'k8s.pod.name' },
{ envVar: 'NODE_NAME', attributeName: 'k8s.node.name' }
],
// Prefix-based mapping (maps all TELEMETRY_ATTR_* vars)
envPrefix: 'TELEMETRY_ATTR_',
disableEnvPrefixDetection: false,
// Custom attributes file
customAttributesFile: './custom-attributes.json'
}
);
// Environment variables automatically mapped:
// REGION=us-east-1 → cloud.region=us-east-1
// VERSION=1.2.3 → service.version=1.2.3
// TELEMETRY_ATTR_COST_CENTER=eng → cost.center=engconst telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
config: {
s3Config: {
bucket: 'my-telemetry-configs',
key: 'services/my-service/config.json',
region: 'us-east-1'
},
pollIntervalMs: 30000
}
}
);Advanced Features
Configuration Validation & Error Handling
const telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
config: {
configPath: './config/telemetry.json',
enableHotReload: true,
// Validation options
validateConfig: true,
fallbackToDefaults: true, // Use defaults if config is invalid
// Error handling
onConfigError: (error) => {
console.error('Config error:', error);
// Send alert, fallback to safe defaults, etc.
},
onConfigChange: (newConfig, oldConfig) => {
console.log('Config changed:', {
oldSamplingRate: oldConfig.traces?.sampling?.defaultRate,
newSamplingRate: newConfig.traces?.sampling?.defaultRate
});
}
}
}
);Feature Flags Integration
// Dynamic feature flags with configuration
{
"features": {
"enableAdvancedSampling": true,
"enableCustomProcessors": true,
"enableBaggagePropagation": true
},
"traces": {
"sampling": {
"defaultRate": "{{features.enableAdvancedSampling ? 0.1 : 0.01}}",
"rules": [
{
"name": "feature_flag_sampling",
"sampleRate": 1.0,
"enabled": "{{features.enableAdvancedSampling}}",
"conditions": [
{ "attribute": "feature.flag", "operator": "Equals", "value": "new_checkout" }
]
}
]
}
}
}Multi-Environment Configuration
// config/base.json (shared configuration)
{
"globalResourceAttributes": {
"service.namespace": "ecommerce"
},
"traces": {
"exporters": {
"mode": "otlp"
}
}
}
```json
// config/production.json (production overrides)
{
"extends": "./base.json",
"globalResourceAttributes": {
"deployment.environment": "production"
},
"traces": {
"exporters": {
"otlp": { "endpoint": "prod-collector:4317" }
},
"sampling": {
"defaultRate": 0.01
}
}
}
```json
// config/development.json (development overrides)
{
"extends": "./base.json",
"globalResourceAttributes": {
"deployment.environment": "development"
},
"traces": {
"exporters": {
"otlp": { "endpoint": "localhost:4317" }
},
"sampling": {
"defaultRate": 1.0
}
}
}Circuit Breaker Configuration
// Automatic fallback when OTLP collector is down
{
"traces": {
"exporters": {
"mode": "otlp",
"otlp": {
"endpoint": "otel-collector:4317",
"timeoutMs": 5000,
"maxRetries": 3
},
"fallback": {
"mode": "console",
"enabled": true
}
},
"circuitBreaker": {
"enabled": true,
"failureThreshold": 5,
"recoveryTimeMs": 30000
}
}
}import { Processors } from '@vtex/diagnostics-nodejs';
const telemetryClient = await NewTelemetryClient(...);
const tracesClient = await telemetryClient.newTracesClient({
// VTEX-specific attribute processor (enabled by default)
enableVtexProcessor: true,
vtexProcessorConfig: {
customAttributes: {
'vtex.workspace': process.env.VTEX_WORKSPACE
}
},
// Baggage processor (enabled by default)
enableBaggageProcessor: true
});Performance & Resource Management
// Fine-tune performance settings
{
"traces": {
"batchTimeoutMs": 5000,
"maxBatchSize": 512,
"maxQueueSize": 2048,
"useSimpleProcessor": false
},
"metrics": {
"exportIntervalMs": 30000,
"maxMetricsPoints": 1000,
"cardinalityLimit": 1000
},
"logs": {
"batchTimeoutMs": 1000,
"maxBatchSize": 100,
"maxQueueSize": 500
}
}Configuration Security
// Secure configuration with encrypted values
{
"traces": {
"exporters": {
"otlp": {
"endpoint": "{{decrypt:aws-kms:endpoint}}",
"headers": {
"authorization": "{{env:OTEL_API_KEY}}"
}
}
}
},
"encryption": {
"provider": "aws-kms",
"keyId": "arn:aws:kms:us-east-1:123456789:key/12345678"
}
}
```javascript
// Runtime decryption
const telemetryClient = await NewTelemetryClient(
'my-app', 'my-client', 'my-service',
{
config: {
configPath: './config/encrypted.json',
decryptionProvider: new AWSKMSDecryption(),
enableConfigValidation: true
}
}
);Custom Processors
import { Processors } from '@vtex/diagnostics-nodejs';
const telemetryClient = await NewTelemetryClient(...);
const tracesClient = await telemetryClient.newTracesClient({
// Built-in VTEX processor (enabled by default)
enableVtexProcessor: true,
vtexProcessorConfig: {
customAttributes: {
'vtex.workspace': process.env.VTEX_WORKSPACE,
'vtex.account': process.env.VTEX_ACCOUNT
}
},
// Baggage processor (enabled by default)
enableBaggageProcessor: true,
// Custom span processor
customProcessors: [
new MyCustomSpanProcessor({
addTimestamp: true,
enrichWithBusinessContext: true
})
]
});// Before: Manual OpenTelemetry setup
const tracer = trace.getTracer('my-service');
const meter = metrics.getMeter('my-service');
// After: Diagnostics library
const telemetryClient = await NewTelemetryClient('app', 'client', 'service');
const instrumentations = Instrumentation.CommonInstrumentations.autoDetect();
const tracesClient = await telemetryClient.newTracesClient();
const metricsClient = await telemetryClient.newMetricsClient();
telemetryClient.registerInstrumentations(instrumentations);Troubleshooting
Common Issues
- No traces generated: Ensure telemetry client is initialized and instrumentations are registered before importing frameworks.
- Sampling not working: Check
http.targetattribute in rules (nothttp.route). - Config not reloading: Verify file permissions and polling interval.
- gRPC connection failed: Use correct port (4317 for insecure, 443 for TLS).
- S3 config not loading: Check AWS credentials and bucket permissions.
- High memory usage: Reduce batch sizes and queue limits in the configuration.
- Missing baggage: Ensure context propagation middleware is installed and used correctly.
Debug & Monitoring
// Enable comprehensive debugging
const telemetryClient = await NewTelemetryClient(
'app', 'client', 'service',
{
debug: true, // OpenTelemetry debug logs
config: {
enableHotReload: true,
onConfigError: (error) => console.error('Config error:', error),
onConfigChange: (newConfig) => console.log('Config updated:', newConfig)
}
}
);
// The ConfigManager is internal and not exposed via a public `getConfigManager()` method.
// To monitor config, use the `onConfigChange` callback in the config options.
// Check sampling decisions by enabling debug logs or creating a custom span processor.Performance Monitoring
// Monitor telemetry overhead
const telemetryMetrics = metricsClient.createHistogram('telemetry_overhead_ms');
const configReloadCounter = metricsClient.createCounter('config_reloads_total');
// The onConfigChange callback can be used to increment the counter.
// Example:
// onConfigChange: (newConfig) => {
// configReloadCounter.increment();
// }
// Monitoring export success/failure would require custom exporters or processors.Debug Logging
const telemetryClient = await NewTelemetryClient(
'app', 'client', 'service',
{ debug: true } // Enables OpenTelemetry debug logs
);Examples & Use Cases
Microservices with Remote Configuration
# Centralized configuration management
my-microservices/
├── services/
│ ├── api-gateway/ # parentBased: true, high sampling
│ ├── user-service/ # parentBased: true, follows gateway
│ ├── inventory/ # parentBased: false, resamples
│ └── payment/ # parentBased: true, 100% sampling
├── configs/
│ ├── s3-bucket: telemetry-configs
│ ├── api-gateway.json
│ ├── user-service.json
│ ├── inventory.json
│ └── payment.json
└── shared/
└── base-config.jsonA/B Testing with Configuration
// Dynamic sampling based on feature flags
{
"traces": {
"sampling": {
"rules": [
{
"name": "new_checkout_flow",
"sampleRate": 1.0,
"conditions": [
{ "attribute": "feature.checkout_v2", "operator": "Equals", "value": "true" }
]
},
{
"name": "legacy_checkout_flow",
"sampleRate": 0.1,
"conditions": [
{ "attribute": "feature.checkout_v2", "operator": "Equals", "value": "false" }
]
}
]
}
}
}
```javascript
// Usage in code
app.post('/checkout', (req, res) => {
const useNewCheckout = featureFlag.isEnabled('checkout_v2', req.user.id);
Traces.addBaggage({
'feature.checkout_v2': useNewCheckout.toString(),
'user.segment': req.user.segment
});
// Automatically sampled based on feature flag
});Disaster Recovery Configuration
// Multi-region failover
{
"traces": {
"exporters": {
"primary": {
"mode": "otlp",
"otlp": { "endpoint": "us-east-1-collector:4317" }
},
"secondary": {
"mode": "otlp",
"otlp": { "endpoint": "us-west-2-collector:4317" }
},
"fallback": {
"mode": "console"
}
},
"failover": {
"enabled": true,
"healthCheckIntervalMs": 10000,
"failoverTimeoutMs": 5000
}
}
}Cost Optimization
// Smart sampling for cost control
{
"traces": {
"sampling": {
"defaultRate": 0.001,
"rules": [
{
"name": "errors_always",
"sampleRate": 1.0,
"conditions": [
{ "attribute": "http.status_code", "operator": "GreaterThanEqual", "value": "400" }
]
},
{
"name": "slow_requests",
"sampleRate": 1.0,
"conditions": [
{ "attribute": "http.response_time_ms", "operator": "GreaterThan", "value": "1000" }
]
},
{
"name": "business_critical",
"sampleRate": 0.1,
"conditions": [
{ "attribute": "http.target", "operator": "Regex", "value": "^/api/(checkout|payment|auth)" }
]
},
{
"name": "high_value_users",
"sampleRate": 0.5,
"conditions": [
{ "attribute": "user.tier", "operator": "Equals", "value": "premium" }
]
}
]
}
}
}Migration from Basic OpenTelemetry
- Express with Auto-Instrumentation
- Microservices with Distributed Tracing
- Custom Sampling Rules
- Configuration Hot-Reload
VTEX Proprietary Software - This library is proprietary to VTEX and licensed for internal use only.