Socket
Book a DemoInstallSign in
Socket

@dqcai/logger

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dqcai/logger

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

latest
Source
npmnpm
Version
2.1.0
Version published
Weekly downloads
100
56.25%
Maintainers
1
Weekly downloads
ย 
Created
Source

@dqcai/logger@2.1.0

๐Ÿš€ Universal Logging Library for JavaScript & TypeScript

Cross-platform logging for Node.js, Web, and React Native with advanced 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

โœจ Why @dqcai/logger?

When building apps across multiple environments (Web, Node.js, React Native), 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
  • ๐Ÿ›  Flexible configuration โ†’ Control logs by module, log level, transport
  • ๐Ÿ“‚ Multiple transports โ†’ Console, File, API, or custom transport
  • ๐Ÿ”ง Runtime control โ†’ Enable/disable logs dynamically
  • ๐ŸŽฏ Module-based logging โ†’ Organize logs per feature/service
  • ๐Ÿ’ก TypeScript-first โ†’ Strongly typed, tree-shakable, ESM & CJS ready
  • โšก Zero dependencies โ†’ Lightweight, only optional peer deps
  • ๐ŸŽจ Logger Decorators โ†’ Advanced patterns for method logging, performance monitoring, caching, and retry logic
  • ๐Ÿ—๏ธ Global Configuration โ†’ Centralized logger management with CommonLoggerConfig (v2.1.0+)

๐Ÿ† 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 transports

# React Native file logging
npm install react-native-fs

# API transport
npm install axios

๐Ÿš€ Quick Start

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,
  I18N_CLIENT: "I18next-client",
  I18N_PROVIDER: "I18next-provider", 
  I18N_SERVER: "I18next-server",
  CONTEXT: "Context",
  AUTH: "Authentication",
  DATABASE: "Database",
  API: "ApiService",
  MIDDLEWARE: "Middleware",
  UTILS: "Utils"
};

// Create global configuration
const config = new LoggerConfigBuilder()
  .setEnabled(true)
  .setDefaultLevel("trace")  // Available: trace, debug, info, warn, error
  .addModule(AppModules.AUTH, true, ["info", "warn", "error"], ["console"])
  .addModule(AppModules.DATABASE, true, ["debug", "info", "error"], ["console", "file"])
  .build();

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

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

/**
 * Basic Usage:
 * Simply import and use logger.trace/debug/info/warn/error instead of console.log/debug/warn/error
 * 
 * import { createModuleLogger, AppModules } from "@/configs/logger";
 * 
 * const logger = createModuleLogger(AppModules.MIDDLEWARE);
 * logger.trace("Middleware importing...");
 * logger.info("User authenticated successfully", { userId: 123 });
 * logger.error("Database connection failed", { error: "Connection timeout" });
 */

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.trace("Login attempt started");
    logger.info("User login attempt", { email: credentials.email });
    
    try {
      // Authentication logic here
      const user = await this.authenticate(credentials);
      
      logger.info("Login successful", { 
        userId: user.id, 
        email: user.email 
      });
      
      return user;
    } catch (error) {
      logger.error("Login failed", { 
        email: credentials.email,
        error: error.message 
      });
      throw error;
    }
  }
  
  private async authenticate(credentials: any) {
    logger.debug("Authenticating user credentials");
    // Authentication implementation
    return { id: 1, email: credentials.email };
  }
}
// ./src/middleware/requestLogger.ts
import { createModuleLogger, AppModules } from "@/configs/logger";

const logger = createModuleLogger(AppModules.MIDDLEWARE);

export function requestLoggerMiddleware(req: any, res: any, next: any) {
  logger.trace("Middleware importing...");
  
  const start = Date.now();
  
  logger.info("Request received", {
    method: req.method,
    url: req.url,
    userAgent: req.get('User-Agent'),
    ip: req.ip
  });

  res.on('finish', () => {
    const duration = Date.now() - start;
    
    logger.info("Request completed", {
      method: req.method,
      url: req.url,
      statusCode: res.statusCode,
      duration: `${duration}ms`
    });
  });

  next();
}

Using BaseModule

import { BaseModule, createLogger } from '@dqcai/logger';

const logger = createLogger();

class DatabaseManager extends BaseModule {
  constructor() {
    super('DatabaseManager', logger);
  }

  async connect(): Promise<void> {
    await this.logInfo('Connecting to database...');
    try {
      // Connection logic here
      await this.logDebug('Connected successfully');
    } catch (error) {
      await this.logError('Connection failed', { error });
      throw error;
    }
  }
}

// Usage
const dbManager = new DatabaseManager();
await dbManager.connect();

โš™๏ธ Advanced Configuration

Configuration Builder

import { LoggerConfigBuilder, createLogger } from '@dqcai/logger';

const config = new LoggerConfigBuilder()
  .setEnabled(true)
  .setDefaultLevel('info')
  .addModule('App', true, ['info', 'warn', 'error'], ['console'])
  .addModule('DatabaseManager', true, ['debug', 'info'], ['console', 'file'])
  .addModule('AuthService', true, ['error'], ['console', 'api'])
  .build();

const logger = createLogger(config);

Runtime Configuration Updates

// Update module configuration at runtime
logger.setModuleConfig('DatabaseManager', {
  enabled: false,
  levels: [],
  transports: []
});

// Enable/disable entire logger
logger.setEnabled(false);

Development vs Production Configuration

import { LoggerUtils } from '@dqcai/logger';

// Development configuration
const devLogger = createLogger(LoggerUtils.createDevelopmentConfig());

// Production configuration
const prodConfig = new LoggerConfigBuilder()
  .setEnabled(true)
  .setDefaultLevel('warn')
  .addModule('critical', true, ['error'], ['console', 'api'])
  .build();

const prodLogger = createLogger(prodConfig);

๐ŸŽจ Logger Decorators - Advanced Patterns

Logger Decorators help you automatically log function/method activities without writing manual logging code. This provides a clean and maintainable solution for monitoring performance, debugging issues, and tracking application flow.

1. LogMethod Decorator - Basic Method Logging

For Standalone Functions

import { createLogger, LoggerUtils } from '@dqcai/logger';

const logger = createLogger(LoggerUtils.createDevelopmentConfig());
const dataLogger = logger.createModuleLogger('DataProcessor');

