Skip to main content
The captureMessage function captures a message string and sends it to Sentry as an event.

Function Signature

export function captureMessage(
  message: string,
  captureContext?: CaptureContext | SeverityLevel
): string

Parameters

message
string
required
The message string to capture.
captureContext
CaptureContext | SeverityLevel
Either a severity level string or additional context. Can be:
  • A SeverityLevel: 'fatal', 'error', 'warning', 'info', 'debug', or 'log'
  • A Scope object
  • A partial ScopeContext object
  • A callback function receiving the current scope

Returns

eventId
string
The unique ID of the captured event.

Basic Usage

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

// Simple message
Sentry.captureMessage('User login successful');

// With severity level
Sentry.captureMessage('Database connection slow', 'warning');

Severity Levels

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

// Fatal - critical errors
Sentry.captureMessage('System crash imminent', 'fatal');

// Error - errors that need attention
Sentry.captureMessage('Payment processing failed', 'error');

// Warning - potential issues
Sentry.captureMessage('API rate limit approaching', 'warning');

// Info - informational messages (default)
Sentry.captureMessage('User completed onboarding', 'info');

// Debug - debugging information
Sentry.captureMessage('Cache hit rate: 95%', 'debug');

// Log - general logging
Sentry.captureMessage('Application started', 'log');

With Context

Using Object Context

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

Sentry.captureMessage('Order processed successfully', {
  level: 'info',
  tags: {
    order_type: 'subscription',
    payment_method: 'stripe'
  },
  extra: {
    orderId: '12345',
    amount: 99.99,
    currency: 'USD'
  },
  user: {
    id: 'user-123',
    email: '[email protected]'
  }
});

Using Scope Callback

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

Sentry.captureMessage('Cache cleared', (scope) => {
  scope.setLevel('info');
  scope.setTag('cache_type', 'redis');
  scope.setContext('performance', {
    duration: 245,
    entries_cleared: 1500
  });
  return scope;
});

Advanced Examples

API Monitoring

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

function logApiCall(endpoint: string, duration: number, statusCode: number) {
  const level = statusCode >= 500 ? 'error' : 
                statusCode >= 400 ? 'warning' : 'info';
  
  Sentry.captureMessage(`API ${endpoint} - ${statusCode}`, {
    level,
    tags: {
      endpoint,
      status_code: statusCode,
      response_time: duration > 1000 ? 'slow' : 'fast'
    },
    extra: {
      duration_ms: duration,
      timestamp: Date.now()
    }
  });
}

logApiCall('/api/users', 850, 200);

Feature Flag Tracking

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

function trackFeatureFlag(flagName: string, enabled: boolean, userId: string) {
  Sentry.captureMessage(`Feature flag: ${flagName}`, {
    level: 'info',
    tags: {
      feature_flag: flagName,
      flag_state: enabled ? 'enabled' : 'disabled'
    },
    user: {
      id: userId
    },
    contexts: {
      feature_flags: {
        [flagName]: enabled
      }
    }
  });
}

trackFeatureFlag('new-checkout', true, 'user-456');

Business Metrics

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

function trackBusinessEvent(
  eventName: string,
  metadata: Record<string, any>
) {
  Sentry.captureMessage(`Business Event: ${eventName}`, {
    level: 'info',
    tags: {
      event_type: 'business',
      event_name: eventName
    },
    extra: metadata
  });
}

trackBusinessEvent('subscription_upgrade', {
  from_plan: 'basic',
  to_plan: 'premium',
  revenue: 29.99,
  userId: 'user-789'
});

Implementation Details

From packages/core/src/client.ts:
public captureMessage(
  message: ParameterizedString,
  level?: SeverityLevel,
  hint?: EventHint,
  currentScope?: Scope,
): string {
  const hintWithEventId = {
    event_id: uuid4(),
    ...hint,
  };

  const eventMessage = isParameterizedString(message) 
    ? message 
    : String(message);
  
  const isMessage = isPrimitive(message);
  const promisedEvent = isMessage
    ? this.eventFromMessage(eventMessage, level, hintWithEventId)
    : this.eventFromException(message, hintWithEventId);

  this._process(
    () => promisedEvent.then(event => 
      this._captureEvent(event, hintWithEventId, currentScope)
    ),
    isMessage ? 'unknown' : 'error',
  );

  return hintWithEventId.event_id;
}

Message vs Exception

Use captureMessage for:
  • Informational logging
  • Business events
  • Feature usage tracking
  • Performance milestones
  • State changes
Use captureException for:
  • Caught exceptions
  • Error conditions
  • Failed operations
  • Unexpected states
import * as Sentry from '@sentry/node';

// Good use of captureMessage
Sentry.captureMessage('User completed tutorial', 'info');
Sentry.captureMessage('API response time exceeded 2s', 'warning');

// Should use captureException instead
try {
  riskyOperation();
} catch (error) {
  // Use captureException for errors
  Sentry.captureException(error);
}

Filtering Messages

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

Sentry.init({
  dsn: 'your-dsn',
  beforeSend(event, hint) {
    // Don't send debug messages in production
    if (event.level === 'debug' && process.env.NODE_ENV === 'production') {
      return null;
    }
    
    // Filter by message content
    if (event.message?.includes('healthcheck')) {
      return null;
    }
    
    return event;
  }
});

Sampling Messages

Control how many messages are sent:
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'your-dsn',
  // Sample 10% of events
  sampleRate: 0.1,
  
  beforeSend(event) {
    // Only sample info messages
    if (event.level === 'info') {
      if (Math.random() > 0.1) {
        return null;
      }
    }
    return event;
  }
});

Best Practices

1. Use Descriptive Messages

// Bad
Sentry.captureMessage('Error');

// Good
Sentry.captureMessage('Failed to sync user data to CRM');

2. Include Relevant Context

// Bad
Sentry.captureMessage('Order failed');

// Good
Sentry.captureMessage('Order payment failed', {
  level: 'error',
  tags: { order_id: '12345' },
  extra: { 
    reason: 'card_declined',
    amount: 99.99 
  }
});

3. Use Appropriate Levels

// User actions - info
Sentry.captureMessage('User logged in', 'info');

// Warnings - warning
Sentry.captureMessage('API retry limit reached', 'warning');

// Errors - error
Sentry.captureMessage('Payment processor unavailable', 'error');

4. Avoid High-Volume Messages

// Bad - will create too many events
app.use((req, res, next) => {
  Sentry.captureMessage(`Request: ${req.path}`);
  next();
});

// Good - use breadcrumbs for high-volume data
app.use((req, res, next) => {
  Sentry.addBreadcrumb({
    category: 'http',
    message: `${req.method} ${req.path}`,
    level: 'info'
  });
  next();
});

Build docs developers (and LLMs) love