or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcore-api.mdhap-integration.mdindex.mdlogging.mdplatform-accessories.mdplugin-system.md
tile.json

logging.mddocs/

Logging System

The Homebridge logging system provides a structured framework with prefixes, log levels, and formatting options for plugin debugging and system monitoring. It supports both plugin-specific logging through the

Logging
interface and system-wide logging through the
Logger
class.

Capabilities

Logging Interface

The main logging interface provided to plugins for structured output.

/**
 * Plugin logging interface provided to all plugins
 * Supports multiple log levels and automatic prefixing
 */
interface Logging {
  /** Plugin-specific log prefix */
  readonly prefix: string;
  
  /** Log informational messages */
  info(message: string, ...parameters: any[]): void;
  /** Log success messages (green output) */
  success(message: string, ...parameters: any[]): void;  
  /** Log warning messages (yellow output) */
  warn(message: string, ...parameters: any[]): void;
  /** Log error messages (red output) */
  error(message: string, ...parameters: any[]): void;
  /** Log debug messages (only shown when debug mode enabled) */
  debug(message: string, ...parameters: any[]): void;
  /** Log messages with specific level */
  log(level: LogLevel, message: string, ...parameters: any[]): void;
  
  /** Log info messages using function call syntax */
  (message: string, ...parameters: any[]): void;
}

Usage Examples:

import { AccessoryPlugin, Logger, AccessoryConfig, API } from "homebridge";

class MyAccessory implements AccessoryPlugin {
  constructor(
    private log: Logger, // Logging interface
    private config: AccessoryConfig,
    private api: API
  ) {
    // Basic logging
    this.log.info("Initializing accessory:", this.config.name);
    this.log.success("Configuration loaded successfully");
    this.log.warn("Using default polling interval");
    this.log.debug("Debug information:", { config: this.config });
    
    // Function call syntax for info level
    this.log("Accessory ready"); // Same as this.log.info("Accessory ready")
    
    // Error logging with details
    try {
      this.initializeDevice();
    } catch (error) {
      this.log.error("Failed to initialize device:", error);
    }
    
    // Formatted logging with parameters
    this.log.info("Device status: %s, Temperature: %d°C", "online", 23);
  }

  private async getState() {
    this.log.debug("Getting device state");
    
    try {
      const state = await this.fetchDeviceState();
      this.log.debug("Retrieved state:", state);
      return state;
    } catch (error) {
      this.log.error("Failed to get state:", error.message);
      throw error;
    }
  }
}

Logger Class

The main Logger implementation with static methods for system-wide configuration.

/**
 * Main logger implementation
 * Provides static methods for system configuration and instance methods for logging
 */
class Logger implements Logging {
  /** Internal system logger instance */
  static readonly internal: Logger;
  
  /** Plugin-specific log prefix */
  readonly prefix: string;
  
  /** Create a logger with a specific prefix */
  static withPrefix(prefix: string): Logger;
  /** Enable or disable debug logging globally */
  static setDebugEnabled(enabled: boolean): void;
  /** Enable or disable timestamps in log output */
  static setTimestampEnabled(enabled: boolean): void;
  /** Force color output even when not connected to a TTY */
  static forceColor(): void;
  
  /** Log informational messages */
  info(message: string, ...parameters: any[]): void;
  /** Log success messages (green output) */
  success(message: string, ...parameters: any[]): void;
  /** Log warning messages (yellow output) */
  warn(message: string, ...parameters: any[]): void;
  /** Log error messages (red output) */
  error(message: string, ...parameters: any[]): void;
  /** Log debug messages (only shown when debug mode enabled) */
  debug(message: string, ...parameters: any[]): void;
  /** Log messages with specific level */
  log(level: LogLevel, message: string, ...parameters: any[]): void;
  
  /** Log info messages using function call syntax */
  (message: string, ...parameters: any[]): void;
}

Usage Examples:

// Create plugin-specific logger
const myLogger = Logger.withPrefix("MyPlugin");
myLogger.info("Plugin initialized");

// Configure global logging settings
Logger.setDebugEnabled(true);
Logger.setTimestampEnabled(false);
Logger.forceColor();

// Use internal logger for system messages
Logger.internal.warn("System warning message");

// Different log levels
const logger = Logger.withPrefix("DeviceManager");
logger.info("Device discovery started");
logger.success("Found 5 devices");
logger.warn("Device offline: Living Room Light");
logger.error("Connection failed: Kitchen Switch");
logger.debug("Device response:", { status: "ok", data: [...] });

// Formatted logging
logger.info("Device %s changed state to %s", deviceName, newState);
logger.debug("Processing %d devices in %dms", deviceCount, processingTime);

Log Levels

Enumeration of available log levels with their output formatting.