// Original function
async function importData(filePath: string, options: any = {}): Promise<any> {
  // Simulate processing
  await new Promise(resolve => setTimeout(resolve, 100));
  return { imported: 150, errors: 0 };
}

// Apply LogMethod decorator
const importDataWithLogging = applyLogMethod(importData, dataLogger, 'importData');

// Helper function to apply LogMethod
function applyLogMethod<T extends (...args: any[]) => any>(
  originalFunction: T,
  logger: any,
  methodName: string
): T {
  return (async function(...args: any[]) {
    if (!logger) return await originalFunction.apply(this, args);

    try {
      await logger.debug(`๐Ÿš€ Calling ${methodName}`, {
        args: args.length,
        argTypes: args.map(arg => typeof arg)
      });

      const start = Date.now();
      try {
        const result = await originalFunction.apply(this, args);
        const duration = Date.now() - start;
        await logger.debug(`โœ… ${methodName} completed in ${duration}ms`);
        return result;
      } catch (error) {
        const duration = Date.now() - start;
        await logger.error(`โŒ ${methodName} failed after ${duration}ms`, {
          error: error.message,
          stack: error.stack
        });
        throw error;
      }
    } catch (logError) {
      console.warn(`[LogMethod] Logging failed for ${methodName}:`, logError);
      return await originalFunction.apply(this, args);
    }
  }) as T;
}

// Usage
async function testImportData(): Promise<void> {
  const result = await importDataWithLogging('/data/users.csv', { skipHeaders: true });
  console.log('Import result:', result);
}

For Class Methods

class DataProcessor extends BaseModule {
  constructor(logger: any) {
    super('DataProcessor', logger);
    
    // Apply decorators to methods
    this.importData = this.applyLogMethod(this.importData.bind(this));
    this.processRecords = this.applyLogMethod(this.processRecords.bind(this));
  }

  async importData(filePath: string, options: any = {}): Promise<any> {
    await new Promise(resolve => setTimeout(resolve, 100));
    return { imported: 150, errors: 0 };
  }

  async processRecords(records: any[]): Promise<any[]> {
    await new Promise(resolve => setTimeout(resolve, 50));
    return records.map(r => ({ ...r, processed: true }));
  }

  private applyLogMethod<T extends (...args: any[]) => any>(method: T): T {
    const self = this;
    const methodName = method.name;
    
    return (async function(...args: any[]) {
      if (!self.logger) return await method.apply(self, args);

      try {
        await self.logDebug(`๐Ÿš€ Calling ${methodName}`, {
          args: args.length,
          argTypes: args.map(arg => typeof arg)
        });

        const start = Date.now();
        try {
          const result = await method.apply(self, args);
          const duration = Date.now() - start;
          await self.logDebug(`โœ… ${methodName} completed in ${duration}ms`);
          return result;
        } catch (error) {
          const duration = Date.now() - start;
          await self.logError(`โŒ ${methodName} failed after ${duration}ms`, {
            error: error.message
          });
          throw error;
        }
      } catch (logError) {
        console.warn(`[LogMethod] Logging failed for ${methodName}:`, logError);
        return await method.apply(self, args);
      }
    }) as T;
  }
}

// Usage
const processor = new DataProcessor(logger);
await processor.importData('/data/products.csv');

2. LogPerformance Decorator - Performance Monitoring

class DatabaseService extends BaseModule {
  constructor(logger: any) {
    super('DatabaseService', logger);
    
    // Apply performance monitoring
    this.heavyQuery = this.applyLogPerformance(this.heavyQuery.bind(this), 2000);
    this.bulkInsert = this.applyLogPerformance(this.bulkInsert.bind(this), 5000);
  }

  async heavyQuery(sql: string): Promise<any> {
    // Simulate slow query
    await new Promise(resolve => setTimeout(resolve, 3000));
    return { rows: 1000, time: '3000ms' };
  }

  async bulkInsert(records: any[]): Promise<any> {
    // Simulate bulk operation
    await new Promise(resolve => setTimeout(resolve, 6000));
    return { inserted: records.length };
  }

  private applyLogPerformance<T extends (...args: any[]) => any>(
    method: T, 
    threshold: number = 1000
  ): T {
    const self = this;
    const methodName = method.name;
    
    return (async function(...args: any[]) {
      const start = Date.now();

      try {
        const result = await method.apply(self, args);
        const duration = Date.now() - start;

        if (self.logger && duration > threshold) {
          await self.logWarn(`๐ŸŒ Slow method: ${methodName} took ${duration}ms`, {
            threshold,
            duration,
            methodName,
            className: self.constructor.name
          });
        }

        return result;
      } catch (error) {
        const duration = Date.now() - start;
        if (self.logger) {
          await self.logError(`โŒ ${methodName} failed after ${duration}ms`, {
            threshold,
            duration,
            error: error.message
          });
        }
        throw error;
      }
    }) as T;
  }
}

// Usage
const dbService = new DatabaseService(logger);
await dbService.heavyQuery('SELECT * FROM large_table');

3. LogCache Decorator - Caching with Logging

// For standalone functions
async function calculateExpensiveResult(input: string): Promise<string> {
  // Simulate heavy calculation
  await new Promise(resolve => setTimeout(resolve, 1000));
  return `Expensive result for: ${input}`;
}

// Apply caching (TTL: 5 seconds)
const calculateExpensiveResultCached = applyLogCache(
  calculateExpensiveResult,
  dataLogger,
  'calculateExpensiveResult',
  5000
);

function applyLogCache<T extends (...args: any[]) => any>(
  originalFunction: T,
  logger: any,
  methodName: string,
  ttlMs: number = 60000
): T {
  const cache = new Map<string, { value: any; expires: number }>();
  
  return (async function(...args: any[]) {
    const cacheKey = `${methodName}.${JSON.stringify(args)}`;
    const now = Date.now();
    const cached = cache.get(cacheKey);

    // Check cache hit
    if (cached && cached.expires > now) {
      if (logger) {
        await logger.debug(`๐Ÿ’พ Cache HIT for ${methodName}`, { cacheKey });
      }
      return cached.value;
    }

    // Cache miss - execute function
    if (logger) {
      await logger.debug(`๐Ÿ” Cache MISS for ${methodName}`, { cacheKey });
    }

    const result = await originalFunction.apply(this, args);

    // Store in cache
    cache.set(cacheKey, {
      value: result,
      expires: now + ttlMs
    });

    return result;
  }) as T;
}

