@nextscope/next 0.1.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/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.js +155 -0
- package/dist/config.js.map +1 -0
- package/dist/forwarder.d.ts +26 -0
- package/dist/forwarder.js +88 -0
- package/dist/forwarder.js.map +1 -0
- package/dist/inspector/model/index.d.ts +79 -0
- package/dist/inspector/model/index.js +514 -0
- package/dist/inspector/model/index.js.map +1 -0
- package/dist/inspector/model/types.d.ts +152 -0
- package/dist/inspector/model/types.js +3 -0
- package/dist/inspector/model/types.js.map +1 -0
- package/dist/inspector-assets.d.ts +2 -0
- package/dist/inspector-assets.js +7 -0
- package/dist/inspector-assets.js.map +1 -0
- package/dist/next-types.d.ts +26 -0
- package/dist/next-types.js +3 -0
- package/dist/next-types.js.map +1 -0
- package/dist/otel.d.ts +102 -0
- package/dist/otel.js +137 -0
- package/dist/otel.js.map +1 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +179 -0
- package/dist/server.js.map +1 -0
- package/dist/store.d.ts +164 -0
- package/dist/store.js +479 -0
- package/dist/store.js.map +1 -0
- package/dist/suppression.d.ts +8 -0
- package/dist/suppression.js +115 -0
- package/dist/suppression.js.map +1 -0
- package/dist/ui.d.ts +3 -0
- package/dist/ui.js +27 -0
- package/dist/ui.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vercel Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# NextScope
|
|
2
|
+
|
|
3
|
+
NextScope is a local OpenTelemetry trace inspector for `next dev`.
|
|
4
|
+
|
|
5
|
+
It is designed for Next.js 16 apps that already use `@vercel/otel >= 2.1`.
|
|
6
|
+
The development plugin starts an in-process OTLP/HTTP JSON trace receiver,
|
|
7
|
+
points `@vercel/otel` at it, and exposes a Next-native inspector at
|
|
8
|
+
`/_nextscope`.
|
|
9
|
+
|
|
10
|
+
The MVP is intentionally narrow:
|
|
11
|
+
|
|
12
|
+
- Next.js 16 only
|
|
13
|
+
- development server only
|
|
14
|
+
- traces only
|
|
15
|
+
- in-memory storage only
|
|
16
|
+
- no external collector, database, or dashboard process
|
|
17
|
+
|
|
18
|
+
## Why
|
|
19
|
+
|
|
20
|
+
Local OpenTelemetry inspection usually means running something outside the app:
|
|
21
|
+
Jaeger, Grafana LGTM, Aspire Dashboard, or Vercel's collector dev setup. Those
|
|
22
|
+
tools work, but they add a second system to configure and keep in view while
|
|
23
|
+
debugging a Next.js request.
|
|
24
|
+
|
|
25
|
+
NextScope keeps the local debugging loop inside `next dev`. Open your app, make
|
|
26
|
+
a request, then inspect the recent request trace at `/_nextscope`.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pnpm add @nextscope/next @vercel/otel
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Peer requirements:
|
|
35
|
+
|
|
36
|
+
- `next >=16.0.0 <17.0.0`
|
|
37
|
+
- `@vercel/otel >=2.1.0`
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
Wrap your Next config with `withNextScope`:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
// next.config.mjs
|
|
45
|
+
import { withNextScope } from '@nextscope/next/config'
|
|
46
|
+
|
|
47
|
+
const nextConfig = {}
|
|
48
|
+
|
|
49
|
+
export default withNextScope(nextConfig)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Register `@vercel/otel` from your app instrumentation file:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// instrumentation.ts
|
|
56
|
+
import { registerOTel } from '@vercel/otel'
|
|
57
|
+
|
|
58
|
+
export function register() {
|
|
59
|
+
registerOTel({ serviceName: 'my-next-app' })
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Start the app:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
pnpm dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Then open:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
http://localhost:3000/_nextscope
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Verify It Works
|
|
76
|
+
|
|
77
|
+
After setup, keep the app running with `pnpm dev`.
|
|
78
|
+
|
|
79
|
+
1. Request one page in the app, for example `http://localhost:3000/`.
|
|
80
|
+
2. Open `http://localhost:3000/_nextscope`.
|
|
81
|
+
3. Expect at least one trace row in the recent requests list.
|
|
82
|
+
|
|
83
|
+
If no trace row appears, check these common misses:
|
|
84
|
+
|
|
85
|
+
- The app is missing `instrumentation.ts`, or it does not call `registerOTel`
|
|
86
|
+
from `@vercel/otel`.
|
|
87
|
+
- The app is not running through `next dev`. NextScope is disabled for normal
|
|
88
|
+
builds and production starts by default.
|
|
89
|
+
- An existing OTLP exporter uses an unsupported protocol. NextScope captures
|
|
90
|
+
locally, but forwarding only supports OTLP/HTTP JSON.
|
|
91
|
+
- `withNextScope` uses a custom `route`, so the inspector is available at that
|
|
92
|
+
route instead of `/_nextscope`.
|
|
93
|
+
- Another rewrite or route collides with the inspector route.
|
|
94
|
+
- The app has not received any non-NextScope traffic yet. Open a real app page
|
|
95
|
+
before checking the inspector.
|
|
96
|
+
|
|
97
|
+
## Options
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
withNextScope(nextConfig, {
|
|
101
|
+
enabled: true,
|
|
102
|
+
route: '/_nextscope',
|
|
103
|
+
maxTraces: 200,
|
|
104
|
+
})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
| Option | Default | Description |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `enabled` | dev auto-detection | Set `false` to disable. Set `true` to force-enable for a non-standard dev runtime. |
|
|
110
|
+
| `route` | `/_nextscope` | Public route where the inspector UI is mounted. |
|
|
111
|
+
| `maxTraces` | `200` | Maximum number of trace groups retained in memory. |
|
|
112
|
+
|
|
113
|
+
By default, NextScope enables itself only for `next dev`. It no-ops for build,
|
|
114
|
+
start, and type generation.
|
|
115
|
+
|
|
116
|
+
## How It Works
|
|
117
|
+
|
|
118
|
+
During development, the config plugin:
|
|
119
|
+
|
|
120
|
+
1. Starts a singleton HTTP sidecar on `127.0.0.1:0`.
|
|
121
|
+
2. Sets `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/json`.
|
|
122
|
+
3. Sets `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` to the sidecar's `/v1/traces`
|
|
123
|
+
endpoint.
|
|
124
|
+
4. Adds a Next rewrite from `/_nextscope/:path*` to the local sidecar.
|
|
125
|
+
|
|
126
|
+
The sidecar:
|
|
127
|
+
|
|
128
|
+
- accepts `POST /v1/traces` OTLP/HTTP JSON batches;
|
|
129
|
+
- normalizes spans and groups them by `traceId`;
|
|
130
|
+
- keeps recent traces in memory with a retention cap;
|
|
131
|
+
- serves the inspector UI assets;
|
|
132
|
+
- exposes `GET /api/traces` and `GET /api/traces/:traceId` for the UI.
|
|
133
|
+
|
|
134
|
+
The inspector highlights request-oriented traces, especially
|
|
135
|
+
`next.span_type=BaseServer.handleRequest`, and shows:
|
|
136
|
+
|
|
137
|
+
- route or target path;
|
|
138
|
+
- method and status code;
|
|
139
|
+
- duration and start time;
|
|
140
|
+
- span count;
|
|
141
|
+
- nested span waterfall with a tree column and timeline column;
|
|
142
|
+
- service-colored span bars, status and error markers, and event markers;
|
|
143
|
+
- trace-level filtering by text, status, method, newest, slowest, errors, and
|
|
144
|
+
fielded filters such as `route:`, `service:`, `duration:>500ms`, and
|
|
145
|
+
`errors:true`;
|
|
146
|
+
- optional trace list grouping by route with per-route count, latest request,
|
|
147
|
+
slowest request, p50/p95 duration, and error rate;
|
|
148
|
+
- span search across names, service names, span types, status, attributes,
|
|
149
|
+
resource attributes, events, and links;
|
|
150
|
+
- zoomable timing view with `Cmd`/`Ctrl` + mouse wheel, reset zoom, and cursor
|
|
151
|
+
crosshair timing;
|
|
152
|
+
- selected span details with timing, parent/child context, attributes, resource
|
|
153
|
+
attributes, events, and links.
|
|
154
|
+
|
|
155
|
+
The public setup and options are unchanged. The React inspector is bundled into
|
|
156
|
+
static sidecar assets and does not require a separate dashboard process.
|
|
157
|
+
|
|
158
|
+
## Existing Exporters
|
|
159
|
+
|
|
160
|
+
If an OTLP trace exporter is already configured, NextScope snapshots the previous
|
|
161
|
+
trace endpoint, protocol, and headers before overriding the active trace endpoint.
|
|
162
|
+
|
|
163
|
+
When the previous exporter is compatible with OTLP/HTTP JSON, NextScope forwards
|
|
164
|
+
captured batches to it after local filtering. Unsupported protocols are warned
|
|
165
|
+
once and skipped.
|
|
166
|
+
|
|
167
|
+
Supported forwarding protocol:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
http/json
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Unsupported examples include gRPC exporters or non-JSON protocols.
|
|
174
|
+
|
|
175
|
+
## Self-Trace Suppression
|
|
176
|
+
|
|
177
|
+
Requests made by the inspector itself are filtered out before storage and before
|
|
178
|
+
forwarding. This prevents the tool from filling the trace list with its own UI,
|
|
179
|
+
static asset, or polling requests.
|
|
180
|
+
|
|
181
|
+
Suppressed requests include:
|
|
182
|
+
|
|
183
|
+
- `/_nextscope`
|
|
184
|
+
- `/_nextscope/app.js`
|
|
185
|
+
- `/_nextscope/style.css`
|
|
186
|
+
- `/_nextscope/api/traces`
|
|
187
|
+
- direct sidecar requests for the same UI and API paths
|
|
188
|
+
|
|
189
|
+
## Fixture App
|
|
190
|
+
|
|
191
|
+
The repository includes a Next.js 16 fixture app at
|
|
192
|
+
`fixtures/next16-app`. It is intentionally heavier than a smoke test so the
|
|
193
|
+
inspector has varied traces to display.
|
|
194
|
+
|
|
195
|
+
Run it with:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
pnpm --filter nextscope-next16-fixture dev
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Useful routes:
|
|
202
|
+
|
|
203
|
+
- `/traced` - minimal traced page
|
|
204
|
+
- `/stress` - fixture dashboard
|
|
205
|
+
- `/stress/nested` - nested spans
|
|
206
|
+
- `/stress/parallel` - parallel spans
|
|
207
|
+
- `/stress/slow` - slow span timing
|
|
208
|
+
- `/stress/error` - recorded exception and error status
|
|
209
|
+
- `/stress/attributes` - large and high-cardinality attributes
|
|
210
|
+
- `/stress/fetch` - fetch-shaped span scenario
|
|
211
|
+
- `/stress/siblings` - many sibling spans
|
|
212
|
+
- `/stress/services` - spans annotated with several service-style peers
|
|
213
|
+
- `/stress/waterfall` - richer sequential and parallel fetch waterfall
|
|
214
|
+
- `/stress/not-found` - traced `notFound()` / 404 route
|
|
215
|
+
- `/stress/long-route-name-with-many-segments/and-a-very-long-leaf` - long route label
|
|
216
|
+
- `/api/stress/attributes` - traced route handler
|
|
217
|
+
- `POST /api/stress/waterfall` - traced POST route handler
|
|
218
|
+
- `/stress/catch/a/b/c` - optional catch-all route
|
|
219
|
+
|
|
220
|
+
Then open:
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
http://localhost:3016/_nextscope
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Development
|
|
227
|
+
|
|
228
|
+
Install dependencies:
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
pnpm install
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Run tests:
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
pnpm test
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Typecheck:
|
|
241
|
+
|
|
242
|
+
```sh
|
|
243
|
+
pnpm typecheck
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Build the package:
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
pnpm build
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Build the fixture app:
|
|
253
|
+
|
|
254
|
+
```sh
|
|
255
|
+
pnpm --filter nextscope-next16-fixture build
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Run the opt-in fixture runtime check:
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
NEXTSCOPE_RUN_RUNTIME=1 pnpm exec vitest run test/fixture-runtime.test.ts
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Current Limitations
|
|
265
|
+
|
|
266
|
+
- Development-only MVP.
|
|
267
|
+
- Trace data is process-local and lost when the dev server exits.
|
|
268
|
+
- No logs or metrics.
|
|
269
|
+
- No persistence, search index, or cross-session history.
|
|
270
|
+
- Forwarding only supports prior OTLP/HTTP JSON trace exporters.
|
|
271
|
+
- The UI is optimized for recent request debugging, not full observability
|
|
272
|
+
workflows.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { NextConfig, Rewrites } from './next-types';
|
|
2
|
+
import { type NextScopeServer, type NextScopeServerOptions } from './server';
|
|
3
|
+
export interface NextScopeOptions {
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
route?: string;
|
|
6
|
+
maxTraces?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface NextScopeRuntime {
|
|
9
|
+
command?: string;
|
|
10
|
+
dev?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface NextConfigContext {
|
|
13
|
+
defaultConfig: NextConfig;
|
|
14
|
+
command?: string;
|
|
15
|
+
dev?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export type NextConfigFactory = (phase: string, context?: NextConfigContext) => Promise<NextConfig>;
|
|
18
|
+
export type NextConfigInputFactory = (phase: string, context: NextConfigContext) => NextConfig | Promise<NextConfig>;
|
|
19
|
+
export declare function withNextScope(nextConfig?: NextConfig, options?: NextScopeOptions): NextConfigFactory;
|
|
20
|
+
export declare function withNextScope(nextConfig: NextConfigInputFactory, options?: NextScopeOptions): NextConfigFactory;
|
|
21
|
+
export declare function resetNextScopeForTests(): void;
|
|
22
|
+
export declare function shouldEnable(runtime: NextScopeRuntime, options?: NextScopeOptions): boolean;
|
|
23
|
+
export declare function normalizeRoute(route: string): string;
|
|
24
|
+
export declare function resolveRewrites(rewrites: NextConfig['rewrites']): Promise<Rewrites>;
|
|
25
|
+
export declare function mergeRewrites(existing: Rewrites | undefined, nextScopeRewrite: Rewrite): Rewrite[] | {
|
|
26
|
+
beforeFiles: Rewrite[];
|
|
27
|
+
afterFiles?: import("./next-types").Rewrite[];
|
|
28
|
+
fallback?: import("./next-types").Rewrite[];
|
|
29
|
+
};
|
|
30
|
+
export declare function ensureServer(options: NextScopeServerOptions): Promise<NextScopeServer | undefined>;
|
|
31
|
+
export declare function configureTelemetryEnv(nextScopeEndpoint: string): void;
|
|
32
|
+
export declare function snapshotTraceExporterEnv(): {
|
|
33
|
+
endpoint: string | undefined;
|
|
34
|
+
protocol: string | undefined;
|
|
35
|
+
headers: string | undefined;
|
|
36
|
+
};
|
|
37
|
+
export declare function isSupportedHttpJson(protocol?: string): boolean;
|
|
38
|
+
interface Rewrite {
|
|
39
|
+
source: string;
|
|
40
|
+
destination: string;
|
|
41
|
+
basePath?: false;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withNextScope = withNextScope;
|
|
4
|
+
exports.resetNextScopeForTests = resetNextScopeForTests;
|
|
5
|
+
exports.shouldEnable = shouldEnable;
|
|
6
|
+
exports.normalizeRoute = normalizeRoute;
|
|
7
|
+
exports.resolveRewrites = resolveRewrites;
|
|
8
|
+
exports.mergeRewrites = mergeRewrites;
|
|
9
|
+
exports.ensureServer = ensureServer;
|
|
10
|
+
exports.configureTelemetryEnv = configureTelemetryEnv;
|
|
11
|
+
exports.snapshotTraceExporterEnv = snapshotTraceExporterEnv;
|
|
12
|
+
exports.isSupportedHttpJson = isSupportedHttpJson;
|
|
13
|
+
const server_1 = require("./server");
|
|
14
|
+
let singletonServer;
|
|
15
|
+
let warnedUnsupportedExporter = false;
|
|
16
|
+
let warnedStartupFailure = false;
|
|
17
|
+
const DEFAULT_ROUTE = '/_nextscope';
|
|
18
|
+
const DEFAULT_MAX_TRACES = 200;
|
|
19
|
+
function withNextScope(nextConfig = {}, options = {}) {
|
|
20
|
+
const wrapped = async (phase, context = { defaultConfig: {} }) => {
|
|
21
|
+
const resolvedConfig = typeof nextConfig === 'function'
|
|
22
|
+
? await nextConfig(phase, context)
|
|
23
|
+
: nextConfig;
|
|
24
|
+
const runtime = inferRuntime(phase, context);
|
|
25
|
+
if (!shouldEnable(runtime, options)) {
|
|
26
|
+
return resolvedConfig;
|
|
27
|
+
}
|
|
28
|
+
const server = await ensureServer({
|
|
29
|
+
route: normalizeRoute(options.route ?? DEFAULT_ROUTE),
|
|
30
|
+
maxTraces: options.maxTraces ?? DEFAULT_MAX_TRACES,
|
|
31
|
+
});
|
|
32
|
+
if (!server) {
|
|
33
|
+
return resolvedConfig;
|
|
34
|
+
}
|
|
35
|
+
configureTelemetryEnv(server.url);
|
|
36
|
+
return {
|
|
37
|
+
...resolvedConfig,
|
|
38
|
+
rewrites: async () => {
|
|
39
|
+
const existing = await resolveRewrites(resolvedConfig.rewrites);
|
|
40
|
+
return mergeRewrites(existing, {
|
|
41
|
+
source: `${server.route}/:path*`,
|
|
42
|
+
destination: `${server.url}/:path*`,
|
|
43
|
+
basePath: false,
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
return wrapped;
|
|
49
|
+
}
|
|
50
|
+
function resetNextScopeForTests() {
|
|
51
|
+
singletonServer = undefined;
|
|
52
|
+
warnedUnsupportedExporter = false;
|
|
53
|
+
warnedStartupFailure = false;
|
|
54
|
+
}
|
|
55
|
+
function shouldEnable(runtime, options = {}) {
|
|
56
|
+
if (options.enabled === false) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (options.enabled === true) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return runtime.dev === true || runtime.command === 'dev';
|
|
63
|
+
}
|
|
64
|
+
function normalizeRoute(route) {
|
|
65
|
+
const trimmed = route.trim();
|
|
66
|
+
const withSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
67
|
+
return withSlash.length > 1 ? withSlash.replace(/\/+$/, '') : withSlash;
|
|
68
|
+
}
|
|
69
|
+
async function resolveRewrites(rewrites) {
|
|
70
|
+
if (!rewrites) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
return typeof rewrites === 'function' ? await rewrites() : rewrites;
|
|
74
|
+
}
|
|
75
|
+
function mergeRewrites(existing, nextScopeRewrite) {
|
|
76
|
+
if (!existing) {
|
|
77
|
+
return [nextScopeRewrite];
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(existing)) {
|
|
80
|
+
return [nextScopeRewrite, ...existing];
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...existing,
|
|
84
|
+
beforeFiles: [nextScopeRewrite, ...(existing.beforeFiles ?? [])],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function ensureServer(options) {
|
|
88
|
+
if (singletonServer) {
|
|
89
|
+
return singletonServer;
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
singletonServer = await (0, server_1.startNextScopeServer)(options);
|
|
93
|
+
return singletonServer;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (!warnedStartupFailure) {
|
|
97
|
+
warnedStartupFailure = true;
|
|
98
|
+
console.warn(`[nextscope] Failed to start local trace inspector: ${formatError(error)}`);
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function configureTelemetryEnv(nextScopeEndpoint) {
|
|
104
|
+
const nextScopeTraceEndpoint = `${nextScopeEndpoint}/v1/traces`;
|
|
105
|
+
const previous = snapshotTraceExporterEnv();
|
|
106
|
+
if (previous.endpoint !== nextScopeTraceEndpoint) {
|
|
107
|
+
process.env.NEXTSCOPE_FORWARD_TRACES_ENDPOINT = previous.endpoint ?? '';
|
|
108
|
+
process.env.NEXTSCOPE_FORWARD_TRACES_PROTOCOL = previous.protocol ?? '';
|
|
109
|
+
process.env.NEXTSCOPE_FORWARD_TRACES_HEADERS = previous.headers ?? '';
|
|
110
|
+
}
|
|
111
|
+
if (previous.endpoint && !isSupportedHttpJson(previous.protocol)) {
|
|
112
|
+
warnUnsupportedExporter(previous.protocol);
|
|
113
|
+
}
|
|
114
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'http/json';
|
|
115
|
+
process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = nextScopeTraceEndpoint;
|
|
116
|
+
}
|
|
117
|
+
function snapshotTraceExporterEnv() {
|
|
118
|
+
return {
|
|
119
|
+
endpoint: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ??
|
|
120
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
121
|
+
protocol: process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ??
|
|
122
|
+
process.env.OTEL_EXPORTER_OTLP_PROTOCOL,
|
|
123
|
+
headers: process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS ??
|
|
124
|
+
process.env.OTEL_EXPORTER_OTLP_HEADERS,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function isSupportedHttpJson(protocol) {
|
|
128
|
+
return !protocol || protocol === 'http/json';
|
|
129
|
+
}
|
|
130
|
+
function inferRuntime(phase, context) {
|
|
131
|
+
return {
|
|
132
|
+
command: typeof context.defaultConfig === 'object' &&
|
|
133
|
+
context.defaultConfig !== null &&
|
|
134
|
+
'command' in context.defaultConfig &&
|
|
135
|
+
typeof context.defaultConfig.command === 'string'
|
|
136
|
+
? context.defaultConfig.command
|
|
137
|
+
: typeof context.command === 'string'
|
|
138
|
+
? context.command
|
|
139
|
+
: undefined,
|
|
140
|
+
dev: typeof context.dev === 'boolean'
|
|
141
|
+
? context.dev
|
|
142
|
+
: phase === 'phase-development-server',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function warnUnsupportedExporter(protocol) {
|
|
146
|
+
if (warnedUnsupportedExporter) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
warnedUnsupportedExporter = true;
|
|
150
|
+
console.warn(`[nextscope] Existing OTLP trace exporter uses unsupported protocol "${protocol ?? 'unset'}"; capturing locally but forwarding is disabled.`);
|
|
151
|
+
}
|
|
152
|
+
function formatError(error) {
|
|
153
|
+
return error instanceof Error ? error.message : String(error);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ForwarderEnv {
|
|
2
|
+
endpoint?: string;
|
|
3
|
+
protocol?: string;
|
|
4
|
+
headers?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ForwarderStatus {
|
|
7
|
+
configured: boolean;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
protocol?: string;
|
|
10
|
+
endpoint?: string;
|
|
11
|
+
lastSuccessAt?: string;
|
|
12
|
+
lastError?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class TraceForwarder {
|
|
15
|
+
private readonly env;
|
|
16
|
+
private warned;
|
|
17
|
+
private lastSuccessAt;
|
|
18
|
+
private lastError;
|
|
19
|
+
constructor(env?: ForwarderEnv);
|
|
20
|
+
forward(body: string): Promise<void>;
|
|
21
|
+
getStatus(): ForwarderStatus;
|
|
22
|
+
private warnOnce;
|
|
23
|
+
}
|
|
24
|
+
export declare function readForwarderEnv(): ForwarderEnv;
|
|
25
|
+
export declare function isForwardableProtocol(protocol?: string): boolean;
|
|
26
|
+
export declare function parseHeaders(headerString?: string): Record<string, string>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TraceForwarder = void 0;
|
|
4
|
+
exports.readForwarderEnv = readForwarderEnv;
|
|
5
|
+
exports.isForwardableProtocol = isForwardableProtocol;
|
|
6
|
+
exports.parseHeaders = parseHeaders;
|
|
7
|
+
class TraceForwarder {
|
|
8
|
+
env;
|
|
9
|
+
warned = false;
|
|
10
|
+
lastSuccessAt;
|
|
11
|
+
lastError;
|
|
12
|
+
constructor(env = readForwarderEnv()) {
|
|
13
|
+
this.env = env;
|
|
14
|
+
}
|
|
15
|
+
async forward(body) {
|
|
16
|
+
if (!this.env.endpoint || !isForwardableProtocol(this.env.protocol)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(this.env.endpoint, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
body,
|
|
23
|
+
headers: {
|
|
24
|
+
'content-type': 'application/json',
|
|
25
|
+
...parseHeaders(this.env.headers),
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error(`forwarding failed with HTTP ${response.status}`);
|
|
30
|
+
}
|
|
31
|
+
this.lastSuccessAt = Date.now();
|
|
32
|
+
this.lastError = undefined;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
this.lastError = formatError(error);
|
|
36
|
+
this.warnOnce(error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
getStatus() {
|
|
40
|
+
return {
|
|
41
|
+
configured: Boolean(this.env.endpoint),
|
|
42
|
+
enabled: Boolean(this.env.endpoint && isForwardableProtocol(this.env.protocol)),
|
|
43
|
+
protocol: this.env.protocol,
|
|
44
|
+
endpoint: this.env.endpoint,
|
|
45
|
+
lastSuccessAt: this.lastSuccessAt
|
|
46
|
+
? new Date(this.lastSuccessAt).toISOString()
|
|
47
|
+
: undefined,
|
|
48
|
+
lastError: this.lastError,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
warnOnce(error) {
|
|
52
|
+
if (this.warned) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.warned = true;
|
|
56
|
+
console.warn(`[nextscope] Failed to forward trace batch to existing exporter: ${formatError(error)}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.TraceForwarder = TraceForwarder;
|
|
60
|
+
function readForwarderEnv() {
|
|
61
|
+
return {
|
|
62
|
+
endpoint: process.env.NEXTSCOPE_FORWARD_TRACES_ENDPOINT || undefined,
|
|
63
|
+
protocol: process.env.NEXTSCOPE_FORWARD_TRACES_PROTOCOL || undefined,
|
|
64
|
+
headers: process.env.NEXTSCOPE_FORWARD_TRACES_HEADERS || undefined,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function isForwardableProtocol(protocol) {
|
|
68
|
+
return !protocol || protocol === 'http/json';
|
|
69
|
+
}
|
|
70
|
+
function parseHeaders(headerString) {
|
|
71
|
+
const headers = {};
|
|
72
|
+
if (!headerString) {
|
|
73
|
+
return headers;
|
|
74
|
+
}
|
|
75
|
+
for (const part of headerString.split(',')) {
|
|
76
|
+
const [rawKey, ...rawValue] = part.split('=');
|
|
77
|
+
const key = rawKey?.trim();
|
|
78
|
+
const value = rawValue.join('=').trim();
|
|
79
|
+
if (key && value) {
|
|
80
|
+
headers[key] = value;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return headers;
|
|
84
|
+
}
|
|
85
|
+
function formatError(error) {
|
|
86
|
+
return error instanceof Error ? error.message : String(error);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=forwarder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forwarder.js","sourceRoot":"","sources":["../src/forwarder.ts"],"names":[],"mappings":"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"}
|