or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdjson-schema.mdlogging.mdnode-integration.mdutilities.mdvirtual-filesystem.mdworkspace.md
tile.json

logging.mddocs/

Logging System

Structured logging infrastructure with multiple logger implementations, level filtering, message transformation, and Observable-based event streaming for comprehensive application monitoring.

Capabilities

Core Logging Types

Basic types and interfaces for the logging system.

/**
 * Available log levels in order of severity
 */
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';

/**
 * A log entry containing all information about a logged message
 */
interface LogEntry {
  /** Severity level of the log entry */
  readonly level: LogLevel;
  /** Log message content */
  readonly message: string;
  /** Timestamp when the entry was created */
  readonly timestamp: Date;
  /** Additional structured metadata */
  readonly metadata: JsonObject;
  /** Logger name that created this entry */
  readonly logger: string;
  /** Full logger path including parent loggers */
  readonly path: readonly string[];
}

/**
 * Metadata associated with a logger instance
 */
interface LoggerMetadata {
  /** Logger name */
  name: string;
  /** Full path to this logger including parents */
  path: readonly string[];
}

/**
 * Core logging API interface
 */
interface LoggerApi {
  /**
   * Create a child logger with the given name
   * @param name - Name for the child logger
   * @returns New child logger instance
   */
  createChild(name: string): Logger;
  
  /**
   * Log a debug message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  debug(message: string, metadata?: JsonObject): void;
  
  /**
   * Log an info message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  info(message: string, metadata?: JsonObject): void;
  
  /**
   * Log a warning message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  warn(message: string, metadata?: JsonObject): void;
  
  /**
   * Log an error message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  error(message: string, metadata?: JsonObject): void;
  
  /**
   * Log a fatal error message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  fatal(message: string, metadata?: JsonObject): void;
}

Main Logger Class

Core logger implementation with Observable event streaming.

/**
 * Main logger class that extends Observable to emit log entries
 * Provides hierarchical logging with parent-child relationships
 */
class Logger extends Observable<LogEntry> implements LoggerApi {
  /** Logger metadata including name and path */
  readonly metadata: LoggerMetadata;
  
  /**
   * Create a new logger instance
   * @param name - Logger name
   * @param parent - Optional parent logger for hierarchy
   */
  constructor(name: string, parent?: Logger);
  
  /**
   * Create a child logger with the given name
   * @param name - Name for the child logger
   * @returns New child logger instance
   */
  createChild(name: string): Logger;
  
  /**
   * Log a debug message (lowest severity)
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  debug(message: string, metadata?: JsonObject): void;
  
  /**
   * Log an informational message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  info(message: string, metadata?: JsonObject): void;
  
  /**
   * Log a warning message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  warn(message: string, metadata?: JsonObject): void;
  
  /**
   * Log an error message
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  error(message: string, metadata?: JsonObject): void;
  
  /**
   * Log a fatal error message (highest severity)
   * @param message - Message to log
   * @param metadata - Optional additional metadata
   */
  fatal(message: string, metadata?: JsonObject): void;
  
  /**
   * Subscribe to log entries from this logger and its children
   * @param observer - Observer to receive log entries
   * @returns Subscription for cleanup
   */
  subscribe(observer: Observer<LogEntry>): Subscription;
  subscribe(
    next?: (value: LogEntry) => void,
    error?: (error: any) => void,
    complete?: () => void
  ): Subscription;
}

Specialized Logger Implementations

Logger implementations with specific behaviors and transformations.

/**
 * Logger that adds indentation to messages based on nesting level
 * Useful for showing hierarchical operations in console output
 */
class IndentLogger extends Logger {
  /**
   * Create an indenting logger
   * @param name - Logger name
   * @param parent - Optional parent logger
   * @param indentBy - String to use for indentation (default: '  ')
   */
  constructor(name: string, parent?: Logger, indentBy?: string);
  
