Skip to main content

Overview

The SDK uses an internal logger for debug output, warnings, and errors — things like retry attempts, rate limiting, queue overflow, and plugin failures. By default, logging is silent. You can enable the built-in console logger or provide your own implementation.

Logger Interface

Both SDKs use the same Logger interface (defined in @miradorlabs/plugins):
interface Logger {
  debug(...args: unknown[]): void;
  warn(...args: unknown[]): void;
  error(...args: unknown[]): void;
}

Quick Start

Silent (Default)

No logging output. All log calls are no-ops.
const client = new Client('your-api-key');
// Equivalent to: logger = { debug() {}, warn() {}, error() {} }

Debug Mode

Enable the built-in console logger with the debug flag:
const client = new Client('your-api-key', {
  debug: true
});
This maps to console.debug, console.warn, and console.error respectively. Useful during development — you’ll see internal SDK activity in your browser or terminal console.

Custom Logger

Pass any object that satisfies the Logger interface:
const client = new Client('your-api-key', {
  logger: myLogger
});
If both debug and logger are provided, the custom logger takes precedence.

What Gets Logged

LevelExamples
debugFlush sent, keep-alive ping, trace created, plugin setup
warnKeep-alive failure, queue approaching capacity, trace closed during async operation
errorFlush failed after retries, rate limited, plugin setup error

Winston (Node.js)

import winston from 'winston';
import { Client } from '@miradorlabs/nodejs-sdk';

const winstonLogger = winston.createLogger({
  level: 'debug',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  defaultMeta: { service: 'mirador-sdk' },
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'mirador.log' })
  ]
});

const client = new Client('your-api-key', {
  logger: {
    debug: (...args) => winstonLogger.debug(args.join(' ')),
    warn:  (...args) => winstonLogger.warn(args.join(' ')),
    error: (...args) => winstonLogger.error(args.join(' '))
  }
});

Pino (Node.js)

import pino from 'pino';
import { Client } from '@miradorlabs/nodejs-sdk';

const pinoLogger = pino({
  name: 'mirador-sdk',
  level: 'debug'
});

const client = new Client('your-api-key', {
  logger: {
    debug: (...args) => pinoLogger.debug({ sdk: true }, args.join(' ')),
    warn:  (...args) => pinoLogger.warn({ sdk: true }, args.join(' ')),
    error: (...args) => pinoLogger.error({ sdk: true }, args.join(' '))
  }
});

Datadog Browser Logs (Web)

import { datadogLogs } from '@datadog/browser-logs';
import { Client } from '@miradorlabs/web-sdk';

datadogLogs.init({
  clientToken: 'your-dd-client-token',
  site: 'datadoghq.com',
  service: 'my-app'
});

const client = new Client('your-api-key', {
  logger: {
    debug: (...args) => datadogLogs.logger.debug(args.join(' ')),
    warn:  (...args) => datadogLogs.logger.warn(args.join(' ')),
    error: (...args) => datadogLogs.logger.error(args.join(' '))
  }
});

Conditional Logging

Log only warnings and errors in production, everything in development:
const isProduction = process.env.NODE_ENV === 'production';

const client = new Client('your-api-key', {
  logger: {
    debug: isProduction ? () => {} : console.debug,
    warn:  console.warn,
    error: console.error
  }
});

Logger in Plugins

Plugins receive the logger from TraceContext during setup(). If you’re building a custom plugin, use context.logger instead of console so your plugin respects the user’s logging configuration:
function MyPlugin(): MiradorPlugin {
  return {
    name: 'my-plugin',
    setup(context: TraceContext) {
      context.logger.debug('[MyPlugin] initialized for trace', context.getTraceId());

      return {
        methods: {
          doWork() {
            context.logger.debug('[MyPlugin] doWork called');
          }
        }
      };
    }
  };
}

Next Steps

Lifecycle Callbacks

Monitor trace events programmatically

Retry Logic

Error handling and retry strategies