1.0.128 • Published 9 months ago

@bookum/logging-client v1.0.128

Weekly downloads
-
License
ISC
Repository
-
Last release
9 months ago

@bookum/logging-client

Internal logging client for Bookum services with support for structured logging, admin impersonation tracking, and automatic batching.

Features

  • 🚀 TypeScript Support - Full type definitions and IntelliSense
  • 📊 Structured Logging - Rich metadata and context tracking
  • 👑 Admin Impersonation - Track admin actions on behalf of users
  • 🔄 Automatic Batching - High-performance log aggregation
  • 🛡️ Error Handling - Graceful failure with configurable error handlers
  • 🔌 Express Middleware - Automatic API request logging
  • 🏭 Factory Functions - Pre-configured loggers for Bookum services
  • 📡 NATS Integration - Seamless integration with existing NATS event systems

Installation

npm install @bookum/logging-client

Quick Start

Basic Usage

import { createServiceLogger, LogLevel, LogType } from '@bookum/logging-client';

const logger = createServiceLogger({
  serviceName: 'my-service',
  environment: 'production',
});

// Log a user action
await logger.log({
  logType: LogType.USER_EVENT,
  logLevel: LogLevel.INFO,
  userId: 'user-123',
  action: 'profile_updated',
  metadata: { field: 'email' },
});

// Log an API request
await logger.logApiRequest({
  userId: 'user-123',
  method: 'POST',
  path: '/api/users/profile',
  responseStatus: 200,
  duration: 150,
});

// Log an error
await logger.logError({
  userId: 'user-123',
  action: 'payment_processing',
  error: {
    type: 'ValidationError',
    message: 'Invalid credit card',
    code: 'INVALID_CARD',
  },
});

NATS Integration

If you have an existing NATS event system, you can easily integrate logging:

1. Add Log Event to Your Event System

// Add to your subjects enum:
export enum Subjects {
  // ... your existing subjects
  Log = 'log',
}

2. Use the Log Publisher

import { LogEventPublisher } from '@bookum/logging-client';
import { natsWrapper } from '../nats-wrapper'; // Your existing NATS wrapper

const logPublisher = new LogEventPublisher(
  natsWrapper.client,
  'bookum-api',
  'production'
);

// Use as fallback or primary transport
const logger = createServiceLogger({
  serviceName: 'bookum-api',
  onError: async (error, logData) => {
    // Publish to NATS on HTTP failure
    await logPublisher.publishSingleLog(logData);
  },
});

3. Set Up Consumer in Your Logging Service

// In your dedicated logging service
const subscription = nc.subscribe(Subjects.Log);

for await (const msg of subscription) {
  const logEvent = JSON.parse(msg.data);
  await processLogs(logEvent);
  msg.ack?.();
}

See src/integration-example.md for detailed integration examples.

Express Middleware

import express from 'express';
import { createServiceLogger, createAutoLogger } from '@bookum/logging-client';

const app = express();
const logger = createServiceLogger({ serviceName: 'api-service' });

// Auto-log all API requests
app.use(
  createAutoLogger({
    client: logger,
    includeRequestBody: true,
    excludePaths: ['/health', '/metrics'],
  })
);

app.listen(3000);

Admin Impersonation Logging

// Log when admin acts on behalf of a user
await logger.logAdminImpersonation({
  adminId: 'admin-456',
  adminEmail: 'admin@bookum.com',
  userId: 'user-123',
  userEmail: 'user@example.com',
  action: 'update_booking',
  impersonationSessionId: 'session-789',
  metadata: { bookingId: 'booking-123' },
});

API Reference

InternalLoggingClient

Constructor

new InternalLoggingClient(config: LoggingClientConfig)

Methods

log(logData: Partial<LogEntryData>): Promise<void>

Main logging method for structured log entries.

logApiRequest(data: {...}): Promise<void>

Convenience method for logging API requests.

logAdminImpersonation(data: {...}): Promise<void>

Log admin impersonation events.

logError(data: {...}): Promise<void>

Log error events with context.

flush(): Promise<void>

Force flush all pending logs.

shutdown(): Promise<void>

Graceful shutdown with log flushing.

Log Types

enum LogType {
  API_REQUEST = 'api_request',
  USER_EVENT = 'user_event',
  ADMIN_IMPERSONATION = 'admin_impersonation',
  PAYMENT_PROCESSING = 'payment_processing',
  EMAIL_EVENT = 'email_event',
  WEBHOOK = 'webhook',
  SYSTEM_EVENT = 'system_event',
  ERROR = 'error',
  AUTHENTICATION = 'authentication',
  BOOKING_EVENT = 'booking_event',
}

