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

@dqcai/logger

v4.0.0

Published

Universal Logger Library for every environment: React, React Native, Vue, Angular, Node.js, Browser

Readme

@dqcai/[email protected]

🚀 Universal Logging Library for JavaScript & TypeScript

Cross-platform logging for Node.js, Web, React Native, and Electron with advanced transport system, decorator patterns, and flexible configuration.

The most flexible, modern, and developer-friendly logger for real-world projects.

💡 This library is fully generated by AI on the author's idea.

NPM Version License Downloads TypeScript ES2017


✨ What's New in v3.0.0?

🚀 Major Features

  • 🗄️ Database Transport → Store logs in SQLite, PostgreSQL, MySQL, MongoDB
  • 🌐 API Transport → Send logs to remote logging services
  • ⚡ Environment-Specific Transports → Optimized for Node.js, React Native, Electron
  • 🔌 Dynamic Import → Load third-party dependencies only when needed
  • 🛠️ Custom Transport API → Build your own transport with simple interface
  • 📊 Built-in Statistics → Track log metrics and performance
  • 🔄 Session Tracking → Group logs by session ID
  • ⚙️ Auto-cleanup → Manage log retention and file rotation

✨ Why @dqcai/logger?

When building apps across multiple environments (Web, Node.js, React Native, Electron), logging is often fragmented and inconsistent.

@dqcai/logger solves this with a single, unified API and pluggable transports that work everywhere:

  • 🌍 Cross-platform → One library for Web, Node.js, React Native, Electron
  • 🛠 Flexible configuration → Control logs by module, log level, transport
  • 📂 Multiple transports → Console, File, Database, API, or custom transport
  • 🗄️ Database logging → Built-in support for SQLite, PostgreSQL, MySQL, MongoDB
  • 🌐 API logging → Send logs to remote services with batching and retry
  • 🔧 Runtime control → Enable/disable logs dynamically
  • 🎯 Module-based logging → Organize logs per feature/service
  • 💡 TypeScript-first → Strongly typed, tree-shakable, ESM & CJS ready
  • Smart dependencies → Dynamic imports, zero overhead for unused features
  • 🎨 Logger Decorators → Advanced patterns for method logging, performance monitoring, caching, and retry logic
  • 🏗️ Global Configuration → Centralized logger management with CommonLoggerConfig

🏆 Instead of juggling winston, pino, and react-native-logs, use one consistent solution across all platforms.


📦 Installation

npm install @dqcai/logger
# or
yarn add @dqcai/logger
# or
pnpm add @dqcai/logger

Optional Dependencies (Auto-loaded when needed)

# Database Transport
npm install @dqcai/orm  # For database logging

# React Native File Transport
npm install react-native-fs  # For React Native file logging

# API Transport
npm install axios  # For HTTP logging

# Electron File Transport
# No additional dependencies needed - uses Electron's native APIs

Note: Third-party dependencies are loaded dynamically only when you use the corresponding transport. This keeps your bundle size minimal.


🚀 Quick Start

🆕 v3.0.0 - Recommended Setup (Global Configuration)

Create a centralized logger configuration file in your project:

// ./src/configs/logger.ts
import {
  LoggerConfigBuilder,
  CommonLoggerConfig,
  CommonModules,
  createModuleLogger,
} from "@dqcai/logger";

// Define your application modules
const AppModules = {
  ...CommonModules,
  AUTH: "Authentication",
  DATABASE: "Database",
  API: "ApiService",
  MIDDLEWARE: "Middleware",
  UTILS: "Utils"
};

// Create global configuration
const config = new LoggerConfigBuilder()
  .setEnabled(true)
  .setDefaultLevel("info")
  .addModule(AppModules.AUTH, true, ["info", "warn", "error"], ["console", "db"])
  .addModule(AppModules.DATABASE, true, ["debug", "info", "error"], ["console", "node-file"])
  .addModule(AppModules.API, true, ["info", "warn", "error"], ["console", "api"])
  .build();

// Apply configuration globally
CommonLoggerConfig.updateConfiguration(config);

// Export for use throughout your application
export { createModuleLogger, AppModules };

Using the Global Configuration

// ./src/services/authService.ts
import { createModuleLogger, AppModules } from "@/configs/logger";

const logger = createModuleLogger(AppModules.AUTH);

class AuthService {
  async login(credentials: { email: string; password: string }) {
    logger.info("User login attempt", { email: credentials.email });
    
    try {
      const user = await this.authenticate(credentials);
      logger.info("Login successful", { userId: user.id });
      return user;
    } catch (error) {
      logger.error("Login failed", { 
        email: credentials.email,
        error: error.message 
      });
      throw error;
    }
  }
}

