@dqcai/logger
v4.0.0
Published
Universal Logger Library for every environment: React, React Native, Vue, Angular, Node.js, Browser
Maintainers
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.
✨ 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, andreact-native-logs, use one consistent solution across all platforms.
📦 Installation
npm install @dqcai/logger
# or
yarn add @dqcai/logger
# or
pnpm add @dqcai/loggerOptional 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 APIsNote: 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-fsfor 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 installExample 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
- Error Handling: Always wrap transport operations in try-catch
- Performance: Use batching for network transports
- Cleanup: Implement cleanup() to release resources
- Async Operations: Make log() async for I/O operations
- Buffering: Buffer logs and flush periodically for efficiency
- Retry Logic: Implement retry for unreliable destinations
- Configuration: Make transports configurable
- 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:
- Update Transport Names
// Before (v2.1.0)
.addModule("Auth", true, ["info"], ["console", "file"])
// After (v3.0.0)
.addModule("Auth", true, ["info"], ["console", "node-file"])- 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
});- 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- 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/loggerYour universal, powerful logging solution is just one command away!
