0.1.1 • Published 8 months ago
@auto-genesis/telemetry v0.1.1
Autonomize Telemetry (@auto-genesis/telemetry)
A lightweight, easy-to-use OpenTelemetry SDK for Node.js and Nest.js applications. This SDK provides unified instrumentation for traces, metrics, and logs with automatic context propagation and built-in support for popular frameworks.
Features
Metrics Collection
- Track custom metrics with counters, histograms, and up/down counters
- Configurable metric export intervals
- Pre-configured metric attributes
- Direct access to OpenTelemetry metrics API
Distributed Tracing
- Automatic trace context propagation
- Built-in span creation and management
- Manual context propagation across services
- Cross-language trace continuity (JavaScript/Python)
- Custom attribute support
- Support for error recording
- Direct access to OpenTelemetry trace API
Structured Logging
- Automatic trace correlation
- Multiple severity levels (INFO, ERROR, WARN, DEBUG)
- Custom attributes support
- Error stack trace handling
Auto-Instrumentation
- Initialization through env setup
- No code changes required
- HTTP client and server
- Express.js framework
- NestJS core components
- Custom request hooks
- Health check endpoint filtering
Installation
# Using npm
npm install @auto-genesis/telemetry
# Using yarn
yarn add @auto-genesis/telemetry
# Using pnpm
pnpm add @auto-genesis/telemetry
## Quick Start
### Auto-Instrumentation
The SDK supports automatic instrumentation of your Node.js application. To enable it:
1. Set the NODE_OPTIONS environment variable:
```bash
NODE_OPTIONS="--require @auto-genesis/telemetry/register"
Configure your environment variables (see Configuration section)
Start your application normally:
node app.js # you start script here
Manual Initialization
If you prefer manual control over the SDK initialization:
import { Telemetry } from '@auto-genesis/telemetry';
const telemetry = new Telemetry({
serviceName: 'my-service',
environment: 'production',
version: '1.0.0',
otlpEndpoint: 'http://otlpendpoint:3000',
});
await telemetry.start();
// Your application code here
// On shutdown
await telemetry.shutdown();
Configuration
TelemetryConfig Options
Option | Type | Required | Default | Description |
---|---|---|---|---|
serviceName | string | Yes | - | Unique identifier for your service |
environment | string | Yes | - | Deployment environment (e.g., 'production') |
version | string | No | undefined | Service version |
otlpEndpoint | string | No | 'http://localhost:4318' | OpenTelemetry collector endpoint |
metricIntervalMs | number | No | 5000 | Metric export interval in milliseconds |
Updated Configuration Options
Environment Variable | Description | Default Value | Type |
---|---|---|---|
TELEMETRY_SERVICE_NAME | Name of your service | 'unknown-service' | string |
TELEMETRY_SERVICE_VERSION | Version of your service | '0.0.0' | string |
TELEMETRY_ENVIRONMENT | Deployment environment | 'development' | string |
TELEMETRY_EXPORTER_OTLP_ENDPOINT | OpenTelemetry Collector endpoint | 'http://localhost:4318' | string |
TELEMETRY_HTTP_ENABLED | Enable HTTP instrumentation | true | boolean |
TELEMETRY_EXPRESS_ENABLED | Enable Express instrumentation | true | boolean |
TELEMETRY_NESTJS_ENABLED | Enable NestJS instrumentation | false | boolean |
TELEMETRY_LOG_LEVEL | Log level (ERROR, WARN, INFO, DEBUG) | 'INFO' | string |
TELEMETRY_METRIC_EXPORT_INTERVAL | Metrics export interval in ms | 5000 | number |
Example .env file
# Basic Service Configuration
TELEMETRY_SERVICE_NAME=my-service
TELEMETRY_SERVICE_VERSION=1.0.0
TELEMETRY_ENVIRONMENT=development
# OpenTelemetry Collector Endpoint
TELEMETRY_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# Instrumentation Configuration
TELEMETRY_HTTP_ENABLED=true
TELEMETRY_EXPRESS_ENABLED=true
TELEMETRY_NESTJS_ENABLED=true
# Logging Configuration
TELEMETRY_LOG_LEVEL=INFO
# Metrics Configuration
TELEMETRY_METRIC_EXPORT_INTERVAL=5000
Usage Examples
Metrics (telemetry.metrics)
Metric Type | Description | Usage Example |
---|---|---|
Counter | Only increases | telemetry.metrics.createCounter(...) |
Histogram | Distribution of values | telemetry.metrics.createHistogram(...) |
UpDownCounter | Can increase/decrease | telemetry.metrics.createUpDownCounter(...) |
import { Telemetry } from '@auto-genesis/telemetry';
const telemetry = new Telemetry();
// Create counter
const requestCounter = telemetry.metrics.createCounter({
name: 'http.requests.total',
description: 'Total number of HTTP requests',
unit: 'requests',
});
// Record metrics
requestCounter.add(1, { 'http.method': 'GET' });
// Create a histogram (distribution of values)
const histogram = telemetry.metrics.createHistogram({
name: 'metric_name',
description: 'metric description',
unit: 'unit',
});
// Create an up/down counter (can increase/decrease)
const upDownCounter = telemetry.metrics.createUpDownCounter({
name: 'metric_name',
description: 'metric description',
unit: 'unit',
});
// Access OpenTelemetry metrics API
const metricsAPI = telemetry.metrics.getMetrics();
Tracing (telemetry.tracing)
import { Telemetry } from '@auto-genesis/telemetry';
const telemetry = new Telemetry();
// Access OpenTelemetry trace API and context
const trace = telemetry.tracing.getTrace();
const context = telemetry.tracing.getContext();
const activeSpan = telemetry.tracing.getActiveSpan();
// Create a traced operation
await telemetry.tracing.createSpan('my-operation', async () => {
// Your code here
await doSomething();
});
// Add attributes to current span
telemetry.tracing.addAttributes({
'custom.attribute': 'value',
});
// Record errors
try {
await riskyOperation();
} catch (error) {
telemetry.tracing.recordError(error);
throw error;
}
// Manual context propagation across services
// Service A (sending trace context)
const traceCarrier = telemetry.tracing.injectCurrentContext();
// Send traceCarrier to Service B via HTTP, message queue, etc.
// Service B (receiving trace context)
const extractedContext = telemetry.tracing.extractContext(receivedCarrier);
await telemetry.tracing.createSpan(
'service-b-operation',
async () => {
// This span will be connected to the trace from Service A
await processRequest();
},
{
context: extractedContext,
attributes: { service: 'service-b' },
},
);
Cross-Language Tracing Example
// JavaScript Service (sending to Python service)
// 1. Create a span and prepare context for transport
const traceCarrier = telemetry.tracing.injectCurrentContext();
// 2. Send request to Python service with context
const response = await axios.post('http://python-service/endpoint', {
data: requestData,
_traceContext: traceCarrier // Include trace context in request
});
// Python Service (receiving from JavaScript)
"""
from opentelemetry import trace, context
from opentelemetry.propagate import extract
@app.route('/endpoint', methods=['POST'])
def handle_request():
# 1. Extract trace context from request
data = request.json
carrier = data.get('_traceContext', {})
ctx = extract(carrier)
# 2. Create a span with the extracted context
with tracer.start_as_current_span("process-request", context=ctx) as span:
# This span will be connected to the JavaScript trace
result = process_data(data['data'])
# 3. When sending response, include context for continuation
response_carrier = {}
inject(response_carrier)
return jsonify({
'result': result,
'_traceContext': response_carrier
})
"""
// Back to JavaScript service (receiving response from Python)
// 3. Extract context from Python service response
const pythonContext = telemetry.tracing.extractContext(response.data._traceContext);
// 4. Continue the trace
await telemetry.tracing.createSpan('process-python-response', async () => {
// This span will be connected to both previous spans
processResult(response.data.result);
}, {
context: pythonContext
});
Logging (telemetry.logging)
import { Telemetry } from '@auto-genesis/telemetry';
const telemetry = new Telemetry();
// Log with different levels
telemetry.logging.info('Operation successful', { operation: 'data-sync' });
telemetry.logging.error('Operation failed', new Error('Sync failed'));
telemetry.logging.debug('Debug information', { details: 'some debug data' });
NestJS Integration
import Telemetry from '@auto-genesis/telemetry';
async function bootstrap() {
const telemetry = new Telemetry({
serviceName: 'nest-service',
environment: process.env.NODE_ENV,
});
await telemetry.start();
const app = await NestFactory.create(AppModule);
await telemetry.listen(3000);
// Graceful shutdown
process.on('SIGTERM', async () => {
await telemetry.shutdown();
await app.close();
});
}
Context Propagation Interface
The SDK provides a standard interface for propagating trace context across service boundaries:
// Carrier interface for transporting trace context
interface TraceCarrier {
traceparent?: string; // W3C Trace Context format
tracestate?: string; // Additional trace state information
}
Playground
To test new features or debug locally:
Clone the repository:
git clone https://github.com/autonomize-ai/autonomize-sdk-js.git cd autonomize-sdk-js
Set up the playground:
cd playground cp .env.example .env # Configure your environment variables pnpm install
Run the OTel playground:
pnpm dev:otel
This will start a development environment where you can test SDK features without publishing to npm.
Requirements
Requirement | Version |
---|---|
Node.js | >= 14.x |
OpenTelemetry Collector | Latest stable |
Dependencies
Package | Version |
---|---|
@opentelemetry/api | ^1.7.0 |
@opentelemetry/sdk-node | ^0.54.1 |
@opentelemetry/auto-instrumentations-node | ^0.52.0 |
@opentelemetry/instrumentation-nestjs-core | ^0.41.0 |
See package.json
for the complete list of dependencies.