Hackable console logger for Node.js applications with 17 out-of-the-box logger types and advanced features including integrated timers, scoped loggers, secrets filtering, and custom pluggable loggers.
—
Create hierarchical scoped loggers with inheritance for organized logging across different modules and components. Scoped loggers help organize log output by adding contextual prefixes while maintaining all functionality of the parent logger.
Create scoped logger instances that inherit all configuration and custom loggers from the parent.
/**
* Create a scoped logger instance
* @param name - One or more scope names (nested scopes supported)
* @returns New Signale instance with the specified scope
*/
function scope(...name: string[]): Signale;
/**
* Get the current scope name
*/
readonly scopeName: string;Remove scope from a logger instance.
/**
* Clear the scope name from the logger
*/
function unscope(): void;Create loggers with a single scope identifier.
Usage Examples:
const signale = require('signale');
// Create scoped logger
const dbLogger = signale.scope('database');
dbLogger.info('Connection established');
// Output: [database] › ℹ info Connection established
dbLogger.success('Query executed successfully');
// Output: [database] › ✔ success Query executed successfully
dbLogger.error('Connection timeout');
// Output: [database] › ✖ error Connection timeoutCreate nested scopes for hierarchical organization.
Usage Examples:
const signale = require('signale');
// Create multi-level scoped logger
const apiLogger = signale.scope('api', 'v2', 'users');
apiLogger.info('Processing user request');
// Output: [api] [v2] [users] › ℹ info Processing user request
apiLogger.warn('Rate limit approaching');
// Output: [api] [v2] [users] › ⚠ warning Rate limit approaching
// Create from existing scope
const authLogger = apiLogger.scope('auth');
authLogger.success('User authenticated');
// Output: [api] [v2] [users] [auth] › ✔ success User authenticatedScoped loggers inherit all properties and custom types from their parent logger.
Usage Examples:
const { Signale } = require('signale');
// Create parent logger with custom types
const parent = new Signale({
types: {
deploy: {
badge: '🚀',
color: 'magenta',
label: 'deploy'
}
}
});
// Create scoped logger - inherits custom types
const prodLogger = parent.scope('production');
// Use inherited custom logger
prodLogger.deploy('Starting production deployment');
// Output: [production] › 🚀 deploy Starting production deployment
// Use inherited default loggers
prodLogger.success('Deployment completed');
// Output: [production] › ✔ success Deployment completedScoped loggers inherit configuration, secrets, streams, and all other settings.
Usage Examples:
const { Signale } = require('signale');
// Parent with configuration
const parent = new Signale({
secrets: ['password123', 'secret-key'],
logLevel: 'warn',
stream: process.stderr
});
parent.addSecrets(['additional-secret']);
// Create scoped logger - inherits all settings
const moduleLogger = parent.scope('auth-module');
// Secrets filtering inherited
moduleLogger.warn('Login failed for password123');
// Output: [auth-module] › ⚠ warning Login failed for [secure]
// Log level inherited
moduleLogger.info('This will not appear'); // Filtered due to warn level
moduleLogger.error('Authentication error'); // AppearsManage scope names and create scope chains.
Usage Examples:
const signale = require('signale');
// Create initial scope
const appLogger = signale.scope('myapp');
console.log(appLogger.scopeName); // "myapp"
// Create nested scope
const moduleLogger = appLogger.scope('users', 'controller');
console.log(moduleLogger.scopeName); // ["myapp", "users", "controller"]
// Remove scope
moduleLogger.unscope();
moduleLogger.info('No scope now');
// Output: ℹ info No scope now
// Scope with array parameter
const serviceLogger = signale.scope('service-layer');
serviceLogger.info('Service started');
// Output: [service-layer] › ℹ info Service startedCommon patterns for organizing scoped loggers in applications.
Usage Examples:
const signale = require('signale');
// Module-based scoping
function createModuleLogger(moduleName) {
return signale.scope('app', moduleName);
}
const userLogger = createModuleLogger('users');
const orderLogger = createModuleLogger('orders');
userLogger.info('User service initialized');
// Output: [app] [users] › ℹ info User service initialized
orderLogger.info('Order processing started');
// Output: [app] [orders] › ℹ info Order processing started
// Request-based scoping
function handleRequest(requestId) {
const reqLogger = signale.scope('request', requestId);
reqLogger.info('Processing request');
reqLogger.success('Request completed');
// Output: [request] [req-123] › ℹ info Processing request
// [request] [req-123] › ✔ success Request completed
}
handleRequest('req-123');Control scope display through global configuration options.
Usage Examples:
const { Signale } = require('signale');
// Disable scope display
const logger = new Signale({
config: {
displayScope: false
}
});
const scoped = logger.scope('hidden');
scoped.info('Scope is hidden');
// Output: ℹ info Scope is hidden (no [hidden] prefix)
// Enable scope display (default)
const visible = new Signale({
config: {
displayScope: true
}
});
const scopedVisible = visible.scope('visible');
scopedVisible.info('Scope is shown');
// Output: [visible] › ℹ info Scope is shownScope creation error handling and validation.
Usage Examples:
const signale = require('signale');
// Error: No scope name provided
try {
const invalid = signale.scope();
} catch (error) {
console.error(error.message); // "No scope name was defined."
}
// Valid: Empty string handling
const emptyScoped = signale.scope('', 'valid');
emptyScoped.info('Empty strings filtered out');
// Output: [valid] › ℹ info Empty strings filtered out
// Array scope names are flattened
const complexScope = signale.scope('level1', 'level2');
console.log(complexScope.scopeName); // ["level1", "level2"]Install with Tessl CLI
npx tessl i tessl/npm-signale