1.0.128 • Published 11 months ago

@bookum/logging-client v1.0.128

Weekly downloads
-
License
ISC
Repository
-
Last release
11 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

11 months ago

1.0.127

11 months ago

1.0.126

11 months ago

1.0.125

11 months ago

1.0.124

11 months ago

1.0.123

11 months ago

1.0.122

11 months ago