CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pino

Super fast, all natural JSON logger with exceptional performance for structured logging applications.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

browser.mddocs/

Browser Support

Browser-compatible logging with console output and transmit functionality for client-side applications. Pino provides a browser-specific build that maintains API compatibility while adapting to browser constraints.

Capabilities

Browser Logger

Use Pino in browser environments with console output and optional remote logging.

/**
 * Create a browser-compatible logger instance
 * @param options - Browser-specific logger options
 * @returns Logger instance optimized for browser use
 */
function pino(options?: BrowserLoggerOptions): Logger;

interface BrowserLoggerOptions extends LoggerOptions {
  /** Browser-specific configuration */
  browser?: BrowserOptions;
}

Usage Examples:

// Basic browser logger
const logger = pino();
logger.info('Hello from browser'); // Outputs to console

// Browser logger with custom options
const logger = pino({
  name: 'my-web-app',
  level: 'debug',
  browser: {
    asObject: true,
    transmit: {
      level: 'error',
      send: (level, logEvent) => {
        // Send errors to monitoring service
        fetch('/api/logs', {
          method: 'POST',
          body: JSON.stringify(logEvent)
        });
      }
    }
  }
});

Browser Options

Configure browser-specific behavior and output formatting.

interface BrowserOptions {
  /** Create log objects instead of calling console methods directly */
  asObject?: boolean;
  
  /** Keep message formatting for deferred console rendering */
  asObjectBindingsOnly?: boolean;
  
  /** Custom write functions for different log levels */
  write?: WriteFn | { [level: string]: WriteFn };
  
  /** Enable serializers in browser (disabled by default) */
  serialize?: boolean | string[];
  
  /** Disable browser logging entirely */
  disabled?: boolean;
  
  /** Browser-specific formatters */
  formatters?: {
    level?: (label: string, number: number) => object;
    log?: (object: Record<string, unknown>) => Record<string, unknown>;
  };
  
  /** Remote log transmission configuration */
  transmit?: {
    level?: string;
    send: (level: string, logEvent: LogEvent) => void;
  };
}

type WriteFn = (obj: object) => void;

Console Output Modes

Object Mode

Output structured log objects instead of formatted strings.

interface BrowserOptions {
  /** Create pino-like log objects instead of console calls */
  asObject?: boolean;
}

Usage Examples:

// Default console output
const logger = pino();
logger.info('Hello world'); // → console.info('Hello world')

// Object mode
const logger = pino({
  browser: {
    asObject: true
  }
});
logger.info('Hello world');
// → console.info({msg: 'Hello world', level: 30, time: 1531171074631})

// With additional data
logger.info({ userId: 123 }, 'User action');
// → console.info({msg: 'User action', level: 30, time: 1531171074631, userId: 123})

Deferred Formatting Mode

Preserve message formatting for better browser devtools rendering.

interface BrowserOptions {
  /** Keep messages unformatted for better browser devtools display */
  asObjectBindingsOnly?: boolean;
}

Usage Examples:

const logger = pino({
  browser: {
    asObjectBindingsOnly: true
  }
});

logger.info('hello %s', 'world');
// → console.info({level: 30, time: 1531171074631}, 'hello %s', 'world')
// Browser devtools will format 'hello world' with proper styling

Custom Write Functions

Level-Specific Writers

Override default console methods with custom write functions.

interface BrowserOptions {
  /** Custom write functions */
  write?: WriteFn | { [level: string]: WriteFn };
}

Usage Examples:

// Single write function for all levels
const logger = pino({
  browser: {
    write: (obj) => {
      // Custom logging implementation
      const logEntry = {
        timestamp: new Date().toISOString(),
        level: obj.level,
        message: obj.msg,
        data: obj
      };
      
      // Send to custom logging service
      window.customLogger.log(logEntry);
    }
  }
});

// Level-specific write functions
const logger = pino({
  browser: {
    write: {
      info: (obj) => {
        console.log('INFO:', obj);
      },
      error: (obj) => {
        console.error('ERROR:', obj);
        // Also send errors to error tracking
        window.errorTracker.captureError(obj);
      },
      debug: (obj) => {
        // Only log debug in development
        if (process.env.NODE_ENV === 'development') {
          console.debug('DEBUG:', obj);
        }
      }
    }
  }
});

Serialization in Browser

Serializer Control

Control which serializers are active in browser environments.

interface BrowserOptions {
  /** Enable serializers (disabled by default in browser) */
  serialize?: boolean | string[];
}

Usage Examples:

// Enable all serializers
const logger = pino({
  serializers: {
    error: (err) => ({
      name: err.name,
      message: err.message,
      stack: err.stack
    })
  },
  browser: {
    serialize: true
  }
});

// Enable specific serializers
const logger = pino({
  serializers: {
    req: reqSerializer,
    res: resSerializer,
    err: errSerializer
  },
  browser: {
    serialize: ['err'] // Only error serializer active
  }
});

// Explicitly disable standard error serializer
const logger = pino({
  browser: {
    serialize: ['!stdSerializers.err', 'custom']
  }
});

Remote Log Transmission

Transmit Configuration

Send browser logs to remote endpoints for centralized logging.

interface BrowserOptions {
  /** Remote transmission configuration */
  transmit?: {
    level?: string;
    send: (level: string, logEvent: LogEvent) => void;
  };
}

interface LogEvent {
  /** Timestamp when log method was called */
  ts: number;
  
  /** Array of arguments passed to log method */
  messages: any[];
  
  /** Child logger bindings hierarchy */
  bindings: Bindings[];
  
  /** Log level information */
  level: {
    label: string;
    value: number;
  };
}

Usage Examples:

