or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-logging.mderror-handling.mdevent-logging.mdindex.mdlogger-management.mdscoping.mdtransports.md
tile.json

scoping.mddocs/

Message Scoping

Scoped logging for message categorization and filtering with automatic label padding, customizable formatting, and hierarchical organization for better log management.

Capabilities

Scope Creation

Create scoped loggers for organized message categorization.

interface Scope {
  /**
   * Create a scoped logger with the specified label
   * @param label - Scope label for message categorization
   * @returns LogFunctions interface with the scope applied
   */
  (label: string): LogFunctions;
  
  /** Label for log message without scope. If set to false and scope isn't set, no padding is used */
  defaultLabel: string | false;
  
  /** 
   * Pad scope label using spaces
   * false: disabled
   * true: automatically
   * number: set exact maximum label length
   */
  labelPadding: boolean | number;
}

Usage Examples:

const log = require('electron-log');

// Create scoped loggers
const authLog = log.scope('auth');
const dbLog = log.scope('database');
const apiLog = log.scope('api');

// Use scoped loggers
authLog.info('User login attempt');
dbLog.debug('Query executed in 45ms');
apiLog.error('Request failed with status 500');

// Nested scoping
const userAuthLog = log.scope('auth:user');
const adminAuthLog = log.scope('auth:admin');

userAuthLog.info('Regular user logged in');
adminAuthLog.warn('Admin access attempt');

Scope Configuration

Configure scope appearance and behavior.

interface ScopeConfiguration {
  /** Default label when no scope is specified */
  defaultLabel: string | false;
  /** Label padding configuration */
  labelPadding: boolean | number;
}

Usage Examples:

const log = require('electron-log');

// Configure default label
log.scope.defaultLabel = 'main';
log.info('This will show [main] prefix');

// Disable default label
log.scope.defaultLabel = false;
log.info('This will have no default prefix');

// Configure automatic padding
log.scope.labelPadding = true;
const shortLog = log.scope('api');
const longLog = log.scope('authentication');

shortLog.info('Short scope');      // [api         ] Short scope
longLog.info('Long scope');        // [authentication] Long scope

// Fixed padding width
log.scope.labelPadding = 12;
shortLog.info('Fixed width');      // [api        ] Fixed width
longLog.info('Fixed width');       // [authentication] Fixed width (truncated if too long)

// Disable padding
log.scope.labelPadding = false;
shortLog.info('No padding');       // [api] No padding
longLog.info('No padding');        // [authentication] No padding

Hierarchical Scoping

Create hierarchical scope structures for complex applications.

interface HierarchicalScoping {
  /** Create nested scopes using delimiter */
  createHierarchy: (path: string, delimiter?: string) => LogFunctions;
}

Usage Examples:

const log = require('electron-log');

// Hierarchical scopes using colon delimiter
const moduleScopes = {
  auth: {
    login: log.scope('auth:login'),
    logout: log.scope('auth:logout'),
    register: log.scope('auth:register')
  },
  database: {
    users: log.scope('db:users'),
    posts: log.scope('db:posts'),
    connection: log.scope('db:connection')
  },
  api: {
    v1: {
      users: log.scope('api:v1:users'),
      posts: log.scope('api:v1:posts')
    },
    v2: {
      users: log.scope('api:v2:users'),
      posts: log.scope('api:v2:posts')
    }
  }
};

// Use hierarchical scopes
moduleScopes.auth.login.info('User authentication started');
moduleScopes.database.users.debug('User query executed');
moduleScopes.api.v1.users.error('V1 API endpoint failed');

// Dynamic scope creation
function createScopedLogger(module, submodule, action) {
  const scopePath = [module, submodule, action].filter(Boolean).join(':');
  return log.scope(scopePath);
}

const paymentLogger = createScopedLogger('payment', 'stripe', 'charge');
paymentLogger.info('Processing payment');

Scope-Based Filtering

Filter log messages based on scope patterns.

interface ScopeFiltering {
  /** Filter messages by scope pattern */
  scopeFilter: (pattern: string | RegExp) => boolean;
}

Usage Examples:

const log = require('electron-log');

// Create various scoped loggers
const authLog = log.scope('auth');
const dbLog = log.scope('database');
const apiLog = log.scope('api');
const debugLog = log.scope('debug');

// Filter using hooks
log.hooks.push((message) => {
  // Only show auth and api logs in production
  if (process.env.NODE_ENV === 'production') {
    if (message.scope && !message.scope.match(/^(auth|api)/)) {
      return false; // Skip non-auth/api messages
    }
  }
  
  // Filter out debug scope in production
  if (process.env.NODE_ENV === 'production' && message.scope === 'debug') {
    return false;
  }
  
  return message;
});

