Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
e133da8076 | |||
d502ab8cc9 | |||
d1c05fb9ae | |||
f81971d148 |
16
changelog.md
16
changelog.md
@@ -1,5 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-09-01 - 3.1.9 - fix(docs)
|
||||
Update README: expand documentation, examples and usage guides
|
||||
|
||||
- Fully rewrote README to a comprehensive documentation page with badges, motivation and feature overview.
|
||||
- Added Quick Start, detailed usage examples and code snippets for Smartlog, destinations, and custom destinations.
|
||||
- Documented interactive console features (spinners, progress bars) including non-interactive fallbacks and configuration options.
|
||||
- Expanded sections on built-in destinations (console, file, devtools, ClickHouse, receiver) with practical examples and env-driven configuration.
|
||||
- Added integration examples (PM2, Docker), CLI usage, advanced features (context management, scoped logging, minimum log levels) and best practices.
|
||||
- Included API reference pointers and contributing / license information.
|
||||
|
||||
## 2025-05-20 - 3.1.8 - fix(devDependencies)
|
||||
Update devDependencies for tstest and Node types
|
||||
|
||||
- Bump @git.zone/tstest from ^1.7.0 to ^1.9.0
|
||||
- Bump @types/node from ^22.15.18 to ^22.15.20
|
||||
|
||||
## 2025-05-20 - 3.1.7 - fix(ts_destination_local)
|
||||
Update debug log color: set textColor to 'pink' in DestinationLocal.
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@push.rocks/smartlog",
|
||||
"version": "3.1.7",
|
||||
"version": "3.1.9",
|
||||
"private": false,
|
||||
"description": "A minimalistic, distributed, and extensible logging tool supporting centralized log management.",
|
||||
"keywords": [
|
||||
@@ -45,8 +45,8 @@
|
||||
"@git.zone/tsbuild": "^2.5.1",
|
||||
"@git.zone/tsbundle": "^2.2.5",
|
||||
"@git.zone/tsrun": "^1.3.3",
|
||||
"@git.zone/tstest": "^1.7.0",
|
||||
"@types/node": "^22.15.18"
|
||||
"@git.zone/tstest": "^1.9.0",
|
||||
"@types/node": "^22.15.20"
|
||||
},
|
||||
"dependencies": {
|
||||
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||
|
964
pnpm-lock.yaml
generated
964
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
820
readme.md
820
readme.md
@@ -1,286 +1,734 @@
|
||||
# @push.rocks/smartlog
|
||||
# @push.rocks/smartlog 🚀
|
||||
*The ultimate TypeScript logging solution for modern applications*
|
||||
|
||||
Minimalistic distributed and extensible logging tool for TypeScript and JavaScript applications.
|
||||
[](https://www.npmjs.com/package/@push.rocks/smartlog)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
## Install
|
||||
> **smartlog** is a powerful, distributed, and extensible logging system designed for the cloud-native era. Whether you're debugging locally, monitoring production systems, or building complex microservices, smartlog adapts to your needs with style. 🎯
|
||||
|
||||
Install `@push.rocks/smartlog` using pnpm (recommended), npm, or yarn:
|
||||
## 🌟 Why smartlog?
|
||||
|
||||
```sh
|
||||
- **🎨 Beautiful Console Output**: Color-coded, formatted logs that are actually readable
|
||||
- **🔌 Extensible Architecture**: Plug in any destination - databases, files, remote servers
|
||||
- **🌍 Distributed by Design**: Built for microservices with correlation and context tracking
|
||||
- **⚡ Zero-Config Start**: Works out of the box, scales when you need it
|
||||
- **🎭 Interactive CLI Tools**: Spinners and progress bars that handle non-TTY environments gracefully
|
||||
- **📊 Structured Logging**: JSON-based for easy parsing and analysis
|
||||
- **🔍 Smart Filtering**: Log levels and context-based filtering
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
```bash
|
||||
# Using pnpm (recommended)
|
||||
pnpm add @push.rocks/smartlog
|
||||
|
||||
# Using npm
|
||||
npm install @push.rocks/smartlog --save
|
||||
npm install @push.rocks/smartlog
|
||||
|
||||
# Using yarn
|
||||
yarn add @push.rocks/smartlog
|
||||
```
|
||||
|
||||
Ensure you have TypeScript and Node.js installed for TypeScript projects.
|
||||
## 🚀 Quick Start
|
||||
|
||||
## Package Exports
|
||||
|
||||
The package provides the following exports:
|
||||
|
||||
```javascript
|
||||
// Main module
|
||||
import { Smartlog, LogGroup, ConsoleLog } from '@push.rocks/smartlog';
|
||||
|
||||
// Type definitions and interfaces
|
||||
import { ILogPackage, ILogDestination, TLogLevel } from '@push.rocks/smartlog/interfaces';
|
||||
|
||||
// Interactive console features (spinners, progress bars)
|
||||
import { SmartlogSourceInteractive, SmartlogProgressBar } from '@push.rocks/smartlog/source-interactive';
|
||||
|
||||
// Context management
|
||||
import { ... } from '@push.rocks/smartlog/context';
|
||||
|
||||
// Log destinations
|
||||
import { SmartlogDestinationClickhouse } from '@push.rocks/smartlog/destination-clickhouse';
|
||||
import { SmartlogDestinationDevtools } from '@push.rocks/smartlog/destination-devtools';
|
||||
import { SmartlogDestinationFile } from '@push.rocks/smartlog/destination-file';
|
||||
import { DestinationLocal } from '@push.rocks/smartlog/destination-local';
|
||||
import { SmartlogDestinationReceiver } from '@push.rocks/smartlog/destination-receiver';
|
||||
|
||||
// Receiver functionality
|
||||
import { SmartlogReceiver } from '@push.rocks/smartlog/receiver';
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`@push.rocks/smartlog` is a flexible, extensible logging tool designed for distributed systems. It provides a consistent logging interface across different environments while being lightweight and customizable.
|
||||
|
||||
### Creating a Logger Instance
|
||||
|
||||
Start by importing `Smartlog` and create a logger instance:
|
||||
### Your First Logger
|
||||
|
||||
```typescript
|
||||
import { Smartlog } from '@push.rocks/smartlog';
|
||||
|
||||
// Create a logger with context
|
||||
const logger = new Smartlog({
|
||||
logContext: {
|
||||
company: 'My Company',
|
||||
companyunit: 'Cloud Team',
|
||||
containerName: 'api-service',
|
||||
environment: 'production', // 'local', 'test', 'staging', 'production'
|
||||
runtime: 'node', // 'node', 'chrome', 'rust', 'deno', 'cloudflare_workers'
|
||||
zone: 'us-west',
|
||||
},
|
||||
minimumLogLevel: 'info', // Optional, defaults to 'silly'
|
||||
company: 'MyStartup',
|
||||
companyunit: 'Backend Team',
|
||||
containerName: 'api-gateway',
|
||||
environment: 'production',
|
||||
runtime: 'node',
|
||||
zone: 'eu-central'
|
||||
}
|
||||
});
|
||||
|
||||
// Enable console output
|
||||
// Enable beautiful console output
|
||||
logger.enableConsole();
|
||||
|
||||
// Start logging!
|
||||
logger.log('info', '🎉 Application started successfully');
|
||||
logger.log('error', '💥 Database connection failed', {
|
||||
errorCode: 'DB_TIMEOUT',
|
||||
attemptCount: 3
|
||||
});
|
||||
```
|
||||
|
||||
The context enriches logs with valuable information for filtering and analysis across distributed systems.
|
||||
### Using the Default Logger
|
||||
|
||||
### Logging Messages
|
||||
|
||||
```typescript
|
||||
// Basic logging
|
||||
logger.log('info', 'User authenticated successfully');
|
||||
logger.log('error', 'Database connection failed', { errorCode: 'DB_CONN_ERR', retryCount: 3 });
|
||||
logger.log('warn', 'Rate limit approaching', { currentRate: 95, limit: 100 });
|
||||
|
||||
// Log levels: 'silly', 'info', 'debug', 'note', 'ok', 'success', 'warn', 'error', 'lifecycle'
|
||||
```
|
||||
|
||||
The third parameter accepts any additional data to attach to the log entry.
|
||||
|
||||
### Default Logger
|
||||
|
||||
For simple cases, use the built-in default logger:
|
||||
For quick prototyping and simple applications:
|
||||
|
||||
```typescript
|
||||
import { defaultLogger } from '@push.rocks/smartlog';
|
||||
|
||||
defaultLogger.log('info', 'Application started');
|
||||
defaultLogger.log('info', 'This is so easy!');
|
||||
```
|
||||
|
||||
### Log Groups
|
||||
## 📚 Core Concepts
|
||||
|
||||
Group related logs for better traceability:
|
||||
### Log Levels
|
||||
|
||||
smartlog supports semantic log levels for different scenarios:
|
||||
|
||||
```typescript
|
||||
// Create a log group with optional transaction ID
|
||||
const requestGroup = logger.createLogGroup('tx-123456');
|
||||
// Lifecycle events
|
||||
logger.log('lifecycle', '🔄 Container starting up...');
|
||||
|
||||
// Logs within this group will be correlated
|
||||
requestGroup.log('info', 'Processing payment request');
|
||||
requestGroup.log('debug', 'Validating payment details');
|
||||
requestGroup.log('success', 'Payment processed successfully');
|
||||
// Success states
|
||||
logger.log('success', '✅ Payment processed');
|
||||
logger.log('ok', '👍 Health check passed');
|
||||
|
||||
// Information and debugging
|
||||
logger.log('info', '📋 User profile updated');
|
||||
logger.log('note', '📌 Cache invalidated');
|
||||
logger.log('debug', '🔍 Query execution plan', { sql: 'SELECT * FROM users' });
|
||||
|
||||
// Warnings and errors
|
||||
logger.log('warn', '⚠️ Memory usage above 80%');
|
||||
logger.log('error', '❌ Failed to send email');
|
||||
|
||||
// Verbose output
|
||||
logger.log('silly', '🔬 Entering function processPayment()');
|
||||
```
|
||||
|
||||
### Custom Log Destinations
|
||||
### Log Groups for Correlation
|
||||
|
||||
Extend logging capabilities by adding custom destinations:
|
||||
Perfect for tracking request flows through your system:
|
||||
|
||||
```typescript
|
||||
import { Smartlog, ILogDestination } from '@push.rocks/smartlog';
|
||||
// Track a user request through multiple operations
|
||||
const requestGroup = logger.createLogGroup('req-7f3a2b');
|
||||
|
||||
class DatabaseLogDestination implements ILogDestination {
|
||||
async handleLog(logPackage) {
|
||||
// Store log in database
|
||||
await db.logs.insert({
|
||||
timestamp: new Date(logPackage.timestamp),
|
||||
level: logPackage.level,
|
||||
message: logPackage.message,
|
||||
data: logPackage.data,
|
||||
context: logPackage.context
|
||||
requestGroup.log('info', 'Received POST /api/users');
|
||||
requestGroup.log('debug', 'Validating request body');
|
||||
requestGroup.log('info', 'Creating user in database');
|
||||
requestGroup.log('success', 'User created successfully', { userId: 'usr_123' });
|
||||
|
||||
// All logs in the group share the same correlation ID
|
||||
```
|
||||
|
||||
## 🎯 Log Destinations
|
||||
|
||||
### Built-in Destinations
|
||||
|
||||
#### 🖥️ Local Console (Enhanced)
|
||||
|
||||
Beautiful, colored output for local development:
|
||||
|
||||
```typescript
|
||||
import { DestinationLocal } from '@push.rocks/smartlog/destination-local';
|
||||
|
||||
const localDestination = new DestinationLocal({
|
||||
logLevel: 'debug' // Optional: filter by minimum log level
|
||||
});
|
||||
|
||||
logger.addLogDestination(localDestination);
|
||||
```
|
||||
|
||||
#### 📁 File Logging
|
||||
|
||||
Persist logs to files with automatic rotation support:
|
||||
|
||||
```typescript
|
||||
import { SmartlogDestinationFile } from '@push.rocks/smartlog/destination-file';
|
||||
|
||||
const fileDestination = new SmartlogDestinationFile('./logs/app.log');
|
||||
logger.addLogDestination(fileDestination);
|
||||
```
|
||||
|
||||
#### 🌐 Browser DevTools
|
||||
|
||||
Optimized for browser environments with styled console output:
|
||||
|
||||
```typescript
|
||||
import { SmartlogDestinationDevtools } from '@push.rocks/smartlog/destination-devtools';
|
||||
|
||||
const devtools = new SmartlogDestinationDevtools();
|
||||
logger.addLogDestination(devtools);
|
||||
```
|
||||
|
||||
#### 📊 ClickHouse Analytics
|
||||
|
||||
Store logs in ClickHouse for powerful analytics:
|
||||
|
||||
```typescript
|
||||
import { SmartlogDestinationClickhouse } from '@push.rocks/smartlog/destination-clickhouse';
|
||||
|
||||
const clickhouse = await SmartlogDestinationClickhouse.createAndStart({
|
||||
host: 'analytics.example.com',
|
||||
port: 8123,
|
||||
database: 'logs',
|
||||
user: 'logger',
|
||||
password: process.env.CLICKHOUSE_PASSWORD
|
||||
});
|
||||
|
||||
logger.addLogDestination(clickhouse);
|
||||
|
||||
// Query your logs with SQL!
|
||||
// SELECT * FROM logs WHERE level = 'error' AND timestamp > now() - INTERVAL 1 HOUR
|
||||
```
|
||||
|
||||
#### 🔗 Remote Receiver
|
||||
|
||||
Send logs to a centralized logging service:
|
||||
|
||||
```typescript
|
||||
import { SmartlogDestinationReceiver } from '@push.rocks/smartlog/destination-receiver';
|
||||
|
||||
const receiver = new SmartlogDestinationReceiver({
|
||||
endpoint: 'https://logs.mycompany.com/ingest',
|
||||
apiKey: process.env.LOG_API_KEY,
|
||||
batchSize: 100, // Send logs in batches
|
||||
flushInterval: 5000 // Flush every 5 seconds
|
||||
});
|
||||
|
||||
logger.addLogDestination(receiver);
|
||||
```
|
||||
|
||||
### 🛠️ Custom Destinations
|
||||
|
||||
Build your own destination for any logging backend:
|
||||
|
||||
```typescript
|
||||
import { ILogDestination, ILogPackage } from '@push.rocks/smartlog/interfaces';
|
||||
|
||||
class ElasticsearchDestination implements ILogDestination {
|
||||
private client: ElasticsearchClient;
|
||||
|
||||
constructor(config: ElasticsearchConfig) {
|
||||
this.client = new ElasticsearchClient(config);
|
||||
}
|
||||
|
||||
async handleLog(logPackage: ILogPackage): Promise<void> {
|
||||
await this.client.index({
|
||||
index: `logs-${new Date().toISOString().split('T')[0]}`,
|
||||
body: {
|
||||
'@timestamp': logPackage.timestamp,
|
||||
level: logPackage.level,
|
||||
message: logPackage.message,
|
||||
context: logPackage.context,
|
||||
data: logPackage.data,
|
||||
correlation: logPackage.correlation
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add the custom destination to your logger
|
||||
logger.addLogDestination(new DatabaseLogDestination());
|
||||
```
|
||||
|
||||
### Built-in Destinations
|
||||
|
||||
SmartLog comes with several built-in destinations for various logging needs:
|
||||
|
||||
```typescript
|
||||
// Log to a file
|
||||
import { SmartlogDestinationFile } from '@push.rocks/smartlog/destination-file';
|
||||
logger.addLogDestination(new SmartlogDestinationFile('/path/to/logfile.log'));
|
||||
|
||||
// Colorful local console logging
|
||||
import { DestinationLocal } from '@push.rocks/smartlog/destination-local';
|
||||
logger.addLogDestination(new DestinationLocal());
|
||||
|
||||
// Browser DevTools with colored formatting
|
||||
import { SmartlogDestinationDevtools } from '@push.rocks/smartlog/destination-devtools';
|
||||
logger.addLogDestination(new SmartlogDestinationDevtools());
|
||||
|
||||
// ClickHouse database logging
|
||||
import { SmartlogDestinationClickhouse } from '@push.rocks/smartlog/destination-clickhouse';
|
||||
const clickhouse = await SmartlogDestinationClickhouse.createAndStart({
|
||||
host: 'clickhouse.example.com',
|
||||
port: 8123,
|
||||
user: 'username',
|
||||
password: 'password',
|
||||
database: 'logs_db'
|
||||
});
|
||||
logger.addLogDestination(clickhouse);
|
||||
|
||||
// Remote receiver logging
|
||||
import { SmartlogDestinationReceiver } from '@push.rocks/smartlog/destination-receiver';
|
||||
logger.addLogDestination(new SmartlogDestinationReceiver({
|
||||
endpoint: 'https://logs.example.com/api/logs'
|
||||
// Use your custom destination
|
||||
logger.addLogDestination(new ElasticsearchDestination({
|
||||
node: 'https://elasticsearch.example.com'
|
||||
}));
|
||||
```
|
||||
|
||||
### Interactive Console Features
|
||||
## 🎨 Interactive Console Features
|
||||
|
||||
For CLI applications, use the interactive console features:
|
||||
### Spinners
|
||||
|
||||
Create beautiful loading animations that degrade gracefully in CI/CD:
|
||||
|
||||
```typescript
|
||||
import { SmartlogSourceInteractive, SmartlogProgressBar } from '@push.rocks/smartlog/source-interactive';
|
||||
```
|
||||
import { SmartlogSourceInteractive } from '@push.rocks/smartlog/source-interactive';
|
||||
|
||||
#### Spinners
|
||||
|
||||
```typescript
|
||||
const spinner = new SmartlogSourceInteractive();
|
||||
|
||||
// Start a spinner with text
|
||||
spinner.text('Loading data...');
|
||||
// Basic usage
|
||||
spinner.text('🔄 Fetching data from API...');
|
||||
// ... perform async operation
|
||||
spinner.finishSuccess('✅ Data fetched successfully!');
|
||||
|
||||
// Chained operations
|
||||
spinner
|
||||
.text('📡 Connecting to database')
|
||||
.successAndNext('🔍 Running migrations')
|
||||
.successAndNext('🌱 Seeding data')
|
||||
.finishSuccess('🎉 Database ready!');
|
||||
|
||||
// Customize appearance
|
||||
spinner.setSpinnerStyle('dots'); // 'dots', 'line', 'star', 'simple'
|
||||
spinner.setColor('blue'); // 'red', 'green', 'yellow', 'blue', etc.
|
||||
spinner.setSpeed(80); // Animation speed in milliseconds
|
||||
spinner
|
||||
.setSpinnerStyle('dots') // dots, line, star, simple
|
||||
.setColor('cyan') // any terminal color
|
||||
.setSpeed(80) // animation speed in ms
|
||||
.text('🚀 Deploying application...');
|
||||
|
||||
// Update spinner status
|
||||
spinner.text('Processing records...');
|
||||
|
||||
// Complete with success or failure
|
||||
spinner.finishSuccess('Data loaded successfully!');
|
||||
spinner.finishFail('Failed to load data!');
|
||||
|
||||
// Chain operations
|
||||
spinner.text('Connecting to server')
|
||||
.successAndNext('Fetching records')
|
||||
.successAndNext('Processing data')
|
||||
.finishSuccess('All done!');
|
||||
// Handle failures
|
||||
try {
|
||||
await deployApp();
|
||||
spinner.finishSuccess('✅ Deployed!');
|
||||
} catch (error) {
|
||||
spinner.finishFail('❌ Deployment failed');
|
||||
}
|
||||
```
|
||||
|
||||
#### Progress Bars
|
||||
### Progress Bars
|
||||
|
||||
Track long-running operations with style:
|
||||
|
||||
```typescript
|
||||
const progressBar = new SmartlogProgressBar({
|
||||
total: 100, // Total number of items
|
||||
width: 40, // Width of the progress bar
|
||||
complete: '█', // Character for completed section
|
||||
incomplete: '░', // Character for incomplete section
|
||||
showEta: true, // Show estimated time remaining
|
||||
showPercent: true, // Show percentage
|
||||
showCount: true // Show count (e.g., "50/100")
|
||||
import { SmartlogProgressBar } from '@push.rocks/smartlog/source-interactive';
|
||||
|
||||
// Create a progress bar
|
||||
const progress = new SmartlogProgressBar({
|
||||
total: 100,
|
||||
width: 40,
|
||||
complete: '█',
|
||||
incomplete: '░',
|
||||
showEta: true,
|
||||
showPercent: true,
|
||||
showCount: true
|
||||
});
|
||||
|
||||
// Update progress
|
||||
progressBar.update(25); // Set to 25% progress
|
||||
for (let i = 0; i <= 100; i++) {
|
||||
progress.update(i);
|
||||
await someAsyncWork();
|
||||
}
|
||||
|
||||
// Increment progress
|
||||
progressBar.increment(5); // Increase by 5 units
|
||||
progress.complete();
|
||||
|
||||
// Change color
|
||||
progressBar.setColor('blue');
|
||||
// Real-world example: Processing files
|
||||
const files = await getFiles();
|
||||
const progress = new SmartlogProgressBar({
|
||||
total: files.length,
|
||||
width: 50
|
||||
});
|
||||
|
||||
// Complete the progress bar
|
||||
progressBar.complete();
|
||||
for (const [index, file] of files.entries()) {
|
||||
await processFile(file);
|
||||
progress.increment(); // or progress.update(index + 1)
|
||||
}
|
||||
```
|
||||
|
||||
#### Non-Interactive Environments
|
||||
### Non-Interactive Fallback
|
||||
|
||||
Both spinners and progress bars automatically detect non-interactive environments (CI/CD, piped output) and fallback to plain text logging:
|
||||
Both spinners and progress bars automatically detect non-interactive environments (CI/CD, Docker logs, piped output) and fallback to simple text output:
|
||||
|
||||
```
|
||||
[Loading] Connecting to server
|
||||
[Success] Connected to server
|
||||
[Loading] Fetching records
|
||||
[Loading] Connecting to database
|
||||
[Success] Connected to database
|
||||
[Loading] Running migrations
|
||||
Progress: 25% (25/100)
|
||||
Progress: 50% (50/100)
|
||||
Progress: 100% (100/100)
|
||||
[Success] Fetching complete
|
||||
[Success] Migrations complete
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
## 🔧 Advanced Features
|
||||
|
||||
### Capturing All Console Output
|
||||
### Context Management
|
||||
|
||||
Capture all `console.log` and `console.error` output through Smartlog:
|
||||
Add context that flows through your entire application:
|
||||
|
||||
```typescript
|
||||
logger.enableConsole({ captureAll: true });
|
||||
// Set global context
|
||||
logger.addLogContext({
|
||||
requestId: 'req-123',
|
||||
userId: 'user-456',
|
||||
feature: 'payment-processing'
|
||||
});
|
||||
|
||||
// All subsequent logs include this context
|
||||
logger.log('info', 'Processing payment');
|
||||
// Output includes: { ...context, message: 'Processing payment' }
|
||||
```
|
||||
|
||||
### Scoped Logging
|
||||
|
||||
Create scoped loggers for different components:
|
||||
|
||||
```typescript
|
||||
const dbLogger = logger.createScope('database');
|
||||
const apiLogger = logger.createScope('api');
|
||||
|
||||
dbLogger.log('info', 'Executing query');
|
||||
apiLogger.log('info', 'Handling request');
|
||||
// Logs include scope information for filtering
|
||||
```
|
||||
|
||||
### Minimum Log Levels
|
||||
|
||||
Control log verbosity per environment:
|
||||
|
||||
```typescript
|
||||
const logger = new Smartlog({
|
||||
logContext: { environment: 'production' },
|
||||
minimumLogLevel: 'warn' // Only warn and above in production
|
||||
});
|
||||
|
||||
// These won't be logged in production
|
||||
logger.log('debug', 'Detailed debug info');
|
||||
logger.log('info', 'Regular info');
|
||||
|
||||
// These will be logged
|
||||
logger.log('warn', 'Warning message');
|
||||
logger.log('error', 'Error message');
|
||||
```
|
||||
|
||||
### Increment Logging
|
||||
|
||||
For metrics and counters:
|
||||
Perfect for metrics and counters:
|
||||
|
||||
```typescript
|
||||
logger.increment('info', 'api_requests', { endpoint: '/users' });
|
||||
// Track API calls
|
||||
logger.increment('info', 'api.requests', { endpoint: '/users', method: 'GET' });
|
||||
logger.increment('info', 'api.requests', { endpoint: '/users', method: 'POST' });
|
||||
|
||||
// Track errors by type
|
||||
logger.increment('error', 'payment.failed', { reason: 'insufficient_funds' });
|
||||
logger.increment('error', 'payment.failed', { reason: 'card_declined' });
|
||||
```
|
||||
|
||||
### Log Correlation
|
||||
### Capture All Console Output
|
||||
|
||||
Correlate logs across services with correlation IDs:
|
||||
Redirect all console.log and console.error through smartlog:
|
||||
|
||||
```typescript
|
||||
logger.log('info', 'Request received', { userId: 'user-123' }, {
|
||||
id: 'req-abc-123',
|
||||
type: 'service',
|
||||
transaction: 'tx-payment-456'
|
||||
logger.enableConsole({
|
||||
captureAll: true // Capture all console.* methods
|
||||
});
|
||||
|
||||
console.log('This goes through smartlog!');
|
||||
console.error('This too!');
|
||||
// All console output is now structured and routed through your destinations
|
||||
```
|
||||
|
||||
## 🏗️ Real-World Examples
|
||||
|
||||
### Microservice with Distributed Tracing
|
||||
|
||||
```typescript
|
||||
import { Smartlog } from '@push.rocks/smartlog';
|
||||
import { SmartlogDestinationClickhouse } from '@push.rocks/smartlog/destination-clickhouse';
|
||||
|
||||
// Initialize logger with service context
|
||||
const logger = new Smartlog({
|
||||
logContext: {
|
||||
company: 'TechCorp',
|
||||
companyunit: 'Platform',
|
||||
containerName: 'user-service',
|
||||
environment: process.env.NODE_ENV,
|
||||
runtime: 'node',
|
||||
zone: process.env.CLOUD_ZONE
|
||||
}
|
||||
});
|
||||
|
||||
// Add ClickHouse for analytics
|
||||
const clickhouse = await SmartlogDestinationClickhouse.createAndStart({
|
||||
host: process.env.CLICKHOUSE_HOST,
|
||||
database: 'microservices_logs'
|
||||
});
|
||||
logger.addLogDestination(clickhouse);
|
||||
|
||||
// Enable local console for development
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
logger.enableConsole();
|
||||
}
|
||||
|
||||
// Express middleware for request tracking
|
||||
app.use((req, res, next) => {
|
||||
const requestId = generateRequestId();
|
||||
const logGroup = logger.createLogGroup(requestId);
|
||||
|
||||
// Attach logger to request
|
||||
req.logger = logGroup;
|
||||
|
||||
// Log request
|
||||
logGroup.log('info', 'Incoming request', {
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
ip: req.ip
|
||||
});
|
||||
|
||||
// Track response
|
||||
res.on('finish', () => {
|
||||
logGroup.log('info', 'Request completed', {
|
||||
statusCode: res.statusCode,
|
||||
duration: Date.now() - req.startTime
|
||||
});
|
||||
});
|
||||
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
### CLI Tool with Progress Tracking
|
||||
|
||||
For detailed API documentation, see the [API.md](API.md) file.
|
||||
```typescript
|
||||
import { Smartlog } from '@push.rocks/smartlog';
|
||||
import { SmartlogSourceInteractive, SmartlogProgressBar } from '@push.rocks/smartlog/source-interactive';
|
||||
|
||||
## License and Legal Information
|
||||
const logger = new Smartlog({
|
||||
logContext: {
|
||||
containerName: 'migration-tool',
|
||||
environment: 'cli'
|
||||
}
|
||||
});
|
||||
|
||||
logger.enableConsole();
|
||||
|
||||
async function migrateDatabase() {
|
||||
const spinner = new SmartlogSourceInteractive();
|
||||
|
||||
// Connect to database
|
||||
spinner.text('🔌 Connecting to database...');
|
||||
await connectDB();
|
||||
spinner.finishSuccess('✅ Connected to database');
|
||||
|
||||
// Get migrations
|
||||
spinner.text('📋 Loading migrations...');
|
||||
const migrations = await getMigrations();
|
||||
spinner.finishSuccess(`✅ Found ${migrations.length} migrations`);
|
||||
|
||||
// Run migrations with progress bar
|
||||
const progress = new SmartlogProgressBar({
|
||||
total: migrations.length,
|
||||
width: 40,
|
||||
showEta: true
|
||||
});
|
||||
|
||||
for (const [index, migration] of migrations.entries()) {
|
||||
logger.log('info', `Running migration: ${migration.name}`);
|
||||
await runMigration(migration);
|
||||
progress.update(index + 1);
|
||||
}
|
||||
|
||||
progress.complete();
|
||||
logger.log('success', '🎉 All migrations completed successfully!');
|
||||
}
|
||||
```
|
||||
|
||||
### Production Logging with Multiple Destinations
|
||||
|
||||
```typescript
|
||||
import { Smartlog } from '@push.rocks/smartlog';
|
||||
import { DestinationLocal } from '@push.rocks/smartlog/destination-local';
|
||||
import { SmartlogDestinationFile } from '@push.rocks/smartlog/destination-file';
|
||||
import { SmartlogDestinationReceiver } from '@push.rocks/smartlog/destination-receiver';
|
||||
|
||||
const logger = new Smartlog({
|
||||
logContext: {
|
||||
company: 'Enterprise Corp',
|
||||
containerName: 'payment-processor',
|
||||
environment: 'production',
|
||||
runtime: 'node',
|
||||
zone: 'us-east-1'
|
||||
},
|
||||
minimumLogLevel: 'info' // No debug logs in production
|
||||
});
|
||||
|
||||
// Console for container logs (structured for log aggregators)
|
||||
logger.addLogDestination(new DestinationLocal());
|
||||
|
||||
// File for audit trail
|
||||
logger.addLogDestination(new SmartlogDestinationFile('/var/log/app/audit.log'));
|
||||
|
||||
// Central logging service
|
||||
logger.addLogDestination(new SmartlogDestinationReceiver({
|
||||
endpoint: 'https://logs.enterprise.com/ingest',
|
||||
apiKey: process.env.LOG_API_KEY,
|
||||
batchSize: 100,
|
||||
flushInterval: 5000
|
||||
}));
|
||||
|
||||
// Critical error alerts
|
||||
logger.addLogDestination({
|
||||
async handleLog(logPackage) {
|
||||
if (logPackage.level === 'error' && logPackage.data?.critical) {
|
||||
await sendAlert({
|
||||
channel: 'ops-team',
|
||||
message: `🚨 Critical error: ${logPackage.message}`,
|
||||
data: logPackage
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 🔌 Integration with Other Tools
|
||||
|
||||
### PM2 Integration
|
||||
|
||||
```typescript
|
||||
// ecosystem.config.js
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'api',
|
||||
script: './dist/index.js',
|
||||
error_file: '/dev/null', // Disable PM2 error log
|
||||
out_file: '/dev/null', // Disable PM2 out log
|
||||
merge_logs: true,
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
// smartlog handles all logging
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
### Docker Integration
|
||||
|
||||
```dockerfile
|
||||
FROM node:18-alpine
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pnpm install --production
|
||||
|
||||
# smartlog handles structured logging
|
||||
# No need for special log drivers
|
||||
CMD ["node", "dist/index.js"]
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
# Logs are structured JSON, perfect for log aggregators
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
```
|
||||
|
||||
## 🏆 Best Practices
|
||||
|
||||
### 1. Use Semantic Log Levels
|
||||
|
||||
```typescript
|
||||
// ✅ Good - semantic and meaningful
|
||||
logger.log('lifecycle', 'Server starting on port 3000');
|
||||
logger.log('success', 'Database connection established');
|
||||
logger.log('error', 'Failed to process payment', { orderId, error });
|
||||
|
||||
// ❌ Bad - everything is 'info'
|
||||
logger.log('info', 'Server starting');
|
||||
logger.log('info', 'Database connected');
|
||||
logger.log('info', 'Error: payment failed');
|
||||
```
|
||||
|
||||
### 2. Include Structured Data
|
||||
|
||||
```typescript
|
||||
// ✅ Good - structured data for analysis
|
||||
logger.log('error', 'API request failed', {
|
||||
endpoint: '/api/users',
|
||||
statusCode: 500,
|
||||
duration: 1234,
|
||||
userId: 'usr_123',
|
||||
errorCode: 'INTERNAL_ERROR'
|
||||
});
|
||||
|
||||
// ❌ Bad - data embedded in message
|
||||
logger.log('error', `API request to /api/users failed with 500 in 1234ms for user usr_123`);
|
||||
```
|
||||
|
||||
### 3. Use Log Groups for Correlation
|
||||
|
||||
```typescript
|
||||
// ✅ Good - correlated logs
|
||||
async function processOrder(orderId: string) {
|
||||
const logGroup = logger.createLogGroup(orderId);
|
||||
|
||||
logGroup.log('info', 'Processing order');
|
||||
logGroup.log('debug', 'Validating items');
|
||||
logGroup.log('info', 'Charging payment');
|
||||
logGroup.log('success', 'Order processed');
|
||||
}
|
||||
|
||||
// ❌ Bad - no correlation
|
||||
async function processOrder(orderId: string) {
|
||||
logger.log('info', `Processing order ${orderId}`);
|
||||
logger.log('debug', `Validating items for ${orderId}`);
|
||||
logger.log('info', `Charging payment for ${orderId}`);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Environment-Specific Configuration
|
||||
|
||||
```typescript
|
||||
// ✅ Good - different configs per environment
|
||||
const logger = new Smartlog({
|
||||
logContext: {
|
||||
environment: process.env.NODE_ENV,
|
||||
// ... other context
|
||||
},
|
||||
minimumLogLevel: process.env.NODE_ENV === 'production' ? 'info' : 'silly'
|
||||
});
|
||||
|
||||
// Add destinations based on environment
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
logger.addLogDestination(clickhouseDestination);
|
||||
logger.addLogDestination(alertingDestination);
|
||||
} else {
|
||||
logger.enableConsole();
|
||||
}
|
||||
```
|
||||
|
||||
## 📖 API Reference
|
||||
|
||||
### Smartlog Class
|
||||
|
||||
```typescript
|
||||
class Smartlog {
|
||||
constructor(options?: ISmartlogOptions)
|
||||
|
||||
// Logging methods
|
||||
log(level: TLogLevel, message: string, data?: any, correlation?: ILogCorrelation): void
|
||||
increment(level: TLogLevel, key: string, data?: any): void
|
||||
|
||||
// Configuration
|
||||
enableConsole(options?: IConsoleOptions): void
|
||||
addLogDestination(destination: ILogDestination): void
|
||||
addLogContext(context: Partial<ILogContext>): void
|
||||
|
||||
// Log groups
|
||||
createLogGroup(transactionId?: string): LogGroup
|
||||
createScope(scopeName: string): Smartlog
|
||||
}
|
||||
```
|
||||
|
||||
### Log Levels
|
||||
|
||||
```typescript
|
||||
type TLogLevel =
|
||||
| 'silly' // Very verbose debugging
|
||||
| 'debug' // Debug information
|
||||
| 'info' // Informational messages
|
||||
| 'note' // Notable events
|
||||
| 'ok' // Success confirmation
|
||||
| 'success' // Major success
|
||||
| 'warn' // Warning messages
|
||||
| 'error' // Error messages
|
||||
| 'lifecycle' // Application lifecycle events
|
||||
```
|
||||
|
||||
### Log Package Structure
|
||||
|
||||
```typescript
|
||||
interface ILogPackage {
|
||||
timestamp: number;
|
||||
level: TLogLevel;
|
||||
message: string;
|
||||
data?: any;
|
||||
context: ILogContext;
|
||||
correlation?: ILogCorrelation;
|
||||
}
|
||||
```
|
||||
|
||||
For complete API documentation, see [API.md](API.md).
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
||||
|
||||
## 📄 License and Legal Information
|
||||
|
||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||
|
||||
|
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartlog',
|
||||
version: '3.1.7',
|
||||
version: '3.1.9',
|
||||
description: 'A minimalistic, distributed, and extensible logging tool supporting centralized log management.'
|
||||
}
|
||||
|
Reference in New Issue
Block a user