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

@catsle/caretta

v1.0.3

Published

A flexible, pluggable logging system with support for custom log levels and external integrations like Sentry and RUM

Readme

Caretta Logger

A powerful, extensible logging system for JavaScript applications with support for federated analytics and plugin architecture.

npm version License: MIT

Quick Start

import { createLogger, LogLevel, Logger } from '@catsle/caretta';

// Set global log level
Logger.setGlobalLevel(LogLevel.WARN);

// Create a logger for your component
const logger = createLogger('MyComponent');

// This won't log (below global level)
logger.debug('Debug information');

// Set instance-specific level
logger.setLevel(LogLevel.DEBUG);

// This will log now!
logger.debug('Debug information'); // shows

Why Caretta?

Modern applications need more than just console logs. You need structured logging that works across environments, integrates with monitoring systems, and scales with your architecture. Most logging libraries either:

  1. Do too little - just wrapping console.log with minimal features
  2. Do too much - forcing specific backends or workflows
  3. Aren't designed for today's federated systems and analytics needs

Caretta solves these problems with a flexible, plugin-based architecture that:

  • Puts you in control of where your logs go
  • Works consistently across browsers, Node.js, and other JavaScript environments
  • Enables federated analytics without vendor lock-in
  • Provides powerful developer tools without sacrificing performance

Table of Contents

Documentation

For comprehensive documentation, visit:

Installation

# Using npm
npm install @catsle/caretta

# Using pnpm (recommended)
pnpm add @catsle/caretta

# Using yarn
yarn add @catsle/caretta

Core Concepts

Loggers

Loggers are the main interface you'll interact with. Each logger has:

  • A unique context name to identify its source
  • Level-based methods (.debug(), .info(), .warn(), .error())
  • Metadata support
  • Instance-specific configuration
import { createLogger } from '@catsle/caretta';

// Create a named logger
const logger = createLogger('AuthService');

// Basic logging
logger.info('User login attempt');

// With metadata
logger.info('Login successful', { userId: '123', method: 'oauth' });

// With error objects
logger.error('Authentication failed', new Error('Invalid credentials'));

Log Levels

Caretta provides standard log levels with symbolic values and a overridable method that enables numeric comparison of log leves to support custom log levels.

import { LogLevel } from '@catsle/caretta';

// Available levels (from most to least verbose)
LogLevel.DEBUG   // Detailed debugging information
LogLevel.INFO    // Interesting runtime events
LogLevel.WARN    // Warning conditions
LogLevel.ERROR   // Error conditions
LogLevel.ALWAYS  // Critical information, never filtered

Metadata

Add context to your logs with metadata at multiple levels:

import { Logger, createLogger } from '@catsle/caretta';

// Global metadata (applied to all loggers)
Logger.setGlobalMetadata('version', '2.3.0');
Logger.setGlobalMetadata('environment', 'production');

// Instance metadata (applied to all logs from this instance)
const userLogger = createLogger('UserService');
userLogger.setMetadata('component', 'Authentication');

// Log-specific metadata (just for this log entry)
userLogger.info('Operation completed', { 
  duration: 127,
  cacheHit: true
});

Global vs. Instance Configuration

Caretta lets you configure logging at both global and instance levels:

import { Logger, LogLevel, createLogger } from '@catsle/caretta';

// === Global Configuration ===

// Set the global minimum log level
Logger.setGlobalLevel(LogLevel.INFO);

// Register plugins for all loggers
import { ConsolePlugin } from '@catsle/caretta-console-plugin';
Logger.registerPlugin(new ConsolePlugin({ colors: true }));

// === Instance Configuration ===

const apiLogger = createLogger('APIClient');
const dbLogger = createLogger('Database');

// Override global level for specific loggers
apiLogger.setLevel(LogLevel.DEBUG);  // More verbose for API debugging
dbLogger.setLevel(LogLevel.WARN);    // Less noise from database

// Add logger-specific metadata
apiLogger.setMetadata('module', 'external-api');

Plugins

Caretta's power comes from its plugin architecture. Plugins receive log entries and can:

  • Format and output logs to different destinations
  • Filter or transform log data
  • Integrate with monitoring and analytics systems
  • Provide developer tools

Official Plugins

import { Logger } from '@catsle/caretta';

// Console output with formatting
import { ConsolePlugin } from '@catsle/caretta-console-plugin';
Logger.registerPlugin(new ConsolePlugin({ 
  colors: true, 
  timestamp: true 
}));

// Error tracking with Sentry
import { SentryPlugin } from '@catsle/caretta-sentry-plugin';
import * as Sentry from '@sentry/browser';
Logger.registerPlugin(new SentryPlugin({ sentry: Sentry }));

// In-browser log viewer
import { BrowserLogViewerPlugin } from '@catsle/caretta-browser-viewer';
Logger.registerPlugin(new BrowserLogViewerPlugin());

Creating Your Own Plugin

import { LoggerPlugin, LogEntry } from '@catsle/caretta';

class MetricsPlugin implements LoggerPlugin {
  name = 'metricsPlugin';
  
  initialize() {
    // Setup connections, initialize storage, etc.
  }
  
  process(entry: LogEntry) {
    if (entry.level === LogLevel.ERROR) {
      // Track error metrics
      trackErrorMetric(entry.context, entry.message);
    }
    
    // Process log-specific metadata
    if (entry.metadata?.duration) {
      trackDurationMetric(entry.context, entry.metadata.duration);
    }
  }
  
  cleanup() {
    // Close connections, flush buffers, etc.
  }
}

// Register your plugin
Logger.registerPlugin(new MetricsPlugin());

Federated Analytics

Caretta supports federated analytics, allowing you to collect insights across your application ecosystem without centralized dependencies.

