or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-ledgerhq--logs

Ledger logs central point for unified logging system across Ledger libraries

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@ledgerhq/logs@6.13.x

To install, run

npx @tessl/cli install tessl/npm-ledgerhq--logs@6.13.0

index.mddocs/

@ledgerhq/logs

@ledgerhq/logs is a unified logging system for all Ledger libraries, providing centralized log dispatching and management across the Ledger Live ecosystem. It offers core logging functionality with the log() function for basic logging, a trace() function for capturing contextual information, and a LocalTracer class for maintaining persistent context across multiple log calls.

Package Information

  • Package Name: @ledgerhq/logs
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @ledgerhq/logs

Core Imports

import { log, trace, listen, LocalTracer, type Log, type TraceContext } from "@ledgerhq/logs";

For CommonJS:

const { log, trace, listen, LocalTracer } = require("@ledgerhq/logs");

Basic Usage

import { log, trace, listen, LocalTracer } from "@ledgerhq/logs";

// Basic logging
log("apdu-in", "Received APDU command", { command: "0x80040000" });

// Enhanced logging with context
trace({
  type: "hw-connection",
  message: "Device connected",
  data: { deviceId: "nano-s-001" },
  context: { sessionId: "abc123" }
});

// Listen to all log events
const unsubscribe = listen((logEntry) => {
  console.log(`[${logEntry.type}] ${logEntry.message}`, logEntry.data);
});

// Tracer for maintaining context
const tracer = new LocalTracer("wallet-sync", { userId: "user123" });
tracer.trace("Starting sync", { accountCount: 5 });

Capabilities

Basic Logging

Core logging function for dispatching log events across the system.

/**
 * Logs something
 * @param type - A namespaced identifier of the log (not a level like "debug", "error" but more like "apdu-in", "apdu-out", etc...)
 * @param message - A clear message of the log associated to the type
 * @param data - Optional data associated to the log event
 */
function log(type: LogType, message?: string, data?: LogData): void;

Enhanced Tracing

Advanced logging function that captures more context than the basic log function.

/**
 * A simple tracer function, only expanding the existing log function
 * @param params - Object containing trace information
 */
function trace(params: {
  type: LogType;
  message?: string;
  data?: LogData;
  context?: TraceContext;
}): void;

Event Subscription

Subscribe to log events with callback functions for processing or forwarding logs.

/**
 * Adds a subscriber to the emitted logs
 * @param cb - Callback function called for each future log() with the Log object
 * @returns Function that can be called to unsubscribe the listener
 */
function listen(cb: Subscriber): Unsubscribe;

Local Tracer Class

Class-based tracer for maintaining persistent context across multiple log calls.

/**
 * A simple tracer class, that can be used to avoid repetition when using the `trace` function
 */
class LocalTracer {
  /**
   * Creates a new LocalTracer instance
   * @param type - A given type (not level) for the current local tracer ("hw", "withDevice", etc.)
   * @param context - Anything representing the context where the log occurred
   */
  constructor(type: LogType, context?: TraceContext);

  /**
   * Trace a message with the tracer's type and context
   * @param message - Log message
   * @param data - Optional additional data (Note: signature uses TraceContext but data is passed as LogData to trace function)
   */
  trace(message: string, data?: TraceContext): void;

  /**
   * Get the current context
   * @returns Current context or undefined
   */
  getContext(): TraceContext | undefined;

  /**
   * Set the context (mutates instance)
   * @param context - New context
   */
  setContext(context?: TraceContext): void;

  /**
   * Merge additional context (mutates instance)
   * @param contextToAdd - Context to merge with existing context
   */
  updateContext(contextToAdd: TraceContext): void;

  /**
   * Get the current log type
   * @returns Current log type
   */
  getType(): LogType;

  /**
   * Set the log type (mutates instance)
   * @param type - New log type
   */
  setType(type: LogType): void;

  /**
   * Create a new instance with an updated type (immutable)
   * @param type - New log type
   * @returns New LocalTracer instance
   */
  withType(type: LogType): LocalTracer;