// Test caching
console.log('First call (cache miss):');
await calculateExpensiveResultCached('test-data');

console.log('Second call (cache hit):');
await calculateExpensiveResultCached('test-data');

4. LogRetry Decorator - Retry with Exponential Backoff

// Unstable function for testing
let attemptCount = 0;
async function unstableApiCall(endpoint: string): Promise<any> {
  attemptCount++;
  
  // Fail first 2 times, succeed on 3rd
  if (attemptCount < 3) {
    throw new Error(`API error #${attemptCount}: Network timeout`);
  }
  
  attemptCount = 0; // Reset for next test
  return { status: 'success', data: `Data from ${endpoint}` };
}

// Apply retry (max 3 retries, base delay 500ms)
const unstableApiCallWithRetry = applyLogRetry(
  unstableApiCall,
  dataLogger,
  'unstableApiCall',
  3,
  500
);

function applyLogRetry<T extends (...args: any[]) => any>(
  originalFunction: T,
  logger: any,
  methodName: string,
  maxRetries: number = 3,
  baseDelayMs: number = 1000
): T {
  return (async function(...args: any[]) {
    let lastError: Error;

    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        if (logger && attempt > 1) {
          await logger.info(`๐Ÿ”„ Retry attempt ${attempt}/${maxRetries} for ${methodName}`);
        }

        return await originalFunction.apply(this, args);
      } catch (error) {
        lastError = error;

        if (logger) {
          await logger.warn(`โš ๏ธ Attempt ${attempt}/${maxRetries} failed for ${methodName}`, {
            attempt,
            maxRetries,
            error: error.message,
            willRetry: attempt < maxRetries
          });
        }

        // Exponential backoff delay
        if (attempt < maxRetries) {
          const delay = baseDelayMs * Math.pow(2, attempt - 1);
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
    }

    // All retries exhausted
    if (logger) {
      await logger.error(`๐Ÿ’ฅ All ${maxRetries} attempts failed for ${methodName}`, {
        maxRetries,
        finalError: lastError.message
      });
    }

    throw lastError;
  }) as T;
}

// Test retry
try {
  const result = await unstableApiCallWithRetry('/api/users');
  console.log('Success:', result);
} catch (error) {
  console.log('Final failure:', error.message);
}

5. Combined Decorators with BaseModule

class FileProcessor extends BaseModule {
  constructor(logger: any) {
    super('FileProcessor', logger);
    
    // Apply multiple decorators
    this.importData = this.applyMultipleDecorators(
      this.importData.bind(this),
      ['method', 'performance:2000', 'cache:10000']
    );
  }

  async importData(filePath: string): Promise<any> {
    await this.logInfo('Starting data import', { filePath });
    
    // Simulate processing
    await new Promise(resolve => setTimeout(resolve, 1500));
    
    const result = { imported: 100, errors: 2 };
    await this.logInfo('Import completed', result);
    
    return result;
  }

  private applyMultipleDecorators<T extends (...args: any[]) => any>(
    method: T, 
    decorators: string[]
  ): T {
    let decoratedMethod = method;
    
    for (const decorator of decorators) {
      if (decorator === 'method') {
        decoratedMethod = this.applyMethodLogging(decoratedMethod);
      } else if (decorator.startsWith('performance:')) {
        const threshold = parseInt(decorator.split(':')[1]);
        decoratedMethod = this.applyPerformanceLogging(decoratedMethod, threshold);
      } else if (decorator.startsWith('cache:')) {
        const ttl = parseInt(decorator.split(':')[1]);
        decoratedMethod = this.applyCaching(decoratedMethod, ttl);
      }
    }
    
    return decoratedMethod;
  }

  private applyMethodLogging<T extends (...args: any[]) => any>(method: T): T {
    const self = this;
    return (async function(...args: any[]) {
      await self.logDebug(`๐Ÿš€ Calling ${method.name}`, { args: args.length });
      
      const start = Date.now();
      try {
        const result = await method.apply(self, args);
        const duration = Date.now() - start;
        await self.logDebug(`โœ… ${method.name} completed in ${duration}ms`);
        return result;
      } catch (error) {
        const duration = Date.now() - start;
        await self.logError(`โŒ ${method.name} failed after ${duration}ms`, { error: error.message });
        throw error;
      }
    }) as T;
  }

  private applyPerformanceLogging<T extends (...args: any[]) => any>(method: T, threshold: number): T {
    const self = this;
    return (async function(...args: any[]) {
      const start = Date.now();
      const result = await method.apply(self, args);
      const duration = Date.now() - start;
      
      if (duration > threshold) {
        await self.logWarn(`๐ŸŒ Slow method: ${method.name} took ${duration}ms`, { threshold, duration });
      }
      
      return result;
    }) as T;
  }

  private applyCaching<T extends (...args: any[]) => any>(method: T, ttlMs: number): T {
    const cache = new Map<string, { value: any; expires: number }>();
    const self = this;
    
    return (async function(...args: any[]) {
      const cacheKey = `${method.name}.${JSON.stringify(args)}`;
      const cached = cache.get(cacheKey);
      
      if (cached && cached.expires > Date.now()) {
        await self.logDebug(`๐Ÿ’พ Cache HIT for ${method.name}`);
        return cached.value;
      }
      
      await self.logDebug(`๐Ÿ” Cache MISS for ${method.name}`);
      const result = await method.apply(self, args);
      
      cache.set(cacheKey, {
        value: result,
        expires: Date.now() + ttlMs
      });
      
      return result;
    }) as T;
  }
}

// Usage
const processor = new FileProcessor(logger);
await processor.importData('/data/large-file.csv');

๐ŸŒ Platform-Specific Examples

React Native

import RNFS from 'react-native-fs';
import { createLogger, ConsoleTransport, ILogTransport, LogEntry } from '@dqcai/logger';

class RNFileTransport implements ILogTransport {
  readonly name = 'file';
  
  constructor(private fileName: string = 'app.log') {}
  
