Skip to main content
The addBreadcrumb function records breadcrumbs that create a trail of events leading up to an error or issue.

Function Signature

export function addBreadcrumb(
  breadcrumb: Breadcrumb,
  hint?: BreadcrumbHint
): void

Parameters

breadcrumb
Breadcrumb
required
The breadcrumb object to add. See Breadcrumb Types for structure.
hint
BreadcrumbHint
Additional context about the breadcrumb for filtering or processing.
export interface Breadcrumb {
  type?: string;
  level?: SeverityLevel;
  event_id?: string;
  category?: string;
  message?: string;
  data?: { [key: string]: any };
  timestamp?: number;
}
type
string
The type of breadcrumb: 'default', 'debug', 'error', 'navigation', 'http', 'info', 'query', 'transaction', 'ui', 'user'.
level
SeverityLevel
The severity level: 'fatal', 'error', 'warning', 'info', 'debug', or 'log'. Defaults to 'info'.
category
string
A dotted string indicating what the breadcrumb is or where it comes from (e.g., 'ui.click', 'console.log', 'http.request').
message
string
A human-readable message for the breadcrumb.
data
object
Arbitrary data associated with the breadcrumb.
timestamp
number
Unix timestamp in seconds when the breadcrumb occurred.

Basic Usage

import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  category: 'auth',
  message: 'User logged in',
  level: 'info'
});
import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  type: 'navigation',
  category: 'navigation',
  message: 'User navigated to /dashboard',
  data: {
    from: '/home',
    to: '/dashboard'
  },
  level: 'info'
});

HTTP Request Breadcrumbs

import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  type: 'http',
  category: 'fetch',
  message: 'GET /api/users',
  data: {
    url: 'https://api.example.com/users',
    method: 'GET',
    status_code: 200,
    request_body_size: 0,
    response_body_size: 1024
  },
  level: 'info',
  timestamp: Date.now() / 1000
});

User Action Breadcrumbs

import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  type: 'user',
  category: 'ui.click',
  message: 'User clicked checkout button',
  data: {
    button_id: 'checkout-btn',
    cart_items: 3,
    total_amount: 99.99
  },
  level: 'info'
});

Database Query Breadcrumbs

import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  type: 'query',
  category: 'db.query',
  message: 'SELECT * FROM users WHERE id = $1',
  data: {
    'db.system': 'postgresql',
    'db.name': 'myapp',
    'db.statement': 'SELECT * FROM users WHERE id = $1',
    duration_ms: 15
  },
  level: 'info'
});

Console Log Breadcrumbs

import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  type: 'debug',
  category: 'console',
  message: 'Processing payment...',
  level: 'debug',
  data: {
    logger: 'console',
    arguments: ['Processing payment for order', '12345']
  }
});

Error Breadcrumbs

import * as Sentry from '@sentry/node';

Sentry.addBreadcrumb({
  type: 'error',
  category: 'exception',
  message: 'TypeError: Cannot read property of undefined',
  level: 'error',
  data: {
    error_name: 'TypeError',
    error_message: 'Cannot read property of undefined'
  }
});

Implementation Details

From packages/core/src/breadcrumbs.ts:
export function addBreadcrumb(
  breadcrumb: Breadcrumb,
  hint?: BreadcrumbHint
): void {
  const client = getClient();
  const isolationScope = getIsolationScope();

  if (!client) return;

  const { 
    beforeBreadcrumb = null, 
    maxBreadcrumbs = DEFAULT_BREADCRUMBS 
  } = client.getOptions();

  if (maxBreadcrumbs <= 0) return;

  const timestamp = dateTimestampInSeconds();
  const mergedBreadcrumb = { timestamp, ...breadcrumb };
  
  const finalBreadcrumb = beforeBreadcrumb
    ? consoleSandbox(() => beforeBreadcrumb(mergedBreadcrumb, hint))
    : mergedBreadcrumb;

  if (finalBreadcrumb === null) return;

  if (client.emit) {
    client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint);
  }

  isolationScope.addBreadcrumb(finalBreadcrumb, maxBreadcrumbs);
}

Automatic Breadcrumbs

Many integrations automatically add breadcrumbs:

HTTP Integration

import * as Sentry from '@sentry/node';
import { httpIntegration } from '@sentry/node';

Sentry.init({
  dsn: 'your-dsn',
  integrations: [
    httpIntegration({
      // Automatically creates breadcrumbs for HTTP requests
      breadcrumbs: true
    })
  ]
});

// Breadcrumbs created automatically for:
// - Outgoing HTTP requests
// - Incoming HTTP requests
// - Request/response details

Console Integration

import * as Sentry from '@sentry/node';
import { captureConsoleIntegration } from '@sentry/node';

