npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gomarbleai/logging-js

v1.0.15

Published

Standardized structured logging library for microservices

Readme

@gomarbleai/logging-js

Standardized structured logging library for microservices that works seamlessly with Next.js, Express.js, and Fastify.

Features

  • Universal Compatibility: Built-in support for Next.js, Express.js, and Fastify frameworks
  • Structured Logging: JSON-formatted logs with consistent schema
  • Request Tracing: Automatic trace ID extraction and propagation
  • Performance Monitoring: Built-in request duration tracking
  • Error Handling: Comprehensive error logging with stack traces
  • Streaming Support: Special handling for SSE and long-lived connections
  • Zero Configuration: Works out of the box with sensible defaults

Installation

npm install @gomarbleai/logging-js

Quick Start

Next.js API Routes

import { withLogging } from '@gomarbleai/logging-js';

async function handler(req: NextApiRequest, res: NextApiResponse) {
  // Your API logic here
  res.status(200).json({ message: 'Success' });
}

export default withLogging(handler);

Express.js Routes

import express from 'express';
import { withLogging, createLogger } from '@gomarbleai/logging-js';

const app = express();

// Apply logging middleware (auto-detects Express)
app.use(withLogging);

app.get('/api/data', (req, res) => {
  const logger = createLogger(req);
  logger.info('Processing request');
  
  res.json({ data: 'success' });
});

Fastify Routes

import Fastify from 'fastify';
import { registerFastifyLogging, createLogger } from '@gomarbleai/logging-js';

const server = Fastify({ logger: true });

const start = async () => {
  try {
    // Register logging hooks (covers all routes automatically)
    registerFastifyLogging(server);

    // Register your routes
    server.get('/api/data', async (request, reply) => {
      const logger = createLogger(request);
      logger.info('Processing request');
      
      return { data: 'success' };
    });

    await server.listen({ port: 3000, host: '0.0.0.0' });
  } catch (err) {
    server.log.error(err);
    process.exit(1);
  }
};

start();

Alternative Plugin Approach:

// You can also use the plugin approach if preferred
await server.register(withFastifyLogging());

Streaming/SSE Endpoints

For Server-Sent Events (SSE) or long-lived streaming connections:

import { withStreamLogging, createLoggingContext } from '@gomarbleai/logging-js';

// Option 1: Use withStreamLogging middleware
app.get('/api/sse', withStreamLogging((req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });
  
  // Your SSE logic here
  const interval = setInterval(() => {
    res.write(`data: ${JSON.stringify({ timestamp: Date.now() })}\n\n`);
  }, 1000);
  
  req.on('close', () => clearInterval(interval));
}, {
  logStart: true,    // Log when connection starts
  logEnd: true,      // Log when connection closes
  timeout: 300000    // Optional: Log timeout after 5 minutes
}));

// Option 2: Use manual logging context for fine-grained control
app.get('/api/sse-manual', (req, res) => {
  const loggingContext = createLoggingContext(req);
  loggingContext.logStart('SSE connection initiated');
  
  try {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    });
    
    // Your SSE logic here
    const interval = setInterval(() => {
      res.write(`data: ${JSON.stringify({ timestamp: Date.now() })}\n\n`);
    }, 1000);
    
    req.on('close', () => {
      clearInterval(interval);
      loggingContext.logEnd('SSE connection closed by client');
    });
    
    req.on('error', (error) => {
      clearInterval(interval);
      loggingContext.logError(error, 'SSE connection error');
    });
    
  } catch (error) {
    loggingContext.logError(error, 'Failed to establish SSE connection');
  }
});

Usage

Automatic Request Logging

For Next.js & Express.js: The withLogging function automatically:

  • Detects whether you're using Next.js or Express.js
  • Logs request start and completion
  • Tracks response time
  • Extracts and propagates trace IDs
  • Handles errors and exceptions

For Fastify: The registerFastifyLogging() function automatically:

  • Registers hooks directly on the Fastify instance
  • Logs request completion with method, path, status, and duration
  • Extracts trace IDs from headers
  • Works with all registered routes
  • Alternative: Use withFastifyLogging() as a plugin