  async log(entry: LogEntry): Promise<void> {
    try {
      const line = JSON.stringify(entry) + '\n';
      const path = `${RNFS.DocumentDirectoryPath}/${this.fileName}`;
      await RNFS.appendFile(path, line, 'utf8');
    } catch (err) {
      console.error('[RNFileTransport] write error', err);
    }
  }
}

const logger = createLogger();
logger.addTransport(new ConsoleTransport());
logger.addTransport(new RNFileTransport('app.log'));

logger.info('App', 'React Native app started');

Web Browser

import { createLogger, ConsoleTransport, ILogTransport, LogEntry } from '@dqcai/logger';

class WebFileTransport implements ILogTransport {
  readonly name = 'file';
  private readonly storageKey = 'app_logs';
  
  async log(entry: LogEntry): Promise<void> {
    try {
      const existingLogs = JSON.parse(localStorage.getItem(this.storageKey) || '[]');
      existingLogs.push(entry);
      
      // Keep only last 1000 logs to prevent storage overflow
      if (existingLogs.length > 1000) {
        existingLogs.splice(0, existingLogs.length - 1000);
      }
      
      localStorage.setItem(this.storageKey, JSON.stringify(existingLogs));
    } catch (e) {
      console.error('[WebFileTransport] persist error', e);
    }
  }
  
  getLogs(): LogEntry[] {
    try {
      return JSON.parse(localStorage.getItem(this.storageKey) || '[]');
    } catch {
      return [];
    }
  }
  
  clearLogs(): void {
    localStorage.removeItem(this.storageKey);
  }
}

const logger = createLogger();
logger.addTransport(new ConsoleTransport());
logger.addTransport(new WebFileTransport());

logger.info('WebApp', 'Web application started');

Node.js

import fs from 'fs/promises';
import path from 'path';
import { createLogger, ConsoleTransport, ILogTransport, LogEntry } from '@dqcai/logger';

class NodeFileTransport implements ILogTransport {
  readonly name = 'file';
  
  constructor(private filePath: string = './app.log') {
    // Ensure directory exists
    this.ensureDirectoryExists();
  }
  
  private async ensureDirectoryExists(): Promise<void> {
    try {
      const dir = path.dirname(this.filePath);
      await fs.mkdir(dir, { recursive: true });
    } catch (error) {
      console.error('[NodeFileTransport] Failed to create directory:', error);
    }
  }
  
  async log(entry: LogEntry): Promise<void> {
    try {
      const logLine = JSON.stringify({
        ...entry,
        timestamp: new Date().toISOString()
      }) + '\n';
      
      await fs.appendFile(this.filePath, logLine);
    } catch (e) {
      console.error('[NodeFileTransport] write error', e);
    }
  }
  
  async rotateLogs(maxSizeBytes: number = 10 * 1024 * 1024): Promise<void> {
    try {
      const stats = await fs.stat(this.filePath);
      if (stats.size > maxSizeBytes) {
        const backupPath = `${this.filePath}.${Date.now()}.backup`;
        await fs.rename(this.filePath, backupPath);
      }
    } catch (error) {
      console.error('[NodeFileTransport] Log rotation failed:', error);
    }
  }
}

const logger = createLogger();
logger.addTransport(new ConsoleTransport());
logger.addTransport(new NodeFileTransport('./logs/server.log'));

logger.info('Server', 'Node.js server started on port 3000');

๐Ÿš› Built-in and Custom Transports

API Transport

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

class ApiTransport implements ILogTransport {
  readonly name = 'api';
  private client: AxiosInstance;
  private endpoint: string;
  private batchSize: number;
  private batchTimeout: number;
  private logQueue: LogEntry[] = [];
  private timer: NodeJS.Timeout | null = null;

  constructor(
    baseURL: string,
    endpoint: string = '/logs',
    batchSize: number = 10,
    batchTimeout: number = 5000
  ) {
    this.client = axios.create({
      baseURL,
      headers: {
        'Content-Type': 'application/json'
      }
    });
    this.endpoint = endpoint;
    this.batchSize = batchSize;
    this.batchTimeout = batchTimeout;
  }

  async log(entry: LogEntry): Promise<void> {
    this.logQueue.push(entry);
    
    if (this.logQueue.length >= this.batchSize) {
      await this.flush();
    } else if (!this.timer) {
      this.timer = setTimeout(() => this.flush(), this.batchTimeout);
    }
  }

  private async flush(): Promise<void> {
    if (this.logQueue.length === 0) return;
    
    const logsToSend = [...this.logQueue];
    this.logQueue = [];
    
    if (this.timer) {
      clearTimeout(this.timer);
      this.timer = null;
    }

    try {
      await this.client.post(this.endpoint, { logs: logsToSend });
    } catch (err) {
      console.error('[ApiTransport] Failed to send logs:', err);
      // Optionally re-queue failed logs
    }
  }
}

// Usage
const apiTransport = new ApiTransport('https://api.example.com', '/api/logs', 5, 3000);
logger.addTransport(apiTransport);

Database Transport

class DatabaseTransport implements ILogTransport {
  readonly name = 'database';
  private connectionString: string;
  
  constructor(connectionString: string) {
    this.connectionString = connectionString;
  }
  
  async log(entry: LogEntry): Promise<void> {
    try {
      // Pseudo-code for database insertion
      // Replace with your actual database client
      /*
      await db.query(`
        INSERT INTO logs (timestamp, level, module, message, metadata)
        VALUES (?, ?, ?, ?, ?)
      `, [
        entry.timestamp,
        entry.level,
        entry.module,
        entry.message,
        JSON.stringify(entry.metadata)
      ]);
      */
    } catch (error) {
      console.error('[DatabaseTransport] Failed to save log:', error);
    }
  }
}

๐Ÿ“Š Best Practices

1. Environment-based Configuration

class LoggerFactory {
  static createLogger(): any {
    const env = process.env.NODE_ENV || 'development';
    
    switch (env) {
      case 'development':
        return createLogger(new LoggerConfigBuilder()
          .setEnabled(true)
          .setDefaultLevel('debug')
          .addModule('App', true, ['debug', 'info', 'warn', 'error'], ['console'])
          .build());
      
      case 'production':
        return createLogger(new LoggerConfigBuilder()
          .setEnabled(true)
          .setDefaultLevel('warn')
          .addModule('critical', true, ['error'], ['console', 'api'])
          .addModule('performance', true, ['warn', 'error'], ['api'])
          .build());
      
      case 'test':
        return createLogger(new LoggerConfigBuilder()
          .setEnabled(false)
          .build());
      
      default:
        return createLogger(LoggerUtils.createDevelopmentConfig());
    }
  }
}

