or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

architecture.mdasync-tasks.mddata-processing.mdfile-system.mdindex.mdlogging.mdprocess-execution.md
tile.json

logging.mddocs/

Logging and Debugging

Structured logging system with debug capabilities, message transformation, and key-value data collection for comprehensive application monitoring. Provides both structured logging and debug data collection utilities.

Capabilities

Logger Class

Main logging interface with structured message support and configurable output.

/**
 * Structured logger with configurable message transformation
 */
class Logger {
  /** Message transformation function for customizing log output */
  messageTransformer: (message: string, level: LogLevel) => string;
  
  /** Whether debug logging is enabled */
  readonly isDebugEnabled: boolean;
  
  constructor(stream: WritableStream);
  
  /**
   * Log informational message with optional structured fields
   * @param messageOrFields - Message string or structured fields object
   * @param message - Message string when first param is fields
   */
  info(messageOrFields: Fields | null | string, message?: string): void;
  
  /**
   * Log error message with optional structured fields
   * @param messageOrFields - Message string or structured fields object
   * @param message - Message string when first param is fields
   */
  error(messageOrFields: Fields | null | string, message?: string): void;
  
  /**
   * Log warning message with optional structured fields
   * @param messageOrFields - Message string or structured fields object
   * @param message - Message string when first param is fields
   */
  warn(messageOrFields: Fields | null | string, message?: string): void;
  
  /**
   * Log debug message with structured fields
   * @param fields - Structured fields object
   * @param message - Debug message
   */
  debug(fields: Fields | null, message: string): void;
  
  /**
   * Log plain message without fields
   * @param message - Message to log
   */
  log(message: string): void;
  
  /**
   * Format file path for logging
   * @param file - File path to format
   * @returns Formatted file path
   */
  filePath(file: string): string;
}

type LogLevel = "info" | "warn" | "debug" | "notice" | "error";

interface Fields {
  [index: string]: any;
}

Usage Examples:

import { Logger, log } from "builder-util";

// Use the default logger instance
log.info("Build process started");
log.info({ platform: "win32", arch: "x64" }, "Building for Windows");

// Error logging with context
log.error({ 
  file: "/project/src/main.ts",
  line: 42,
  error: "TypeScript compilation failed"
}, "Compilation error");

// Debug logging with structured data
log.debug({
  operation: "file-copy",
  src: "/source/file.txt",
  dest: "/dest/file.txt",
  size: 1024
}, "copying file");

// Simple message logging
log.log("Operation completed successfully");

// Check if debug is enabled
if (log.isDebugEnabled) {
  log.debug({ details: expensiveToCompute() }, "debug information");
}

Debug Logger

Key-value debug data collection and persistence for detailed debugging information.

/**
 * Debug data collector with persistence capabilities
 */
class DebugLogger {
  /** Collected debug data as key-value pairs */
  readonly data: Map<string, any>;
  
  /** Whether debug logging is enabled */
  readonly isEnabled: boolean;
  
  constructor(isEnabled?: boolean);
  
  /**
   * Add key-value pair to debug data
   * @param key - Data key
   * @param value - Data value (any type)
   */
  add(key: string, value: any): void;
  
  /**
   * Save collected debug data to file
   * @param file - Output file path
   * @returns Promise resolving when save completes
   */
  save(file: string): Promise<void>;
}

Usage Examples:

import { DebugLogger } from "builder-util";

// Create debug logger
const debugLogger = new DebugLogger(true);

// Collect debug information
debugLogger.add("buildStart", new Date().toISOString());
debugLogger.add("targetPlatform", "win32");
debugLogger.add("targetArch", "x64");
debugLogger.add("nodeVersion", process.version);

// Add complex data
debugLogger.add("buildConfig", {
  production: true,
  minify: true,
  sourceMaps: false
});

// Add performance metrics
debugLogger.add("compilationTime", 5.2);
debugLogger.add("bundleSize", 1024 * 500);

// Save debug data to file
await debugLogger.save("/debug/build-debug.json");

// Check if enabled before expensive operations
if (debugLogger.isEnabled) {
  debugLogger.add("memoryUsage", process.memoryUsage());
}

Global Debug and Logger Instances

Pre-configured debug and logger instances for immediate use.