/**
 * Available log levels for structured logging
 * Each level has distinct formatting and color coding
 */
enum LogLevel {
  /** Informational messages (white/default color) */
  INFO = "info",
  /** Success messages (green color) */
  SUCCESS = "success",
  /** Warning messages (yellow color) */
  WARN = "warn", 
  /** Error messages (red color) */
  ERROR = "error",
  /** Debug messages (gray color, only shown when debug enabled) */
  DEBUG = "debug"
}

Usage Examples:

// Using log levels explicitly
logger.log(LogLevel.INFO, "System ready");
logger.log(LogLevel.SUCCESS, "Operation completed");
logger.log(LogLevel.WARN, "Configuration issue detected");
logger.log(LogLevel.ERROR, "Critical error occurred");
logger.log(LogLevel.DEBUG, "Detailed debugging information");

// Using convenience methods (preferred)
logger.info("System ready");
logger.success("Operation completed");
logger.warn("Configuration issue detected");
logger.error("Critical error occurred");
logger.debug("Detailed debugging information");

// Conditional logging based on level
const logLevel = LogLevel.DEBUG;
if (logLevel === LogLevel.DEBUG) {
  logger.debug("Verbose debugging information");
}

Platform Logging Integration

Logging integration patterns for different plugin types.

Accessory Plugin Logging:

class MyAccessory implements AccessoryPlugin {
  constructor(
    private log: Logger,
    private config: AccessoryConfig,
    private api: API
  ) {
    this.log.info("Accessory starting:", this.config.name);
  }
  
  async setState(value: boolean) {
    this.log.debug("Setting state to:", value);
    
    try {
      await this.deviceApi.setState(value);
      this.log.success("State changed successfully");
    } catch (error) {
      this.log.error("Failed to set state:", error.message);
      throw error;
    }
  }
}

Platform Plugin Logging:

class MyPlatform implements DynamicPlatformPlugin {
  private readonly log: Logger;
  
  constructor(log: Logger, config: PlatformConfig, api: API) {
    this.log = log;
    this.log.info("Platform initializing with", config.devices?.length || 0, "devices");
  }
  
  configureAccessory(accessory: PlatformAccessory) {
    this.log.info("Configuring cached accessory:", accessory.displayName);
    
    // Create accessory-specific logger
    const accessoryLog = Logger.withPrefix(`${this.log.prefix}:${accessory.displayName}`);
    accessoryLog.debug("Restoring accessory services");
  }
  
  private async discoverDevices() {
    this.log.info("Starting device discovery");
    
    try {
      const devices = await this.deviceApi.discover();
      this.log.success("Discovered", devices.length, "devices");
      
      for (const device of devices) {
        this.log.debug("Found device:", device.name, device.id);
      }
    } catch (error) {
      this.log.error("Device discovery failed:", error.message);
    }
  }
}

Deprecated Functions

Legacy logging functions maintained for backward compatibility.

/**
 * @deprecated Use Logger.withPrefix() instead
 */
function withPrefix(prefix: string): Logger;

/**
 * @deprecated Use Logger.setDebugEnabled() instead  
 */
function setDebugEnabled(enabled: boolean): void;

/**
 * @deprecated Use Logger.setTimestampEnabled() instead
 */
function setTimestampEnabled(enabled: boolean): void;

/**
 * @deprecated Use Logger.forceColor() instead
 */
function forceColor(): void;

Advanced Logging Patterns

Contextual Logging:

class DeviceManager {
  private createLogger(context: string): Logger {
    return Logger.withPrefix(`DeviceManager:${context}`);
  }
  
  async manageDevice(deviceId: string) {
    const log = this.createLogger(deviceId);
    
    log.info("Starting device management");
    log.debug("Device configuration:", this.getDeviceConfig(deviceId));
    
    try {
      await this.initializeDevice(deviceId);
      log.success("Device initialized successfully");
    } catch (error) {
      log.error("Device initialization failed:", error.message);
    }
  }
}

Structured Logging:

class ApiClient {
  private log = Logger.withPrefix("ApiClient");
  
  async makeRequest(endpoint: string, data: any) {
    const requestId = Math.random().toString(36).substr(2, 9);
    const requestLog = Logger.withPrefix(`ApiClient:${requestId}`);
    
    requestLog.info("Making API request to:", endpoint);
    requestLog.debug("Request data:", data);
    
    const startTime = Date.now();
    
    try {
      const response = await this.httpClient.post(endpoint, data);
      const duration = Date.now() - startTime;
      
      requestLog.success("Request completed in", duration, "ms");
      requestLog.debug("Response:", response.data);
      
      return response.data;
    } catch (error) {
      const duration = Date.now() - startTime;
      requestLog.error("Request failed after", duration, "ms:", error.message);
      throw error;
    }
  }
}

Types

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