const logger = LoggerFactory.createLogger();

2. Structured Logging

interface UserLoginEvent {
  userId: string;
  email: string;
  timestamp: string;
  userAgent?: string;
  ip?: string;
  sessionId?: string;
}

class UserService extends BaseModule {
  async login(credentials: any, context: any): Promise<void> {
    const loginEvent: UserLoginEvent = {
      userId: credentials.userId,
      email: credentials.email,
      timestamp: new Date().toISOString(),
      userAgent: context.userAgent,
      ip: context.ip,
      sessionId: context.sessionId
    };

    // Good: Structured data
    await this.logInfo('User login attempt', loginEvent);
    
    try {
      // Login logic here
      await this.logInfo('User login successful', {
        ...loginEvent,
        success: true,
        loginDuration: Date.now() - context.startTime
      });
    } catch (error) {
      await this.logError('User login failed', {
        ...loginEvent,
        success: false,
        error: error.message,
        stack: error.stack
      });
      throw error;
    }
  }
}

3. Performance Monitoring

class PerformanceMonitor extends BaseModule {
  private performanceThresholds = {
    database: 1000,
    api: 3000,
    file: 5000,
    calculation: 500
  };

  async measureOperation<T>(
    operationType: keyof typeof this.performanceThresholds,
    operation: string,
    fn: () => Promise<T>
  ): Promise<T> {
    const start = Date.now();
    const threshold = this.performanceThresholds[operationType];
    
    await this.logDebug(`Starting ${operationType} operation: ${operation}`);
    
    try {
      const result = await fn();
      const duration = Date.now() - start;
      
      if (duration > threshold) {
        await this.logWarn(`Slow ${operationType} operation detected`, {
          operation,
          duration: `${duration}ms`,
          threshold: `${threshold}ms`,
          operationType
        });
      } else {
        await this.logDebug(`${operationType} operation completed`, {
          operation,
          duration: `${duration}ms`
        });
      }
      
      return result;
    } catch (error) {
      const duration = Date.now() - start;
      
      await this.logError(`${operationType} operation failed`, {
        operation,
        duration: `${duration}ms`,
        error: error.message,
        operationType
      });
      
      throw error;
    }
  }
}

// Usage
const monitor = new PerformanceMonitor(logger);

await monitor.measureOperation('database', 'getUserById', async () => {
  return await db.findUserById('123');
});

await monitor.measureOperation('api', 'fetchExternalData', async () => {
  return await fetch('/api/external/data');
});

4. Error Context and Recovery

class ErrorHandler extends BaseModule {
  async safeExecute<T>(
    operation: string,
    fn: () => Promise<T>,
    fallback?: () => Promise<T>
  ): Promise<T | null> {
    try {
      await this.logDebug(`Starting safe execution: ${operation}`);
      const result = await fn();
      await this.logDebug(`Safe execution completed: ${operation}`, { success: true });
      return result;
    } catch (error) {
      await this.logError(`Safe execution failed: ${operation}`, {
        error: error.message,
        stack: error.stack,
        operation,
        hasFallback: !!fallback
      });

      if (fallback) {
        try {
          await this.logInfo(`Attempting fallback for: ${operation}`);
          const result = await fallback();
          await this.logInfo(`Fallback successful for: ${operation}`);
          return result;
        } catch (fallbackError) {
          await this.logError(`Fallback failed for: ${operation}`, {
            fallbackError: fallbackError.message,
            originalError: error.message
          });
        }
      }

      return null;
    }
  }
}

5. Real-world API Service Example

interface ApiResponse<T> {
  data: T;
  status: number;
  headers: Record<string, string>;
}

class ApiService extends BaseModule {
  private httpClient: any;
  private baseURL: string;
  private retryConfig = {
    maxRetries: 3,
    baseDelay: 1000,
    backoffFactor: 2
  };

  constructor(logger: any, httpClient: any, baseURL: string) {
    super('ApiService', logger);
    this.httpClient = httpClient;
    this.baseURL = baseURL;
    
    // Apply decorators to all API methods
    this.get = this.applyApiDecorators(this.get.bind(this));
    this.post = this.applyApiDecorators(this.post.bind(this));
    this.put = this.applyApiDecorators(this.put.bind(this));
    this.delete = this.applyApiDecorators(this.delete.bind(this));
  }

  async get<T>(endpoint: string, params?: any): Promise<ApiResponse<T>> {
    await this.logDebug('GET request initiated', { endpoint, params });
    
    const response = await this.httpClient.get(`${this.baseURL}${endpoint}`, { params });
    
    await this.logInfo('GET request successful', {
      endpoint,
      status: response.status,
      responseSize: JSON.stringify(response.data).length
    });
    
    return response;
  }

  async post<T>(endpoint: string, data: any): Promise<ApiResponse<T>> {
    await this.logDebug('POST request initiated', { 
      endpoint, 
      dataSize: JSON.stringify(data).length 
    });
    
    const response = await this.httpClient.post(`${this.baseURL}${endpoint}`, data);
    
    await this.logInfo('POST request successful', {
      endpoint,
      status: response.status,
      dataSize: JSON.stringify(data).length
    });
    
    return response;
  }

  async put<T>(endpoint: string, data: any): Promise<ApiResponse<T>> {
    await this.logDebug('PUT request initiated', { endpoint });
    
    const response = await this.httpClient.put(`${this.baseURL}${endpoint}`, data);
    
    await this.logInfo('PUT request successful', {
      endpoint,
      status: response.status
    });
    
    return response;
  }

  async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
    await this.logDebug('DELETE request initiated', { endpoint });
    
    const response = await this.httpClient.delete(`${this.baseURL}${endpoint}`);
    
    await this.logInfo('DELETE request successful', {
      endpoint,
      status: response.status
    });
    
