Skip to content

Conversation

@Ansonhkg
Copy link
Collaborator

1. Centralized logging

WHAT

  • Centralized logging for the Lit Protocol SDK. The default backend is structured pino logging, but you can attach custom transports (DataDog, Sentry, your own system) and it works in both Node.js and browsers.
  • Unified all loggings to use import { getChildLogger } from '@lit-protocol/logger'; instead of console.log.

USAGE

Centralized logging for the Lit Protocol SDK. The default backend is structured pino logging, but you can attach custom transports (DataDog, Sentry, your own system) and it works in both Node.js and browsers.

Basic usage

import { logger, getChildLogger } from '@lit-protocol/logger';

logger.info('SDK started');

const log = getChildLogger({ module: 'my-feature' });
log.debug({ foo: 'bar' }, 'doing work');

Log levels

Logging verbosity is controlled by:

  • Node.js: process.env.LOG_LEVEL
  • Browser: globalThis.LOG_LEVEL

Supported levels: silent, fatal, error, warn, info, debug, trace, debug_text.

debug_text switches the default output to console-style text (not JSON). debug2 is a deprecated alias for debug_text.

Configuration

Use setLoggerOptions at app startup to change level/name or add metadata:

import { setLoggerOptions } from '@lit-protocol/logger';

setLoggerOptions({
  level: 'info',
  name: 'MyApp',
  bindings: { app: 'my-app' },
});

2. Consolidate CURL debugging

WHAT

  • Consolidate curl debugging helpers into @lit-protocol/logger and point both Lit node and Wrapped Keys request paths at the shared implementation, preserving the opt-in LIT_DEBUG_CURL behavior while eliminating duplicated fs/path/env logic.

USAGE

# enable writing curl commands to disk
export LIT_DEBUG_CURL=1

# optional: change output directory (defaults to ./debug)
export LIT_DEBUG_CURL_DIR=./debug

After your run, copy the correlation id (for example X-Request-Id from node calls, or x-correlation-id / the Request(<id>) value from Wrapped Keys errors) and print the stored curl command:

pnpm debug:curl -- <X-Request-Id>

If you only have a prefix/substring, pnpm debug:curl will try to match it (and will list matches if more than one file fits).

// BEFORE
process.env.LOG_LEVEL = 'debug2';
logger.debug2('verbose console output');

// AFTER
process.env.LOG_LEVEL = 'debug_text'; // clearer name; debug2 still works
logger.debugText('verbose console output');
@Ansonhkg Ansonhkg marked this pull request as ready for review January 7, 2026 04:49
Copilot AI review requested due to automatic review settings January 7, 2026 04:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR centralizes logging across the Lit Protocol SDK by introducing a new @lit-protocol/logger package and consolidating CURL debugging functionality for easier request replay during development and debugging.

Key Changes

  • Implemented centralized structured logging with pino backend supporting both Node.js and browser environments
  • Added support for custom log transports (DataDog, Sentry, OpenTelemetry, etc.)
  • Consolidated CURL debugging helpers from multiple locations into @lit-protocol/logger
  • Migrated console.log/console.error calls to structured logging throughout runtime library code
  • Added CLI tool (pnpm debug:curl) to retrieve stored curl commands by request ID

Reviewed changes

Copilot reviewed 43 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tools/debug-curl.js New CLI tool for retrieving curl commands by request ID with fuzzy matching support
packages/logger/src/lib/curlDebug.ts Centralized curl command generation and file writing utilities for Node.js
packages/logger/src/lib/logger.ts Core logger implementation with pino backend, custom transports, and debug_text mode
packages/logger/src/lib/logger.spec.ts Updated tests to validate new logger functionality
packages/logger/README.md Comprehensive documentation with usage examples including DataDog and OpenTelemetry
packages/networks/src/networks/shared/logger.ts Refactored to re-export from centralized logger package
packages/wrapped-keys/src/lib/service-client/utils.ts Integrated curl debugging for wrapped keys service requests
packages/lit-client/src/lib/LitNodeClient/LitNodeApi/src/helper/sendNodeRequest.ts Integrated curl debugging for Lit node requests
packages/crypto/src/lib/misc.ts Migrated logging functions to use centralized logger
packages/auth/src/lib/storage/*.ts Replaced console logging with structured logger
packages/auth/src/lib/authenticators/**/*.ts Replaced console.error with structured logger for Stytch authenticators
packages/networks/src/networks/vNaga/**/*.ts Removed debug console.log statements and replaced with structured logging
docs/guides/debugging-node-requests.mdx New guide documenting curl debugging workflow
package.json Added debug:curl script
.gitignore Added debug directory to ignore list
pnpm-lock.yaml Updated dependencies, removed direct pino dependencies from multiple packages
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +89 to +95
const headers = headerEntries
.map(([key, value]) => `-H "${key}: ${value}"`)
.join(' ');

const body = typeof init.body === 'string' ? `--data '${init.body}'` : '';

return `curl -X ${method} ${headers} ${body} "${url}"`.trim();
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The curl command generation does not escape special characters in header values and request body. If header values or the body contain single quotes, double quotes, or shell metacharacters, the generated curl command could be malformed or potentially execute unintended commands when copied to a shell.

Consider properly escaping the values:

  • Header values should escape double quotes and backslashes
  • The body should escape single quotes and backslashes when using single-quoted strings
  • Alternatively, consider using safer shell escaping libraries or base64 encoding for complex payloads

Copilot uses AI. Check for mistakes.
const filePath = path.join(dirPath, safeRequestId);
const idHeaderName = params.idHeaderName ?? 'request-id';

await fs.mkdir(path.dirname(filePath), { recursive: true });
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When creating the directory for the debug file, only the parent directory is created. If filePath points to just dirPath/safeRequestId (a file directly in the debug directory), then path.dirname(filePath) returns dirPath. However, if there are subdirectories in the sanitized request ID (which shouldn't happen with the current sanitization), this logic assumes the parent exists.

While the current sanitization replaces all special characters with underscores, making subdirectories impossible, it would be safer to create the full dirPath instead of path.dirname(filePath) for clarity and to avoid potential issues if sanitization logic changes in the future.

Suggested change
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.mkdir(dirPath, { recursive: true });

Copilot uses AI. Check for mistakes.
Comment on lines +175 to +180
if (typeof first === 'string') {
if (second && typeof second === 'object') {
return { msg: first, data: second };
}
return { msg: first };
}
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extractMsgAndData function doesn't follow the standard pino logging signature correctly. In pino, the first argument should be an object (for structured data) and the second should be a message string. The current implementation reverses this order in line 175-179, treating a string first argument as the message and an object second argument as data.

This is the opposite of pino's signature: logger.info({ data }, 'message'). While this may be intentional to support console.log-style calls, it creates confusion and inconsistency with pino's conventions. The code should either follow pino's standard signature or clearly document this deviation.

Copilot uses AI. Check for mistakes.
typeof moduleName === 'string' ? `${name}:${moduleName}` : name;
return createConsoleLogger(childName);
},
isLevelEnabled: () => true,
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The console logger's isLevelEnabled method always returns true regardless of the configured log level. This means when using debug_text mode, all log levels will be output even if a higher threshold is configured.

The method should check against the configured level, similar to the shouldLog function used for transport-based logging. This inconsistency could cause unexpected log output when users expect silent or higher log levels to filter messages.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants