JSPM

@bancame/logger

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q22454F
  • License MIT

AWS CloudWatch logger library with structured logging and traceability

Package Exports

  • @bancame/logger
  • @bancame/logger/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bancame/logger) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@bancame/logger

A modern TypeScript logging library for AWS CloudWatch with structured logging and cross-service traceability.

✨ Features

  • Structured logging with flexible data objects
  • AWS CloudWatch integration for centralized log storage
  • Cross-service traceability with unique trace IDs
  • Multiple log levels (error, warn, info, debug)
  • Console logging with colors for development
  • Environment-based configuration
  • Full TypeScript support with complete type definitions
  • Comprehensive test suite with >90% coverage

📦 Installation

npm install @bancame/logger

🚀 Quick Start

import { Logger } from '@bancame/logger';

// Create logger instance
const logger = new Logger({
  name: 'my-service',
  logGroupName: '/services-backend',
  enableCloudWatch: true,
  enableConsole: true,
  level: 'info',
  region: 'us-east-1',
});

// Generate trace ID for request tracking
const traceId = logger.generateTraceId();
logger.setTraceId(traceId);

// Log structured data
logger.info('User login successful', {
  userId: 'user123',
  email: 'user@example.com',
  loginTime: new Date().toISOString(),
});

logger.error('Database connection failed', {
  error: 'Connection timeout',
  database: 'users',
  retryAttempt: 3,
});

⚙️ Configuration

The logger can be configured in multiple ways. Choose the approach that best fits your project:

interface LoggerConfig {
  name: string; // Service/application name
  logGroupName?: string; // CloudWatch log group (default: '/application')
  enableCloudWatch?: boolean; // Enable CloudWatch logging (default: false)
  enableConsole?: boolean; // Enable console logging (default: true)
  level?: LogLevel; // Minimum log level (default: 'info')
  region?: string; // AWS region (default: 'us-east-1')
  credentials?: object; // AWS credentials (optional)
}

Environment Variables

# AWS Configuration
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key

# Logger Configuration
LOG_LEVEL=info
ENABLE_CLOUDWATCH=true
ENABLE_CONSOLE=true
LOG_GROUP_NAME=/services-backend

📝 Usage Examples

Basic Logging

const logger = new Logger({ name: 'api-service' });

logger.debug('Debug information', { debugData: 'value' });
logger.info('Information message', { userId: 123 });
logger.warn('Warning message', { warning: 'deprecated API' });
logger.error('Error occurred', { error: 'Database timeout' });

Request Tracing

// Generate unique trace ID for request
const traceId = logger.generateTraceId();
logger.setTraceId(traceId);

logger.info('Request started', {
  method: 'POST',
  path: '/api/users',
});

// All subsequent logs will include the trace ID
logger.info('Processing user data', { userId: 'user123' });
logger.info('Request completed', { duration: '150ms' });

// Clear trace ID when request ends
logger.clearTraceId();

Cross-Service Trace ID Propagation

To track requests across multiple services, you need to pass the trace ID between them. Here's how to do it:

AWS CloudWatch Integration

Cross-Service Trace ID Propagation

To track requests across multiple services, you need to pass the trace ID through HTTP headers or message payloads:

Step 1: Service A (API Gateway/Frontend)

import logger from '@bancame/logger';

// Start request with optional trace ID
const traceId = logger.startRequest({
  userId: 'user123',
  operation: 'CreateOrder',
});

// When calling Service B, include trace ID in headers
const response = await fetch('https://service-b/api/process', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Trace-ID': traceId, // Pass trace ID to next service
  },
  body: JSON.stringify({ orderId: '12345' }),
});

logger.info('Called Service B', { serviceB: response.status });

Step 2: Service B (Intermediate Service)

import logger from '@bancame/logger';

// Extract trace ID from incoming request
app.post('/api/process', (req, res) => {
  const incomingTraceId = req.headers['x-trace-id'];

  // Continue with existing trace ID
  logger.startRequest({
    traceId: incomingTraceId, // Use incoming trace ID
    operation: 'ProcessOrder',
    orderId: req.body.orderId,
  });

  // When calling Service C, forward the trace ID
  const serviceC = await fetch('https://service-c/api/validate', {
    method: 'POST',
    headers: {
      'X-Trace-ID': incomingTraceId, // Forward same trace ID
    },
    body: JSON.stringify({ orderId: req.body.orderId }),
  });

  logger.info('Processing complete');
  res.json({ success: true });
});

Step 3: Service C (Final Service)

import logger from '@bancame/logger';

app.post('/api/validate', (req, res) => {
  const traceId = req.headers['x-trace-id'];

  // Continue the same trace
  logger.startRequest({
    traceId: traceId,
    operation: 'ValidateOrder',
  });

  logger.info('Order validated successfully');
  res.json({ valid: true });
});

Message Queue Pattern

For asynchronous communication via message queues:

// Publisher (Service A)
const message = {
  orderId: '12345',
  traceId: logger.getTraceId(), // Include current trace ID
  payload: {
    /* ... */
  },
};
await queue.publish('order.created', message);

// Consumer (Service B)
queue.subscribe('order.created', (message) => {
  // Start request with trace ID from message
  logger.startRequest({
    traceId: message.traceId,
    operation: 'ProcessOrderAsync',
  });

  // Process the order...
  logger.info('Order processed asynchronously');
});

Best Practices

  • Header Name: Use X-Trace-ID for HTTP headers
  • Message Field: Include traceId field in message payloads
  • Validation: Always check if trace ID exists before using it
  • Fallback: If no trace ID is provided, startRequest() will generate a new one
  • Logging: Log the trace ID when starting each service to verify propagation
const logger = new Logger({
  name: 'production-service',
  logGroupName: '/aws/lambda/my-function',
  enableCloudWatch: true,
  enableConsole: false, // Disable console in production
  level: 'warn', // Only log warnings and errors
  region: 'us-west-2',
});

logger.error('Critical error', {
  error: 'Payment processing failed',
  amount: 100.5,
  currency: 'USD',
  userId: 'user123',
});

🧪 Development

Commands

# Run all integration tests and demos
npm run demo

# CloudWatch demo (requires AWS credentials)
npm run demo:cloudwatch

# All examples (console + CloudWatch + tracing)
npm run demo:all

# Build and lint
npm run build
npm run lint

# Run tests with coverage
npm test

Testing

The library includes comprehensive unit tests and integration examples:

# Run unit tests
npm test

# Run with coverage report
npm run test:coverage

# Run integration tests
npm run demo

📚 Documentation