    return response;
  }

  private applyApiDecorators<T extends (...args: any[]) => any>(method: T): T {
    // 1. Method logging
    let decorated = this.applyMethodLogging(method);
    
    // 2. Performance monitoring (warn if > 3 seconds)
    decorated = this.applyPerformanceLogging(decorated, 3000);
    
    // 3. Retry mechanism for network issues
    decorated = this.applyRetryLogging(decorated);
    
    // 4. Rate limiting awareness
    decorated = this.applyRateLimitLogging(decorated);
    
    return decorated;
  }

  private applyRateLimitLogging<T extends (...args: any[]) => any>(method: T): T {
    const self = this;
    return (async function(...args: any[]) {
      try {
        return await method.apply(self, args);
      } catch (error) {
        if (error.response && error.response.status === 429) {
          const retryAfter = error.response.headers['retry-after'] || 60;
          await self.logWarn('Rate limit exceeded', {
            retryAfter: `${retryAfter}s`,
            endpoint: args[0],
            method: method.name
          });
          
          // Optional: implement automatic retry after delay
          await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
          return await method.apply(self, args);
        }
        throw error;
      }
    }) as T;
  }

  // Include previous decorator methods here...
  private applyMethodLogging<T extends (...args: any[]) => any>(method: T): T {
    const self = this;
    return (async function(...args: any[]) {
      await self.logDebug(`๐Ÿš€ API Call: ${method.name}`, { args: args.length });
      
      const start = Date.now();
      try {
        const result = await method.apply(self, args);
        const duration = Date.now() - start;
        await self.logDebug(`โœ… API Call completed: ${method.name} (${duration}ms)`);
        return result;
      } catch (error) {
        const duration = Date.now() - start;
        await self.logError(`โŒ API Call failed: ${method.name} (${duration}ms)`, {
          error: error.message,
          status: error.response?.status,
          statusText: error.response?.statusText
        });
        throw error;
      }
    }) as T;
  }

  private applyPerformanceLogging<T extends (...args: any[]) => any>(method: T, threshold: number): T {
    const self = this;
    return (async function(...args: any[]) {
      const start = Date.now();
      const result = await method.apply(self, args);
      const duration = Date.now() - start;
      
      if (duration > threshold) {
        await self.logWarn(`๐ŸŒ Slow API call: ${method.name}`, {
          duration: `${duration}ms`,
          threshold: `${threshold}ms`,
          endpoint: args[0]
        });
      }
      
      return result;
    }) as T;
  }

  private applyRetryLogging<T extends (...args: any[]) => any>(method: T): T {
    const self = this;
    return (async function(...args: any[]) {
      const { maxRetries, baseDelay, backoffFactor } = self.retryConfig;
      let lastError: Error;

      for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
          if (attempt > 1) {
            await self.logInfo(`๐Ÿ”„ API Retry attempt ${attempt}/${maxRetries}`, {
              method: method.name,
              endpoint: args[0]
            });
          }

          return await method.apply(self, args);
        } catch (error) {
          lastError = error;
          
          // Don't retry for client errors (4xx)
          if (error.response && error.response.status >= 400 && error.response.status < 500) {
            throw error;
          }

          await self.logWarn(`โš ๏ธ API attempt ${attempt}/${maxRetries} failed`, {
            method: method.name,
            endpoint: args[0],
            error: error.message,
            status: error.response?.status,
            willRetry: attempt < maxRetries
          });

          if (attempt < maxRetries) {
            const delay = baseDelay * Math.pow(backoffFactor, attempt - 1);
            await new Promise(resolve => setTimeout(resolve, delay));
          }
        }
      }

      await self.logError(`๐Ÿ’ฅ All API retry attempts failed`, {
        method: method.name,
        endpoint: args[0],
        maxRetries,
        finalError: lastError.message
      });

      throw lastError;
    }) as T;
  }
}

// Usage Example
const apiService = new ApiService(logger, httpClient, 'https://api.example.com');

// All methods now have comprehensive logging, performance monitoring, and retry logic
const userData = await apiService.get('/users/123');
const newUser = await apiService.post('/users', { name: 'John', email: 'john@example.com' });

๐Ÿ“‹ Migration Guide

From console.log

// โŒ Before: Basic console logging
console.log('User logged in:', user);
console.error('API Error:', error);
console.warn('Deprecated function called');

// โœ… After: Structured logging with @dqcai/logger
logger.info('AuthService', 'User logged in', { 
  userId: user.id, 
  email: user.email,
  loginTime: new Date().toISOString()
});

logger.error('ApiService', 'API request failed', { 
  endpoint: '/api/users',
  error: error.message,
  stack: error.stack,
  requestId: context.requestId
});

logger.warn('UtilsService', 'Deprecated function called', {
  function: 'oldUtilFunction',
  caller: 'UserController.createUser',
  deprecatedSince: '2024-01-01'
});

From Other Logging Libraries

// From winston
// winston.info('message', { meta });
logger.info('ModuleName', 'message', { meta });

// From pino
// logger.info({ msg: 'message', ...meta });
logger.info('ModuleName', 'message', meta);

// From react-native-logs
// const log = logger.createLogger();
// log.debug('message');
const moduleLogger = logger.createModuleLogger('ModuleName');
await moduleLogger.debug('message');

Gradual Migration Strategy

// Step 1: Create wrapper for existing code
class LegacyLoggerWrapper {
  constructor(private newLogger: any, private moduleName: string) {}

  info(message: string, meta?: any) {
    this.newLogger.info(this.moduleName, message, meta);
  }

  error(message: string, error?: Error, meta?: any) {
    this.newLogger.error(this.moduleName, message, { 
      error: error?.message,
      stack: error?.stack,
      ...meta 
    });
  }

  debug(message: string, meta?: any) {
    this.newLogger.debug(this.moduleName, message, meta);
  }

  warn(message: string, meta?: any) {
    this.newLogger.warn(this.moduleName, message, meta);
  }
}

// Step 2: Replace gradually
// OLD: const logger = winston.createLogger(...);
const logger = createLogger();
const legacyLogger = new LegacyLoggerWrapper(logger, 'LegacyModule');

// Step 3: Eventually migrate to BaseModule or direct usage
class NewService extends BaseModule {
  constructor() {
    super('NewService', logger);
  }
  
  async doSomething() {
    await this.logInfo('Operation started');
    // ... business logic
    await this.logInfo('Operation completed successfully');
  }
}