Configuration

interface LoggingClientConfig {
  baseUrl: string;
  serviceName: string;
  environment?: string;
  enableBatching?: boolean;
  batchSize?: number;
  batchTimeout?: number;
  enableAsync?: boolean;
  maxQueueSize?: number;
  onError?: (error: Error, logData: LogEntryData) => void;
}

Factory Functions

Pre-configured Service Loggers

import { BookumLoggers } from '@bookum/logging-client';

const apiLogger = BookumLoggers.createApiLogger();
const authLogger = BookumLoggers.createAuthLogger();
const paymentLogger = BookumLoggers.createPaymentLogger();

Environment-specific Loggers

import { createEnvironmentLogger } from '@bookum/logging-client';

// Development logger (immediate, verbose)
const devLogger = createEnvironmentLogger.development('my-service');

// Production logger (batched, optimized)
const prodLogger = createEnvironmentLogger.production('my-service');

// Test logger (silent errors)
const testLogger = createEnvironmentLogger.test('my-service');

Express Middleware

Auto Logger

app.use(
  createAutoLogger({
    client: logger,
    includeRequestBody: false, // Include request body in logs
    includeResponseBody: false, // Include response body in logs
    excludePaths: ['/health'], // Paths to skip logging
    extractUserId: (req) => req.user?.id,
    extractAdminContext: (req) => ({
      adminId: req.headers['x-admin-id'],
      adminEmail: req.headers['x-admin-email'],
      impersonationSessionId: req.headers['x-impersonation-session'],
    }),
  })
);

Event Logger

import { createEventLogger } from '@bookum/logging-client';

const eventLogger = createEventLogger(logger);

app.post('/api/bookings', async (req, res) => {
  // Your booking logic here

  // Log the booking event
  await eventLogger.logUserEvent(req, {
    action: 'booking_created',
    logType: LogType.BOOKING_EVENT,
    metadata: { bookingId: booking.id },
  });

  res.json(booking);
});

Environment Variables

# Set the logging service URL
BOOKUM_LOGGING_URL=https://logging.bookum.com/api/logs

# Set environment (affects default configurations)
NODE_ENV=production

# NATS configuration (if using NATS integration)
NATS_URL=nats://nats.bookum.internal:4222

Best Practices

1. Use Appropriate Log Levels

// Use INFO for normal user actions
await logger.log({
  logLevel: LogLevel.INFO,
  logType: LogType.USER_EVENT,
  // ...
});

// Use WARN for admin impersonation
await logger.log({
  logLevel: LogLevel.WARN,
  logType: LogType.ADMIN_IMPERSONATION,
  // ...
});

// Use ERROR for failures
await logger.log({
  logLevel: LogLevel.ERROR,
  logType: LogType.ERROR,
  // ...
});

2. Include Correlation IDs

// In your middleware
app.use((req, res, next) => {
  req.correlationId = req.headers['x-correlation-id'] || generateId();
  next();
});

// Use in logs
await logger.log({
  // ...
  correlationId: req.correlationId,
});

3. Sanitize Sensitive Data

// Don't log sensitive information
await logger.log({
  // ...
  metadata: {
    userId: user.id,
    // DON'T: password: user.password
    // DON'T: creditCard: payment.cardNumber
    action: 'password_changed', // OK
  },
});

4. Use Structured Metadata

// Good: structured metadata
await logger.log({
  // ...
  metadata: {
    bookingId: 'booking-123',
    hotelId: 'hotel-456',
    checkIn: '2024-01-01',
    guests: 2,
  },
});

// Avoid: unstructured strings
// metadata: { info: "booking-123 for hotel-456 with 2 guests" }

Error Handling

The client includes robust error handling:

const logger = createServiceLogger({
  serviceName: 'my-service',
  onError: (error, logData) => {
    // Custom error handling
    console.error('Logging failed:', error.message);

    // Could implement fallback logging here
    // e.g., write to local file, send to alternative service
  },
});

Performance

  • Batching: Logs are batched by default for better performance
  • Async: Non-blocking logging operations
  • Queue Management: Configurable queue size with overflow protection
  • Graceful Shutdown: Automatic log flushing on process termination

Development

# Install dependencies
npm install

# Build the project
npm run build

# Clean build artifacts
npm run clean

License

ISC

1.0.128

9 months ago

1.0.127

9 months ago

1.0.126

9 months ago

1.0.125

9 months ago

1.0.124

9 months ago

1.0.123

9 months ago

1.0.122

9 months ago