🚛 Transport System

Transport Architecture

@dqcai/logger v3.0 introduces a powerful transport system that allows you to send logs to multiple destinations simultaneously. Each transport is independent and can be configured separately.

Key Features:

  • ✅ Multiple transports active simultaneously
  • ✅ Environment-specific optimizations
  • ✅ Dynamic dependency loading
  • ✅ Automatic batching and buffering
  • ✅ Built-in retry mechanisms
  • ✅ Session tracking
  • ✅ Statistics and monitoring

Available Transports

| Transport | Platform | Use Case | Dependencies | |-----------|----------|----------|--------------| | ConsoleTransport | All | Development, debugging | None | | NodeFileTransport | Node.js | Server logs, audit trails | None (uses fs) | | RNFileTransport | React Native | Mobile app logs | react-native-fs | | ElectronFileTransport | Electron | Desktop app logs | None (uses Electron API) | | DBTransport | All | Structured logging, analytics | @dqcai/orm | | ApiTransport | All | Remote logging, monitoring | axios | | Custom | All | Your specific needs | As needed |


📂 Built-in Transports

1. ConsoleTransport (Default)

The simplest transport for console output. Works everywhere.

import { ConsoleTransport, CommonLoggerConfig } from "@dqcai/logger";

const consoleTransport = new ConsoleTransport();
CommonLoggerConfig.addTransport(consoleTransport);

Features:

  • ✅ Zero dependencies
  • ✅ Colored output (in supported terminals)
  • ✅ Minimal overhead
  • ✅ Perfect for development

2. NodeFileTransport (Node.js)

High-performance file logging for Node.js applications with automatic rotation.

import { NodeFileTransport, CommonLoggerConfig } from "@dqcai/logger";

const fileTransport = new NodeFileTransport({
  filePath: "./logs/app.log",
  maxFileSize: 10 * 1024 * 1024, // 10MB
  maxFiles: 5, // Keep 5 rotated files
  enableInternalLogging: false
});

CommonLoggerConfig.addTransport(fileTransport);

Configuration Options:

interface NodeFileTransportConfig {
  filePath: string;              // Path to log file
  maxFileSize?: number;          // Max size before rotation (default: 10MB)
  maxFiles?: number;             // Number of rotated files to keep (default: 5)
  enableInternalLogging?: boolean; // Log transport operations (default: false)
}

Features:

  • ✅ Automatic file rotation when size limit reached
  • ✅ Configurable retention policy
  • ✅ High-performance async I/O
  • ✅ JSON format for easy parsing
  • ✅ No external dependencies

Example Usage:

import { createModuleLogger, CommonLoggerConfig } from "@dqcai/logger";
import { NodeFileTransport } from "@dqcai/logger";

// Setup transport
const fileTransport = new NodeFileTransport({
  filePath: "./logs/server.log",
  maxFileSize: 5 * 1024 * 1024, // 5MB
  maxFiles: 10
});

CommonLoggerConfig.addTransport(fileTransport);

// Use logger
const logger = createModuleLogger("ServerApp");

logger.info("Server started", { port: 3000 });
logger.error("Database connection failed", { 
  error: "ECONNREFUSED",
  host: "localhost" 
});

// Flush logs before shutdown
await CommonLoggerConfig.flush();

// Read logs programmatically
const logs = await fileTransport.getLogs();
logs.forEach(content => {
  const lines = content.split('\n').filter(l => l.trim());
  lines.forEach(line => {
    const entry = JSON.parse(line);
    console.log(`[${entry.level}] ${entry.message}`);
  });
});

// Clear old logs
await fileTransport.clearLogs();

File Rotation Example:

logs/
├── app.log              ← Current log file
├── app.log.1            ← Most recent rotation
├── app.log.2
├── app.log.3
├── app.log.4
└── app.log.5            ← Oldest rotation (will be deleted next)

3. RNFileTransport (React Native)

Optimized file logging for React Native applications.

import { RNFileTransport, CommonLoggerConfig } from "@dqcai/logger";

const rnFileTransport = new RNFileTransport({
  fileName: "app.log",
  maxFileSize: 5 * 1024 * 1024, // 5MB
  enableInternalLogging: false
});

CommonLoggerConfig.addTransport(rnFileTransport);

Configuration Options:

interface RNFileTransportConfig {
  fileName?: string;             // Log filename (default: 'app.log')
  maxFileSize?: number;          // Max size before rotation (default: 10MB)
  enableInternalLogging?: boolean; // Log transport operations (default: false)
}

Features:

  • ✅ Uses react-native-fs for file operations
  • ✅ Automatic file rotation
  • ✅ Works on both iOS and Android
  • ✅ Persists across app restarts