๐Ÿ”ง Advanced Utilities and Helpers

Decorator Utility Class

class DecoratorUtils {
  static createCombinedDecorator(logger: any, options: {
    enableMethod?: boolean;
    performanceThreshold?: number;
    cacheEnabled?: boolean;
    cacheTTL?: number;
    retryEnabled?: boolean;
    maxRetries?: number;
    retryDelay?: number;
  } = {}) {
    const {
      enableMethod = true,
      performanceThreshold = 1000,
      cacheEnabled = false,
      cacheTTL = 60000,
      retryEnabled = false,
      maxRetries = 3,
      retryDelay = 1000
    } = options;

    return function<T extends (...args: any[]) => any>(
      originalFunction: T, 
      functionName: string
    ): T {
      let decorated = originalFunction;

      if (enableMethod) {
        decorated = DecoratorUtils.applyMethodLogging(decorated, logger, functionName);
      }

      if (performanceThreshold > 0) {
        decorated = DecoratorUtils.applyPerformanceLogging(
          decorated, 
          logger, 
          functionName, 
          performanceThreshold
        );
      }

      if (cacheEnabled) {
        decorated = DecoratorUtils.applyCaching(decorated, logger, functionName, cacheTTL);
      }

      if (retryEnabled) {
        decorated = DecoratorUtils.applyRetry(
          decorated, 
          logger, 
          functionName, 
          maxRetries, 
          retryDelay
        );
      }

      return decorated;
    };
  }

  static applyMethodLogging<T extends (...args: any[]) => any>(
    originalFunction: T,
    logger: any,
    methodName: string
  ): T {
    return (async function(...args: any[]) {
      if (!logger) return await originalFunction.apply(this, args);

      try {
        await logger.debug(`๐Ÿš€ ${methodName} started`, {
          args: args.length,
          timestamp: new Date().toISOString()
        });

        const start = Date.now();
        try {
          const result = await originalFunction.apply(this, args);
          const duration = Date.now() - start;
          await logger.debug(`โœ… ${methodName} completed`, { duration: `${duration}ms` });
          return result;
        } catch (error) {
          const duration = Date.now() - start;
          await logger.error(`โŒ ${methodName} failed`, {
            duration: `${duration}ms`,
            error: error.message
          });
          throw error;
        }
      } catch (logError) {
        console.warn(`[DecoratorUtils] Logging failed for ${methodName}:`, logError);
        return await originalFunction.apply(this, args);
      }
    }) as T;
  }

  // Include other utility methods...
}

// Usage
const combinedDecorator = DecoratorUtils.createCombinedDecorator(logger, {
  enableMethod: true,
  performanceThreshold: 2000,
  cacheEnabled: true,
  cacheTTL: 30000,
  retryEnabled: true,
  maxRetries: 2
});

const optimizedFunction = combinedDecorator(originalFunction, 'optimizedFunction');

Log Analysis Helper

class LogAnalyzer {
  constructor(private transport: any) {}

  async analyzePerformance(moduleName: string, timeRange: { start: Date; end: Date }) {
    const logs = await this.transport.getLogs(moduleName, timeRange);
    
    const performanceLogs = logs
      .filter((log: any) => log.message.includes('completed') || log.message.includes('failed'))
      .map((log: any) => ({
        method: this.extractMethodName(log.message),
        duration: this.extractDuration(log.metadata),
        success: !log.message.includes('failed'),
        timestamp: log.timestamp
      }));

    return {
      totalCalls: performanceLogs.length,
      successRate: performanceLogs.filter(l => l.success).length / performanceLogs.length,
      averageDuration: performanceLogs.reduce((sum, l) => sum + l.duration, 0) / performanceLogs.length,
      slowestCalls: performanceLogs
        .sort((a, b) => b.duration - a.duration)
        .slice(0, 10),
      errorRate: performanceLogs.filter(l => !l.success).length / performanceLogs.length
    };
  }

  private extractMethodName(message: string): string {
    const match = message.match(/([a-zA-Z_][a-zA-Z0-9_]*)\s+(completed|failed)/);
    return match ? match[1] : 'unknown';
  }

  private extractDuration(metadata: any): number {
    if (metadata && metadata.duration) {
      const duration = metadata.duration.replace('ms', '');
      return parseInt(duration, 10) || 0;
    }
    return 0;
  }
}

๐ŸŽฏ TypeScript and ES2017 Features

Type-Safe Module Logger

interface LogMetadata {
  [key: string]: any;
}

interface TypedLogger {
  debug(module: string, message: string, metadata?: LogMetadata): Promise<void>;
  info(module: string, message: string, metadata?: LogMetadata): Promise<void>;
  warn(module: string, message: string, metadata?: LogMetadata): Promise<void>;
  error(module: string, message: string, metadata?: LogMetadata): Promise<void>;
}

class TypedBaseModule {
  protected logger: TypedLogger;
  protected moduleName: string;

  constructor(moduleName: string, logger: TypedLogger) {
    this.moduleName = moduleName;
    this.logger = logger;
  }

  protected async logDebug(message: string, metadata?: LogMetadata): Promise<void> {
    await this.logger.debug(this.moduleName, message, metadata);
  }

  protected async logInfo(message: string, metadata?: LogMetadata): Promise<void> {
    await this.logger.info(this.moduleName, message, metadata);
  }

  protected async logWarn(message: string, metadata?: LogMetadata): Promise<void> {
    await this.logger.warn(this.moduleName, message, metadata);
  }

  protected async logError(message: string, metadata?: LogMetadata): Promise<void> {
    await this.logger.error(this.moduleName, message, metadata);
  }
}

Generic Decorator Types

type AsyncFunction<T extends any[] = any[], R = any> = (...args: T) => Promise<R>;
type DecoratorFunction<T extends AsyncFunction> = (fn: T) => T;

interface DecoratorOptions {
  performance?: {
    enabled: boolean;
    threshold: number;
  };
  caching?: {
    enabled: boolean;
    ttl: number;
  };
  retry?: {
    enabled: boolean;
    maxRetries: number;
    baseDelay: number;
  };
}