  debug(message: string, metadata?: JsonObject): void;
  info(message: string, metadata?: JsonObject): void;
  warn(message: string, metadata?: JsonObject): void;
  error(message: string, metadata?: JsonObject): void;
  fatal(message: string, metadata?: JsonObject): void;
}

/**
 * No-operation logger that discards all log messages
 * Useful for testing or when logging needs to be disabled
 */
class NullLogger extends Logger {
  constructor();
  
  debug(message: string, metadata?: JsonObject): void;
  info(message: string, metadata?: JsonObject): void;
  warn(message: string, metadata?: JsonObject): void;
  error(message: string, metadata?: JsonObject): void;
  fatal(message: string, metadata?: JsonObject): void;
}

/**
 * Logger that transforms log levels before emitting
 * Allows remapping of log levels (e.g., debug -> info)
 */
class LevelTransformLogger extends Logger {
  /**
   * Create a level-transforming logger
   * @param name - Logger name
   * @param parent - Optional parent logger
   * @param levelTransform - Function to transform log levels
   */
  constructor(
    name: string, 
    parent?: Logger, 
    levelTransform?: (level: LogLevel) => LogLevel
  );
  
  debug(message: string, metadata?: JsonObject): void;
  info(message: string, metadata?: JsonObject): void;
  warn(message: string, metadata?: JsonObject): void;
  error(message: string, metadata?: JsonObject): void;
  fatal(message: string, metadata?: JsonObject): void;
}

/**
 * Logger that filters out messages below a specified level
 * Only messages at or above the cap level are emitted
 */
class LevelCapLogger extends Logger {
  /**
   * Create a level-capped logger
   * @param name - Logger name
   * @param parent - Optional parent logger
   * @param levelCap - Minimum level to emit (default: 'info')
   */
  constructor(name: string, parent?: Logger, levelCap?: LogLevel);
  
