@deeptracer/nextjs 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +38 -0
- package/dist/client.d.cts +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +15 -0
- package/dist/index.cjs +141 -0
- package/dist/index.d.cts +148 -0
- package/dist/index.d.ts +148 -0
- package/dist/index.js +134 -0
- package/package.json +13 -6
package/dist/client.cjs
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/client.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
DeepTracerErrorBoundary: () => import_react.DeepTracerErrorBoundary,
|
|
24
|
+
DeepTracerErrorPage: () => import_react.DeepTracerErrorPage,
|
|
25
|
+
DeepTracerProvider: () => import_react.DeepTracerProvider,
|
|
26
|
+
useDeepTracerErrorReporter: () => import_react.useDeepTracerErrorReporter,
|
|
27
|
+
useLogger: () => import_react.useLogger
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(client_exports);
|
|
30
|
+
var import_react = require("@deeptracer/react");
|
|
31
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
32
|
+
0 && (module.exports = {
|
|
33
|
+
DeepTracerErrorBoundary,
|
|
34
|
+
DeepTracerErrorPage,
|
|
35
|
+
DeepTracerProvider,
|
|
36
|
+
useDeepTracerErrorReporter,
|
|
37
|
+
useLogger
|
|
38
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DeepTracerErrorBoundary, DeepTracerErrorPage, DeepTracerProvider, DeepTracerProviderProps, useDeepTracerErrorReporter, useLogger } from '@deeptracer/react';
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DeepTracerErrorBoundary, DeepTracerErrorPage, DeepTracerProvider, DeepTracerProviderProps, useDeepTracerErrorReporter, useLogger } from '@deeptracer/react';
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
import {
|
|
3
|
+
DeepTracerProvider,
|
|
4
|
+
DeepTracerErrorPage,
|
|
5
|
+
DeepTracerErrorBoundary,
|
|
6
|
+
useDeepTracerErrorReporter,
|
|
7
|
+
useLogger
|
|
8
|
+
} from "@deeptracer/react";
|
|
9
|
+
export {
|
|
10
|
+
DeepTracerErrorBoundary,
|
|
11
|
+
DeepTracerErrorPage,
|
|
12
|
+
DeepTracerProvider,
|
|
13
|
+
useDeepTracerErrorReporter,
|
|
14
|
+
useLogger
|
|
15
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,10 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
6
10
|
var __copyProps = (to, from, except, desc) => {
|
|
7
11
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
12
|
for (let key of __getOwnPropNames(from))
|
|
@@ -16,9 +20,146 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
16
20
|
|
|
17
21
|
// src/index.ts
|
|
18
22
|
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
init: () => init,
|
|
25
|
+
withRouteHandler: () => withRouteHandler,
|
|
26
|
+
withServerAction: () => withServerAction
|
|
27
|
+
});
|
|
19
28
|
module.exports = __toCommonJS(index_exports);
|
|
20
29
|
__reExport(index_exports, require("@deeptracer/node"), module.exports);
|
|
30
|
+
|
|
31
|
+
// src/init.ts
|
|
32
|
+
var import_core = require("@deeptracer/core");
|
|
33
|
+
function init(config) {
|
|
34
|
+
const logger = (0, import_core.createLogger)(config);
|
|
35
|
+
const shouldCaptureGlobalErrors = config.captureGlobalErrors !== false;
|
|
36
|
+
const shouldCaptureConsole = config.captureConsole === true;
|
|
37
|
+
function register() {
|
|
38
|
+
const runtime = typeof process !== "undefined" ? process.env?.NEXT_RUNTIME : void 0;
|
|
39
|
+
if (runtime === "nodejs") {
|
|
40
|
+
if (shouldCaptureGlobalErrors) {
|
|
41
|
+
process.on("uncaughtException", (error) => {
|
|
42
|
+
logger.captureError(error, {
|
|
43
|
+
severity: "critical",
|
|
44
|
+
context: { source: "uncaughtException", runtime: "nodejs" }
|
|
45
|
+
});
|
|
46
|
+
logger.flush();
|
|
47
|
+
});
|
|
48
|
+
process.on("unhandledRejection", (reason) => {
|
|
49
|
+
logger.captureError(
|
|
50
|
+
reason instanceof Error ? reason : new Error(String(reason)),
|
|
51
|
+
{
|
|
52
|
+
severity: "high",
|
|
53
|
+
context: { source: "unhandledRejection", runtime: "nodejs" }
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
logger.flush();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (shouldCaptureConsole) {
|
|
60
|
+
const origLog = console.log;
|
|
61
|
+
const origInfo = console.info;
|
|
62
|
+
const origWarn = console.warn;
|
|
63
|
+
const origError = console.error;
|
|
64
|
+
const origDebug = console.debug;
|
|
65
|
+
console.log = (...args) => {
|
|
66
|
+
logger.info(args.map(String).join(" "));
|
|
67
|
+
origLog(...args);
|
|
68
|
+
};
|
|
69
|
+
console.info = (...args) => {
|
|
70
|
+
logger.info(args.map(String).join(" "));
|
|
71
|
+
origInfo(...args);
|
|
72
|
+
};
|
|
73
|
+
console.warn = (...args) => {
|
|
74
|
+
logger.warn(args.map(String).join(" "));
|
|
75
|
+
origWarn(...args);
|
|
76
|
+
};
|
|
77
|
+
console.error = (...args) => {
|
|
78
|
+
logger.error(args.map(String).join(" "));
|
|
79
|
+
origError(...args);
|
|
80
|
+
};
|
|
81
|
+
console.debug = (...args) => {
|
|
82
|
+
logger.debug(args.map(String).join(" "));
|
|
83
|
+
origDebug(...args);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
logger.info("DeepTracer initialized", {
|
|
87
|
+
runtime: "nodejs",
|
|
88
|
+
product: config.product,
|
|
89
|
+
service: config.service
|
|
90
|
+
});
|
|
91
|
+
} else if (runtime === "edge") {
|
|
92
|
+
logger.info("DeepTracer initialized", {
|
|
93
|
+
runtime: "edge",
|
|
94
|
+
product: config.product,
|
|
95
|
+
service: config.service
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function onRequestError(err, request, context) {
|
|
100
|
+
const reqLogger = logger.withContext(
|
|
101
|
+
`${context.routeType}:${context.routePath}`
|
|
102
|
+
);
|
|
103
|
+
reqLogger.addBreadcrumb({
|
|
104
|
+
type: "http",
|
|
105
|
+
message: `${request.method} ${request.path}`
|
|
106
|
+
});
|
|
107
|
+
reqLogger.captureError(err, {
|
|
108
|
+
severity: "high",
|
|
109
|
+
context: {
|
|
110
|
+
source: "nextjs-onRequestError",
|
|
111
|
+
method: request.method,
|
|
112
|
+
path: request.path,
|
|
113
|
+
routerKind: context.routerKind,
|
|
114
|
+
routePath: context.routePath,
|
|
115
|
+
routeType: context.routeType
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return { register, onRequestError, logger };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/server-action.ts
|
|
123
|
+
async function withServerAction(logger, name, fn) {
|
|
124
|
+
return logger.startSpan(`server-action:${name}`, async () => {
|
|
125
|
+
try {
|
|
126
|
+
return await fn();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
logger.captureError(error, {
|
|
129
|
+
severity: "high",
|
|
130
|
+
context: { source: "server-action", action: name }
|
|
131
|
+
});
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/route-handler.ts
|
|
138
|
+
function withRouteHandler(logger, name, handler) {
|
|
139
|
+
return async (request) => {
|
|
140
|
+
const reqLogger = logger.forRequest(request);
|
|
141
|
+
return reqLogger.startSpan(`route:${name}`, async () => {
|
|
142
|
+
try {
|
|
143
|
+
return await handler(request);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
reqLogger.captureError(error, {
|
|
146
|
+
severity: "high",
|
|
147
|
+
context: {
|
|
148
|
+
source: "route-handler",
|
|
149
|
+
route: name,
|
|
150
|
+
method: request.method,
|
|
151
|
+
url: request.url
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
}
|
|
21
159
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22
160
|
0 && (module.exports = {
|
|
161
|
+
init,
|
|
162
|
+
withRouteHandler,
|
|
163
|
+
withServerAction,
|
|
23
164
|
...require("@deeptracer/node")
|
|
24
165
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1 +1,149 @@
|
|
|
1
1
|
export * from '@deeptracer/node';
|
|
2
|
+
import { Logger, LoggerConfig } from '@deeptracer/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for the DeepTracer Next.js integration.
|
|
6
|
+
* Extends the base LoggerConfig with Next.js-specific options.
|
|
7
|
+
*/
|
|
8
|
+
interface NextjsConfig extends LoggerConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Automatically capture uncaught exceptions and unhandled rejections
|
|
11
|
+
* via Node.js process events (only in Node.js runtime, not Edge).
|
|
12
|
+
* Default: true
|
|
13
|
+
*/
|
|
14
|
+
captureGlobalErrors?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Intercept console.log/warn/error/debug calls and forward them to DeepTracer.
|
|
17
|
+
* Default: false (can be noisy in development)
|
|
18
|
+
*/
|
|
19
|
+
captureConsole?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Return type of `init()`. Destructure `register` and `onRequestError`
|
|
23
|
+
* to re-export them from your `instrumentation.ts` file.
|
|
24
|
+
*/
|
|
25
|
+
interface InitResult {
|
|
26
|
+
/**
|
|
27
|
+
* Called by Next.js when the server starts.
|
|
28
|
+
* Sets up global error capture and console interception.
|
|
29
|
+
* Re-export this from your `instrumentation.ts`.
|
|
30
|
+
*/
|
|
31
|
+
register: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Called by Next.js on every server-side error (Server Components,
|
|
34
|
+
* Route Handlers, Middleware). Captures errors and sends them to DeepTracer.
|
|
35
|
+
* Re-export this as `onRequestError` from your `instrumentation.ts`.
|
|
36
|
+
*/
|
|
37
|
+
onRequestError: (err: Error, request: {
|
|
38
|
+
path: string;
|
|
39
|
+
method: string;
|
|
40
|
+
headers: Record<string, string>;
|
|
41
|
+
}, context: {
|
|
42
|
+
routerKind: string;
|
|
43
|
+
routePath: string;
|
|
44
|
+
routeType: string;
|
|
45
|
+
}) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* The DeepTracer Logger instance. Use this for manual logging,
|
|
48
|
+
* error capture, or to pass to `withServerAction` / `withRouteHandler`.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const deeptracer = init({ ... })
|
|
53
|
+
* export const { register, onRequestError } = deeptracer
|
|
54
|
+
* export const logger = deeptracer.logger
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
logger: Logger;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Initialize DeepTracer for Next.js. Returns `register` and `onRequestError`
|
|
61
|
+
* to be re-exported from your `instrumentation.ts` file.
|
|
62
|
+
*
|
|
63
|
+
* This is the **only setup required** for server-side error capture in Next.js.
|
|
64
|
+
* Every server-side error (Server Components, Route Handlers, Middleware) is
|
|
65
|
+
* automatically captured via Next.js's built-in `onRequestError` hook.
|
|
66
|
+
*
|
|
67
|
+
* @param config - Logger configuration with optional Next.js-specific options
|
|
68
|
+
* @returns Object with `register`, `onRequestError`, and `logger`
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* Create `instrumentation.ts` in your project root:
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { init } from "@deeptracer/nextjs"
|
|
74
|
+
*
|
|
75
|
+
* export const { register, onRequestError } = init({
|
|
76
|
+
* product: "my-app",
|
|
77
|
+
* service: "web",
|
|
78
|
+
* environment: "production",
|
|
79
|
+
* endpoint: "https://deeptracer.example.com",
|
|
80
|
+
* apiKey: process.env.DEEPTRACER_API_KEY!,
|
|
81
|
+
* })
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* That's it. All server-side errors are now captured automatically.
|
|
85
|
+
*/
|
|
86
|
+
declare function init(config: NextjsConfig): InitResult;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Wrap a Next.js Server Action with automatic tracing and error capture.
|
|
90
|
+
*
|
|
91
|
+
* Creates a span for the action's execution and captures any errors.
|
|
92
|
+
* The original error is always re-thrown so Next.js error handling works normally.
|
|
93
|
+
*
|
|
94
|
+
* @param logger - DeepTracer Logger instance (from `init().logger`)
|
|
95
|
+
* @param name - A descriptive name for the action (e.g., "createUser", "submitForm")
|
|
96
|
+
* @param fn - The async function to execute
|
|
97
|
+
* @returns The result of the server action function
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* // app/actions.ts
|
|
102
|
+
* "use server"
|
|
103
|
+
* import { withServerAction } from "@deeptracer/nextjs"
|
|
104
|
+
* import { logger } from "@/instrumentation"
|
|
105
|
+
*
|
|
106
|
+
* export async function createUser(formData: FormData) {
|
|
107
|
+
* return withServerAction(logger, "createUser", async () => {
|
|
108
|
+
* const name = formData.get("name") as string
|
|
109
|
+
* const user = await db.user.create({ data: { name } })
|
|
110
|
+
* return user
|
|
111
|
+
* })
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
declare function withServerAction<T>(logger: Logger, name: string, fn: () => Promise<T>): Promise<T>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Wrap a Next.js App Router Route Handler with automatic tracing and error capture.
|
|
119
|
+
*
|
|
120
|
+
* Creates a request-scoped span, extracts trace context from headers,
|
|
121
|
+
* and captures any errors. The original error is re-thrown so Next.js
|
|
122
|
+
* error handling works normally.
|
|
123
|
+
*
|
|
124
|
+
* @param logger - DeepTracer Logger instance (from `init().logger`)
|
|
125
|
+
* @param name - A descriptive name for the route (e.g., "GET /api/users")
|
|
126
|
+
* @param handler - The route handler function
|
|
127
|
+
* @returns A wrapped route handler function
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* // app/api/users/route.ts
|
|
132
|
+
* import { withRouteHandler } from "@deeptracer/nextjs"
|
|
133
|
+
* import { logger } from "@/instrumentation"
|
|
134
|
+
*
|
|
135
|
+
* export const GET = withRouteHandler(logger, "GET /api/users", async (request) => {
|
|
136
|
+
* const users = await db.user.findMany()
|
|
137
|
+
* return Response.json(users)
|
|
138
|
+
* })
|
|
139
|
+
*
|
|
140
|
+
* export const POST = withRouteHandler(logger, "POST /api/users", async (request) => {
|
|
141
|
+
* const body = await request.json()
|
|
142
|
+
* const user = await db.user.create({ data: body })
|
|
143
|
+
* return Response.json(user, { status: 201 })
|
|
144
|
+
* })
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
declare function withRouteHandler(logger: Logger, name: string, handler: (request: Request) => Promise<Response>): (request: Request) => Promise<Response>;
|
|
148
|
+
|
|
149
|
+
export { type InitResult, type NextjsConfig, init, withRouteHandler, withServerAction };
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,149 @@
|
|
|
1
1
|
export * from '@deeptracer/node';
|
|
2
|
+
import { Logger, LoggerConfig } from '@deeptracer/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for the DeepTracer Next.js integration.
|
|
6
|
+
* Extends the base LoggerConfig with Next.js-specific options.
|
|
7
|
+
*/
|
|
8
|
+
interface NextjsConfig extends LoggerConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Automatically capture uncaught exceptions and unhandled rejections
|
|
11
|
+
* via Node.js process events (only in Node.js runtime, not Edge).
|
|
12
|
+
* Default: true
|
|
13
|
+
*/
|
|
14
|
+
captureGlobalErrors?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Intercept console.log/warn/error/debug calls and forward them to DeepTracer.
|
|
17
|
+
* Default: false (can be noisy in development)
|
|
18
|
+
*/
|
|
19
|
+
captureConsole?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Return type of `init()`. Destructure `register` and `onRequestError`
|
|
23
|
+
* to re-export them from your `instrumentation.ts` file.
|
|
24
|
+
*/
|
|
25
|
+
interface InitResult {
|
|
26
|
+
/**
|
|
27
|
+
* Called by Next.js when the server starts.
|
|
28
|
+
* Sets up global error capture and console interception.
|
|
29
|
+
* Re-export this from your `instrumentation.ts`.
|
|
30
|
+
*/
|
|
31
|
+
register: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Called by Next.js on every server-side error (Server Components,
|
|
34
|
+
* Route Handlers, Middleware). Captures errors and sends them to DeepTracer.
|
|
35
|
+
* Re-export this as `onRequestError` from your `instrumentation.ts`.
|
|
36
|
+
*/
|
|
37
|
+
onRequestError: (err: Error, request: {
|
|
38
|
+
path: string;
|
|
39
|
+
method: string;
|
|
40
|
+
headers: Record<string, string>;
|
|
41
|
+
}, context: {
|
|
42
|
+
routerKind: string;
|
|
43
|
+
routePath: string;
|
|
44
|
+
routeType: string;
|
|
45
|
+
}) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* The DeepTracer Logger instance. Use this for manual logging,
|
|
48
|
+
* error capture, or to pass to `withServerAction` / `withRouteHandler`.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const deeptracer = init({ ... })
|
|
53
|
+
* export const { register, onRequestError } = deeptracer
|
|
54
|
+
* export const logger = deeptracer.logger
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
logger: Logger;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Initialize DeepTracer for Next.js. Returns `register` and `onRequestError`
|
|
61
|
+
* to be re-exported from your `instrumentation.ts` file.
|
|
62
|
+
*
|
|
63
|
+
* This is the **only setup required** for server-side error capture in Next.js.
|
|
64
|
+
* Every server-side error (Server Components, Route Handlers, Middleware) is
|
|
65
|
+
* automatically captured via Next.js's built-in `onRequestError` hook.
|
|
66
|
+
*
|
|
67
|
+
* @param config - Logger configuration with optional Next.js-specific options
|
|
68
|
+
* @returns Object with `register`, `onRequestError`, and `logger`
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* Create `instrumentation.ts` in your project root:
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { init } from "@deeptracer/nextjs"
|
|
74
|
+
*
|
|
75
|
+
* export const { register, onRequestError } = init({
|
|
76
|
+
* product: "my-app",
|
|
77
|
+
* service: "web",
|
|
78
|
+
* environment: "production",
|
|
79
|
+
* endpoint: "https://deeptracer.example.com",
|
|
80
|
+
* apiKey: process.env.DEEPTRACER_API_KEY!,
|
|
81
|
+
* })
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* That's it. All server-side errors are now captured automatically.
|
|
85
|
+
*/
|
|
86
|
+
declare function init(config: NextjsConfig): InitResult;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Wrap a Next.js Server Action with automatic tracing and error capture.
|
|
90
|
+
*
|
|
91
|
+
* Creates a span for the action's execution and captures any errors.
|
|
92
|
+
* The original error is always re-thrown so Next.js error handling works normally.
|
|
93
|
+
*
|
|
94
|
+
* @param logger - DeepTracer Logger instance (from `init().logger`)
|
|
95
|
+
* @param name - A descriptive name for the action (e.g., "createUser", "submitForm")
|
|
96
|
+
* @param fn - The async function to execute
|
|
97
|
+
* @returns The result of the server action function
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* // app/actions.ts
|
|
102
|
+
* "use server"
|
|
103
|
+
* import { withServerAction } from "@deeptracer/nextjs"
|
|
104
|
+
* import { logger } from "@/instrumentation"
|
|
105
|
+
*
|
|
106
|
+
* export async function createUser(formData: FormData) {
|
|
107
|
+
* return withServerAction(logger, "createUser", async () => {
|
|
108
|
+
* const name = formData.get("name") as string
|
|
109
|
+
* const user = await db.user.create({ data: { name } })
|
|
110
|
+
* return user
|
|
111
|
+
* })
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
declare function withServerAction<T>(logger: Logger, name: string, fn: () => Promise<T>): Promise<T>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Wrap a Next.js App Router Route Handler with automatic tracing and error capture.
|
|
119
|
+
*
|
|
120
|
+
* Creates a request-scoped span, extracts trace context from headers,
|
|
121
|
+
* and captures any errors. The original error is re-thrown so Next.js
|
|
122
|
+
* error handling works normally.
|
|
123
|
+
*
|
|
124
|
+
* @param logger - DeepTracer Logger instance (from `init().logger`)
|
|
125
|
+
* @param name - A descriptive name for the route (e.g., "GET /api/users")
|
|
126
|
+
* @param handler - The route handler function
|
|
127
|
+
* @returns A wrapped route handler function
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* // app/api/users/route.ts
|
|
132
|
+
* import { withRouteHandler } from "@deeptracer/nextjs"
|
|
133
|
+
* import { logger } from "@/instrumentation"
|
|
134
|
+
*
|
|
135
|
+
* export const GET = withRouteHandler(logger, "GET /api/users", async (request) => {
|
|
136
|
+
* const users = await db.user.findMany()
|
|
137
|
+
* return Response.json(users)
|
|
138
|
+
* })
|
|
139
|
+
*
|
|
140
|
+
* export const POST = withRouteHandler(logger, "POST /api/users", async (request) => {
|
|
141
|
+
* const body = await request.json()
|
|
142
|
+
* const user = await db.user.create({ data: body })
|
|
143
|
+
* return Response.json(user, { status: 201 })
|
|
144
|
+
* })
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
declare function withRouteHandler(logger: Logger, name: string, handler: (request: Request) => Promise<Response>): (request: Request) => Promise<Response>;
|
|
148
|
+
|
|
149
|
+
export { type InitResult, type NextjsConfig, init, withRouteHandler, withServerAction };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,136 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
export * from "@deeptracer/node";
|
|
3
|
+
|
|
4
|
+
// src/init.ts
|
|
5
|
+
import { createLogger } from "@deeptracer/core";
|
|
6
|
+
function init(config) {
|
|
7
|
+
const logger = createLogger(config);
|
|
8
|
+
const shouldCaptureGlobalErrors = config.captureGlobalErrors !== false;
|
|
9
|
+
const shouldCaptureConsole = config.captureConsole === true;
|
|
10
|
+
function register() {
|
|
11
|
+
const runtime = typeof process !== "undefined" ? process.env?.NEXT_RUNTIME : void 0;
|
|
12
|
+
if (runtime === "nodejs") {
|
|
13
|
+
if (shouldCaptureGlobalErrors) {
|
|
14
|
+
process.on("uncaughtException", (error) => {
|
|
15
|
+
logger.captureError(error, {
|
|
16
|
+
severity: "critical",
|
|
17
|
+
context: { source: "uncaughtException", runtime: "nodejs" }
|
|
18
|
+
});
|
|
19
|
+
logger.flush();
|
|
20
|
+
});
|
|
21
|
+
process.on("unhandledRejection", (reason) => {
|
|
22
|
+
logger.captureError(
|
|
23
|
+
reason instanceof Error ? reason : new Error(String(reason)),
|
|
24
|
+
{
|
|
25
|
+
severity: "high",
|
|
26
|
+
context: { source: "unhandledRejection", runtime: "nodejs" }
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
logger.flush();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (shouldCaptureConsole) {
|
|
33
|
+
const origLog = console.log;
|
|
34
|
+
const origInfo = console.info;
|
|
35
|
+
const origWarn = console.warn;
|
|
36
|
+
const origError = console.error;
|
|
37
|
+
const origDebug = console.debug;
|
|
38
|
+
console.log = (...args) => {
|
|
39
|
+
logger.info(args.map(String).join(" "));
|
|
40
|
+
origLog(...args);
|
|
41
|
+
};
|
|
42
|
+
console.info = (...args) => {
|
|
43
|
+
logger.info(args.map(String).join(" "));
|
|
44
|
+
origInfo(...args);
|
|
45
|
+
};
|
|
46
|
+
console.warn = (...args) => {
|
|
47
|
+
logger.warn(args.map(String).join(" "));
|
|
48
|
+
origWarn(...args);
|
|
49
|
+
};
|
|
50
|
+
console.error = (...args) => {
|
|
51
|
+
logger.error(args.map(String).join(" "));
|
|
52
|
+
origError(...args);
|
|
53
|
+
};
|
|
54
|
+
console.debug = (...args) => {
|
|
55
|
+
logger.debug(args.map(String).join(" "));
|
|
56
|
+
origDebug(...args);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
logger.info("DeepTracer initialized", {
|
|
60
|
+
runtime: "nodejs",
|
|
61
|
+
product: config.product,
|
|
62
|
+
service: config.service
|
|
63
|
+
});
|
|
64
|
+
} else if (runtime === "edge") {
|
|
65
|
+
logger.info("DeepTracer initialized", {
|
|
66
|
+
runtime: "edge",
|
|
67
|
+
product: config.product,
|
|
68
|
+
service: config.service
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function onRequestError(err, request, context) {
|
|
73
|
+
const reqLogger = logger.withContext(
|
|
74
|
+
`${context.routeType}:${context.routePath}`
|
|
75
|
+
);
|
|
76
|
+
reqLogger.addBreadcrumb({
|
|
77
|
+
type: "http",
|
|
78
|
+
message: `${request.method} ${request.path}`
|
|
79
|
+
});
|
|
80
|
+
reqLogger.captureError(err, {
|
|
81
|
+
severity: "high",
|
|
82
|
+
context: {
|
|
83
|
+
source: "nextjs-onRequestError",
|
|
84
|
+
method: request.method,
|
|
85
|
+
path: request.path,
|
|
86
|
+
routerKind: context.routerKind,
|
|
87
|
+
routePath: context.routePath,
|
|
88
|
+
routeType: context.routeType
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return { register, onRequestError, logger };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/server-action.ts
|
|
96
|
+
async function withServerAction(logger, name, fn) {
|
|
97
|
+
return logger.startSpan(`server-action:${name}`, async () => {
|
|
98
|
+
try {
|
|
99
|
+
return await fn();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
logger.captureError(error, {
|
|
102
|
+
severity: "high",
|
|
103
|
+
context: { source: "server-action", action: name }
|
|
104
|
+
});
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/route-handler.ts
|
|
111
|
+
function withRouteHandler(logger, name, handler) {
|
|
112
|
+
return async (request) => {
|
|
113
|
+
const reqLogger = logger.forRequest(request);
|
|
114
|
+
return reqLogger.startSpan(`route:${name}`, async () => {
|
|
115
|
+
try {
|
|
116
|
+
return await handler(request);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
reqLogger.captureError(error, {
|
|
119
|
+
severity: "high",
|
|
120
|
+
context: {
|
|
121
|
+
source: "route-handler",
|
|
122
|
+
route: name,
|
|
123
|
+
method: request.method,
|
|
124
|
+
url: request.url
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export {
|
|
133
|
+
init,
|
|
134
|
+
withRouteHandler,
|
|
135
|
+
withServerAction
|
|
136
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deeptracer/nextjs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DeepTracer Next.js integration — server
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "DeepTracer Next.js integration — automatic server-side error capture with one-file setup",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -11,11 +11,16 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./client": {
|
|
16
|
+
"types": "./dist/client.d.ts",
|
|
17
|
+
"import": "./dist/client.js",
|
|
18
|
+
"require": "./dist/client.cjs"
|
|
14
19
|
}
|
|
15
20
|
},
|
|
16
21
|
"files": ["dist", "README.md"],
|
|
17
22
|
"sideEffects": false,
|
|
18
|
-
"keywords": ["deeptracer", "nextjs", "observability"],
|
|
23
|
+
"keywords": ["deeptracer", "nextjs", "observability", "error-tracking", "instrumentation"],
|
|
19
24
|
"repository": {
|
|
20
25
|
"type": "git",
|
|
21
26
|
"url": "https://github.com/getdeeptracer/deeptracer-js.git",
|
|
@@ -23,11 +28,13 @@
|
|
|
23
28
|
},
|
|
24
29
|
"license": "MIT",
|
|
25
30
|
"dependencies": {
|
|
26
|
-
"@deeptracer/node": "0.
|
|
27
|
-
"@deeptracer/react": "0.
|
|
31
|
+
"@deeptracer/node": "0.3.0",
|
|
32
|
+
"@deeptracer/react": "0.3.0"
|
|
28
33
|
},
|
|
29
34
|
"peerDependencies": {
|
|
30
|
-
"next": ">=14"
|
|
35
|
+
"next": ">=14",
|
|
36
|
+
"react": ">=18",
|
|
37
|
+
"react-dom": ">=18"
|
|
31
38
|
},
|
|
32
39
|
"scripts": {
|
|
33
40
|
"build": "tsup",
|