Installation:

npm install react-native-fs
# iOS
cd ios && pod install

Example Usage:

import { createModuleLogger, CommonLoggerConfig } from "@dqcai/logger";
import { RNFileTransport } from "@dqcai/logger";
import RNFS from "react-native-fs";

// Setup transport
const rnTransport = new RNFileTransport({
  fileName: "myapp.log",
  maxFileSize: 3 * 1024 * 1024 // 3MB
});

CommonLoggerConfig.addTransport(rnTransport);

// Use logger
const logger = createModuleLogger("MobileApp");

logger.info("App launched", { version: "1.0.0" });
logger.warn("Low storage", { available: "50MB" });

// Export logs for user
const exportLogs = async () => {
  const logs = await rnTransport.getLogs();
  const logPath = `${RNFS.DocumentDirectoryPath}/exported-logs.txt`;
  await RNFS.writeFile(logPath, logs.join('\n\n'), 'utf8');
  // Share file with user...
};

4. ElectronFileTransport (Electron)

Specialized transport for Electron desktop applications.

import { ElectronFileTransport, CommonLoggerConfig } from "@dqcai/logger";

const electronTransport = new ElectronFileTransport({
  fileName: "app.log",
  maxFileSize: 10 * 1024 * 1024, // 10MB
  maxFiles: 5,
  enableInternalLogging: false
});

CommonLoggerConfig.addTransport(electronTransport);

Configuration Options:

interface ElectronFileTransportConfig {
  fileName?: string;             // Log filename (default: 'app.log')
  maxFileSize?: number;          // Max size before rotation (default: 10MB)
  maxFiles?: number;             // Number of rotated files (default: 5)
  enableInternalLogging?: boolean; // Log transport operations (default: false)
}

Features:

  • ✅ Uses Electron's app.getPath('userData') for log directory
  • ✅ Works in both main and renderer processes
  • ✅ Automatic file rotation
  • ✅ No external dependencies

Example Usage:

// Main Process
import { app } from "electron";
import { createModuleLogger, CommonLoggerConfig } from "@dqcai/logger";
import { ElectronFileTransport } from "@dqcai/logger";

app.on("ready", () => {
  const electronTransport = new ElectronFileTransport({
    fileName: "main.log",
    maxFileSize: 5 * 1024 * 1024
  });

  CommonLoggerConfig.addTransport(electronTransport);

  const logger = createModuleLogger("ElectronMain");
  logger.info("Electron app ready", { version: app.getVersion() });
});

// Renderer Process
import { createModuleLogger } from "@dqcai/logger";

const logger = createModuleLogger("ElectronRenderer");
logger.info("Window loaded", { url: window.location.href });

Log Location:

  • Windows: %APPDATA%\YourApp\logs\app.log
  • macOS: ~/Library/Application Support/YourApp/logs/app.log
  • Linux: ~/.config/YourApp/logs/app.log

5. DBTransport (Database Logging)

Store logs in a database for advanced querying, analytics, and monitoring.

import { DBTransport, CommonLoggerConfig } from "@dqcai/logger";

const dbTransport = new DBTransport({
  databaseType: "sqlite",      // 'sqlite' | 'postgresql' | 'mysql' | 'mongodb'
  database: "logger",
  dbDirectory: "./logs",       // For SQLite
  batchSize: 50,               // Batch insert size
  flushInterval: 5000,         // Auto-flush every 5s
  enableStatistics: true,      // Track log statistics
  enableErrorTable: true,      // Separate table for errors
  enableInternalLogging: false
});

CommonLoggerConfig.addTransport(dbTransport);

Configuration Options:

interface DBTransportConfig {
  databaseType: 'sqlite' | 'postgresql' | 'mysql' | 'mongodb';
  database: string;              // Database name
  dbDirectory?: string;          // SQLite directory (default: './logs')
  host?: string;                 // For remote databases
  port?: number;                 // For remote databases
  username?: string;             // For remote databases
  password?: string;             // For remote databases
  batchSize?: number;            // Batch insert size (default: 50)
  flushInterval?: number;        // Auto-flush interval (default: 5000ms)
  enableStatistics?: boolean;    // Track statistics (default: true)
  enableErrorTable?: boolean;    // Separate error table (default: true)
  enableInternalLogging?: boolean; // Log transport operations (default: false)
}

Features:

  • ✅ Support for SQLite, PostgreSQL, MySQL, MongoDB
  • ✅ Automatic table creation and schema management
  • ✅ Batch inserts for performance
  • ✅ Session tracking
  • ✅ Built-in statistics
  • ✅ Query logs by level, module, session, date range
  • ✅ Automatic cleanup of old logs