import { Logger } from '@catsle/caretta';
import { AnalyticsPlugin } from '@catsle/caretta-analytics';

// Setup federated analytics
Logger.registerPlugin(new AnalyticsPlugin({
  endpoint: 'https://analytics.example.com/collect',
  sampleRate: 0.1,  // Sample 10% of events
  consent: () => userHasOptedIn(),  // Respect user preferences
  eventMapping: (entry) => {
    // Map log entries to analytics events
    return {
      eventName: `${entry.context}:${entry.levelName}`,
      properties: entry.metadata || {}
    };
  }
}));

// Now regular logs can trigger analytics when appropriate
const checkoutLogger = createLogger('Checkout');
checkoutLogger.info('Purchase completed', { 
  amount: 99.99,
  productId: 'PRD-123',
  currency: 'USD'
});

Benefits of federated analytics with Caretta:

  • Unified logging and analytics instrumentation
  • Consistent sampling and filtering across services
  • Privacy controls built-in
  • No vendor lock-in

Advanced Usage

Environment Detection

import { Logger, LogLevel, createLogger } from '@catsle/caretta';

// Configure based on environment
const isDevelopment = process.env.NODE_ENV !== 'production';
Logger.setGlobalLevel(isDevelopment ? LogLevel.DEBUG : LogLevel.INFO);

// Add environment-specific plugins
if (isDevelopment) {
  const { DevToolsPlugin } = require('@catsle/caretta-devtools');
  Logger.registerPlugin(new DevToolsPlugin());
} else {
  const { CloudWatchPlugin } = require('@catsle/caretta-cloudwatch');
  Logger.registerPlugin(new CloudWatchPlugin({ region: 'us-west-2' }));
}

Log Management

import { Logger, createLogger } from '@catsle/caretta';

// Create loggers for different components
const authLogger = createLogger('Auth');
const apiLogger = createLogger('API');
const uiLogger = createLogger('UI');

// List all registered loggers (useful for debugging)
Logger.listFormatted();
// Output:
// | Context | Level | Enabled | Instance Level |
// |---------|-------|---------|---------------|
// | Auth    | INFO  | Yes     | (Global)      |
// | API     | INFO  | Yes     | DEBUG         |
// | UI      | INFO  | Yes     | (Global)      |

// Disable noisy loggers temporarily
Logger.disableByContext('API');

// Later, re-enable with specific level
Logger.enableByContext('API', LogLevel.WARN);

Global Access

// After importing and setting up @catsle/caretta
import { setupGlobalAccess } from '@catsle/caretta';

// Make logger available globally
await setupGlobalAccess();

// Now you can access logger anywhere, even in imported scripts
console.log('Global logger available:', typeof globalThis.log !== 'undefined');

// Create new loggers
const logger = globalThis.log.create('GlobalExample');

// Use global helpers
globalThis.log.setLevel(globalThis.log.levels.DEBUG);

Recipes

React Application Setup

// src/logging/setup.ts
import { Logger, LogLevel, createLogger } from '@catsle/caretta';
import { ConsolePlugin } from '@catsle/caretta-console-plugin';
import { ReactLoggerPlugin } from '@catsle/caretta-react';

export function setupLogging() {
  // Configure based on environment
  const isDev = process.env.NODE_ENV === 'development';
  Logger.setGlobalLevel(isDev ? LogLevel.DEBUG : LogLevel.INFO);
  
  // Add application metadata
  Logger.setGlobalMetadata('appVersion', process.env.APP_VERSION);
  Logger.setGlobalMetadata('environment', process.env.NODE_ENV);
  
  // Register plugins
  Logger.registerPlugin(new ConsolePlugin({ colors: isDev }));
  Logger.registerPlugin(new ReactLoggerPlugin());
  
  // Production-only plugins
  if (!isDev) {
    import('@catsle/caretta-sentry-plugin').then(({ SentryPlugin }) => {
      Logger.registerPlugin(new SentryPlugin({ dsn: process.env.SENTRY_DSN }));
    });
  }
  
  // Return root logger
  return createLogger('App');
}

// In your React components:
import { createLogger } from '@catsle/caretta';

function UserProfile({ userId }) {
  const logger = createLogger('UserProfile');
  
  useEffect(() => {
    logger.info('Component mounted', { userId });
    
    return () => {
      logger.debug('Component unmounted');
    };
  }, [userId]);
  
  // Rest of component...
}

Node.js API Server

// src/logger.ts
import { Logger, LogLevel, createLogger } from '@catsle/caretta';
import { ConsolePlugin } from '@catsle/caretta-console-plugin';
import { PinoPlugin } from '@catsle/caretta-pino';

export function initializeLogging() {
  // Set up global configuration
  Logger.setGlobalLevel(process.env.LOG_LEVEL || LogLevel.INFO);
  
  // Add server metadata
  Logger.setGlobalMetadata('serverId', process.env.SERVER_ID);
  Logger.setGlobalMetadata('region', process.env.AWS_REGION);
  
  // Register plugins
  Logger.registerPlugin(new ConsolePlugin({ 
    format: 'json',
    timestamp: true
  }));
  
  // Use Pino for production logging
  if (process.env.NODE_ENV === 'production') {
    Logger.registerPlugin(new PinoPlugin({
      destination: pino.destination({
        dest: process.env.LOG_FILE || '/var/log/app.log',
        sync: false
      })
    }));
  }
}

// In your API routes:
import { createLogger } from '@catsle/caretta';

const apiLogger = createLogger('API');

app.get('/users/:id', (req, res) => {
  apiLogger.info('User request', { 
    userId: req.params.id,
    ip: req.ip,
    route: '/users/:id' 
  });
  
  // Rest of handler...
});

API Reference

See the full API documentation for complete details.

Contributing

We welcome contributions! See CONTRIBUTING.md for details.

License

MIT