SDK Reference
registerGlasstrace(options?)
Section titled “registerGlasstrace(options?)”Call registerGlasstrace() in your instrumentation.ts file. It configures OpenTelemetry, registers Prisma instrumentation, attaches a Glasstrace span exporter, and starts a non-blocking init call to the Glasstrace backend.
Parameters
Section titled “Parameters”registerGlasstrace() accepts an optional GlasstraceOptions object:
| Name | Type | Default | Description |
|---|---|---|---|
apiKey | string | undefined | Glasstrace API key. Overrides GLASSTRACE_API_KEY env var. If omitted and no env var is set, anonymous mode activates with an auto-generated gt_anon_xxx key. |
endpoint | string (URL) | undefined | Glasstrace ingestion endpoint URL. Overrides the default (https://glasstrace.vercel.app). |
forceEnable | boolean | undefined | When true, the SDK stays active even in production environments. Overrides GLASSTRACE_FORCE_ENABLE env var. |
verbose | boolean | undefined | When true, the SDK logs detailed startup and export information to stdout. |
Return Value
Section titled “Return Value”void — registerGlasstrace() is synchronous from the caller’s perspective. It applies cached config immediately and fires a background POST /v1/sdk/init call that updates config when it resolves.
Examples
Section titled “Examples”Register Glasstrace in your instrumentation file:
import { registerGlasstrace } from "@glasstrace/sdk";
export function register() { registerGlasstrace();}Pass options explicitly:
registerGlasstrace({ apiKey: "<your-api-key>", verbose: true,});Errors
Section titled “Errors”If the SDK detects a production environment (NODE_ENV=production or VERCEL_ENV=production) and forceEnable is not set, it logs a warning and returns a no-op. No OTel setup occurs, no init call is made, and no spans are exported.
{ "level": "warn", "message": "Glasstrace disabled: production environment detected. Set GLASSTRACE_FORCE_ENABLE=true to override."}If the background init call fails (network error, invalid key), the SDK continues operating with cached or default config. Errors are logged when verbose is enabled but never thrown to the caller.
withGlasstraceConfig(nextConfig)
Section titled “withGlasstraceConfig(nextConfig)”Wrap your Next.js config with withGlasstraceConfig() to enable source map generation and upload during next build.
Parameters
Section titled “Parameters”| Name | Type | Default | Description |
|---|---|---|---|
nextConfig | NextConfig | — | Your existing Next.js configuration object. |
Return Value
Section titled “Return Value”Returns the augmented NextConfig with source map generation enabled and a post-build hook that uploads .map files to the Glasstrace backend.
Examples
Section titled “Examples”Wrap your Next.js config:
import { withGlasstraceConfig } from "@glasstrace/sdk";
const nextConfig = { // your existing config};
export default withGlasstraceConfig(nextConfig);When It Runs
Section titled “When It Runs”withGlasstraceConfig() hooks into the Next.js build process:
- Enables source map generation if not already enabled
- After build completion, collects
.mapfiles from the output - Uploads them via
POST /v1/source-mapswith the build hash and API key auth
Source maps enable the Glasstrace backend to resolve compiled stack traces to TypeScript file paths and line numbers.
Errors
Section titled “Errors”Source map upload requires a gt_dev_xxx API key. In anonymous mode, withGlasstraceConfig() enables local source map generation but skips the upload. The SDK logs a message explaining that source-mapped stack traces require a dev key.
{ "level": "info", "message": "Source map upload skipped: no GLASSTRACE_API_KEY set. Source maps are generated locally but not uploaded."}If the upload fails (network error, auth failure), the build completes normally. Source map upload never blocks or fails the build.
{ "level": "warn", "message": "Source map upload failed: 401 Unauthorized. Verify your GLASSTRACE_API_KEY."}npx @glasstrace/sdk init
Section titled “npx @glasstrace/sdk init”One-time scaffolding command that sets up Glasstrace in your Next.js project.
What It Creates
Section titled “What It Creates”| File | Action | Description |
|---|---|---|
instrumentation.ts | Create (or prompt before overwriting) | Calls registerGlasstrace() with Prisma initialization order comment |
next.config.ts / next.config.js | Modify | Wraps existing config with withGlasstraceConfig() |
.env.local | Create or append | Adds GLASSTRACE_API_KEY= placeholder |
.gitignore | Create or append | Adds .glasstrace/ entry. Also consider adding MCP config files (.mcp.json, .cursor/mcp.json) if they contain tokens. |
.mcp.json, .cursor/mcp.json, etc. | Create | MCP config files for detected AI agents |
Parameters
Section titled “Parameters”The init command has no required flags. It detects your project structure and prompts interactively.
| Name | Type | Default | Description |
|---|---|---|---|
| (no flags) | — | — | Runs interactive scaffolding with auto-detection |
Detection Logic
Section titled “Detection Logic”The CLI detects:
- Whether
instrumentation.tsalready exists (prompts before overwriting) - Whether
next.config.jsornext.config.tsis present (wraps the detected format) - Which AI agent CLIs are installed (Claude Code, Codex, Cursor, Windsurf, Gemini)
Idempotency
Section titled “Idempotency”Running init a second time prompts before overwriting existing files. It does not duplicate .gitignore entries or .env.local variables.
Examples
Section titled “Examples”npx @glasstrace/sdk initErrors
Section titled “Errors”{ "error": "no_next_config", "message": "Could not find next.config.js or next.config.ts. Run this command from your Next.js project root."}npx @glasstrace/sdk mcp add
Section titled “npx @glasstrace/sdk mcp add”Register the Glasstrace MCP server with your AI coding agents. This command detects installed agents and writes native MCP configuration files for each one.
Parameters
Section titled “Parameters”| Name | Type | Default | Description |
|---|---|---|---|
--dry-run | flag | false | Print what would be written without making changes. |
--force | flag | false | Overwrite existing MCP config entries without prompting. |
What It Does Per Agent
Section titled “What It Does Per Agent”| Agent | Config File | Key Format |
|---|---|---|
| Claude Code | .mcp.json | { "type": "http", "url": "..." } |
| Cursor | .cursor/mcp.json | { "url": "..." } |
| Windsurf | ~/.codeium/windsurf/mcp_config.json | { "serverUrl": "..." } |
| Codex | .codex/config.toml or codex mcp add CLI | bearer_token_env_var |
| Gemini | .gemini/settings.json | { "httpUrl": "..." } |
Each agent’s config points to https://api.glasstrace.dev/mcp with a Bearer auth header containing the anonymous key from .glasstrace/anon_key (or your GLASSTRACE_API_KEY if set).
Examples
Section titled “Examples”Preview changes without writing:
npx @glasstrace/sdk mcp add --dry-runForce overwrite existing config:
npx @glasstrace/sdk mcp add --forceErrors
Section titled “Errors”{ "error": "no_agents_detected", "message": "No supported AI agents detected. Install Claude Code, Cursor, Windsurf, Codex, or Gemini CLI, then retry."}{ "error": "no_anon_key", "message": "No anonymous key found. Run 'npx @glasstrace/sdk init' first, or set GLASSTRACE_API_KEY."}Span Attributes
Section titled “Span Attributes”Glasstrace attaches glasstrace.* semantic attributes to every span at export time. These attributes provide structured context for the MCP debugging tools.
Server-Side Attributes
Section titled “Server-Side Attributes”| Attribute | Description |
|---|---|
glasstrace.trace.type | 'server' — distinguishes from client events |
glasstrace.session.id | Time-bounded session identifier |
glasstrace.correlation.id | From x-gt-cid header if present |
glasstrace.environment | From GLASSTRACE_ENV or derived from origin |
glasstrace.route | e.g. 'POST /api/orders' |
glasstrace.http.method | GET, POST, PUT, DELETE, etc. |
glasstrace.http.status_code | e.g. 500, 200, 403 |
glasstrace.http.duration_ms | Wall-clock request duration |
glasstrace.error.message | Error message text |
glasstrace.error.code | e.g. 'P2003' for Prisma |
glasstrace.error.category | e.g. 'foreign-key-violation', 'auth-failure', 'timeout' |
glasstrace.error.field | Affected field (e.g. 'orders.userId') |
glasstrace.orm.provider | 'prisma', 'drizzle', or 'none' |
glasstrace.orm.model | e.g. 'Order', 'User' |
glasstrace.orm.operation | e.g. 'create', 'findMany', 'delete' |
glasstrace.orm.duration_ms | ORM query duration |
glasstrace.fetch.url | Outbound request URL |
glasstrace.fetch.method | Outbound GET, POST, etc. |
glasstrace.fetch.status_code | Outbound response status |
glasstrace.fetch.duration_ms | Outbound round-trip duration |
glasstrace.fetch.target | Classified target: 'supabase', 'stripe', 'internal', 'unknown' |
glasstrace.env.referenced | Array of env var names referenced in error context |
glasstrace.source.file | Source-mapped TypeScript file path |
glasstrace.source.line | Source-mapped line number |
glasstrace.source.mapped | Boolean — whether source mapping was applied |
Attributes are enriched at export time by the GlasstraceExporter, not at span creation. This means attributes reflect the final state of the span (resolved API key, computed session ID) rather than an in-progress state.
The glasstrace.fetch.target attribute classifies outbound HTTP requests by URL pattern. For example, requests to *.supabase.co are classified as 'supabase', requests to *.stripe.com as 'stripe', and requests to your own app’s origin as 'internal'. Unrecognized URLs are classified as 'unknown'.
Discovery Endpoint
Section titled “Discovery Endpoint”GET /__glasstrace/config — a localhost endpoint that the Glasstrace browser extension uses to discover the anonymous key and session ID.
When It Is Active
Section titled “When It Is Active”The discovery endpoint is registered only when all three conditions are true:
- Anonymous mode — no
GLASSTRACE_API_KEYis set - Development environment —
NODE_ENVis not'production' - SDK is active — not disabled by the production guard
When any condition fails, the endpoint does not exist.
Response
Section titled “Response”{ "key": "gt_anon_<generated-key>", "sessionId": "<current-session-id>"}Security Constraints
Section titled “Security Constraints”The discovery endpoint only exists in development on localhost. It exposes the anonymous key (not a paid API key) to allow the browser extension to correlate client-side events with server traces without requiring the developer to copy keys manually.
When you set a GLASSTRACE_API_KEY (a gt_dev_xxx key from a paid account), the endpoint ceases to exist. The extension then authenticates via session token from sign-in, not anonymous discovery.
Errors
Section titled “Errors”If the endpoint is accessed in a context where it should not be active, the middleware is not registered and the request falls through to the host framework’s default 404 handling. The exact response format depends on the framework (e.g. Next.js serves its own 404 page).
Drizzle Adapter
Section titled “Drizzle Adapter”The @glasstrace/sdk/drizzle subpath export provides a Drizzle ORM adapter that creates OpenTelemetry spans for database queries.
Import Path
Section titled “Import Path”import { GlasstraceDrizzleLogger } from "@glasstrace/sdk/drizzle";The adapter is a separate subpath export to avoid pulling in Drizzle as a dependency for developers who only use Prisma. Drizzle is declared as an optional peer dependency.
Pass the logger when creating your Drizzle instance:
import { drizzle } from "drizzle-orm/node-postgres";import { GlasstraceDrizzleLogger } from "@glasstrace/sdk/drizzle";
const db = drizzle(client, { logger: new GlasstraceDrizzleLogger(),});What It Captures
Section titled “What It Captures”The adapter implements Drizzle’s Logger interface and creates an OTel span for each query with:
| Attribute | Value |
|---|---|
glasstrace.orm.provider | 'drizzle' |
glasstrace.orm.model | Extracted from SQL (best-effort) |
glasstrace.orm.operation | Extracted from SQL (e.g. 'SELECT', 'INSERT') |
glasstrace.orm.duration_ms | Query execution time |
Query parameters are included by default. Set CaptureConfig.queryParamValues to false in the dashboard to redact them.
Errors
Section titled “Errors”{ "level": "warn", "message": "GlasstraceDrizzleLogger: failed to parse SQL for model extraction. Span created with orm.model='unknown'."}Import Graph
Section titled “Import Graph”The import graph is an opt-in feature that captures the module dependency structure of your test files. It powers the get_test_suggestions MCP tool’s coverage map.
Enabling
Section titled “Enabling”Enable import graph capture by setting CaptureConfig.importGraph to true in the dashboard capture settings. Import graph requires a paid tier (Free Trial or Pro).
You can also enable it via environment variable during setup:
GLASSTRACE_COVERAGE_MAP=trueWhat It Captures
Section titled “What It Captures”The SDK performs lightweight static analysis of import and require statements in your test files. It builds a map from test file paths to their imported module paths. No code is executed — the analysis uses pattern matching on import statements, not the TypeScript compiler.
Test files are discovered by checking vitest.config, jest.config, or conventional paths (__tests__/, *.test.ts, *.spec.ts).
When It Runs
Section titled “When It Runs”The import graph is built and uploaded during the SDK init call (POST /v1/sdk/init). It runs at server startup, not continuously.
What It Enables
Section titled “What It Enables”The get_test_suggestions MCP tool uses the import graph to generate a coverage map (Part 1) that identifies which test files cover which modules. When an error occurs in a specific module, the tool can suggest the most relevant test files.
The import graph is typically under 50KB even for large projects. It adds negligible overhead to server startup.
Without the import graph, get_test_suggestions still works — it provides test ideas based on trace patterns (Parts 2 and 3). The coverage map (Part 1) is the import-graph-dependent part.
Errors
Section titled “Errors”{ "error": "tier_restricted", "message": "Import graph capture requires a paid tier (Free Trial or Pro). Sign up at https://glasstrace.dev to enable.", "upgrade_url": "https://glasstrace.dev"}Session Lifecycle
Section titled “Session Lifecycle”Glasstrace uses deterministic session IDs to group traces from the same developer, project, and time window.
How Session IDs Are Derived
Section titled “How Session IDs Are Derived”Session IDs are computed via:
SHA-256(apiKey + origin + date + window_index)Truncated to 16 hex characters.
| Component | Source | Example |
|---|---|---|
apiKey | Your API key or auto-generated anonymous key | gt_anon_<key> |
origin | Hostname + port (or GLASSTRACE_ENV if set) | localhost:3000 |
date | Current date (UTC) | 2026-04-08 |
window_index | Increments after 4 hours of inactivity | 0, 1, 2 |
Window Boundaries
Section titled “Window Boundaries”The SDK tracks the last activity timestamp in memory. On each span export, it checks if more than 4 hours have elapsed since the last activity. If so, it increments the window index and derives a new session ID.
The window index resets daily (the date component in the hash changes).
Session Continuity
Section titled “Session Continuity”- Server restarts typically do not create new sessions — the same inputs produce the same hash. Note: a restart resets the in-memory
window_indexto 0, so if it had incremented (after a 4-hour gap) the session ID will change. - Different ports (
localhost:3000vslocalhost:3001) are separate sessions — they represent different services - Different days start new sessions — the date component changes
- 4-hour gaps start new sessions — the window index increments
- Custom environments — set
GLASSTRACE_ENVto use a fixed environment name (e.g.staging) instead of hostname + port
Errors
Section titled “Errors”{ "level": "warn", "message": "Session ID derivation failed: missing apiKey. Using fallback session ID."}