diff --git a/docs/platforms/javascript/guides/nextjs/index.mdx b/docs/platforms/javascript/guides/nextjs/index.mdx index 2584c519b0123..2ebfb2faed4ab 100644 --- a/docs/platforms/javascript/guides/nextjs/index.mdx +++ b/docs/platforms/javascript/guides/nextjs/index.mdx @@ -112,6 +112,9 @@ Sentry.init({ // ___PRODUCT_OPTION_START___ performance tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1, // ___PRODUCT_OPTION_END___ performance + // ___PRODUCT_OPTION_START___ logs + enableLogs: true, + // ___PRODUCT_OPTION_END___ logs }); ``` diff --git a/docs/platforms/javascript/guides/nextjs/logs/index.mdx b/docs/platforms/javascript/guides/nextjs/logs/index.mdx new file mode 100644 index 0000000000000..96fd7db9548f9 --- /dev/null +++ b/docs/platforms/javascript/guides/nextjs/logs/index.mdx @@ -0,0 +1,492 @@ +--- +title: Set Up Logs +sidebar_title: Logs +description: "Send structured logs from your Next.js application to Sentry for debugging and observability." +sidebar_order: 4 +sidebar_section: features +new: true +--- + +Sentry Logs let you send structured log data from your Next.js application. Unlike traditional string-based logging, structured logs include queryable attributes that help you debug issues faster by filtering on specific users, orders, or any business context you include. + +## Setup + + + + + +### Enable Logging + +Add `enableLogs: true` to your Sentry configuration in all three runtime files. + +Logs work across all Next.js runtimes: + +- **Client** — Browser-side logging +- **Server** — Node.js server-side logging +- **Edge** — Edge runtime logging + + + + +```typescript {tabTitle:Client} {filename:instrumentation-client.ts} +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, +}); +``` + +```typescript {tabTitle:Server} {filename:sentry.server.config.ts} +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, +}); +``` + +```typescript {tabTitle:Edge} {filename:sentry.edge.config.ts} +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, +}); +``` + + + + + +## Send Logs + + + + + +### Log Levels + +Use the appropriate level for each message: + +| Level | When to Use | +| ------- | -------------------------------- | +| `trace` | Fine-grained debugging | +| `debug` | Development diagnostics | +| `info` | Normal operations, milestones | +| `warn` | Potential issues, degraded state | +| `error` | Failures that need attention | +| `fatal` | Critical failures, system down | + + + + +```typescript +import * as Sentry from "@sentry/nextjs"; + +// Different log levels +Sentry.logger.trace("Entering function", { fn: "processOrder" }); +Sentry.logger.debug("Cache lookup", { key: "user:123" }); +Sentry.logger.info("Order created", { orderId: "order_456" }); +Sentry.logger.warn("Rate limit approaching", { current: 95, max: 100 }); +Sentry.logger.error("Payment failed", { reason: "card_declined" }); +Sentry.logger.fatal("Database unavailable", { host: "primary" }); +``` + + + + + +## Add Context + + + + + +### Attributes + +Pass structured data as the second argument. These attributes become queryable columns in Sentry. + +Use the `fmt` helper for parameterized messages — values are extracted as searchable attributes. + + + + +```typescript +// Pass attributes directly +Sentry.logger.info("User signed up", { + userId: user.id, + plan: "pro", + referrer: "google", +}); + +// Use fmt for parameterized messages +Sentry.logger.info(Sentry.logger.fmt`User ${userId} purchased ${productName}`); +``` + + + + + + + +### Scope Attributes + +Set attributes on the scope to automatically include them in all logs within that context. + + + + +```typescript +// Global attributes (all logs) +Sentry.getGlobalScope().setAttributes({ + service: "checkout", + version: "2.1.0", +}); + +// Scoped attributes (logs within scope) +Sentry.withScope((scope) => { + scope.setAttribute("requestId", req.id); + + // Both logs include requestId + Sentry.logger.info("Processing order"); + Sentry.logger.info("Order complete"); +}); +``` + + + + + +## Best Practices + + + + + +### Wide Events Over Scattered Logs + +Instead of many thin logs that are hard to correlate, emit one comprehensive log per operation with all relevant context. + +This makes debugging dramatically faster — one query returns everything about a specific order, user, or request. + + + + +```typescript +// ❌ Scattered thin logs +Sentry.logger.info("Starting checkout"); +Sentry.logger.info("Validating cart"); +Sentry.logger.info("Processing payment"); +Sentry.logger.info("Checkout complete"); + +// ✅ One wide event with full context +Sentry.logger.info("Checkout completed", { + orderId: order.id, + userId: user.id, + userTier: user.subscription, + cartValue: cart.total, + itemCount: cart.items.length, + paymentMethod: "stripe", + duration: Date.now() - startTime, +}); +``` + + + + + + + +### Include Business Context + +Add attributes that help you prioritize and debug: + +- **User context** — tier, account age, lifetime value +- **Transaction data** — order value, item count +- **Feature state** — active feature flags +- **Request metadata** — endpoint, method, duration + +This lets you filter logs by high-value customers or specific features. + + + + +```typescript +Sentry.logger.info("API request completed", { + // User context + userId: user.id, + userTier: user.plan, // "free" | "pro" | "enterprise" + accountAgeDays: user.ageDays, + + // Request data + endpoint: "/api/orders", + method: "POST", + duration: 234, + + // Business context + orderValue: 149.99, + featureFlags: ["new-checkout", "discount-v2"], +}); +``` + + + + + + + +### Consistent Attribute Naming + +Pick a naming convention and stick with it across your codebase. Inconsistent names make queries impossible. + +**Recommended:** Use `snake_case` for custom attributes to match common conventions. + + + + +```typescript +// ❌ Inconsistent naming +{ user: "123" } +{ userId: "123" } +{ user_id: "123" } +{ UserID: "123" } + +// ✅ Consistent snake_case +{ + user_id: "123", + order_id: "456", + cart_value: 99.99, + item_count: 3, +} +``` + + + + + +## Integrations + + + + + +### Console + +Capture `console.log`, `console.warn`, and `console.error` calls as structured logs. + +The integration parses multiple arguments as searchable attributes. + + + + +```typescript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.consoleLoggingIntegration({ + levels: ["log", "warn", "error"], + }), + ], +}); + +// Arguments become searchable attributes +console.log("User action:", userId, success); +// -> message.parameter.0: userId +// -> message.parameter.1: success +``` + + + + + + + +### Pino + +Send logs from the [Pino](https://github.com/pinojs/pino) logging library to Sentry. + +Requires SDK version `10.18.0` or higher. + + + + +```typescript +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [Sentry.pinoIntegration()], +}); +``` + +See Pino integration docs for configuration options. + + + + + + + +### Consola + +Send logs from the [Consola](https://github.com/unjs/consola) logging library to Sentry. + +Requires SDK version `10.12.0` or higher. + + + + +```typescript +import { consola } from "consola"; + +const sentryReporter = Sentry.createConsolaReporter({ + levels: ["error", "warn"], // optional filter +}); + +consola.addReporter(sentryReporter); +``` + + + + + + + +### Winston + +Send logs from the [Winston](https://github.com/winstonjs/winston) logging library to Sentry. + +Requires SDK version `9.13.0` or higher. + + + + +```typescript +import winston from "winston"; +import Transport from "winston-transport"; + +const SentryTransport = Sentry.createSentryWinstonTransport(Transport, { + levels: ["error", "warn"], // optional filter +}); + +const logger = winston.createLogger({ + transports: [new SentryTransport()], +}); +``` + + + + + + +### Upcoming Integrations + +- [Node Bunyan](https://github.com/getsentry/sentry-javascript/issues/16474) + +[Request an integration](https://github.com/getsentry/sentry-javascript/issues/new/choose) + +## Filter Logs + + + + + +### beforeSendLog + +Filter or modify logs before they're sent. Return `null` to drop a log. + +Use this to: + +- Remove sensitive data +- Filter noisy logs +- Add computed attributes + + + + +```typescript {filename:instrumentation-client.ts} +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, + + beforeSendLog(log) { + // Drop debug logs in production + if (log.level === "debug") { + return null; + } + + // Remove sensitive attributes + if (log.attributes?.password) { + delete log.attributes.password; + } + + return log; + }, +}); +``` + + + + + +## Default Attributes + +Sentry automatically adds these attributes to every log: + +```json {10-13,16-18,21-22,25,28-29,32-33,36} +{ + "message": "Order completed", + "level": "info", + "attributes": { + // Your custom attributes + "order_id": "order_123", + "user_tier": "pro", + + // Core (always present) + "sentry.environment": "production", + "sentry.release": "my-app@1.2.3", + "sentry.sdk.name": "sentry.javascript.nextjs", + "sentry.sdk.version": "9.0.0", + + // User (if set via Sentry.setUser) + "user.id": "user_456", + "user.email": "jane@example.com", + "user.name": "Jane", + + // Browser (client-side only) + "browser.name": "Chrome", + "browser.version": "120.0.0", + + // Server (server-side only) + "server.address": "api-server-1", + + // Trace (if tracing enabled) + "sentry.trace.parent_span_id": "abc123", + "sentry.replay_id": "def456", + + // Message (when using fmt) + "sentry.message.template": "Order {} completed", + "sentry.message.parameter.0": "order_123", + + // Payload + "payload_size": 342 + } +} +``` + +## Troubleshooting + +### Logs not appearing + +Make sure `enableLogs: true` is set in **all** Sentry config files: + +- `instrumentation-client.ts` (client) +- `sentry.server.config.ts` (server) +- `sentry.edge.config.ts` (edge) + +### Logs being dropped + +Logs larger than 1 MB are dropped. Check your [org stats](https://sentry.io/orgredirect/organizations/:orgslug/stats/?dataCategory=logBytes&statsPeriod=30d) to see if logs are being rate limited or dropped. + +### Attributes showing [Filtered] + +If attributes show `[Filtered]`, they're being removed by [server-side data scrubbing](/security-legal-pii/scrubbing/server-side-scrubbing/). Check your project's data scrubbing settings to adjust what gets filtered. diff --git a/platform-includes/logs/setup/javascript.nextjs.mdx b/platform-includes/logs/setup/javascript.nextjs.mdx new file mode 100644 index 0000000000000..04da6ff89b5c9 --- /dev/null +++ b/platform-includes/logs/setup/javascript.nextjs.mdx @@ -0,0 +1,28 @@ +To enable logging in Next.js, add `enableLogs: true` to all your Sentry configuration files: + +```typescript {tabTitle:Client} {filename:instrumentation-client.ts} +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, +}); +``` + +```typescript {tabTitle:Server} {filename:sentry.server.config.ts} +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, +}); +``` + +```typescript {tabTitle:Edge} {filename:sentry.edge.config.ts} +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + enableLogs: true, +}); +```