class TypedDecoratorFactory {
  static createDecorator<T extends AsyncFunction>(
    logger: TypedLogger,
    options: DecoratorOptions
  ): DecoratorFunction<T> {
    return (fn: T): T => {
      let decorated: T = fn;

      if (options.performance?.enabled) {
        decorated = this.addPerformanceLogging(
          decorated, 
          logger, 
          options.performance.threshold
        );
      }

      if (options.caching?.enabled) {
        decorated = this.addCaching(decorated, logger, options.caching.ttl);
      }

      if (options.retry?.enabled) {
        decorated = this.addRetry(
          decorated, 
          logger, 
          options.retry.maxRetries,
          options.retry.baseDelay
        );
      }

      return decorated;
    };
  }

  private static addPerformanceLogging<T extends AsyncFunction>(
    fn: T,
    logger: TypedLogger,
    threshold: number
  ): T {
    return (async (...args: Parameters<T>): Promise<ReturnType<T>> => {
      const start = Date.now();
      const result = await fn(...args);
      const duration = Date.now() - start;

      if (duration > threshold) {
        await logger.warn('Performance', `Slow execution detected`, {
          function: fn.name,
          duration: `${duration}ms`,
          threshold: `${threshold}ms`
        });
      }

      return result;
    }) as T;
  }

  // Additional typed decorator methods...
}

ES2017 Async/Await Patterns

class ES2017Logger extends TypedBaseModule {
  // Using ES2017 async/await with proper error handling
  async processWithLogging<T>(
    operation: string,
    processor: () => Promise<T>
  ): Promise<T> {
    await this.logInfo(`Starting ${operation}`);
    
    try {
      const result = await processor();
      await this.logInfo(`Completed ${operation} successfully`);
      return result;
    } catch (error) {
      await this.logError(`Failed ${operation}`, {
        error: error.message,
        stack: error.stack
      });
      throw error;
    }
  }

  // ES2017 Object.entries for metadata processing
  async logWithProcessedMetadata(
    level: 'debug' | 'info' | 'warn' | 'error',
    message: string,
    metadata: LogMetadata = {}
  ): Promise<void> {
    const processedMetadata = Object.entries(metadata).reduce((acc, [key, value]) => {
      // Process and sanitize metadata values
      acc[key] = this.sanitizeValue(value);
      return acc;
    }, {} as LogMetadata);

    await this.logger[level](this.moduleName, message, processedMetadata);
  }

  private sanitizeValue(value: any): any {
    if (value === null || value === undefined) return value;
    if (typeof value === 'string' && value.length > 1000) {
      return `${value.substring(0, 1000)}... [truncated]`;
    }
    if (typeof value === 'object') {
      return JSON.stringify(value).substring(0, 500);
    }
    return value;
  }

  // ES2017 async iterators for log streaming
  async* streamLogs(filter?: (log: any) => boolean): AsyncIterableIterator<any> {
    const logs = await this.getLogs();
    for (const log of logs) {
      if (!filter || filter(log)) {
        yield log;
      }
    }
  }

  private async getLogs(): Promise<any[]> {
    // Implementation depends on your transport
    return [];
  }
}

๐Ÿ“ˆ Comparison Table

Feature@dqcai/loggerwinstonpinoreact-native-logstslog
Platform Support
Node.jsโœ…โœ…โœ…โŒโœ…
Web Browserโœ…โš ๏ธโš ๏ธโœ…โœ…
React Nativeโœ…โŒโŒโœ…โŒ
Features
TypeScript Supportโœ…โš ๏ธโœ…โŒโœ…
Module-based Loggingโœ…โš ๏ธโŒโŒโŒ
Runtime Configurationโœ…โš ๏ธโŒโš ๏ธโŒ
Multiple Transportsโœ…โœ…โœ…โš ๏ธโš ๏ธ
Logger Decoratorsโœ…โŒโŒโŒโŒ
Performance Monitoringโœ…โŒโŒโŒโŒ
Built-in Cachingโœ…โŒโŒโŒโŒ
Retry Logicโœ…โŒโŒโŒโŒ
Bundle Size
Core Size~15KB~200KB~50KB~20KB~30KB
Tree Shakableโœ…โŒโš ๏ธโš ๏ธโœ…
Zero Dependenciesโœ…โŒโŒโš ๏ธโŒ

๐Ÿค– AI-Powered Development

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

AI Development Benefits

  • โšก Rapid Prototyping: From concept to working library in minutes
  • ๐ŸŽฏ Focus on Ideas: Let AI handle implementation details
  • ๐Ÿ“š Comprehensive Documentation: AI-generated examples and guides
  • ๐Ÿงช Test Coverage: AI-generated test cases and scenarios
  • ๐Ÿ”ง Best Practices: AI implements industry-standard patterns

Using AI with @dqcai/logger

You can use AI tools to generate custom transports, decorators, and configurations:

// Example AI prompt:
// "Create a custom transport for @dqcai/logger that sends logs to Elasticsearch
// with batching and retry logic"

// AI-generated ElasticsearchTransport
class ElasticsearchTransport implements ILogTransport {
  readonly name = 'elasticsearch';
  // ... AI-generated implementation
}

๐ŸŒ 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
  • ๐Ÿ”ง Sample system prompts for code generation
  • ๐Ÿ›  Custom transport implementations
  • ๐Ÿ’ฌ Direct discussion with other developers
  • ๐Ÿš€ AI learning resources from zero to advanced

Contributing

Contributions, issues, and feature requests are welcome!

๐Ÿ“„ License

MIT ยฉ Cuong Doan

๐Ÿ”ฅ Summary

@dqcai/logger is the only logger you need for modern JavaScript/TypeScript applications:

  • โœ… Universal: Works on Node.js, Web, and React Native
  • โœ… Type-Safe: Full TypeScript support with ES2017 compatibility
  • โœ… Flexible: Module-based configuration with runtime control
  • โœ… Advanced: Built-in decorators for logging, performance, caching, retry
  • โœ… Lightweight: Zero dependencies, tree-shakable
  • โœ… AI-Ready: Perfect for AI-assisted development workflows

Stop juggling multiple logging libraries. Start with @dqcai/logger today and enjoy consistent, powerful logging across all your applications.

npm install @dqcai/logger

Your universal logging solution is just one command away!

Keywords

logger

FAQs

Package last updated on 25 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts