CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-homebridge

HomeKit support for the impatient - lightweight Node.js server enabling HomeKit integration for non-native smart home devices through plugin ecosystem

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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";

docs

configuration.md

core-api.md

hap-integration.md

index.md

logging.md

platform-accessories.md

plugin-system.md

tile.json