Skip to content

Debugging Guide ​

This guide explains how to use the debug configuration API to troubleshoot Cap'n Proto RPC connections and message handling.

Enabling Debug Mode ​

Environment Variable (Node.js) ​

The simplest way to enable debugging is by setting the CAPNP_DEBUG environment variable:

bash
CAPNP_DEBUG=1 node your-app.js

Or in your code before importing the library:

typescript
process.env.CAPNP_DEBUG = '1';
import { enableDebug } from '@naeemo/capnp';

Programmatic API ​

You can also enable debug mode programmatically at runtime:

typescript
import { enableDebug, disableDebug, isDebugEnabled } from '@naeemo/capnp';

// Enable with default options
enableDebug();

// Enable with custom options
enableDebug({
  colors: true,      // Enable colored output
  maxBytes: 512,     // Log up to 512 bytes of binary data
  filter: 'Call'     // Only log messages matching 'Call'
});

// Check if debug is enabled
if (isDebugEnabled()) {
  console.log('Debug mode is active');
}

// Disable debug mode
disableDebug();

Debug Options ​

colors?: boolean ​

Enable ANSI color codes in debug output. Default: true

Colors help distinguish different message types and make logs easier to read in terminal environments.

maxBytes?: number ​

Maximum number of bytes to display when logging binary message data. Default: 256

Large messages can generate overwhelming output. This option limits how much raw binary data is shown.

typescript
enableDebug({ maxBytes: 1024 }); // Show up to 1KB of binary data

filter?: string | RegExp ​

Filter debug output by message type or peer identifier. Default: '' (no filter)

Useful when you only want to see specific types of messages:

typescript
// Filter by message type name
enableDebug({ filter: 'Call' });

// Filter using regular expression
enableDebug({ filter: /^(Call|Return)$/ });

// Filter by peer (format: "messageType:peerId")
enableDebug({ filter: 'Call:client1' });

What Information is Logged ​

When debug mode is enabled, the following information is logged:

Message Events ​

  • Send/Receive: All RPC messages sent and received
  • Message Type: Bootstrap, Call, Return, Finish, Resolve, Release, etc.
  • Payload Size: Number of bytes in the message
  • Binary Preview: Hex dump of message content (respecting maxBytes)

Connection Events ​

  • Connection Opened: When a new RPC connection is established
  • Connection Closed: When a connection is terminated
  • Capability Resolution: When promises are resolved
  • Pipeline Operations: Promise pipelining activity

Error Events ​

  • Serialization Errors: Issues encoding/decoding messages
  • Protocol Errors: RPC protocol violations
  • Transport Errors: WebSocket/TCP connection issues
  • Timeout Events: Operation timeouts

Example Debug Output ​

[CAPNP:DEBUG] [SND] Call (questionId=1, interfaceId=0x12345678, methodId=0)
  Target: imported capability #5
  Payload: 45 bytes
  Hex: 00 00 00 00 05 00 00 00 00 00 00 00 ...
[CAPNP:DEBUG] [RCV] Return (answerId=1)
  Result: success (30 bytes)
  Hex: 00 00 00 00 00 00 00 00 0a 00 00 00 ...

Performance Impact ​

Debug mode has the following performance implications:

Minimal Impact (when disabled) ​

When debug mode is disabled (default):

  • No runtime overhead for debug checks
  • Debug code is tree-shakeable in production builds
  • Zero memory overhead

Moderate Impact (when enabled) ​

When debug mode is enabled:

  • CPU: ~5-10% overhead due to message inspection
  • Memory: Additional buffering for hex formatting
  • I/O: Console output can slow down high-throughput scenarios

Recommendations ​

  1. Development: Always enable debug mode during development
  2. Production: Use environment variable to conditionally enable
  3. High Throughput: Use filtering to reduce log volume
  4. Binary Data: Lower maxBytes for large message scenarios
typescript
// Production-safe debug setup
import { enableDebug } from '@naeemo/capnp';

if (process.env.NODE_ENV !== 'production' || process.env.CAPNP_DEBUG) {
  enableDebug({
    colors: process.env.NODE_ENV !== 'production',
    maxBytes: 128,
    filter: process.env.CAPNP_FILTER
  });
}

Troubleshooting Tips ​

No Debug Output ​

  1. Verify debug mode is enabled: console.log(isDebugEnabled())
  2. Check filter settings - might be too restrictive
  3. Ensure imports happen after enabling debug

Too Much Output ​

  1. Use filter option to narrow scope
  2. Reduce maxBytes to limit binary data
  3. Consider disabling colors if piping to a file

Performance Issues ​

  1. Disable debug in production builds
  2. Use aggressive filtering for high-frequency messages
  3. Set maxBytes: 0 to skip binary data entirely

Integration with Logging Libraries ​

The debug API can be integrated with structured logging systems:

typescript
import { enableDebug, isDebugEnabled } from '@naeemo/capnp';
import { createLogger } from './my-logger';

const logger = createLogger();

// Enable Cap'n Proto debug mode
enableDebug({
  colors: false,  // Let the logging library handle colors
  maxBytes: 256
});

// Redirect debug output to your logger
const originalLog = console.log;
console.log = (...args) => {
  if (isDebugEnabled() && args[0]?.includes('[CAPNP:DEBUG]')) {
    logger.debug('capnp', args.join(' '));
  } else {
    originalLog.apply(console, args);
  }
};

Released under the MIT License.