/** Global debug instance for electron-builder */
const debug: DebuggerInstance;

/** Global logger instance for stdout */
const log: Logger;

/** Debug instance specifically for 7z operations */
const debug7z: DebuggerInstance;

/** Logging padding constant */
const PADDING: number;

Usage Examples:

import { debug, log, debug7z } from "builder-util";

// Use global debug instance
debug("Starting build process");
debug("Configuration loaded: %o", config);

// Use 7z-specific debug
debug7z("Starting 7z compression");
debug7z("Archive size: %d bytes", archiveSize);

// Use global logger
log.info("Build completed successfully");

Logger Configuration

Customize logger behavior and output formatting.

/**
 * Set custom printer function for log output
 * @param value - Custom printer function or null to reset
 */
function setPrinter(value: ((message: string) => void) | null): void;

/**
 * Create formatted message with fields
 * @param message - Base message
 * @param fields - Structured fields
 * @param level - Log level
 * @param color - Color function for output
 * @param messagePadding - Message padding amount
 * @returns Formatted message string
 */
static createMessage(
  message: string,
  fields: Fields | null,
  level: LogLevel,
  color: (it: string) => string,
  messagePadding?: number
): string;

Usage Examples:

import { setPrinter, Logger } from "builder-util";

// Custom printer for redirecting logs
setPrinter((message) => {
  // Send to custom logging service
  myLoggingService.send(message);
});

// Create custom logger with transformation
const customLogger = new Logger(process.stdout);
customLogger.messageTransformer = (message, level) => {
  const timestamp = new Date().toISOString();
  return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
};

// Reset to default printer
setPrinter(null);

Usage Patterns

Structured Application Logging

import { log } from "builder-util";

class BuildManager {
  async build(config: BuildConfig) {
    log.info({ 
      platform: config.platform,
      arch: config.arch,
      version: config.version
    }, "Starting build");
    
    try {
      const result = await this.performBuild(config);
      
      log.info({
        duration: result.duration,
        outputSize: result.size,
        outputPath: result.path
      }, "Build completed");
      
      return result;
    } catch (error) {
      log.error({
        platform: config.platform,
        error: error.message,
        stack: error.stack
      }, "Build failed");
      
      throw error;
    }
  }
}

Debug Data Collection

import { DebugLogger } from "builder-util";

class PerformanceTracker {
  private debugLogger = new DebugLogger();
  private startTimes = new Map<string, number>();
  
  start(operation: string) {
    this.startTimes.set(operation, Date.now());
    this.debugLogger.add(`${operation}_start`, new Date().toISOString());
  }
  
  end(operation: string) {
    const startTime = this.startTimes.get(operation);
    if (startTime) {
      const duration = Date.now() - startTime;
      this.debugLogger.add(`${operation}_duration`, duration);
      this.debugLogger.add(`${operation}_end`, new Date().toISOString());
    }
  }
  
  async saveMetrics(filepath: string) {
    await this.debugLogger.save(filepath);
  }
}

// Usage
const tracker = new PerformanceTracker();
tracker.start("compilation");
await compileTypeScript();
tracker.end("compilation");
await tracker.saveMetrics("/debug/performance.json");

Conditional Debug Logging

import { log, debug } from "builder-util";

function processFiles(files: Array<string>) {
  log.info({ fileCount: files.length }, "Processing files");
  
  for (let i = 0; i < files.length; i++) {
    const file = files[i];
    
    // Only log debug info if debug is enabled
    if (log.isDebugEnabled) {
      log.debug({
        file,
        index: i,
        total: files.length,
        progress: ((i + 1) / files.length * 100).toFixed(1) + "%"
      }, "processing file");
    }
    
    processFile(file);
  }
  
  log.info("File processing completed");
}

Custom Log Formatting

import { Logger } from "builder-util";

// Create logger with custom formatting
const customLogger = new Logger(process.stdout);

customLogger.messageTransformer = (message, level) => {
  const timestamp = new Date().toISOString();
  const levelUpper = level.toUpperCase().padEnd(5);
  return `${timestamp} ${levelUpper} ${message}`;
};

// Use custom logger
customLogger.info("This will be formatted with timestamp");
customLogger.error({ code: 500 }, "Server error occurred");