// Basic remote logging
const logger = pino({
  browser: {
    transmit: {
      level: 'error',
      send: (level, logEvent) => {
        fetch('/api/logs', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            level,
            timestamp: logEvent.ts,
            messages: logEvent.messages,
            bindings: logEvent.bindings
          })
        }).catch(console.error);
      }
    }
  }
});

// Advanced transmission with batching
const logger = pino({
  browser: {
    transmit: {
      level: 'warn',
      send: (() => {
        const logBuffer = [];
        let sendTimer;
        
        return (level, logEvent) => {
          logBuffer.push({ level, logEvent, timestamp: Date.now() });
          
          // Batch send every 5 seconds or on critical errors
          if (level === 'fatal' || level === 'error') {
            sendLogs();
          } else {
            clearTimeout(sendTimer);
            sendTimer = setTimeout(sendLogs, 5000);
          }
        };
        
        function sendLogs() {
          if (logBuffer.length === 0) return;
          
          fetch('/api/logs/batch', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(logBuffer.splice(0))
          }).catch(console.error);
        }
      })()
    }
  }
});

Browser-Specific Patterns

Error Tracking Integration

Integrate with browser error tracking services.

Usage Examples:

// Sentry integration
const logger = pino({
  browser: {
    transmit: {
      level: 'error',
      send: (level, logEvent) => {
        if (typeof Sentry !== 'undefined') {
          Sentry.captureMessage(logEvent.messages[0], level);
          
          // Add context from bindings
          logEvent.bindings.forEach(binding => {
            Sentry.setContext('logger', binding);
          });
        }
      }
    }
  }
});

// Google Analytics event tracking
const logger = pino({
  browser: {
    transmit: {
      level: 'info',
      send: (level, logEvent) => {
        if (typeof gtag !== 'undefined' && level === 'info') {
          // Track important events
          if (logEvent.messages[0].includes('user_action')) {
            gtag('event', 'user_action', {
              event_category: 'engagement',
              event_label: logEvent.messages[0]
            });
          }
        }
      }
    }
  }
});

Local Storage Logging

Store logs locally for offline scenarios.

Usage Examples:

const logger = pino({
  browser: {
    write: {
      error: (obj) => {
        // Always show errors in console
        console.error(obj);
        
        // Store errors locally
        try {
          const errors = JSON.parse(localStorage.getItem('app_errors') || '[]');
          errors.push({
            ...obj,
            timestamp: Date.now(),
            url: window.location.href,
            userAgent: navigator.userAgent
          });
          
          // Keep only last 50 errors
          if (errors.length > 50) {
            errors.splice(0, errors.length - 50);
          }
          
          localStorage.setItem('app_errors', JSON.stringify(errors));
        } catch (e) {
          console.warn('Failed to store error in localStorage:', e);
        }
      }
    }
  }
});

// Function to retrieve stored errors
function getStoredErrors() {
  try {
    return JSON.parse(localStorage.getItem('app_errors') || '[]');
  } catch (e) {
    return [];
  }
}

// Function to send stored errors when online
function syncStoredErrors() {
  const errors = getStoredErrors();
  if (errors.length > 0) {
    fetch('/api/logs/sync', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(errors)
    }).then(() => {
      localStorage.removeItem('app_errors');
    }).catch(console.error);
  }
}

Development vs Production

Environment-Specific Configuration

Configure different behaviors for development and production builds.

Usage Examples:

function createBrowserLogger() {
  const isDevelopment = process.env.NODE_ENV === 'development';
  
  return pino({
    level: isDevelopment ? 'debug' : 'warn',
    browser: {
      asObject: isDevelopment, // Objects in dev, formatted in prod
      disabled: false,
      
      transmit: isDevelopment ? undefined : {
        level: 'error',
        send: (level, logEvent) => {
          // Only transmit in production
          fetch('/api/logs', {
            method: 'POST',
            body: JSON.stringify(logEvent)
          });
        }
      },
      
      write: isDevelopment ? undefined : {
        // Custom production logging
        error: (obj) => {
          console.error(obj);
          // Track errors in production
          window.analytics?.track('error', obj);
        }
      }
    }
  });
}

const logger = createBrowserLogger();

Browser Formatters

Custom formatting for log levels and objects in browser environments.

interface BrowserOptions {
  /** Browser-specific formatting functions */
  formatters?: {
    /** Changes the shape of the log level in browser output */
    level?: (label: string, number: number) => object;
    /** Changes the shape of the log object in browser output */
    log?: (object: Record<string, unknown>) => Record<string, unknown>;
  };
}

Usage Examples:

// Custom level formatting
const logger = pino({
  browser: {
    formatters: {
      level: (label, number) => {
        return { 
          severity: label.toUpperCase(), 
          levelNum: number,
          timestamp: Date.now()
        };
      },
      log: (object) => {
        // Add browser-specific context
        return {
          ...object,
          userAgent: navigator.userAgent,
          url: window.location.href,
          viewport: {
            width: window.innerWidth,
            height: window.innerHeight
          }
        };
      }
    }
  }
});

logger.info({ action: 'page_load' }, 'Page loaded');
// Output includes custom formatting with browser context

Bundle Size Optimization

Minimize browser bundle size when using Pino.

Usage Examples:

// Import only what you need
import pino from 'pino/browser';

// Or use a custom build
const logger = pino({
  browser: {
    // Disable features not needed in browser
    serialize: false,
    disabled: process.env.NODE_ENV === 'test'
  }
});

// Tree-shake unused features in webpack
module.exports = {
  resolve: {
    alias: {
      'pino': 'pino/browser'
    }
  }
};

Install with Tessl CLI

npx tessl i tessl/npm-pino

docs

browser.md

child-loggers.md

index.md

logger-configuration.md

logger-methods.md

serializers.md

streams.md

transports.md

tile.json