Node.js Support

OpenTelemetry exporter for AWS Lambda that writes telemetry data to stdout in OTLP format.

npm Node Version License: MIT

Installation

Install the exporter and its dependencies:

npm install @dev7a/otlp-stdout-exporter \
            @opentelemetry/api \
            @opentelemetry/sdk-trace-node \
            @opentelemetry/sdk-trace-base \
            @opentelemetry/resources \
            @opentelemetry/resource-detector-aws

The package requires Node.js 18 or later.

Basic Usage

The following example shows an AWS Lambda function that:

  • Handles API Gateway requests
  • Creates a tracer provider with AWS Lambda resource detection
  • Creates a span for each invocation
  • Ensures telemetry is flushed before the function exits

The provider is created for each invocation to handle Lambda cold starts and ensure proper resource cleanup.

const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { Resource } = require('@opentelemetry/resources');
const { trace, SpanKind, context } = require('@opentelemetry/api');
const { StdoutOTLPExporterNode } = require('@dev7a/otlp-stdout-exporter');
const { AwsLambdaDetectorSync } = require('@opentelemetry/resource-detector-aws');

const createProvider = () => {
  // Detect AWS Lambda resources (function name, version, etc.)
  const awsResource = new AwsLambdaDetectorSync().detect();
  
  // Create a resource merging Lambda attributes with service name
  const resource = new Resource({
    ["service.name"]: process.env.AWS_LAMBDA_FUNCTION_NAME || 'demo-function',
  }).merge(awsResource);

  // Initialize provider with resource attributes
  const provider = new NodeTracerProvider({ resource });
  provider.addSpanProcessor(new BatchSpanProcessor(new StdoutOTLPExporterNode()));
  return provider;
};

exports.handler = async (event, context) => {
  const provider = createProvider();
  provider.register();
  const tracer = trace.getTracer('lambda-handler');

  try {
    const span = tracer.startSpan('process-request', {
      kind: SpanKind.SERVER
    });

    return await context.with(trace.setSpan(context.active(), span), async () => {
      const result = { message: 'Hello from Lambda!' };
      span.end();
      return {
        statusCode: 200,
        body: JSON.stringify(result)
      };
    });
  } finally {
    // Ensure all spans are flushed before the Lambda ends
    await provider.forceFlush();
  }
};

Environment Variables

Configuration is handled through environment variables:

VariableDescriptionDefault
OTEL_EXPORTER_OTLP_PROTOCOLProtocol for OTLP data (http/protobuf or http/json)http/protobuf
OTEL_EXPORTER_OTLP_COMPRESSIONCompression type (gzip or none)none
OTEL_SERVICE_NAMEName of your serviceFunction name

Troubleshooting

Common issues and solutions:

  1. Missing Spans
    • Check if forceFlush() is called
    • Verify span lifecycle management
    • Check context propagation
  2. Performance Issues
    • Enable batch processing
    • Adjust batch configuration
    • Monitor memory usage
  3. Build Errors
    • Check TypeScript configuration
    • Verify package versions