Database Schema:

-- logs table
CREATE TABLE logs (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  timestamp TEXT NOT NULL,
  level TEXT NOT NULL,
  module TEXT NOT NULL,
  message TEXT NOT NULL,
  data TEXT,
  session_id TEXT,
  created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

-- errors table (if enableErrorTable: true)
CREATE TABLE errors (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  timestamp TEXT NOT NULL,
  module TEXT NOT NULL,
  message TEXT NOT NULL,
  error_data TEXT,
  stack_trace TEXT,
  session_id TEXT,
  created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

-- statistics table (if enableStatistics: true)
CREATE TABLE log_statistics (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  date TEXT NOT NULL,
  module TEXT NOT NULL,
  level TEXT NOT NULL,
  count INTEGER DEFAULT 0,
  UNIQUE(date, module, level)
);

Example Usage:

import { createModuleLogger, CommonLoggerConfig } from "@dqcai/logger";
import { DBTransport } from "@dqcai/logger";

// Setup transport
const dbTransport = new DBTransport({
  databaseType: "sqlite",
  database: "myapp",
  dbDirectory: "./logs",
  batchSize: 100,
  enableStatistics: true,
  enableErrorTable: true
});

CommonLoggerConfig.addTransport(dbTransport);

// Start a session
const sessionId = await dbTransport.startSession("user_session_001");

// Use logger
const logger = createModuleLogger("UserService");

logger.info("User logged in", { 
  userId: "user_123",
  email: "[email protected]"
});

logger.error("Payment failed", {
  orderId: "order_456",
  amount: 99.99,
  error: "Insufficient funds"
});

// Flush logs
await CommonLoggerConfig.flush();

// Query logs
const errorLogs = await dbTransport.getLogsByLevel("error", 10);
console.log("Recent errors:", errorLogs);

const userLogs = await dbTransport.getLogsByModule("UserService", 20);
console.log("User service logs:", userLogs);

const sessionLogs = await dbTransport.getLogsBySession(sessionId);
console.log("Session logs:", sessionLogs);

// Get statistics
const stats = await dbTransport.getStatistics();
console.log("Daily statistics:", stats);

// Advanced query
const customLogs = await dbTransport.queryLogs(
  {
    level: "error",
    module: "UserService",
    startDate: "2025-01-01",
    endDate: "2025-01-31"
  },
  { limit: 50, offset: 0 }
);

// Cleanup old logs (older than 90 days)
const deletedCount = await dbTransport.clearOldLogs(90);
console.log(`Deleted ${deletedCount} old logs`);

// End session
await dbTransport.endSession();

// Get transport statistics
const transportStats = await dbTransport.getTransportStats();
console.log("Transport stats:", transportStats);
/*
{
  totalLogs: 1523,
  errorCount: 45,
  bufferSize: 12,
  levelCounts: {
    trace: 234,
    debug: 567,
    info: 634,
    warn: 43,
    error: 45
  }
}
*/

PostgreSQL Example:

const dbTransport = new DBTransport({
  databaseType: "postgresql",
  database: "myapp_logs",
  host: "localhost",
  port: 5432,
  username: "logger",
  password: "secure_password",
  batchSize: 100,
  enableStatistics: true
});

MongoDB Example:

const dbTransport = new DBTransport({
  databaseType: "mongodb",
  database: "myapp_logs",
  host: "localhost",
  port: 27017,
  username: "logger",
  password: "secure_password",
  batchSize: 100
});

6. ApiTransport (Remote Logging)

Send logs to a remote API endpoint with batching, retry, and error handling.

import { ApiTransport, CommonLoggerConfig } from "@dqcai/logger";

const apiTransport = new ApiTransport({
  baseURL: "https://logs.example.com",
  endpoint: "/api/logs",
  apiKey: "your-api-key",
  batchSize: 20,
  batchTimeout: 5000,
  maxRetries: 3,
  retryDelay: 1000,
  enableInternalLogging: false
});

CommonLoggerConfig.addTransport(apiTransport);

Configuration Options:

interface ApiTransportConfig {
  baseURL: string;               // API base URL
  endpoint?: string;             // Log endpoint (default: '/logs')
  apiKey?: string;               // API authentication key
  headers?: Record<string, string>; // Custom headers
  batchSize?: number;            // Batch size (default: 10)
  batchTimeout?: number;         // Batch timeout (default: 5000ms)
  maxRetries?: number;           // Retry attempts (default: 3)
  retryDelay?: number;           // Retry delay (default: 1000ms)
  enableInternalLogging?: boolean; // Log transport operations (default: false)
}

Features:

  • ✅ Automatic batching for efficiency
  • ✅ Exponential backoff retry
  • ✅ Custom headers and authentication
  • ✅ Network error handling
  • ✅ Queue management
  • ✅ Uses axios (auto-loaded)

Example Usage:

import { createModuleLogger, CommonLoggerConfig } from "@dqcai/logger";
import { ApiTransport } from "@dqcai/logger";

// Setup transport
const apiTransport = new ApiTransport({
  baseURL: "https://api.loggingservice.com",
  endpoint: "/v1/logs",
  apiKey: "sk_live_abc123xyz",
  headers: {
    "X-App-Version": "1.0.0",
    "X-Environment": "production"
  },
  batchSize: 50,
  batchTimeout: 10000,
  maxRetries: 5
});

CommonLoggerConfig.addTransport(apiTransport);

// Use logger
const logger = createModuleLogger("ApiService");

logger.info("API request", {
  method: "POST",
  endpoint: "/users",
  duration: "45ms"
});

logger.error("API timeout", {
  endpoint: "/orders",
  timeout: 5000,
  retries: 3
});

// Manually flush if needed (automatic batching handles this normally)
await apiTransport.flush();

Expected API Request Format:

POST /api/logs
Content-Type: application/json
Authorization: Bearer your-api-key

{
  "logs": [
    {
      "timestamp": "2025-01-15T10:30:45.123Z",
      "level": "info",
      "module": "ApiService",
      "message": "API request",
      "data": {
        "method": "POST",
        "endpoint": "/users",
        "duration": "45ms"
      }
    },
    {
      "timestamp": "2025-01-15T10:31:12.456Z",
      "level": "error",
      "module": "ApiService",
      "message": "API timeout",
      "data": {
        "endpoint": "/orders",
        "timeout": 5000,
        "retries": 3
      }
    }
  ]
}

🔧 Creating Custom Transports

You can create your own transport to send logs anywhere you need. Simply implement the ILogTransport interface.

Transport Interface

interface ILogTransport {
  readonly name: string;                    // Unique transport name
  log(entry: LogEntry): Promise<void>;      // Handle a single log entry
  flush?(): Promise<void>;                  // Optional: flush buffered logs
  cleanup?(): Promise<void>;                // Optional: cleanup resources
}

interface LogEntry {
  timestamp: string;
  level: string;
  module: string;
  message: string;
  data?: any;
  metadata?: any;
}

Example: Slack Transport

import { ILogTransport, LogEntry } from "@dqcai/logger";
import axios from "axios";

export class SlackTransport implements ILogTransport {
  readonly name = "slack";
  private webhookUrl: string;
  private channel: string;
  private minLevel: string;

  constructor(config: {
    webhookUrl: string;
    channel?: string;
    minLevel?: string;
  }) {
    this.webhookUrl = config.webhookUrl;
    this.channel = config.channel || "#logs";
    this.minLevel = config.minLevel || "error";
  }

  async log(entry: LogEntry): Promise<void> {
    // Only send errors and above
    if (!this.shouldLog(entry.level)) {
      return;
    }

    const color = this.getLevelColor(entry.level);
    const emoji = this.getLevelEmoji(entry.level);

    try {
      await axios.post(this.webhookUrl, {
        channel: this.channel,
        attachments: [
          {
            color: color,
            title: `${emoji} ${entry.level.toUpperCase()}: ${entry.module}`,
            text: entry.message,
            fields: entry.data ? [
              {
                title: "Details",
                value: "```" + JSON.stringify(entry.data, null, 2) + "```",
                short: false
              }
            ] : [],
            footer: "Logger",
            ts: Date.now() / 1000
          }
        ]
      });
    } catch (error) {
      console.error("[SlackTransport] Failed to send log:", error);
    }
  }

  private shouldLog(level: string): boolean {
    const levels = ["trace", "debug", "info", "warn", "error"];
    const minIndex = levels.indexOf(this.minLevel);
    const currentIndex = levels.indexOf(level);
    return currentIndex >= minIndex;
  }

  private getLevelColor(level: string): string {
    const colors: Record<string, string> = {
      error: "danger",
      warn: "warning",
      info: "good",
      debug: "#439FE0",
      trace: "#CCCCCC"
    };
    return colors[level] || "good";
  }

  private getLevelEmoji(level: string): string {
    const emojis: Record<string, string> = {
      error: "🚨",
      warn: "⚠️",
      info: "ℹ️",
      debug: "🐛",
      trace: "🔍"
    };
    return emojis[level] || "📝";
  }
}

// Usage
import { CommonLoggerConfig, createModuleLogger } from "@dqcai/logger";

const slackTransport = new SlackTransport({
  webhookUrl: "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
  channel: "#production-errors",
  minLevel: "error"
});

CommonLoggerConfig.addTransport(slackTransport);

const logger = createModuleLogger("CriticalService");
logger.error("Payment processing failed", {
  orderId: "12345",
  amount: 99.99,
  reason: "Card declined"
});

Example: Sentry Transport

import { ILogTransport, LogEntry } from "@dqcai/logger";
import * as Sentry from "@sentry/node";

export class SentryTransport implements ILogTransport {
  readonly name = "sentry";

  constructor(config: { dsn: string; environment?: string }) {
    Sentry.init({
      dsn: config.dsn,
      environment: config.environment || "production"
    });
  }

  async log(entry: LogEntry): Promise<void> {
    if (entry.level === "error") {
      Sentry.captureException(new Error(entry.message), {
        level: "error",
        tags: {
          module: entry.module
        },
        extra: entry.data
      });
    } else if (entry.level === "warn") {
      Sentry.captureMessage(entry.message, {
        level: "warning",
        tags: {
          module: entry.module
        },
        extra: entry.data
      });
    }
  }

  async cleanup(): Promise<void> {
    await Sentry.close(2000);
  }
}

Example: Email Transport

import { ILogTransport, LogEntry } from "@dqcai/logger";
import nodemailer from "nodemailer";

export class EmailTransport implements ILogTransport {
  readonly name = "email";
  private transporter: any;
  private recipient: string;
  private logBuffer: LogEntry[] = [];
  private flushTimer: NodeJS.Timeout | null = null;

  constructor(config: {
    smtpHost: string;
    smtpPort: number;
    smtpUser: string;
    smtpPass: string;
    recipient: string;
    batchSize?: number;
    batchTimeout?: number;
  }) {
    this.transporter = nodemailer.createTransporter({
      host: config.smtpHost,
      port: config.smtpPort,
      auth: {
        user: config.smtpUser,
        pass: config.smtpPass
      }
    });
    this.recipient = config.recipient;
  }

  async log(entry: LogEntry): Promise<void> {
    // Only email errors
    if (entry.level !== "error") return;

    this.logBuffer.push(entry);

    if (this.logBuffer.length >= 5) {
      await this.flush();
    } else if (!this.flushTimer) {
      this.flushTimer = setTimeout(() => this.flush(), 60000); // 1 minute
    }
  }

  async flush(): Promise<void> {
    if (this.logBuffer.length === 0) return;

    const logs = [...this.logBuffer];
    this.logBuffer = [];

    if (this.flushTimer) {
      clearTimeout(this.flushTimer);
      this.flushTimer = null;
    }

    const html = this.formatLogsAsHTML(logs);

    try {
      await this.transporter.sendMail({
        from: "[email protected]",
        to: this.recipient,
        subject: `[Logger] ${logs.length} Error(s) Detected`,
        html: html
      });
    } catch (error) {
      console.error("[EmailTransport] Failed to send email:", error);
    }
  }

  private formatLogsAsHTML(logs: LogEntry[]): string {
    return `
      <h2>Error Log Report</h2>
      <p>Generated: ${new Date().toISOString()}</p>
      <table border="1" cellpadding="5">
        <thead>
          <tr>
            <th>Time</th>
            <th>Module</th>
            <th>Message</th>
            <th>Details</th>
          </tr>
        </thead>
        <tbody>
          ${logs.map(log => `
            <tr>
              <td>${log.timestamp}</td>
              <td>${log.module}</td>
              <td>${log.message}</td>
              <td><pre>${JSON.stringify(log.data, null, 2)}</pre></td>
            </tr>
          `).join('')}
        </tbody>
      </table>
    `;
  }
}

Best Practices for Custom Transports

  1. Error Handling: Always wrap transport operations in try-catch
  2. Performance: Use batching for network transports
  3. Cleanup: Implement cleanup() to release resources
  4. Async Operations: Make log() async for I/O operations
  5. Buffering: Buffer logs and flush periodically for efficiency
  6. Retry Logic: Implement retry for unreliable destinations
  7. Configuration: Make transports configurable
  8. Testing: Test with CommonLoggerConfig.flush()

⚙️ Advanced Configuration

Multi-Transport Setup

import {
  LoggerConfigBuilder,
  CommonLoggerConfig,
  NodeFileTransport,
  DBTransport,
  ApiTransport
} from "@dqcai/logger";

// Create transports
const fileTransport = new NodeFileTransport({
  filePath: "./logs/app.log",
  maxFileSize: 10 * 1024 * 1024
});

const dbTransport = new DBTransport({
  databaseType: "sqlite",
  database: "logs",
  enableStatistics: true
});

const apiTransport = new ApiTransport({
  baseURL: "https://logs.example.com",
  apiKey: "your-api-key",
  batchSize: 50
});

// Add all transports
CommonLoggerConfig.addTransport(fileTransport);
CommonLoggerConfig.addTransport(dbTransport);
CommonLoggerConfig.addTransport(apiTransport);

// Configure modules with different transport combinations
const config = new LoggerConfigBuilder()
  .setEnabled(true)
  .setDefaultLevel("info")
  .addModule("CriticalService", true, 
    ["error"], 
    ["console", "node-file", "db", "api"]  // All transports
  )
  .addModule("BackgroundJob", true,
    ["info", "warn", "error"],
    ["node-file", "db"]  // File and DB only
  )
  .addModule("WebServer", true,
    ["debug", "info", "warn", "error"],
    ["console", "node-file"]  // Console and file
  )
  .build();

CommonLoggerConfig.updateConfiguration(config);

Environment-Based Configuration

class LoggerFactory {
  static createLogger() {
    const env = process.env.NODE_ENV || "development";
    
    // Clear existing transports
    CommonLoggerConfig.setTransports([]);
    
    switch (env) {
      case "development":
        CommonLoggerConfig.addTransport(new ConsoleTransport());
        return this.createDevConfig();
      
      case "production":
        CommonLoggerConfig.addTransport(new DBTransport({
          databaseType: "postgresql",
          host: process.env.DB_HOST,
          database: "logs"
        }));
        CommonLoggerConfig.addTransport(new ApiTransport({
          baseURL: process.env.LOG_API_URL,
          apiKey: process.env.LOG_API_KEY
        }));
        return this.createProdConfig();
      
      case "test":
        // No transports for testing
        return this.createTestConfig();
    }
  }
  
  private static createDevConfig() {
    return new LoggerConfigBuilder()
      .setEnabled(true)
      .setDefaultLevel("debug")
      .addModule("App", true, ["debug", "info", "warn", "error"], ["console"])
      .build();
  }
  
  private static createProdConfig() {
    return new LoggerConfigBuilder()
      .setEnabled(true)
      .setDefaultLevel("info")
      .addModule("critical", true, ["error"], ["db", "api"])
      .addModule("normal", true, ["warn", "error"], ["db"])
      .build();
  }
  
  private static createTestConfig() {
    return new LoggerConfigBuilder()
      .setEnabled(false)
      .build();
  }
}

// Apply configuration
const config = LoggerFactory.createLogger();
CommonLoggerConfig.updateConfiguration(config);

🎨 Logger Decorators

Logger Decorators remain unchanged from v2.1.0. See the decorator examples in the original documentation for:

  • LogMethod Decorator
  • LogPerformance Decorator
  • LogCache Decorator
  • LogRetry Decorator
  • Combined Decorators

📊 Best Practices

1. Transport Selection by Environment

// Development: Console only for fast feedback
if (process.env.NODE_ENV === "development") {
  CommonLoggerConfig.addTransport(new ConsoleTransport());
}

// Staging: File + DB for testing
if (process.env.NODE_ENV === "staging") {
  CommonLoggerConfig.addTransport(new NodeFileTransport({
    filePath: "./logs/staging.log"
  }));
  CommonLoggerConfig.addTransport(new DBTransport({
    databaseType: "sqlite",
    database: "staging_logs"
  }));
}

// Production: DB + API for monitoring
if (process.env.NODE_ENV === "production") {
  CommonLoggerConfig.addTransport(new DBTransport({
    databaseType: "postgresql",
    host: process.env.DB_HOST,
    database: "production_logs"
  }));
  CommonLoggerConfig.addTransport(new ApiTransport({
    baseURL: process.env.MONITORING_URL,
    apiKey: process.env.MONITORING_API_KEY
  }));
}

2. Graceful Shutdown

process.on("SIGTERM", async () => {
  console.log("Shutting down gracefully...");
  
  // Flush all pending logs
  await CommonLoggerConfig.flush();
  
  // Cleanup transports
  await CommonLoggerConfig.cleanup();
  
  process.exit(0);
});

3. Session Tracking

// Express middleware
app.use(async (req, res, next) => {
  const sessionId = req.sessionID || generateSessionId();
  
  // Start session in DB transport
  const dbTransport = CommonLoggerConfig.getTransport("db");
  if (dbTransport) {
    await dbTransport.startSession(sessionId);
  }
  
  // Attach logger to request
  req.logger = createModuleLogger("WebServer");
  req.logger.info("Request received", {
    method: req.method,
    url: req.url,
    ip: req.ip
  });
  
  res.on("finish", async () => {
    req.logger.info("Request completed", {
      statusCode: res.statusCode,
      duration: Date.now() - req.startTime
    });
    
    // End session
    if (dbTransport) {
      await dbTransport.endSession();
    }
  });
  
  next();
});

4. Log Retention Strategy

// Cleanup job (run daily)
import { DBTransport } from "@dqcai/logger";

const dbTransport = CommonLoggerConfig.getTransport("db") as DBTransport;

// Delete logs older than 90 days
const deletedCount = await dbTransport.clearOldLogs(90);
console.log(`Cleaned up ${deletedCount} old logs`);

// Rotate files daily
import { NodeFileTransport } from "@dqcai/logger";

const fileTransport = CommonLoggerConfig.getTransport("node-file") as NodeFileTransport;
await fileTransport.rotateLogs(10 * 1024 * 1024); // Rotate if > 10MB

📋 Migration Guide

From v2.1.0 to v3.0.0

Breaking Changes:

  • Transport names have changed (e.g., "file""node-file")
  • Dynamic imports for optional dependencies
  • New transport configuration format

Migration Steps:

  1. Update Transport Names
// Before (v2.1.0)
.addModule("Auth", true, ["info"], ["console", "file"])

// After (v3.0.0)
.addModule("Auth", true, ["info"], ["console", "node-file"])
  1. Update File Transport Configuration
// Before (v2.1.0)
import { FileTransport } from "@dqcai/logger";
const transport = new FileTransport("./logs/app.log");

// After (v3.0.0)
import { NodeFileTransport } from "@dqcai/logger";
const transport = new NodeFileTransport({
  filePath: "./logs/app.log",
  maxFileSize: 10 * 1024 * 1024,
  maxFiles: 5
});
  1. Install Optional Dependencies
# Only if you use these transports
npm install @dqcai/orm      # For DBTransport
npm install react-native-fs # For RNFileTransport
npm install axios           # For ApiTransport
  1. New Features (Optional)
// Use new DBTransport
import { DBTransport } from "@dqcai/logger";

const dbTransport = new DBTransport({
  databaseType: "sqlite",
  database: "logs"
});

CommonLoggerConfig.addTransport(dbTransport);

// Query logs
const errors = await dbTransport.getLogsByLevel("error");

📈 Comparison Table

| Feature | v2.1.0 | v3.0.0 | |---------|--------|--------| | Console Transport | ✅ | ✅ | | File Transport (Generic) | ✅ | ❌ | | Node.js File Transport | ❌ | ✅ | | React Native File Transport | ⚠️ | ✅ | | Electron File Transport | ❌ | ✅ | | Database Transport | ❌ | ✅ | | API Transport | ⚠️ | ✅ | | Custom Transports | ⚠️ | ✅ | | Dynamic Imports | ❌ | ✅ | | Session Tracking | ❌ | ✅ | | Statistics | ❌ | ✅ | | Log Querying | ❌ | ✅ | | Auto Cleanup | ❌ | ✅ | | Bundle Size | ~15KB | ~18KB core (transports loaded on-demand) |


🤖 AI-Powered Development

This project was built with AI assistance using Claude, ChatGPT, Grok, and Gemini.

Using AI with @dqcai/logger v3.0

You can use AI tools to generate custom transports:

Example Prompt:

Create a Redis transport for @dqcai/logger v3.0 that:
- Implements ILogTransport interface
- Stores logs in Redis lists with TTL
- Supports log levels as separate lists
- Has automatic cleanup of old logs
- Uses ioredis library

🌐 Community & Support

Get Help and Learn More

Join our AI developer community on Facebook:

👉 Facebook Fan Page: Doan Cuong AI

What you'll get:

  • 📘 Advanced usage patterns and examples
  • 🔧 Custom transport implementations
  • 🛠 Sample configurations for different platforms
  • 💬 Direct discussion with other developers
  • 🚀 AI learning resources

Contributing

Contributions, issues, and feature requests are welcome!


📄 License

MIT © Cuong Doan


🔥 Summary

@dqcai/logger v3.0 is the ultimate logging solution for modern JavaScript/TypeScript applications:

  • Universal: Node.js, Web, React Native, Electron
  • Powerful Transports: Console, File, Database, API, Custom
  • Smart Loading: Dynamic imports keep bundle size minimal
  • Production-Ready: Session tracking, statistics, auto-cleanup
  • Developer-Friendly: TypeScript-first, simple API, great DX
  • AI-Powered: Built with and for AI-assisted development

Stop juggling multiple logging libraries. Start with @dqcai/logger v3.0 today!

npm install @dqcai/logger

Your universal, powerful logging solution is just one command away!