  /**
   * Create a new instance with a new context (immutable)
   * @param context - New context (can be undefined to reset)
   * @returns New LocalTracer instance
   */
  withContext(context?: TraceContext): LocalTracer;

  /**
   * Create a new instance with an updated context (immutable)
   * @param contextToAdd - Context to merge with existing context
   * @returns New LocalTracer instance
   */
  withUpdatedContext(contextToAdd: TraceContext): LocalTracer;
}

Types

/**
 * Context data structure for tracing system
 */
type TraceContext = Record<string, unknown>;

/**
 * Data associated with log events
 */
type LogData = any;

/**
 * Namespaced identifier for log types
 */
type LogType = string;

/**
 * Core log object structure
 */
interface Log {
  /** A namespaced identifier of the log (not a level like "debug", "error" but more like "apdu", "hw", etc...) */
  type: LogType;
  /** Optional log message */
  message?: string;
  /** Data associated to the log event */
  data?: LogData;
  /** Context data, coming for example from the caller's parent, to enable a simple tracing system */
  context?: TraceContext;
  /** Unique id among all logs */
  id: string;
  /** Date when the log occurred */
  date: Date;
}

/**
 * Function to unsubscribe from log events
 */
type Unsubscribe = () => void;

/**
 * Callback function for log event subscribers
 */
type Subscriber = (log: Log) => void;

Usage Examples

Multi-step Process Logging

import { LocalTracer } from "@ledgerhq/logs";

// Create a tracer for a specific operation
const syncTracer = new LocalTracer("account-sync", {
  userId: "user123",
  sessionId: "session456"
});

// Log start of operation
syncTracer.trace("Starting account synchronization");

// Log progress with additional data
syncTracer.trace("Fetching account data", { accountId: "acc789" });

// Create new tracer for sub-operation
const apiTracer = syncTracer.withType("api-call");
apiTracer.trace("Calling accounts endpoint", { 
  url: "/api/accounts",
  method: "GET"
});

// Log completion
syncTracer.trace("Account synchronization completed", {
  duration: 1250,
  accountsUpdated: 3
});

Event Processing Pipeline

import { log, listen } from "@ledgerhq/logs";

// Set up log processing
const unsubscribe = listen((logEntry) => {
  // Forward critical logs to monitoring service
  if (logEntry.type.includes("error") || logEntry.type.includes("critical")) {
    sendToMonitoring(logEntry);
  }
  
  // Store all logs in local database
  saveToDatabase(logEntry);
  
  // Debug output in development
  if (process.env.NODE_ENV === "development") {
    console.log(`[${logEntry.date.toISOString()}] ${logEntry.type}: ${logEntry.message}`);
  }
});

// Emit various log types throughout application
log("device-connection", "Hardware wallet connected", { deviceType: "Nano S" });
log("transaction-broadcast", "Transaction sent to network", { txHash: "0x..." });
log("error-recovery", "Recovered from network error", { attempts: 3 });

// Clean up when done
unsubscribe();

Context Propagation

import { LocalTracer } from "@ledgerhq/logs";

class WalletService {
  private tracer: LocalTracer;

  constructor(userId: string) {
    this.tracer = new LocalTracer("wallet-service", { userId });
  }

  async processTransaction(txData: any) {
    // Create operation-specific tracer
    const txTracer = this.tracer.withUpdatedContext({
      operation: "process-transaction",
      txId: txData.id
    });

    txTracer.trace("Starting transaction processing");

    try {
      // Validation step
      const validationTracer = txTracer.withType("validation");
      validationTracer.trace("Validating transaction data");
      
      // Processing step
      const processingTracer = txTracer.withType("processing");
      processingTracer.trace("Processing transaction", { amount: txData.amount });
      
      txTracer.trace("Transaction processed successfully");
    } catch (error) {
      txTracer.trace("Transaction processing failed", { error: error.message });
      throw error;
    }
  }
}

Browser Integration

When used in browser environments, @ledgerhq/logs automatically exposes the listen function globally for debugging purposes:

// Available in browser console for debugging
window.__ledgerLogsListen((log) => {
  console.log("Debug log:", log);
});