Skip to content

Latest commit

 

History

History
267 lines (199 loc) · 9.74 KB

File metadata and controls

267 lines (199 loc) · 9.74 KB

Initialization

Prerequisites

Before setting up the SDK, ensure you have:

📦 Using Next.js? Next.js applications require a different initialization process. Go to the Next.js Initialization Guide →

For standard Node.js applications (Express, Fastify, plain Node.js, etc.), follow these steps in order to properly initialize the Tusk Drift SDK:

1. Create SDK Initialization File

Create a separate file (e.g. tuskDriftInit.ts or tuskDriftInit.js) to initialize the Tusk Drift SDK. This ensures the SDK is initialized as early as possible before any other modules are loaded.

Note: The code examples in this guide use ES module import/export syntax. If your JavaScript project uses CommonJS, adapt the examples to use require()/module.exports instead.

IMPORTANT: Ensure that TuskDrift is initialized before any other telemetry providers (e.g. OpenTelemetry, Sentry, etc.). If not, your existing telemetry may not work properly.

The initialization file is the same for both CommonJS and ESM applications. The SDK automatically registers ESM loader hooks when running in an ESM environment (Node.js >= 18.19.0 or >= 20.6.0).

// tuskDriftInit.ts or tuskDriftInit.js
import { TuskDrift } from "@use-tusk/drift-node-sdk";

// Initialize SDK immediately
TuskDrift.initialize({
  apiKey: process.env.TUSK_API_KEY,
  env: process.env.NODE_ENV,
});

export { TuskDrift };

Note: ESM applications still require the --import flag when starting Node.js. See Step 2 for details.

Initialization Parameters

Option Type Default Description
apiKey string Required if using Tusk Cloud Your Tusk Drift API key.
env string process.env.NODE_ENV The environment name.
logLevel 'silent' | 'error' | 'warn' | 'info' | 'debug' 'info' The logging level.
samplingRate number 1.0 Override sampling rate (0.0 - 1.0) for recording. Takes precedence over TUSK_SAMPLING_RATE env var and config file.
registerEsmLoaderHooks boolean true Automatically register ESM loader hooks for module interception. Set to false to disable if import-in-the-middle causes issues with certain packages. See Troubleshooting ESM.

See also: Environment Variables guide for detailed information about environment variables.

2. Import SDK at Application Entry Point

Determining Your Module System

You need to know whether your application uses CommonJS or ESM (ECMAScript Modules) because the entry point setup differs.

If your application uses require():

  • Your application is CommonJS

If your application uses import statements:

  • This could be either CommonJS or ESM, depending on your build configuration
  • Check your compiled output (if you compile to a directory like dist/):
    • If the compiled code contains require() statements → CommonJS application
    • If the compiled code contains import statements → ESM application
  • If you don't compile your code (running source files directly):
    • It is an ESM application

For CommonJS Applications

In your main server file (e.g., server.ts, index.ts, app.ts), require the initialized SDK at the very top, before any other requires:

// e.g. server.ts
import { TuskDrift } from "./tuskDriftInit"; // MUST be the first import

// ... other imports ...

// Your application setup...

IMPORTANT: Ensure NO require calls are made before requiring the SDK initialization file. This guarantees proper instrumentation of all dependencies.

For ESM Applications

For ESM applications, you cannot control import order within your application code because all imports are hoisted. Instead, use the --import flag:

Update your package.json scripts:

{
  "scripts": {
    "dev": "node --import ./dist/tuskDriftInit.js dist/server.js",
    "dev:record": "TUSK_DRIFT_MODE=RECORD node --import ./dist/tuskDriftInit.js dist/server.js"
  }
}

Why --import is required for ESM: In ESM, all import statements are hoisted and evaluated before any code runs, making it impossible to control import order within a file. The --import flag ensures the SDK initialization happens in a separate phase before your application code loads, guaranteeing proper module interception.

3. Configure Sampling Rate

The sampling rate determines what percentage of requests are recorded during replay tests. Tusk Drift supports three ways to configure the sampling rate, with the following precedence (highest to lowest):

  1. Init Parameter
  2. Environment Variable (TUSK_SAMPLING_RATE)
  3. Configuration File (.tusk/config.yaml)

If not specified, the default sampling rate is 1.0 (100%).

Method 1: Init Parameter (Programmatic Override)

Set the sampling rate directly in your initialization code:

TuskDrift.initialize({
  apiKey: process.env.TUSK_API_KEY,
  env: process.env.NODE_ENV,
  samplingRate: 0.1, // 10% of requests
});

Method 2: Environment Variable

Set the TUSK_SAMPLING_RATE environment variable:

# Development - record everything
TUSK_SAMPLING_RATE=1.0 npm run dev

# Production - sample 10% of requests
TUSK_SAMPLING_RATE=0.1 npm start

Method 3: Configuration File

Update the configuration file .tusk/config.yaml to include a recording section. Example recording configuration:

# ... existing configuration ...

recording:
  sampling_rate: 0.1
  export_spans: true
  enable_env_var_recording: true

Additional Recording Configuration Options

Option Type Default Description
sampling_rate number 1.0 The sampling rate (0.0 - 1.0). 1.0 means 100% of requests are recorded, 0.0 means 0% of requests are recorded.
export_spans boolean false Whether to export spans to Tusk backend or local files (.tusk/traces). If false, spans are only exported to local files.
enable_env_var_recording boolean false Whether to enable environment variable recording and replaying. Recommended if your application's business logic depends on environment variables, as this ensures the most accurate replay behavior.

4. Mark App as Ready

Once your application has completed initialization (database connections, middleware setup, etc.), mark it as ready:

// e.g. server.ts
import { TuskDrift } from "./tuskDriftInit";

// ... other imports ...

const app = express();

// Your application setup...

app.listen(8000, () => {
  // Mark app as ready for recording/replay
  TuskDrift.markAppAsReady();
  console.log("Server started and ready for Tusk Drift");
});

Troubleshooting ESM

The SDK automatically registers ESM loader hooks via import-in-the-middle to intercept ES module imports. Only modules that the SDK instruments have their exports wrapped with getter/setter proxies -- unrelated modules are left untouched.

In rare cases, the wrapping can cause issues with instrumented packages:

  • Non-standard export patterns: Some packages use dynamic export * re-exports or conditional exports that the wrapper's static analysis cannot parse, resulting in runtime syntax errors.
  • Native or WASM bindings: Packages with native addons loaded via ESM can conflict with the proxy wrapping mechanism.
  • Bundler-generated ESM: Code that was bundled (e.g., by esbuild or webpack) into ESM sometimes produces patterns the wrapper does not handle correctly.
  • Circular ESM imports: The proxy layer can interact badly with circular ESM import graphs in some edge cases.

If you encounter errors like:

SyntaxError: The requested module '...' does not provide an export named '...'
(node:1234) Error: 'import-in-the-middle' failed to wrap 'file://../../path/to/file.js'

You can disable the automatic ESM hook registration:

TuskDrift.initialize({
  apiKey: process.env.TUSK_API_KEY,
  env: process.env.NODE_ENV,
  registerEsmLoaderHooks: false,
});

Note: Disabling ESM loader hooks means the SDK will only be able to instrument packages loaded via CommonJS (require()). Packages loaded purely through ESM import statements will not be intercepted. Node.js built-in modules (like http, https, net) are always loaded through the CJS path internally, so they will continue to be instrumented regardless of this setting.