Streaming Request Logging

The withStreamLogging function is designed for long-lived connections:

  • Logs connection initiation and closure
  • Handles connection events (close, error, finish)
  • Supports optional timeout warnings
  • Doesn't wait for handler completion (non-blocking)

Manual Logging

import { createLogger, createLoggingContext } from '@gomarbleai/logging-js';

// Basic manual logging
export default withLogging(async (req, res) => {
  const logger = createLogger(req);
  
  logger.info('Processing user data');
  logger.warn('Rate limit approaching');
  logger.error('Database connection failed', {
    error: new Error('Connection timeout'),
    custom_data: { user_id: 123 }
  });
});

// Manual logging with context (for streaming)
app.post('/api/users', (req, res) => {
  const context = createLoggingContext(req);
  
  context.logStart('Creating new user');
  
  try {
    // Your logic here
    context.logEnd('User created successfully');
  } catch (error) {
    context.logError(error, 'Failed to create user');
  }
});

// Fastify manual logging  
const start = async () => {
  // Register logging hooks
  registerFastifyLogging(server);
  
  server.post('/api/users', async (request, reply) => {
    const logger = createLogger(request);
    
    logger.info('Creating new user');
    
    try {
      // Your logic here
      logger.info('User created successfully');
      return { success: true };
    } catch (error) {
      logger.error('Failed to create user', { error });
      throw error;
    }
  });
  
  await server.listen({ port: 3000 });
};

Logger Methods

logger.debug(message, metadata?);
logger.info(message, metadata?);
logger.warn(message, metadata?);
logger.error(message, metadata?);

// Context methods
context.logStart(message?);
context.logEnd(message?);
context.logError(error, message?);

Configuration

Set environment variables to configure the logger:

SERVICE_NAME=user-service
ENVIRONMENT=production
NODE_ENV=production

Streaming Options

Configure withStreamLogging with these options:

interface StreamLoggingOptions {
  logStart?: boolean;  // Log connection start (default: true)
  logEnd?: boolean;    // Log connection end (default: true)
  timeout?: number;    // Timeout in ms for warning (optional)
}

Log Format

All logs follow this structured JSON format:

{
  "timestamp": "2024-01-01T12:00:00.000Z",
  "level": "INFO",
  "message": "request processed",
  "service_name": "user-service",
  "environment": "production",
  "trace_id": "internal-abc123def456",
  "http": {
    "method": "POST",
    "path": "/api/users",
    "status_code": 200
  },
  "duration_ms": 150,
  "custom_data": {
    "user_id": 123
  }
}

Framework Support

The library provides different middleware for each framework:

  • Next.js: Use withLogging - automatically detects Next.js API handlers
  • Express.js: Use withLogging - automatically detects Express middleware signature
  • Fastify: Use registerFastifyLogging() for direct registration or withFastifyLogging() as a plugin

Each framework has optimized integration that respects framework conventions!

Fastify Integration Notes

Direct Registration (Recommended):

registerFastifyLogging(server);
  • Registers hooks directly on the Fastify instance
  • Ensures hooks apply to all routes regardless of plugin encapsulation
  • Simpler setup for most use cases

Plugin Approach:

await server.register(withFastifyLogging());
  • Follows Fastify plugin conventions
  • May require careful ordering relative to route registration
  • Use when you need plugin-specific encapsulation

Best Practices

For Regular APIs

  • Next.js/Express: Use withLogging for standard request/response cycles
  • Fastify: Use registerFastifyLogging(server) for direct hook registration, or withFastifyLogging() plugin
  • Use createLogger for manual logging within handlers

For Streaming/SSE

  • Use withStreamLogging for SSE endpoints with automatic lifecycle logging
  • Use createLoggingContext for fine-grained control over streaming logs
  • Set appropriate timeout values for long-running connections
  • Always handle connection close events to prevent resource leaks

General

  • Include meaningful custom_data for business context
  • Use descriptive messages that explain what happened
  • Pass Error objects for automatic stack trace formatting

License

MIT