Sentry.init({
  dsn: 'your-dsn',
  integrations: [
    captureConsoleIntegration({
      levels: ['log', 'info', 'warn', 'error']
    })
  ]
});

// Automatically captures console calls as breadcrumbs
console.log('User action'); // Becomes a breadcrumb

Filtering Breadcrumbs

Use beforeBreadcrumb to filter or modify breadcrumbs:
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'your-dsn',
  beforeBreadcrumb(breadcrumb, hint) {
    // Filter out console breadcrumbs
    if (breadcrumb.category === 'console') {
      return null;
    }
    
    // Scrub sensitive data
    if (breadcrumb.data?.url) {
      breadcrumb.data.url = breadcrumb.data.url.replace(/token=[^&]+/, 'token=REDACTED');
    }
    
    return breadcrumb;
  }
});

Advanced Examples

API Call Tracking

import * as Sentry from '@sentry/node';

async function makeApiCall(endpoint: string, options: RequestInit) {
  const startTime = Date.now();
  
  Sentry.addBreadcrumb({
    type: 'http',
    category: 'fetch',
    message: `${options.method} ${endpoint}`,
    data: {
      url: endpoint,
      method: options.method
    },
    level: 'info'
  });
  
  try {
    const response = await fetch(endpoint, options);
    const duration = Date.now() - startTime;
    
    Sentry.addBreadcrumb({
      type: 'http',
      category: 'fetch',
      message: `${options.method} ${endpoint} - ${response.status}`,
      data: {
        url: endpoint,
        method: options.method,
        status_code: response.status,
        duration_ms: duration
      },
      level: response.ok ? 'info' : 'error'
    });
    
    return response;
  } catch (error) {
    Sentry.addBreadcrumb({
      type: 'error',
      category: 'fetch',
      message: `${options.method} ${endpoint} failed`,
      data: {
        error: String(error)
      },
      level: 'error'
    });
    throw error;
  }
}

User Journey Tracking

import * as Sentry from '@sentry/node';

class UserJourneyTracker {
  trackStep(step: string, metadata?: Record<string, any>) {
    Sentry.addBreadcrumb({
      type: 'user',
      category: 'user.journey',
      message: `User completed: ${step}`,
      data: {
        step,
        ...metadata
      },
      level: 'info'
    });
  }
}

const tracker = new UserJourneyTracker();

// Track user journey
tracker.trackStep('view_product', { productId: '123' });
tracker.trackStep('add_to_cart', { productId: '123', quantity: 2 });
tracker.trackStep('view_cart');
tracker.trackStep('checkout_started');
tracker.trackStep('payment_info_entered');
tracker.trackStep('order_completed', { orderId: '456', amount: 99.99 });

State Change Tracking

import * as Sentry from '@sentry/node';

function trackStateChange<T>(
  stateName: string,
  oldValue: T,
  newValue: T
) {
  Sentry.addBreadcrumb({
    type: 'default',
    category: 'state',
    message: `${stateName} changed`,
    data: {
      state: stateName,
      from: oldValue,
      to: newValue
    },
    level: 'debug'
  });
}

// Usage
trackStateChange('connectionStatus', 'disconnected', 'connected');
trackStateChange('userRole', 'guest', 'authenticated');
By default, Sentry keeps the last 100 breadcrumbs:
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'your-dsn',
  maxBreadcrumbs: 50 // Keep only last 50 breadcrumbs
});

Best Practices

1. Use Descriptive Categories

// Bad
Sentry.addBreadcrumb({ message: 'Action' });

// Good
Sentry.addBreadcrumb({
  category: 'user.action',
  message: 'User clicked submit button'
});

2. Include Relevant Data

Sentry.addBreadcrumb({
  category: 'api',
  message: 'Fetching user data',
  data: {
    userId: '123',
    endpoint: '/api/users/123',
    cacheHit: false
  }
});

3. Use Appropriate Levels

// Debug: Development info
Sentry.addBreadcrumb({ message: 'Cache miss', level: 'debug' });

// Info: Normal operations
Sentry.addBreadcrumb({ message: 'User login', level: 'info' });

// Warning: Potential issues
Sentry.addBreadcrumb({ message: 'Retry attempt 3/5', level: 'warning' });

// Error: Error conditions
Sentry.addBreadcrumb({ message: 'API timeout', level: 'error' });

4. Don’t Log Sensitive Data

// Bad
Sentry.addBreadcrumb({
  message: 'User login',
  data: {
    username: '[email protected]',
    password: 'secret123' // Never log passwords!
  }
});

// Good
Sentry.addBreadcrumb({
  message: 'User login',
  data: {
    username: '[email protected]',
    method: 'password'
  }
});

Build docs developers (and LLMs) love