// Conditional scope creation
function createConditionalScope(name, condition) {
  const scopedLogger = log.scope(name);
  
  return new Proxy(scopedLogger, {
    get(target, prop) {
      if (typeof target[prop] === 'function') {
        return (...args) => {
          if (condition()) {
            return target[prop](...args);
          }
        };
      }
      return target[prop];
    }
  });
}

// Only log debug messages in development
const conditionalDebug = createConditionalScope('debug', () => 
  process.env.NODE_ENV === 'development'
);

conditionalDebug.info('This only appears in development');

Advanced Scoping Patterns

Complex scoping patterns for large applications.

interface AdvancedScopingPatterns {
  /** Factory for creating scoped loggers */
  createScopeFactory: (baseScope: string) => (subScope: string) => LogFunctions;
  /** Scope inheritance */
  inheritScope: (parentScope: LogFunctions, childScopeName: string) => LogFunctions;
}

Usage Examples:

const log = require('electron-log');

// Scope factory pattern
function createModuleLogger(moduleName) {
  const moduleScope = log.scope(moduleName);
  
  return {
    base: moduleScope,
    sub: (subName) => log.scope(`${moduleName}:${subName}`),
    action: (actionName) => log.scope(`${moduleName}:action:${actionName}`),
    error: (errorType) => log.scope(`${moduleName}:error:${errorType}`)
  };
}

const userModule = createModuleLogger('user');
userModule.base.info('User module initialized');
userModule.sub('profile').debug('Loading user profile');
userModule.action('update').info('Updating user data');
userModule.error('validation').error('Invalid user data');

// Scope inheritance with context
function createContextualScope(baseLogger, context) {
  const contextScope = baseLogger.scope(`${baseLogger.logId || 'default'}:${context}`);
  
  // Add context methods
  contextScope.withContext = (additionalContext) => {
    return createContextualScope(baseLogger, `${context}:${additionalContext}`);
  };
  
  contextScope.timed = (operation) => {
    const start = Date.now();
    return {
      end: () => {
        const duration = Date.now() - start;
        contextScope.debug(`${operation} completed in ${duration}ms`);
      }
    };
  };
  
  return contextScope;
}

// Usage of contextual scoping
const requestScope = createContextualScope(log, 'request');
const userRequestScope = requestScope.withContext('user:123');

const timer = userRequestScope.timed('database-query');
// ... perform operation
timer.end(); // Logs: [request:user:123] database-query completed in 45ms

// Scope-based transport routing
log.hooks.push((message) => {
  // Route different scopes to different files
  if (message.scope && message.scope.startsWith('error:')) {
    // Only send error-scoped messages to file
    return message;
  } else if (message.scope && message.scope.startsWith('debug:')) {
    // Send debug messages only to console in development
    if (process.env.NODE_ENV === 'development') {
      message.transports = ['console'];
    } else {
      return false; // Skip in production
    }
  }
  
  return message;
});

Scope-Aware Formatting

Custom formatting that leverages scope information.

interface ScopeAwareFormatting {
  /** Format messages differently based on scope */
  formatByScope: (scope: string, message: LogMessage) => string;
}

Usage Examples:

const log = require('electron-log');

// Configure scope-aware formatting
log.transports.console.format = (params) => {
  const { message, level } = params;
  const scope = message.scope;
  
  // Different formats for different scopes
  if (scope && scope.startsWith('error:')) {
    return `🚨 [${scope.toUpperCase()}] ${level.toUpperCase()}: ${message.data.join(' ')}`;
  } else if (scope && scope.startsWith('debug:')) {
    return `πŸ” [${scope}] ${message.data.join(' ')}`;
  } else if (scope && scope.startsWith('api:')) {
    return `🌐 [${scope}] ${level}: ${message.data.join(' ')}`;
  } else if (scope) {
    return `πŸ“ [${scope}] ${message.data.join(' ')}`;
  }
  
  // Default format
  return `${level}: ${message.data.join(' ')}`;
};

// Use scoped loggers with custom formatting
const errorLog = log.scope('error:validation');
const debugLog = log.scope('debug:performance');
const apiLog = log.scope('api:users');

errorLog.error('User validation failed');     // 🚨 [ERROR:VALIDATION] ERROR: User validation failed
debugLog.info('Query took 150ms');            // πŸ” [debug:performance] Query took 150ms
apiLog.info('User created successfully');     // 🌐 [api:users] info: User created successfully

Types

interface Scope {
  (label: string): LogFunctions;
  defaultLabel: string | false;
  labelPadding: boolean | number;
}

interface LogFunctions {
  error(...params: any[]): void;
  warn(...params: any[]): void;
  info(...params: any[]): void;
  verbose(...params: any[]): void;
  debug(...params: any[]): void;
  silly(...params: any[]): void;
  log(...params: any[]): void;
}

interface LogMessage {
  data: any[];
  date: Date;
  level: LogLevel;
  logId?: string;
  scope?: string;
  variables?: Variables;
}