Documentation Index
Fetch the complete documentation index at: https://mintlify.com/getsentry/sentry-javascript/llms.txt
Use this file to discover all available pages before exploring further.
Integrations extend the Sentry SDK with additional functionality like automatic instrumentation, error filtering, and context enrichment.
Overview
Integrations provide:
- Automatic instrumentation (HTTP, database, etc.)
- Error filtering and processing
- Context enrichment
- Framework-specific features
- Custom event processing
Integration Interface
export interface Integration {
/**
* The name of the integration.
*/
name: string;
/**
* This hook is only called once, even if multiple clients are created.
* It does not receive a client argument, and should not rely on client state.
*/
setupOnce?(): void;
/**
* Set up an integration for the given client.
* Receives the client and the integration index as arguments.
*/
setup?(client: Client): void;
/**
* This hook is triggered after all integrations have been set up.
* You can use it to e.g. register handlers.
*/
afterAllSetup?(client: Client): void;
/**
* An optional hook to process events.
*/
processEvent?(event: Event, hint: EventHint, client: Client): Event | PromiseLike<Event | null> | null;
}
Adding Integrations
During Initialization
import * as Sentry from '@sentry/node';
import { httpIntegration, captureConsoleIntegration } from '@sentry/node';
Sentry.init({
dsn: 'your-dsn',
integrations: [
httpIntegration(),
captureConsoleIntegration({ levels: ['error', 'warn'] })
]
});
Adding at Runtime
import { getClient } from '@sentry/node';
import { httpIntegration } from '@sentry/node';
const client = getClient();
if (client) {
client.addIntegration(httpIntegration());
}
Built-in Integrations
HTTP Instrumentation
Automatically captures HTTP requests:
import { httpIntegration } from '@sentry/node';
httpIntegration({
// Ignore specific URLs
ignoreOutgoingRequests: (url) => {
return url.includes('healthcheck');
},
// Capture request/response bodies
breadcrumbs: true,
tracing: true
})
Capture Console
Captures console messages as breadcrumbs:
import { captureConsoleIntegration } from '@sentry/node';
captureConsoleIntegration({
levels: ['error', 'warn', 'info']
})
Context Lines
Adds source code context to stack traces:
import { contextLinesIntegration } from '@sentry/node';
contextLinesIntegration({
frameContextLines: 5 // Lines before and after
})
Modules
Adds module information to events:
import { modulesIntegration } from '@sentry/node';
modulesIntegration()
Creating Custom Integrations
Basic Integration
import { defineIntegration, getClient } from '@sentry/core';
import type { Integration, IntegrationFn } from '@sentry/types';
const _customIntegration = (() => {
return {
name: 'CustomIntegration',
setupOnce() {
// Called once when the SDK is initialized
console.log('Custom integration setup');
},
setup(client) {
// Called when integration is added to a client
client.on('beforeSendEvent', (event) => {
// Modify events before sending
event.tags = { ...event.tags, custom: 'true' };
});
},
afterAllSetup(client) {
// Called after all integrations are set up
console.log('All integrations ready');
}
} satisfies Integration;
}) satisfies IntegrationFn;
export const customIntegration = defineIntegration(_customIntegration);
Event Processing Integration
import { defineIntegration } from '@sentry/core';
import type { Event, EventHint, Integration, IntegrationFn } from '@sentry/types';
interface FilterOptions {
allowedDomains: string[];
}
const _domainFilterIntegration = ((options: FilterOptions) => {
return {
name: 'DomainFilterIntegration',
processEvent(event: Event, hint: EventHint): Event | null {
// Filter events based on domain
const url = event.request?.url;
if (!url) return event;
const isAllowed = options.allowedDomains.some(domain =>
url.includes(domain)
);
return isAllowed ? event : null;
}
} satisfies Integration;
}) satisfies IntegrationFn;
export const domainFilterIntegration = defineIntegration(_domainFilterIntegration);
// Usage
Sentry.init({
dsn: 'your-dsn',
integrations: [
domainFilterIntegration({
allowedDomains: ['myapp.com', 'api.myapp.com']
})
]
});
Instrumentation Integration
import { defineIntegration } from '@sentry/core';
import { startInactiveSpan } from '@sentry/core';
import type { Client, Integration, IntegrationFn } from '@sentry/types';
const _databaseIntegration = (() => {
return {
name: 'DatabaseIntegration',
setup(client: Client) {
// Monkey-patch database library
const originalQuery = Database.prototype.query;
Database.prototype.query = function(sql: string, ...args: any[]) {
// Create span for database query
return startInactiveSpan({
name: sql,
op: 'db.query',
attributes: {
'db.system': 'postgresql',
'db.statement': sql
}
}, (span) => {
try {
const result = originalQuery.call(this, sql, ...args);
span?.setStatus({ code: 1 }); // OK
return result;
} catch (error) {
span?.setStatus({ code: 2 }); // ERROR
throw error;
}
});
};
}
} satisfies Integration;
}) satisfies IntegrationFn;
export const databaseIntegration = defineIntegration(_databaseIntegration);
Integration Setup Flow
From packages/core/src/integration.ts:
export function setupIntegrations(
client: Client,
integrations: Integration[]
): IntegrationIndex {
const integrationIndex: IntegrationIndex = {};
for (const integration of integrations) {
// setupOnce is called once per integration
if (integration.setupOnce) {
integration.setupOnce();
}
integrationIndex[integration.name] = integration;
// setup is called for each client
if (integration.setup) {
integration.setup(client);
}
}
return integrationIndex;
}
export function afterSetupIntegrations(
client: Client,
integrations: Integration[]
): void {
for (const integration of integrations) {
if (integration.afterAllSetup) {
integration.afterAllSetup(client);
}
}
}
Getting Integrations
import { getClient } from '@sentry/node';
const client = getClient();
if (client) {
// Get integration by name
const httpIntegration = client.getIntegrationByName('Http');
if (httpIntegration) {
console.log('HTTP integration is active');
}
}
Integration Best Practices
1. Use setupOnce for Global Setup
setupOnce() {
// One-time global setup
registerGlobalErrorHandler();
}
2. Use setup for Client-Specific Setup
setup(client: Client) {
// Client-specific setup
client.on('beforeSendEvent', this.handleEvent);
}
3. Clean Up Resources
let unsubscribe: (() => void) | undefined;
setup(client: Client) {
unsubscribe = client.on('spanStart', handleSpan);
}
shutdown?() {
// Clean up when integration is removed
unsubscribe?.();
}
4. Handle Errors Gracefully
processEvent(event: Event): Event | null {
try {
return this.transformEvent(event);
} catch (error) {
console.error('Integration error:', error);
return event; // Return original event on error
}
}