Skip to content

feat: add Next.js support#27

Merged
sohankshirsagar merged 3 commits into
mainfrom
sohan/nextjs-instrumentation
Oct 14, 2025
Merged

feat: add Next.js support#27
sohankshirsagar merged 3 commits into
mainfrom
sohan/nextjs-instrumentation

Conversation

@sohankshirsagar

@sohankshirsagar sohankshirsagar commented Oct 13, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR adds Next.js support to Tusk Drift Node SDK.

Changes

1. Next.js Instrumentation (/src/instrumentation/libraries/nextjs/)

Key features:

  • Intercepts Next.js requests at the framework level (BaseServer) rather than the HTTP protocol level
  • Patches loaded modules via require.cache to handle early-loading race conditions
  • Captures request/response bodies similar to HTTP instrumentation
  • Supports RECORD, REPLAY, and DISABLED modes
  • Filters SDK traffic to prevent recursive instrumentation
  • Handles sampling and trace context propagation

Why needed: Next.js wraps the native Node.js HTTP server with its own abstractions, making HTTP-level instrumentation insufficient. Framework-level interception ensures we capture the complete Next.js request lifecycle with proper routing and middleware context.

2. withTuskDrift Configuration Wrapper (/src/nextjs/)

New files:

  • withTuskDrift.ts - Main configuration wrapper function
  • types.ts - TypeScript interfaces for configuration options
  • utils.ts - Helper functions for Next.js version detection and semver parsing

Key features:

  • Automatic Next.js version detection
  • Conditional instrumentationHook setting (only for Next.js < 15.0.0-rc.1)
  • Configures webpack externals for required packages (require-in-the-middle, jsonpath)
  • Duplicate wrapping prevention
  • Debug logging support
    • This is needed since Tusk Drift logging wouldn't have been initialized at this point
  • Preserves existing Next.js and webpack configurations

Configuration options:

  • debug - Enable debug logging for configuration
  • disableInstrumentationHook - Disable automatic instrumentationHook (not recommended)
  • suppressWarnings - Suppress all warnings

Why externals are needed: Webpack would otherwise bundle instrumentation packages, preventing require-in-the-middle from intercepting module loads.

3. Documentation (/docs/)

New file:

  • nextjs-initialization.md - Comprehensive Next.js setup guide with step-by-step instructions

Updated file:

  • initialization.md - Added callout directing Next.js users to dedicated guide

Usage Example

// next.config.js
const { withTuskDrift } = require('@use-tusk/drift-node-sdk');

module.exports = withTuskDrift({
  // Your Next.js config
});
// instrumentation.ts
export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    const { TuskDrift } = await import('@use-tusk/drift-node-sdk');

    TuskDrift.initialize({
      apiKey: process.env.TUSK_DRIFT_API_KEY,
      env: process.env.NODE_ENV,
    });

    TuskDrift.markAppAsReady();
  }
}

  • e2e tests will be added in a follow up
  • transforms will be added in a follow up

Note

Adds first-class Next.js support with framework-level instrumentation and a withTuskDrift config wrapper, plus docs and minor core/export updates.

  • Next.js Support:
    • Instrumentation: New nextjs instrumentation intercepts next/dist/server/base-server requests; captures req/res bodies; supports RECORD/REPLAY; patches already-loaded modules via require.cache.
    • Config Wrapper: Adds nextjs/withTuskDrift (exported from root) with options (debug, disableInstrumentationHook, suppressWarnings); auto-detects Next.js version to set experimental.instrumentationHook; adjusts webpack externals.
  • Core SDK:
    • Registers NextjsInstrumentation in TuskDrift.
    • TdSpanExporter: filters out spans where instrumentationLibrary.name === "next.js"; adds guarded transform with error logging.
    • Notes next excluded from TuskDriftInstrumentationModuleNames.
    • Root exports updated to expose Next.js integration.
  • Docs:
    • New docs/nextjs-initialization.md with step-by-step setup.
    • docs/initialization.md: adds Next.js callout and minor ESM snippet tweaks.
  • Dependencies:
    • Adds next (and related transient packages) to dev deps.

Written by Cursor Bugbot for commit c540d71. This will update automatically on new commits. Configure here.

cursor[bot]

This comment was marked as outdated.

@sohankshirsagar sohankshirsagar marked this pull request as ready for review October 13, 2025 23:55
Comment thread src/core/TuskDrift.ts

@sohil-kshirsagar sohil-kshirsagar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! do we ignore inbound next.js calls that are meant to fetch html/css pages?


const filteredSpans = spans.filter((span) => {
// Filter out spans exported from Next.js internal telemetry
if (span.instrumentationLibrary?.name === "next.js") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are there other spans we'd want to ignore? wonder if this should be in a constant somewhere

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • we don't ignore next.js calls that are meant to fetch html/css, will add this in a follow up
  • there are no other spans currently that we'd want to ignore. + if there were, we might identify them differently. will create a constant once we have a better idea of other types of spans we'd want to ignore

@sohankshirsagar sohankshirsagar merged commit b21d20d into main Oct 14, 2025
3 checks passed
@sohankshirsagar sohankshirsagar deleted the sohan/nextjs-instrumentation branch October 14, 2025 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants