> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirador.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Logging

> Configure SDK logging with built-in or custom logger implementations

## 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`):

```typescript theme={null}
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.

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
const client = new Client('your-api-key', {
  logger: myLogger
});
```

<Note>
  If both `debug` and `logger` are provided, the custom `logger` takes precedence.
</Note>

## What Gets Logged

| Level   | Examples                                                                            |
| ------- | ----------------------------------------------------------------------------------- |
| `debug` | Flush sent, keep-alive ping, trace created, plugin setup                            |
| `warn`  | Keep-alive failure, queue approaching capacity, trace closed during async operation |
| `error` | Flush failed after retries, rate limited, plugin setup error                        |

## Examples with Popular Libraries

### Winston (Node.js)

```typescript theme={null}
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)

```typescript theme={null}
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)

```typescript theme={null}
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:

```typescript theme={null}
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](/concepts/plugins), use `context.logger` instead of `console` so your plugin respects the user's logging configuration:

```typescript theme={null}
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

<CardGroup cols={2}>
  <Card title="Lifecycle Callbacks" icon="arrows-spin" href="/advanced/lifecycle-callbacks">
    Monitor trace events programmatically
  </Card>

  <Card title="Retry Logic" icon="rotate" href="/advanced/retry-logic">
    Error handling and retry strategies
  </Card>
</CardGroup>