  debug(message: string, metadata?: JsonObject): void;
  info(message: string, metadata?: JsonObject): void;
  warn(message: string, metadata?: JsonObject): void;
  error(message: string, metadata?: JsonObject): void;
  fatal(message: string, metadata?: JsonObject): void;
}

/**
 * Logger that applies transformations to messages and metadata
 * Useful for formatting, filtering, or enriching log data
 */
class TransformLogger extends Logger {
  /**
   * Create a transforming logger
   * @param name - Logger name
   * @param stream - Source stream of log entries to transform
   * @param transform - Function to transform log entries
   */
  constructor(
    name: string,
    stream: Observable<LogEntry>,
    transform?: (entry: LogEntry) => LogEntry
  );
}

Logger Utility Functions

Utility functions for working with log levels and logger operations.

/**
 * Check if a log level meets or exceeds a minimum level
 * @param level - Level to check
 * @param minimum - Minimum required level
 * @returns True if level is at or above minimum
 */
function isLevelEnabled(level: LogLevel, minimum: LogLevel): boolean;

/**
 * Compare two log levels numerically
 * @param a - First level
 * @param b - Second level
 * @returns Negative if a < b, positive if a > b, 0 if equal
 */
function compareLevels(a: LogLevel, b: LogLevel): number;

/**
 * Get numeric value for a log level
 * @param level - Log level
 * @returns Numeric value (debug=0, info=1, warn=2, error=3, fatal=4)
 */
function levelToNumber(level: LogLevel): number;

/**
 * Convert numeric value back to log level
 * @param num - Numeric level value
 * @returns Corresponding log level
 */
function numberToLevel(num: number): LogLevel;

Usage Examples

Basic Logging

import { logging } from "@angular-devkit/core";

// Create a logger
const logger = new logging.Logger('my-app');

// Log messages at different levels
logger.debug('Debug information', { userId: 123 });
logger.info('Operation completed successfully');
logger.warn('This is a warning message');
logger.error('An error occurred', { errorCode: 'E001' });
logger.fatal('Critical system failure');

// Subscribe to log entries
logger.subscribe(entry => {
  console.log(`[${entry.level.toUpperCase()}] ${entry.logger}: ${entry.message}`);
  if (Object.keys(entry.metadata).length > 0) {
    console.log('Metadata:', entry.metadata);
  }
});

Hierarchical Logging

import { logging } from "@angular-devkit/core";

// Create parent logger
const appLogger = new logging.Logger('app');

// Create child loggers
const dbLogger = appLogger.createChild('database');
const httpLogger = appLogger.createChild('http');

// Subscribe to parent to receive all messages
appLogger.subscribe(entry => {
  console.log(`[${entry.path.join('.')}] ${entry.message}`);
});

// Child loggers emit through parent
dbLogger.info('Database connection established');
// Output: [app.database] Database connection established

httpLogger.warn('Request timeout');
// Output: [app.http] Request timeout

Specialized Loggers

import { logging } from "@angular-devkit/core";

// Indented logger for showing operation hierarchy
const indentLogger = new logging.IndentLogger('build');
const taskLogger = indentLogger.createChild('task');

indentLogger.info('Starting build process');
taskLogger.info('Compiling TypeScript');
// Output: 
// Starting build process
//   Compiling TypeScript

// Level-capped logger (only warn and above)
const productionLogger = new logging.LevelCapLogger('prod', undefined, 'warn');
productionLogger.debug('Debug info'); // Filtered out
productionLogger.info('Info message'); // Filtered out
productionLogger.warn('Warning message'); // Shown
productionLogger.error('Error message'); // Shown

// Null logger (discards everything)
const testLogger = new logging.NullLogger();
testLogger.info('This message is discarded');

Message Transformation

import { logging } from "@angular-devkit/core";

// Transform logger that adds timestamps and formats messages
const baseLogger = new logging.Logger('base');
const transformLogger = new logging.TransformLogger(
  'formatted',
  baseLogger,
  (entry) => ({
    ...entry,
    message: `[${entry.timestamp.toISOString()}] ${entry.message}`,
    metadata: {
      ...entry.metadata,
      transformed: true
    }
  })
);

transformLogger.subscribe(entry => {
  console.log(entry.message);
  // Output: [2023-10-15T10:30:00.000Z] Original message
});

baseLogger.info('Original message');

Level Filtering and Comparison

import { logging } from "@angular-devkit/core";

// Check if logging is enabled for a level
const minLevel: logging.LogLevel = 'warn';
const currentLevel: logging.LogLevel = 'info';

if (logging.isLevelEnabled(currentLevel, minLevel)) {
  console.log('Logging enabled');
} else {
  console.log('Logging filtered out');
}

// Compare levels
const comparison = logging.compareLevels('error', 'warn');
console.log(comparison > 0 ? 'error is higher' : 'warn is higher or equal');

// Convert to/from numbers
const errorNum = logging.levelToNumber('error'); // 3
const levelBack = logging.numberToLevel(errorNum); // 'error'

Advanced Logger Patterns

import { logging } from "@angular-devkit/core";
import { filter, map } from 'rxjs/operators';

// Create logger with multiple output streams
const logger = new logging.Logger('multi-output');

// Console output for all levels
logger.subscribe(entry => {
  console.log(`${entry.level}: ${entry.message}`);
});

// File output for errors only
logger.pipe(
  filter(entry => entry.level === 'error' || entry.level === 'fatal'),
  map(entry => `${entry.timestamp.toISOString()} [${entry.level}] ${entry.message}\n`)
).subscribe(line => {
  // Write to error log file
  fs.appendFileSync('error.log', line);
});

// Metrics collection for warnings and errors
logger.pipe(
  filter(entry => entry.level === 'warn' || entry.level === 'error' || entry.level === 'fatal')
).subscribe(entry => {
  // Send to monitoring system
  metrics.increment(`log.${entry.level}`, 1, { logger: entry.logger });
});