@wular/pnext 0.0.4 → 0.0.7
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/README.md +22 -16
- package/bin/pnext +6 -1
- package/config/lint/base.js +7 -7
- package/config/ts/base.json +2 -4
- package/config/ts/react.json +2 -6
- package/package.json +23 -2
- package/reference/compat.md +87 -22
- package/reference/config.md +40 -93
- package/reference/css.md +42 -33
- package/reference/dev.md +26 -33
- package/reference/env.md +18 -20
- package/reference/getting-started.md +132 -0
- package/reference/metadata.md +31 -46
- package/reference/navigation.md +65 -105
- package/reference/performance.md +21 -142
- package/reference/rendering.md +78 -75
- package/reference/routing.md +97 -107
- package/reference/typegen.md +27 -29
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +121 -114
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +52 -53
- package/src/api/navigation.ts +59 -58
- package/src/api/server.ts +152 -144
- package/src/api/suspense.ts +4 -4
- package/src/cli/adapters/vercel-warm.ts +126 -121
- package/src/cli/adapters/vercel.ts +437 -443
- package/src/cli/analyze.ts +333 -144
- package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
- package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
- package/src/cli/build.ts +976 -978
- package/src/cli/create.ts +72 -64
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +94 -85
- package/src/cli/migrate/package-json.ts +73 -71
- package/src/cli/migrate/report.ts +32 -33
- package/src/cli/migrate/{index.ts → run.ts} +48 -49
- package/src/cli/migrate/scan.ts +46 -46
- package/src/cli/migrate/spinner.ts +9 -9
- package/src/cli/migrate/tsconfig.ts +35 -35
- package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
- package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
- package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
- package/src/cli/start.ts +65 -66
- package/src/{typegen.ts → cli/typegen.ts} +59 -59
- package/src/client/build.ts +802 -768
- package/src/client/chunk-fold.ts +245 -240
- package/src/client/{paths.ts → chunk-name.ts} +6 -6
- package/src/client/entry.ts +162 -147
- package/src/client/prebuilt.ts +231 -223
- package/src/client/profile.ts +29 -29
- package/src/client/react-compiler.ts +20 -15
- package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
- package/src/client/reference-stub.ts +51 -51
- package/src/client/reference.ts +19 -19
- package/src/{api → client}/router/events.ts +32 -17
- package/src/{api → client}/router/history.ts +16 -16
- package/src/{api → client}/router/hub.ts +52 -53
- package/src/{api/router.ts → client/router/index.ts} +61 -60
- package/src/{api → client}/router/policies.ts +24 -24
- package/src/{api → client}/router/runtime.ts +2022 -1995
- package/src/{api → client}/router/types.ts +98 -98
- package/src/compat/actions/client-plugin.ts +42 -43
- package/src/compat/actions/client-stub.ts +14 -14
- package/src/compat/actions/{action-client.ts → client.ts} +194 -193
- package/src/compat/actions/config.ts +63 -64
- package/src/compat/actions/detect.ts +68 -68
- package/src/compat/actions/discovery.ts +105 -105
- package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
- package/src/compat/actions/early-submit.ts +1 -1
- package/src/compat/actions/endpoint.ts +198 -198
- package/src/compat/actions/extensions.ts +811 -0
- package/src/compat/actions/flight.ts +23 -23
- package/src/compat/actions/form-state.ts +34 -34
- package/src/compat/actions/hoist.ts +382 -236
- package/src/compat/actions/ids.ts +7 -12
- package/src/compat/actions/index.ts +8 -8
- package/src/compat/actions/instances.ts +46 -46
- package/src/compat/actions/origin.ts +47 -48
- package/src/compat/actions/protocol.ts +22 -22
- package/src/compat/actions/registry.ts +19 -19
- package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
- package/src/compat/actions/rewrite.ts +125 -125
- package/src/compat/actions/{action-router.ts → router.ts} +10 -10
- package/src/compat/actions/serve.ts +132 -136
- package/src/compat/actions/server-tag.ts +4 -4
- package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
- package/src/compat/actions/unrecognized-error.ts +4 -4
- package/src/compat/{index.ts → aliases.ts} +112 -109
- package/src/compat/bundler/bun-externals.ts +18 -18
- package/src/compat/bundler/cjs-exports.ts +271 -223
- package/src/compat/bundler/config.ts +116 -111
- package/src/compat/bundler/externals.ts +12 -12
- package/src/compat/bundler/import-meta-url.ts +19 -19
- package/src/compat/bundler/modularize-imports.ts +36 -33
- package/src/compat/bundler/new-url-asset.ts +22 -24
- package/src/compat/bundler/optimize-package-imports.ts +111 -107
- package/src/compat/bundler/polyfill.ts +28 -28
- package/src/compat/bundler/react-compiler.ts +35 -29
- package/src/compat/bundler/react-profiler.tsx +11 -11
- package/src/compat/bundler/relay-transform.ts +48 -47
- package/src/compat/bundler/require-context.ts +119 -113
- package/src/compat/bundler/resolve-extensions.ts +19 -19
- package/src/compat/bundler/source-cache.ts +25 -25
- package/src/compat/bundler/static-imports.ts +7 -7
- package/src/compat/bundler/symlink-imports.ts +46 -46
- package/src/compat/bundler/tsconfig-paths.ts +13 -15
- package/src/compat/bundler/wasm.ts +58 -60
- package/src/compat/bundler/webpack-loaders.ts +254 -241
- package/src/compat/bundler/worker.ts +101 -104
- package/src/compat/cache/build-flags.ts +29 -29
- package/src/compat/cache/build-prerender-errors.ts +40 -44
- package/src/compat/cache/custom-handler.ts +60 -53
- package/src/compat/cache/fetch-patch.ts +240 -240
- package/src/compat/cache/handler.ts +27 -31
- package/src/compat/cache/modern-handler.ts +148 -126
- package/src/compat/cache/resume-data-cache.ts +47 -45
- package/src/compat/cache/revalidate.ts +233 -232
- package/src/compat/cache/runtime-error.ts +35 -35
- package/src/compat/cache/use-cache-transform.ts +442 -417
- package/src/compat/cache/use-cache.ts +650 -614
- package/src/compat/cache-control.ts +140 -142
- package/src/compat/client/base-path.ts +21 -20
- package/src/compat/client/css-order.ts +18 -18
- package/src/compat/client/errors/bare-boundary.ts +11 -11
- package/src/compat/client/errors/control-flow.ts +23 -23
- package/src/compat/client/errors/error-boundary.ts +61 -61
- package/src/compat/client/errors/global-error.ts +101 -91
- package/src/compat/client/errors/install.ts +71 -72
- package/src/compat/client/errors/lazy.ts +23 -23
- package/src/compat/client/errors/primitive-throw.ts +47 -45
- package/src/compat/client/errors/soft-refresh.ts +4 -4
- package/src/compat/client/link-status.ts +33 -33
- package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
- package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
- package/src/compat/client/navigation-scroll.ts +63 -63
- package/src/compat/client/optimistic-routing.ts +93 -88
- package/src/compat/client/prefetch-cache.ts +23 -24
- package/src/compat/client/route-announcer.ts +35 -35
- package/src/compat/client/segment-cache-policy.ts +20 -20
- package/src/compat/client/segment-cache.ts +309 -315
- package/src/compat/client/segment-prefetch.ts +127 -132
- package/src/compat/client/trailing-slash.ts +5 -4
- package/src/compat/css/chunking.ts +113 -116
- package/src/compat/css/inline-css.ts +21 -21
- package/src/compat/css/lightningcss.ts +37 -38
- package/src/compat/css/modules.ts +161 -175
- package/src/compat/css/nonce.ts +7 -7
- package/src/compat/css/sass-plugin.ts +18 -21
- package/src/compat/css/sass.ts +150 -152
- package/src/compat/css/styled-jsx-runtime.ts +27 -27
- package/src/compat/css/styled-jsx.ts +21 -21
- package/src/compat/edge-runtime.ts +27 -27
- package/src/compat/{adapter → export}/build-complete.ts +72 -75
- package/src/compat/export/client.ts +29 -31
- package/src/compat/export/{index.ts → emit.ts} +111 -110
- package/src/compat/export/standalone.ts +62 -54
- package/src/compat/image-optimizer/cache.ts +51 -49
- package/src/compat/image-optimizer/detect.ts +52 -52
- package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
- package/src/compat/image-optimizer/source.ts +77 -80
- package/src/compat/lifecycle/after-scope.ts +26 -26
- package/src/compat/lifecycle/after.ts +48 -45
- package/src/compat/lifecycle/error-funnel.ts +98 -102
- package/src/compat/lifecycle/error-serialize.ts +30 -26
- package/src/compat/lifecycle/error-ui.ts +67 -32
- package/src/compat/lifecycle/instrumentation-client.ts +36 -38
- package/src/compat/lifecycle/instrumentation.ts +85 -85
- package/src/compat/lifecycle/node-console.ts +11 -11
- package/src/compat/lifecycle/testmode.ts +160 -132
- package/src/compat/mdx/compile.ts +60 -57
- package/src/compat/mdx/plugin.ts +11 -11
- package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
- package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
- package/src/compat/metadata.ts +75 -81
- package/src/compat/next/cache.ts +68 -69
- package/src/compat/next/canonical-url.ts +9 -9
- package/src/compat/next/client-cache.ts +19 -19
- package/src/compat/next/client-navigation.ts +112 -116
- package/src/compat/next/client-only.ts +1 -1
- package/src/compat/next/client-script.tsx +99 -93
- package/src/compat/next/client-server.ts +10 -10
- package/src/compat/next/config-loader.ts +176 -173
- package/src/compat/next/config.ts +7 -7
- package/src/compat/next/constants.cjs +6 -6
- package/src/compat/next/constants.ts +6 -6
- package/src/compat/next/custom-server.ts +26 -24
- package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
- package/src/compat/next/dynamic.tsx +21 -18
- package/src/compat/next/error.tsx +52 -52
- package/src/compat/next/font/cache.ts +74 -74
- package/src/compat/next/font/google.ts +2 -2
- package/src/compat/next/font/index.ts +1 -1
- package/src/compat/next/font/local.ts +3 -3
- package/src/compat/next/font/runtime-client.ts +17 -15
- package/src/compat/next/font/runtime.ts +443 -408
- package/src/compat/next/font/shared.ts +120 -108
- package/src/compat/next/form.tsx +63 -63
- package/src/compat/next/head.tsx +2 -2
- package/src/compat/next/headers.ts +103 -95
- package/src/compat/next/image/client.tsx +220 -0
- package/src/compat/next/image/config.ts +56 -58
- package/src/compat/next/image/optimizer.ts +40 -36
- package/src/compat/next/image/patterns.ts +37 -40
- package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
- package/src/compat/next/image/shared.ts +65 -57
- package/src/compat/next/image/static-metadata.ts +98 -107
- package/src/compat/next/image/validate.ts +79 -88
- package/src/compat/next/image.tsx +19 -23
- package/src/compat/next/index.ts +1 -1
- package/src/compat/next/legacy-image.tsx +59 -60
- package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
- package/src/compat/next/link.tsx +158 -158
- package/src/compat/next/navigation.cjs +12 -3
- package/src/compat/next/navigation.ts +48 -50
- package/src/compat/next/offline.ts +27 -27
- package/src/compat/next/og.ts +121 -124
- package/src/compat/next/preferred-region.ts +13 -14
- package/src/compat/next/redirects.ts +58 -56
- package/src/compat/next/resource-hints.ts +73 -76
- package/src/compat/next/rewrites.ts +130 -133
- package/src/compat/next/root-params.ts +45 -45
- package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
- package/src/compat/next/router.cjs +4 -2
- package/src/compat/next/router.ts +58 -61
- package/src/compat/next/script.tsx +108 -108
- package/src/compat/next/server-only.ts +1 -1
- package/src/compat/next/server.ts +19 -19
- package/src/compat/next/svgr.ts +18 -17
- package/src/compat/next/telemetry.ts +24 -24
- package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
- package/src/compat/next/user-agent.ts +53 -49
- package/src/compat/next/web-vitals.ts +22 -24
- package/src/compat/otel/api.ts +41 -41
- package/src/compat/otel/client-trace-metadata.ts +25 -27
- package/src/compat/otel/fetch-span.ts +29 -29
- package/src/compat/otel/tracer.ts +331 -331
- package/src/compat/pages/api.ts +456 -0
- package/src/compat/pages/client-plugin.ts +36 -36
- package/src/compat/pages/router-state.ts +34 -34
- package/src/compat/pages/{index.ts → router.ts} +130 -135
- package/src/compat/ppr/io.ts +12 -12
- package/src/compat/ppr/missing-root-params.ts +34 -38
- package/src/compat/ppr/root-params-scan.ts +66 -66
- package/src/compat/ppr/root-params-transform.ts +24 -26
- package/src/compat/ppr/root-params.ts +30 -30
- package/src/compat/ppr/segment-config-incompat.ts +6 -7
- package/src/compat/protocol.ts +71 -70
- package/src/compat/react/action-state.ts +47 -48
- package/src/compat/react/client-lite.ts +15 -15
- package/src/compat/react/client.ts +4 -4
- package/src/compat/react/compiler-runtime.ts +11 -11
- package/src/compat/react/dom-client.ts +44 -44
- package/src/compat/react/dom-react-server.ts +10 -16
- package/src/compat/react/dom-server.ts +10 -10
- package/src/compat/react/dom.ts +52 -52
- package/src/compat/react/hooks-extra.ts +34 -35
- package/src/compat/react/parity.ts +64 -61
- package/src/compat/react/preact.ts +81 -82
- package/src/compat/react/react-server.ts +28 -28
- package/src/compat/react/router-shim.ts +1 -1
- package/src/compat/react/server-component-use.ts +8 -8
- package/src/compat/react/server-inserted-html.ts +30 -31
- package/src/compat/react/server.ts +53 -55
- package/src/compat/react/use.ts +32 -32
- package/src/compat/react/view-transition.ts +20 -20
- package/src/compat/register/actions.ts +35 -824
- package/src/compat/register/boot.ts +41 -41
- package/src/compat/register/build-tier.ts +5 -5
- package/src/compat/register/build.ts +74 -70
- package/src/compat/register/bundler.ts +161 -156
- package/src/compat/register/cache.ts +20 -20
- package/src/compat/register/client-errors.ts +3 -3
- package/src/compat/register/config.ts +6 -6
- package/src/compat/register/css-extras.ts +30 -34
- package/src/compat/register/edge-runtime.ts +3 -3
- package/src/compat/register/errors.ts +10 -12
- package/src/compat/register/export.ts +16 -16
- package/src/compat/register/font.ts +11 -11
- package/src/compat/register/hooks.ts +2 -2
- package/src/compat/register/image.ts +40 -40
- package/src/compat/register/index.ts +59 -62
- package/src/compat/register/instrumentation-client.ts +10 -10
- package/src/compat/register/lifecycle.ts +25 -28
- package/src/compat/register/mdx.ts +10 -10
- package/src/compat/register/middleware.ts +226 -16
- package/src/compat/register/otel.ts +80 -88
- package/src/compat/register/pages-api.ts +10 -463
- package/src/compat/register/ppr.ts +16 -16
- package/src/compat/register/protocol.ts +17 -18
- package/src/compat/register/proxy.ts +49 -51
- package/src/compat/register/render.ts +79 -76
- package/src/compat/register/routing.ts +162 -159
- package/src/compat/register/segment.ts +24 -1897
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +86 -69
- package/src/css/build.ts +230 -227
- package/src/css/postcss.ts +79 -80
- package/src/css/worker.ts +14 -15
- package/src/dev/client-actions.ts +10 -10
- package/src/dev/client-chunk-store.ts +27 -27
- package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
- package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
- package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
- package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
- package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
- package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
- package/src/dev/server.ts +804 -820
- package/src/env.ts +46 -43
- package/src/extensions.ts +491 -478
- package/src/index.ts +8 -8
- package/src/internal.ts +20 -23
- package/src/{islands → render}/boundary-error.ts +3 -3
- package/src/render/hooks.ts +71 -71
- package/src/render/island-context.ts +14 -14
- package/src/render/metadata.ts +310 -310
- package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
- package/src/{ppr.ts → render/ppr.ts} +244 -245
- package/src/render/renderer.ts +2087 -2082
- package/src/render/resource-hints.ts +16 -17
- package/src/render/slots.tsx +224 -235
- package/src/{islands → render}/static-children.ts +9 -12
- package/src/{islands → render}/static-slots.ts +37 -37
- package/src/{cache/context.ts → request/cache.ts} +20 -20
- package/src/request/context.ts +107 -107
- package/src/{dynamic/source.ts → resolve/dynamic.ts} +139 -139
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +318 -296
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +87 -70
- package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
- package/src/{proxy.ts → routing/proxy.ts} +306 -312
- package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
- package/src/routing/routes.ts +827 -815
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +954 -0
- package/src/{dev → runtime}/module-cache.ts +309 -287
- package/src/{dev → runtime}/module-generations.ts +9 -9
- package/src/{dev → runtime}/module-transform.ts +81 -72
- package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
- package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
- package/src/runtime/vendor.ts +428 -406
- package/src/styles.d.ts +9 -0
- package/src/types.ts +324 -335
- package/src/utils/ansi.ts +5 -5
- package/src/utils/{source.ts → code.ts} +15 -12
- package/src/utils/content-type.ts +3 -3
- package/src/utils/decode.ts +2 -2
- package/src/utils/dev-profile.ts +13 -13
- package/src/utils/error-log.ts +6 -6
- package/src/utils/esbuild.ts +18 -18
- package/src/utils/fs-cache.ts +13 -13
- package/src/utils/fs.ts +57 -49
- package/src/utils/html.ts +20 -24
- package/src/utils/native-require.ts +8 -8
- package/src/utils/serialize.ts +139 -146
- package/src/utils/verbose.ts +18 -18
- package/reference/overview.md +0 -35
- package/src/cli/analyze-print.ts +0 -181
- package/src/compat/middleware/manifest.ts +0 -210
- package/src/compat/next/image-client.tsx +0 -215
- package/src/compat/next/link-usage.ts +0 -29
- package/src/css/index.ts +0 -2
- package/src/render/index.ts +0 -1
- package/src/style-modules.d.ts +0 -9
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
//
|
|
9
9
|
// Everything is inert unless @opentelemetry/api resolves from the app AND a work unit is active.
|
|
10
10
|
|
|
11
|
-
import { getWorkUnit, queueAfterTask, type WorkUnit } from '../../request/context'
|
|
12
|
-
import { getOtelApi, type OtelApi, type OtelContext, type OtelSpan } from './api'
|
|
11
|
+
import { getWorkUnit, queueAfterTask, type WorkUnit } from '../../request/context'
|
|
12
|
+
import { getOtelApi, type OtelApi, type OtelContext, type OtelSpan } from './api'
|
|
13
13
|
|
|
14
14
|
// next.span_type taxonomy (exact strings Next emits; asserted verbatim).
|
|
15
15
|
export const SPAN_TYPE = {
|
|
@@ -29,14 +29,14 @@ export const SPAN_TYPE = {
|
|
|
29
29
|
renderDocument: 'Render.renderDocument',
|
|
30
30
|
getServerSideProps: 'Render.getServerSideProps',
|
|
31
31
|
getStaticProps: 'Render.getStaticProps',
|
|
32
|
-
} as const
|
|
32
|
+
} as const
|
|
33
33
|
|
|
34
34
|
// The runtime label the app's exporter reads at export time. Next's test exporter serializes
|
|
35
35
|
// `process.env.NEXT_RUNTIME` per span; for a route declared `runtime: 'edge'` Next runs the render in
|
|
36
36
|
// the edge sandbox, so its spans say 'edge' while node-server-side spans stay 'nodejs'. pnext runs
|
|
37
37
|
// everything in one Bun process, so the tracer mirrors the per-span runtime split by setting
|
|
38
38
|
// NEXT_RUNTIME around each span.end() - SimpleSpanProcessor exports synchronously inside end().
|
|
39
|
-
type SpanRuntime = 'edge' | 'nodejs'
|
|
39
|
+
type SpanRuntime = 'edge' | 'nodejs'
|
|
40
40
|
|
|
41
41
|
// Span types Next emits from INSIDE the edge sandbox when the route is edge.
|
|
42
42
|
const EDGE_SANDBOX_SPAN_TYPES: ReadonlySet<string> = new Set([
|
|
@@ -48,30 +48,30 @@ const EDGE_SANDBOX_SPAN_TYPES: ReadonlySet<string> = new Set([
|
|
|
48
48
|
SPAN_TYPE.renderDocument,
|
|
49
49
|
SPAN_TYPE.getServerSideProps,
|
|
50
50
|
SPAN_TYPE.getStaticProps,
|
|
51
|
-
])
|
|
51
|
+
])
|
|
52
52
|
|
|
53
53
|
// Per-WorkUnit otel state (stashed on the compat scratch map).
|
|
54
|
-
const OTEL_STATE = Symbol.for('pnext.compat.otel.state')
|
|
54
|
+
const OTEL_STATE = Symbol.for('pnext.compat.otel.state')
|
|
55
55
|
|
|
56
56
|
interface OtelState {
|
|
57
|
-
api: OtelApi
|
|
57
|
+
api: OtelApi
|
|
58
58
|
/** Context with the root span active — children re-enter this to nest. */
|
|
59
|
-
rootContext: OtelContext
|
|
59
|
+
rootContext: OtelContext
|
|
60
60
|
/** The root BaseServer.handleRequest span (closed by the finalizer). */
|
|
61
|
-
rootSpan: OtelSpan
|
|
61
|
+
rootSpan: OtelSpan
|
|
62
62
|
/** Guard so the root span is ended exactly once. */
|
|
63
|
-
rootEnded: boolean
|
|
63
|
+
rootEnded: boolean
|
|
64
64
|
/** Request method, kept for the pattern-rename span name. */
|
|
65
|
-
method: string
|
|
65
|
+
method: string
|
|
66
66
|
/** Whether this was an RSC request, kept for the pattern-rename span name. */
|
|
67
|
-
rsc: boolean
|
|
67
|
+
rsc: boolean
|
|
68
68
|
/** The raw request target (`pathname + search`) the root span opened with. */
|
|
69
|
-
target: string
|
|
69
|
+
target: string
|
|
70
70
|
/**
|
|
71
71
|
* The extracted INCOMING context (traceparent applied, no pnext span active). Top-level spans parent
|
|
72
72
|
* here, mirroring Next's spans that sit beside - not under - handleRequest.
|
|
73
73
|
*/
|
|
74
|
-
incomingContext: OtelContext
|
|
74
|
+
incomingContext: OtelContext
|
|
75
75
|
/**
|
|
76
76
|
* Edge emulation mode for the matched route. 'page': the whole render tree
|
|
77
77
|
* exports as runtime 'edge' with the params-query target (Next renders edge
|
|
@@ -79,70 +79,70 @@ interface OtelState {
|
|
|
79
79
|
* and it parents on the incoming context (Next's node server keeps its own
|
|
80
80
|
* nodejs spans; the sandbox emits a stand-alone runHandler).
|
|
81
81
|
*/
|
|
82
|
-
edgeMode?: 'page' | 'handler'
|
|
82
|
+
edgeMode?: 'page' | 'handler'
|
|
83
83
|
/** NEXT_OTEL_VERBOSE=1 wrapper span (NextServer.getRequestHandler). */
|
|
84
|
-
verboseSpan?: OtelSpan
|
|
84
|
+
verboseSpan?: OtelSpan
|
|
85
85
|
/**
|
|
86
86
|
* The context a NEW child span parents under. Starts as rootContext; each
|
|
87
87
|
* withChildSpan pushes its own child context for the duration of `fn` so a
|
|
88
88
|
* nested withChildSpan (e.g. `resolve segment modules` inside `build component
|
|
89
89
|
* tree`) nests under its lexical parent, not the root. Restored on settle.
|
|
90
90
|
*/
|
|
91
|
-
currentContext: OtelContext
|
|
91
|
+
currentContext: OtelContext
|
|
92
92
|
/** The stamped display route pattern (`/pages/[param]/getServerSideProps`). */
|
|
93
|
-
route?: string
|
|
93
|
+
route?: string
|
|
94
94
|
/**
|
|
95
95
|
* A pages-router data fetcher errored or returned notFound and the fallback span set replaced the
|
|
96
96
|
* render span. Post-fallback render-internal leaves must not surface as root children - Next does not
|
|
97
97
|
* emit them there.
|
|
98
98
|
*/
|
|
99
|
-
pagesFallback?: boolean
|
|
99
|
+
pagesFallback?: boolean
|
|
100
100
|
/** A materialized pages-API handler ran (suppresses the start-response leaf). */
|
|
101
|
-
pagesApi?: boolean
|
|
101
|
+
pagesApi?: boolean
|
|
102
102
|
renderSpan?: {
|
|
103
|
-
span: OtelSpan
|
|
104
|
-
parentContext: OtelContext
|
|
105
|
-
spanContext: OtelContext
|
|
106
|
-
ended: boolean
|
|
103
|
+
span: OtelSpan
|
|
104
|
+
parentContext: OtelContext
|
|
105
|
+
spanContext: OtelContext
|
|
106
|
+
ended: boolean
|
|
107
107
|
/** markRenderSpanError already set an ERROR status; finish must keep it. */
|
|
108
|
-
errored?: boolean
|
|
108
|
+
errored?: boolean
|
|
109
109
|
/** `next.span_type` the span opened with (runtime label at end). */
|
|
110
|
-
spanType: string
|
|
110
|
+
spanType: string
|
|
111
111
|
/**
|
|
112
112
|
* Pages-router notFound/error fallback: Next replaces the route's render
|
|
113
113
|
* span with the fallback page's own spans (`/_error`, `/_not-found`). A
|
|
114
114
|
* discarded span is NEVER ended, so SimpleSpanProcessor never exports it
|
|
115
115
|
* (its children become orphans the suite's tree-builder filters out).
|
|
116
116
|
*/
|
|
117
|
-
discarded?: boolean
|
|
118
|
-
}
|
|
117
|
+
discarded?: boolean
|
|
118
|
+
}
|
|
119
119
|
componentTreeSpan?: {
|
|
120
|
-
span: OtelSpan
|
|
121
|
-
parentContext: OtelContext
|
|
122
|
-
spanContext: OtelContext
|
|
123
|
-
ended: boolean
|
|
124
|
-
}
|
|
120
|
+
span: OtelSpan
|
|
121
|
+
parentContext: OtelContext
|
|
122
|
+
spanContext: OtelContext
|
|
123
|
+
ended: boolean
|
|
124
|
+
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
/** The runtime label for a child span of the given next.span_type. */
|
|
128
128
|
function childRuntime(state: OtelState, spanType: string): SpanRuntime {
|
|
129
|
-
return state.edgeMode === 'page' && EDGE_SANDBOX_SPAN_TYPES.has(spanType) ? 'edge' : 'nodejs'
|
|
129
|
+
return state.edgeMode === 'page' && EDGE_SANDBOX_SPAN_TYPES.has(spanType) ? 'edge' : 'nodejs'
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
let cachedAppRoot: string | undefined
|
|
133
|
-
let spanEndDepth = 0
|
|
132
|
+
let cachedAppRoot: string | undefined
|
|
133
|
+
let spanEndDepth = 0
|
|
134
134
|
|
|
135
135
|
/** Called once at init so the tracer can resolve @opentelemetry/api from the app. */
|
|
136
136
|
export function setOtelAppRoot(root: string): void {
|
|
137
|
-
cachedAppRoot = root
|
|
137
|
+
cachedAppRoot = root
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
function api(): OtelApi | null {
|
|
141
|
-
return cachedAppRoot ? getOtelApi(cachedAppRoot) : null
|
|
141
|
+
return cachedAppRoot ? getOtelApi(cachedAppRoot) : null
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
function stateOf(unit: WorkUnit | undefined): OtelState | undefined {
|
|
145
|
-
return unit?.compat?.[OTEL_STATE] as OtelState | undefined
|
|
145
|
+
return unit?.compat?.[OTEL_STATE] as OtelState | undefined
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
@@ -152,34 +152,34 @@ function stateOf(unit: WorkUnit | undefined): OtelState | undefined {
|
|
|
152
152
|
* unavailable, no work unit is active, or a root is already open.
|
|
153
153
|
*/
|
|
154
154
|
export function startRootSpan(input: {
|
|
155
|
-
method: string
|
|
156
|
-
target: string
|
|
157
|
-
rsc: boolean
|
|
158
|
-
headers: Headers
|
|
155
|
+
method: string
|
|
156
|
+
target: string
|
|
157
|
+
rsc: boolean
|
|
158
|
+
headers: Headers
|
|
159
159
|
}): void {
|
|
160
|
-
const a = api()
|
|
161
|
-
if (!a) return
|
|
162
|
-
const unit = getWorkUnit()
|
|
163
|
-
if (!unit) return
|
|
164
|
-
unit.compat ??= {}
|
|
165
|
-
if (unit.compat[OTEL_STATE]) return
|
|
160
|
+
const a = api()
|
|
161
|
+
if (!a) return
|
|
162
|
+
const unit = getWorkUnit()
|
|
163
|
+
if (!unit) return
|
|
164
|
+
unit.compat ??= {}
|
|
165
|
+
if (unit.compat[OTEL_STATE]) return
|
|
166
166
|
|
|
167
167
|
// Extract incoming context (traceparent + any custom propagators, e.g. the
|
|
168
168
|
// test's x-custom sampler entry). The carrier is a plain header record.
|
|
169
|
-
const carrier: Record<string, string> = {}
|
|
169
|
+
const carrier: Record<string, string> = {}
|
|
170
170
|
input.headers.forEach((value, key) => {
|
|
171
|
-
carrier[key] = value
|
|
172
|
-
})
|
|
173
|
-
const incomingContext = a.propagation.extract(a.context.active(), carrier, headerGetter)
|
|
171
|
+
carrier[key] = value
|
|
172
|
+
})
|
|
173
|
+
const incomingContext = a.propagation.extract(a.context.active(), carrier, headerGetter)
|
|
174
174
|
|
|
175
|
-
const spanName = `${input.rsc ? 'RSC ' : ''}${input.method} ${input.target}
|
|
176
|
-
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
175
|
+
const spanName = `${input.rsc ? 'RSC ' : ''}${input.method} ${input.target}`
|
|
176
|
+
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
177
177
|
// NEXT_OTEL_VERBOSE=1: Next additionally emits the NextServer.getRequestHandler
|
|
178
178
|
// wrapper span between the incoming context and handleRequest. The verbose
|
|
179
179
|
// suite asserts its span_type + that it parents directly on the incoming
|
|
180
180
|
// traceparent while everything else nests below.
|
|
181
|
-
let verboseSpan: OtelSpan | undefined
|
|
182
|
-
let rootParentCtx = incomingContext
|
|
181
|
+
let verboseSpan: OtelSpan | undefined
|
|
182
|
+
let rootParentCtx = incomingContext
|
|
183
183
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
184
184
|
if (process.env.NEXT_OTEL_VERBOSE === '1') {
|
|
185
185
|
verboseSpan = tracer.startSpan(
|
|
@@ -192,8 +192,8 @@ export function startRootSpan(input: {
|
|
|
192
192
|
},
|
|
193
193
|
},
|
|
194
194
|
incomingContext,
|
|
195
|
-
)
|
|
196
|
-
rootParentCtx = a.trace.setSpan(incomingContext, verboseSpan)
|
|
195
|
+
)
|
|
196
|
+
rootParentCtx = a.trace.setSpan(incomingContext, verboseSpan)
|
|
197
197
|
}
|
|
198
198
|
const rootSpan = tracer.startSpan(
|
|
199
199
|
spanName,
|
|
@@ -208,8 +208,8 @@ export function startRootSpan(input: {
|
|
|
208
208
|
},
|
|
209
209
|
},
|
|
210
210
|
rootParentCtx,
|
|
211
|
-
)
|
|
212
|
-
const rootContext = a.trace.setSpan(rootParentCtx, rootSpan)
|
|
211
|
+
)
|
|
212
|
+
const rootContext = a.trace.setSpan(rootParentCtx, rootSpan)
|
|
213
213
|
const state: OtelState = {
|
|
214
214
|
api: a,
|
|
215
215
|
rootContext,
|
|
@@ -221,8 +221,8 @@ export function startRootSpan(input: {
|
|
|
221
221
|
incomingContext,
|
|
222
222
|
...(verboseSpan ? { verboseSpan } : {}),
|
|
223
223
|
currentContext: rootContext,
|
|
224
|
-
}
|
|
225
|
-
unit.compat[OTEL_STATE] = state
|
|
224
|
+
}
|
|
225
|
+
unit.compat[OTEL_STATE] = state
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
@@ -234,44 +234,44 @@ export function setRootSpanRoute(
|
|
|
234
234
|
route: string,
|
|
235
235
|
options: {
|
|
236
236
|
/** The matched route declared `runtime: 'edge'`. */
|
|
237
|
-
edge?: boolean
|
|
237
|
+
edge?: boolean
|
|
238
238
|
/** 'handler' for a route handler, 'page' otherwise. */
|
|
239
|
-
kind?: 'page' | 'handler'
|
|
239
|
+
kind?: 'page' | 'handler'
|
|
240
240
|
/** Resolved dynamic params (edge target emulation). */
|
|
241
|
-
params?: Record<string, string | string[]
|
|
241
|
+
params?: Record<string, string | string[]>
|
|
242
242
|
} = {},
|
|
243
243
|
): void {
|
|
244
|
-
const state = stateOf(getWorkUnit())
|
|
245
|
-
if (!state) return
|
|
246
|
-
state.route = route
|
|
247
|
-
const { rootSpan } = state
|
|
248
|
-
const name = `${state.rsc ? 'RSC ' : ''}${state.method} ${route}
|
|
249
|
-
rootSpan.setAttribute('next.route', route)
|
|
250
|
-
rootSpan.setAttribute('http.route', route)
|
|
251
|
-
rootSpan.setAttribute('next.span_name', name)
|
|
252
|
-
rootSpan.updateName(name)
|
|
253
|
-
if (!options.edge) return
|
|
254
|
-
state.edgeMode = options.kind === 'handler' ? 'handler' : 'page'
|
|
255
|
-
if (state.edgeMode !== 'page') return
|
|
244
|
+
const state = stateOf(getWorkUnit())
|
|
245
|
+
if (!state) return
|
|
246
|
+
state.route = route
|
|
247
|
+
const { rootSpan } = state
|
|
248
|
+
const name = `${state.rsc ? 'RSC ' : ''}${state.method} ${route}`
|
|
249
|
+
rootSpan.setAttribute('next.route', route)
|
|
250
|
+
rootSpan.setAttribute('http.route', route)
|
|
251
|
+
rootSpan.setAttribute('next.span_name', name)
|
|
252
|
+
rootSpan.updateName(name)
|
|
253
|
+
if (!options.edge) return
|
|
254
|
+
state.edgeMode = options.kind === 'handler' ? 'handler' : 'page'
|
|
255
|
+
if (state.edgeMode !== 'page') return
|
|
256
256
|
// A production start invokes an edge page through the sandbox with the resolved dynamic params
|
|
257
257
|
// appended as query params, so the sandbox-side handleRequest span reports them in its route. Mirror
|
|
258
258
|
// that. Always rebuilt from the ORIGINAL request target - the route is stamped twice (early
|
|
259
259
|
// pre-rewrite and late post-rewrite interceptors) and the params must not accumulate.
|
|
260
|
-
const [pathname = '', search = ''] = splitTarget(state.target)
|
|
261
|
-
const query = new URLSearchParams(search)
|
|
260
|
+
const [pathname = '', search = ''] = splitTarget(state.target)
|
|
261
|
+
const query = new URLSearchParams(search)
|
|
262
262
|
for (const [key, value] of Object.entries(options.params ?? {})) {
|
|
263
|
-
if (Array.isArray(value)) query.set(key, value.join('/'))
|
|
264
|
-
else query.set(key, value)
|
|
263
|
+
if (Array.isArray(value)) query.set(key, value.join('/'))
|
|
264
|
+
else query.set(key, value)
|
|
265
265
|
}
|
|
266
|
-
const queryText = query.toString()
|
|
266
|
+
const queryText = query.toString()
|
|
267
267
|
if (queryText) {
|
|
268
|
-
rootSpan.setAttribute('http.target', `${pathname}?${queryText}`)
|
|
268
|
+
rootSpan.setAttribute('http.target', `${pathname}?${queryText}`)
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
function splitTarget(target: string): [string, string] {
|
|
273
|
-
const index = target.indexOf('?')
|
|
274
|
-
return index === -1 ? [target, ''] : [target.slice(0, index), target.slice(index + 1)]
|
|
273
|
+
const index = target.indexOf('?')
|
|
274
|
+
return index === -1 ? [target, ''] : [target.slice(0, index), target.slice(index + 1)]
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
/**
|
|
@@ -280,21 +280,21 @@ function splitTarget(target: string): [string, string] {
|
|
|
280
280
|
* marked on the render span instead. Idempotent.
|
|
281
281
|
*/
|
|
282
282
|
export function endRootSpan(status: number): void {
|
|
283
|
-
const state = stateOf(getWorkUnit())
|
|
284
|
-
if (!state || state.rootEnded) return
|
|
285
|
-
state.rootEnded = true
|
|
286
|
-
const { api: a, rootSpan } = state
|
|
287
|
-
rootSpan.setAttribute('http.status_code', status)
|
|
283
|
+
const state = stateOf(getWorkUnit())
|
|
284
|
+
if (!state || state.rootEnded) return
|
|
285
|
+
state.rootEnded = true
|
|
286
|
+
const { api: a, rootSpan } = state
|
|
287
|
+
rootSpan.setAttribute('http.status_code', status)
|
|
288
288
|
if (status >= 500) {
|
|
289
|
-
rootSpan.setAttribute('error.type', String(status))
|
|
290
|
-
rootSpan.setStatus({ code: a.SpanStatusCode.ERROR })
|
|
289
|
+
rootSpan.setAttribute('error.type', String(status))
|
|
290
|
+
rootSpan.setStatus({ code: a.SpanStatusCode.ERROR })
|
|
291
291
|
} else {
|
|
292
|
-
rootSpan.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
292
|
+
rootSpan.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
293
293
|
}
|
|
294
|
-
endSpan(rootSpan, state.edgeMode === 'page' ? 'edge' : 'nodejs')
|
|
294
|
+
endSpan(rootSpan, state.edgeMode === 'page' ? 'edge' : 'nodejs')
|
|
295
295
|
if (state.verboseSpan) {
|
|
296
|
-
state.verboseSpan.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
297
|
-
endSpan(state.verboseSpan, 'nodejs')
|
|
296
|
+
state.verboseSpan.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
297
|
+
endSpan(state.verboseSpan, 'nodejs')
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
|
|
@@ -306,31 +306,31 @@ export function endRootSpan(status: number): void {
|
|
|
306
306
|
* already-ended 200 span to 500.
|
|
307
307
|
*/
|
|
308
308
|
export function endRootSpanIfUnclosed(fallbackStatus: number): void {
|
|
309
|
-
const state = stateOf(getWorkUnit())
|
|
310
|
-
if (!state || state.rootEnded) return
|
|
311
|
-
endRootSpan(fallbackStatus)
|
|
309
|
+
const state = stateOf(getWorkUnit())
|
|
310
|
+
if (!state || state.rootEnded) return
|
|
311
|
+
endRootSpan(fallbackStatus)
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
/** The active root span's spanContext. */
|
|
315
315
|
export function rootSpanContext(): { traceId: string; spanId: string } | undefined {
|
|
316
|
-
const state = stateOf(getWorkUnit())
|
|
317
|
-
if (!state) return undefined
|
|
318
|
-
const sc = state.rootSpan.spanContext()
|
|
319
|
-
return { traceId: sc.traceId, spanId: sc.spanId }
|
|
316
|
+
const state = stateOf(getWorkUnit())
|
|
317
|
+
if (!state) return undefined
|
|
318
|
+
const sc = state.rootSpan.spanContext()
|
|
319
|
+
return { traceId: sc.traceId, spanId: sc.spanId }
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
/** The stashed root OTel context (root span active). */
|
|
323
323
|
export function rootOtelContext(): { api: OtelApi; context: OtelContext } | undefined {
|
|
324
|
-
const state = stateOf(getWorkUnit())
|
|
325
|
-
if (!state) return undefined
|
|
326
|
-
return { api: state.api, context: state.rootContext }
|
|
324
|
+
const state = stateOf(getWorkUnit())
|
|
325
|
+
if (!state) return undefined
|
|
326
|
+
return { api: state.api, context: state.rootContext }
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
/** The active render context, for client trace propagation. */
|
|
330
330
|
export function activeOtelContext(): { api: OtelApi; context: OtelContext } | undefined {
|
|
331
|
-
const state = stateOf(getWorkUnit())
|
|
332
|
-
if (!state) return undefined
|
|
333
|
-
return { api: state.api, context: state.api.context.active() }
|
|
331
|
+
const state = stateOf(getWorkUnit())
|
|
332
|
+
if (!state) return undefined
|
|
333
|
+
return { api: state.api, context: state.api.context.active() }
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
/**
|
|
@@ -346,13 +346,13 @@ export function withChildSpan<T>(
|
|
|
346
346
|
fn: () => T,
|
|
347
347
|
options: { kind?: number; onError?: (span: OtelSpan, error: unknown) => void } = {},
|
|
348
348
|
): T {
|
|
349
|
-
const state = stateOf(getWorkUnit())
|
|
350
|
-
if (!state) return fn()
|
|
351
|
-
const { api: a } = state
|
|
349
|
+
const state = stateOf(getWorkUnit())
|
|
350
|
+
if (!state) return fn()
|
|
351
|
+
const { api: a } = state
|
|
352
352
|
// Parent under the lexically-enclosing span (currentContext), not always the
|
|
353
353
|
// root, so nested withChildSpan calls form the right tree.
|
|
354
|
-
const parentContext = state.currentContext
|
|
355
|
-
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
354
|
+
const parentContext = state.currentContext
|
|
355
|
+
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
356
356
|
const span = tracer.startSpan(
|
|
357
357
|
name,
|
|
358
358
|
{
|
|
@@ -364,42 +364,42 @@ export function withChildSpan<T>(
|
|
|
364
364
|
},
|
|
365
365
|
},
|
|
366
366
|
parentContext,
|
|
367
|
-
)
|
|
368
|
-
const childContext = a.trace.setSpan(parentContext, span)
|
|
369
|
-
state.currentContext = childContext
|
|
367
|
+
)
|
|
368
|
+
const childContext = a.trace.setSpan(parentContext, span)
|
|
369
|
+
state.currentContext = childContext
|
|
370
370
|
const settle = (error?: unknown) => {
|
|
371
371
|
// Restore the enclosing context so siblings parent correctly.
|
|
372
|
-
state.currentContext = parentContext
|
|
372
|
+
state.currentContext = parentContext
|
|
373
373
|
if (error !== undefined) {
|
|
374
|
-
if (options.onError) options.onError(span, error)
|
|
374
|
+
if (options.onError) options.onError(span, error)
|
|
375
375
|
else {
|
|
376
|
-
span.recordException(error)
|
|
377
|
-
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
376
|
+
span.recordException(error)
|
|
377
|
+
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
378
378
|
}
|
|
379
379
|
} else {
|
|
380
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
380
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
381
381
|
}
|
|
382
|
-
endSpan(span, childRuntime(state, spanType))
|
|
383
|
-
}
|
|
382
|
+
endSpan(span, childRuntime(state, spanType))
|
|
383
|
+
}
|
|
384
384
|
try {
|
|
385
|
-
const result = a.context.with(childContext, fn)
|
|
385
|
+
const result = a.context.with(childContext, fn)
|
|
386
386
|
if (isThenable(result)) {
|
|
387
387
|
return (result as PromiseLike<unknown>).then(
|
|
388
388
|
value => {
|
|
389
|
-
settle()
|
|
390
|
-
return value
|
|
389
|
+
settle()
|
|
390
|
+
return value
|
|
391
391
|
},
|
|
392
392
|
error => {
|
|
393
|
-
settle(error)
|
|
394
|
-
throw error
|
|
393
|
+
settle(error)
|
|
394
|
+
throw error
|
|
395
395
|
},
|
|
396
|
-
) as T
|
|
396
|
+
) as T
|
|
397
397
|
}
|
|
398
|
-
settle()
|
|
399
|
-
return result
|
|
398
|
+
settle()
|
|
399
|
+
return result
|
|
400
400
|
} catch (error) {
|
|
401
|
-
settle(error)
|
|
402
|
-
throw error
|
|
401
|
+
settle(error)
|
|
402
|
+
throw error
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
|
|
@@ -409,11 +409,11 @@ export function withRenderBodySpan<T>(
|
|
|
409
409
|
fn: () => T,
|
|
410
410
|
spanType: string = SPAN_TYPE.getBodyResult,
|
|
411
411
|
): T {
|
|
412
|
-
const state = stateOf(getWorkUnit())
|
|
413
|
-
if (!state) return fn()
|
|
414
|
-
const { api: a } = state
|
|
415
|
-
const parentContext = state.currentContext
|
|
416
|
-
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
412
|
+
const state = stateOf(getWorkUnit())
|
|
413
|
+
if (!state) return fn()
|
|
414
|
+
const { api: a } = state
|
|
415
|
+
const parentContext = state.currentContext
|
|
416
|
+
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
417
417
|
const span = tracer.startSpan(
|
|
418
418
|
name,
|
|
419
419
|
{
|
|
@@ -425,63 +425,63 @@ export function withRenderBodySpan<T>(
|
|
|
425
425
|
},
|
|
426
426
|
},
|
|
427
427
|
parentContext,
|
|
428
|
-
)
|
|
429
|
-
const spanContext = a.trace.setSpan(parentContext, span)
|
|
430
|
-
const previousRenderSpan = state.renderSpan
|
|
431
|
-
state.renderSpan = { span, parentContext, spanContext, ended: false, spanType }
|
|
432
|
-
state.currentContext = spanContext
|
|
428
|
+
)
|
|
429
|
+
const spanContext = a.trace.setSpan(parentContext, span)
|
|
430
|
+
const previousRenderSpan = state.renderSpan
|
|
431
|
+
state.renderSpan = { span, parentContext, spanContext, ended: false, spanType }
|
|
432
|
+
state.currentContext = spanContext
|
|
433
433
|
|
|
434
434
|
const finish = (error?: unknown) => {
|
|
435
|
-
const current = state.renderSpan
|
|
436
|
-
if (current?.span !== span || current.ended) return
|
|
437
|
-
current.ended = true
|
|
438
|
-
endComponentTreeSpan(state)
|
|
435
|
+
const current = state.renderSpan
|
|
436
|
+
if (current?.span !== span || current.ended) return
|
|
437
|
+
current.ended = true
|
|
438
|
+
endComponentTreeSpan(state)
|
|
439
439
|
if (current.discarded) {
|
|
440
440
|
// Pages fallback replaced this span — leave it un-ended (never exported).
|
|
441
|
-
state.renderSpan = previousRenderSpan
|
|
442
|
-
if (state.currentContext === spanContext) state.currentContext = parentContext
|
|
443
|
-
return
|
|
441
|
+
state.renderSpan = previousRenderSpan
|
|
442
|
+
if (state.currentContext === spanContext) state.currentContext = parentContext
|
|
443
|
+
return
|
|
444
444
|
}
|
|
445
|
-
if (error !== undefined) markSpanError(a, span, error)
|
|
445
|
+
if (error !== undefined) markSpanError(a, span, error)
|
|
446
446
|
// A streaming (Suspense-boundary) error already stamped ERROR through
|
|
447
447
|
// markRenderSpanError — never downgrade it back to UNSET here.
|
|
448
448
|
else if (!current.errored && span.isRecording()) {
|
|
449
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
449
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
450
450
|
}
|
|
451
|
-
endSpan(span, childRuntime(state, spanType))
|
|
452
|
-
state.renderSpan = previousRenderSpan
|
|
453
|
-
if (state.currentContext === spanContext) state.currentContext = parentContext
|
|
454
|
-
}
|
|
451
|
+
endSpan(span, childRuntime(state, spanType))
|
|
452
|
+
state.renderSpan = previousRenderSpan
|
|
453
|
+
if (state.currentContext === spanContext) state.currentContext = parentContext
|
|
454
|
+
}
|
|
455
455
|
|
|
456
|
-
const queued = queueAfterTask(() => finish())
|
|
456
|
+
const queued = queueAfterTask(() => finish())
|
|
457
457
|
try {
|
|
458
|
-
const result = a.context.with(spanContext, fn)
|
|
458
|
+
const result = a.context.with(spanContext, fn)
|
|
459
459
|
if (isThenable(result)) {
|
|
460
460
|
return (result as PromiseLike<unknown>).then(
|
|
461
461
|
value => {
|
|
462
|
-
if (!queued) finish()
|
|
463
|
-
return value
|
|
462
|
+
if (!queued) finish()
|
|
463
|
+
return value
|
|
464
464
|
},
|
|
465
465
|
error => {
|
|
466
|
-
finish(error)
|
|
467
|
-
throw error
|
|
466
|
+
finish(error)
|
|
467
|
+
throw error
|
|
468
468
|
},
|
|
469
|
-
) as T
|
|
469
|
+
) as T
|
|
470
470
|
}
|
|
471
|
-
if (!queued) finish()
|
|
472
|
-
return result
|
|
471
|
+
if (!queued) finish()
|
|
472
|
+
return result
|
|
473
473
|
} catch (error) {
|
|
474
|
-
finish(error)
|
|
475
|
-
throw error
|
|
474
|
+
finish(error)
|
|
475
|
+
throw error
|
|
476
476
|
}
|
|
477
477
|
}
|
|
478
478
|
|
|
479
479
|
export function markRenderSpanError(error: unknown): void {
|
|
480
|
-
const state = stateOf(getWorkUnit())
|
|
481
|
-
const render = state?.renderSpan
|
|
482
|
-
if (!state || !render || render.ended) return
|
|
483
|
-
render.errored = true
|
|
484
|
-
markSpanError(state.api, render.span, error)
|
|
480
|
+
const state = stateOf(getWorkUnit())
|
|
481
|
+
const render = state?.renderSpan
|
|
482
|
+
if (!state || !render || render.ended) return
|
|
483
|
+
render.errored = true
|
|
484
|
+
markSpanError(state.api, render.span, error)
|
|
485
485
|
}
|
|
486
486
|
|
|
487
487
|
/**
|
|
@@ -496,7 +496,7 @@ export function withRouteHandlerSpan<T>(route: string, fn: () => T): T {
|
|
|
496
496
|
SPAN_TYPE.runHandler,
|
|
497
497
|
{ 'next.route': route },
|
|
498
498
|
fn,
|
|
499
|
-
)
|
|
499
|
+
)
|
|
500
500
|
}
|
|
501
501
|
|
|
502
502
|
function runHandlerSpan<T>(
|
|
@@ -505,12 +505,12 @@ function runHandlerSpan<T>(
|
|
|
505
505
|
attributes: Record<string, unknown>,
|
|
506
506
|
fn: () => T,
|
|
507
507
|
): T {
|
|
508
|
-
const state = stateOf(getWorkUnit())
|
|
509
|
-
if (!state) return fn()
|
|
510
|
-
const { api: a } = state
|
|
511
|
-
const edge = state.edgeMode === 'handler'
|
|
512
|
-
const parentContext = edge ? state.incomingContext : state.currentContext
|
|
513
|
-
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
508
|
+
const state = stateOf(getWorkUnit())
|
|
509
|
+
if (!state) return fn()
|
|
510
|
+
const { api: a } = state
|
|
511
|
+
const edge = state.edgeMode === 'handler'
|
|
512
|
+
const parentContext = edge ? state.incomingContext : state.currentContext
|
|
513
|
+
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
514
514
|
const span = tracer.startSpan(
|
|
515
515
|
name,
|
|
516
516
|
{
|
|
@@ -522,39 +522,39 @@ function runHandlerSpan<T>(
|
|
|
522
522
|
},
|
|
523
523
|
},
|
|
524
524
|
parentContext,
|
|
525
|
-
)
|
|
526
|
-
const spanContext = a.trace.setSpan(parentContext, span)
|
|
527
|
-
const previousContext = state.currentContext
|
|
528
|
-
state.currentContext = spanContext
|
|
525
|
+
)
|
|
526
|
+
const spanContext = a.trace.setSpan(parentContext, span)
|
|
527
|
+
const previousContext = state.currentContext
|
|
528
|
+
state.currentContext = spanContext
|
|
529
529
|
const settle = (error?: unknown) => {
|
|
530
|
-
state.currentContext = previousContext
|
|
530
|
+
state.currentContext = previousContext
|
|
531
531
|
if (error !== undefined) {
|
|
532
|
-
span.recordException(error)
|
|
533
|
-
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
532
|
+
span.recordException(error)
|
|
533
|
+
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
534
534
|
} else {
|
|
535
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
535
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
536
536
|
}
|
|
537
|
-
endSpan(span, edge ? 'edge' : 'nodejs')
|
|
538
|
-
}
|
|
537
|
+
endSpan(span, edge ? 'edge' : 'nodejs')
|
|
538
|
+
}
|
|
539
539
|
try {
|
|
540
|
-
const result = a.context.with(spanContext, fn)
|
|
540
|
+
const result = a.context.with(spanContext, fn)
|
|
541
541
|
if (isThenable(result)) {
|
|
542
542
|
return (result as PromiseLike<unknown>).then(
|
|
543
543
|
value => {
|
|
544
|
-
settle()
|
|
545
|
-
return value
|
|
544
|
+
settle()
|
|
545
|
+
return value
|
|
546
546
|
},
|
|
547
547
|
error => {
|
|
548
|
-
settle(error)
|
|
549
|
-
throw error
|
|
548
|
+
settle(error)
|
|
549
|
+
throw error
|
|
550
550
|
},
|
|
551
|
-
) as T
|
|
551
|
+
) as T
|
|
552
552
|
}
|
|
553
|
-
settle()
|
|
554
|
-
return result
|
|
553
|
+
settle()
|
|
554
|
+
return result
|
|
555
555
|
} catch (error) {
|
|
556
|
-
settle(error)
|
|
557
|
-
throw error
|
|
556
|
+
settle(error)
|
|
557
|
+
throw error
|
|
558
558
|
}
|
|
559
559
|
}
|
|
560
560
|
|
|
@@ -566,10 +566,10 @@ function runHandlerSpan<T>(
|
|
|
566
566
|
* start-response leaf is suppressed for the rest of the request.
|
|
567
567
|
*/
|
|
568
568
|
export function withPagesApiHandlerSpan<T>(route: string, fn: () => T): T {
|
|
569
|
-
const state = stateOf(getWorkUnit())
|
|
570
|
-
if (state) state.pagesApi = true
|
|
571
|
-
const name = `executing api route (pages) ${route}
|
|
572
|
-
return runHandlerSpan(name, SPAN_TYPE.nodeRunHandler, {}, fn)
|
|
569
|
+
const state = stateOf(getWorkUnit())
|
|
570
|
+
if (state) state.pagesApi = true
|
|
571
|
+
const name = `executing api route (pages) ${route}`
|
|
572
|
+
return runHandlerSpan(name, SPAN_TYPE.nodeRunHandler, {}, fn)
|
|
573
573
|
}
|
|
574
574
|
|
|
575
575
|
/**
|
|
@@ -586,13 +586,13 @@ export function withPagesDataSpan<T>(
|
|
|
586
586
|
kind: 'getServerSideProps' | 'getStaticProps',
|
|
587
587
|
fn: () => T,
|
|
588
588
|
): T {
|
|
589
|
-
const state = stateOf(getWorkUnit())
|
|
590
|
-
const route = state?.route
|
|
591
|
-
if (!state || !route) return fn()
|
|
592
|
-
const { api: a } = state
|
|
589
|
+
const state = stateOf(getWorkUnit())
|
|
590
|
+
const route = state?.route
|
|
591
|
+
if (!state || !route) return fn()
|
|
592
|
+
const { api: a } = state
|
|
593
593
|
const spanType =
|
|
594
|
-
kind === 'getServerSideProps' ? SPAN_TYPE.getServerSideProps : SPAN_TYPE.getStaticProps
|
|
595
|
-
const name = `${kind} ${route}
|
|
594
|
+
kind === 'getServerSideProps' ? SPAN_TYPE.getServerSideProps : SPAN_TYPE.getStaticProps
|
|
595
|
+
const name = `${kind} ${route}`
|
|
596
596
|
const span = a.trace.getTracer('next.js', '0.0.1').startSpan(
|
|
597
597
|
name,
|
|
598
598
|
{
|
|
@@ -604,38 +604,38 @@ export function withPagesDataSpan<T>(
|
|
|
604
604
|
},
|
|
605
605
|
},
|
|
606
606
|
state.rootContext,
|
|
607
|
-
)
|
|
607
|
+
)
|
|
608
608
|
const settle = (error: unknown, result: unknown) => {
|
|
609
609
|
if (error !== undefined) {
|
|
610
|
-
markSpanError(a, span, error)
|
|
611
|
-
emitPagesErrorFallbackSpans(state, route)
|
|
610
|
+
markSpanError(a, span, error)
|
|
611
|
+
emitPagesErrorFallbackSpans(state, route)
|
|
612
612
|
} else {
|
|
613
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
613
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
614
614
|
if ((result as { notFound?: boolean } | null | undefined)?.notFound) {
|
|
615
|
-
emitPagesNotFoundFallbackSpans(state, route)
|
|
615
|
+
emitPagesNotFoundFallbackSpans(state, route)
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
|
-
endSpan(span, childRuntime(state, spanType))
|
|
619
|
-
}
|
|
618
|
+
endSpan(span, childRuntime(state, spanType))
|
|
619
|
+
}
|
|
620
620
|
try {
|
|
621
|
-
const result = fn()
|
|
621
|
+
const result = fn()
|
|
622
622
|
if (isThenable(result)) {
|
|
623
623
|
return (result as PromiseLike<unknown>).then(
|
|
624
624
|
value => {
|
|
625
|
-
settle(undefined, value)
|
|
626
|
-
return value
|
|
625
|
+
settle(undefined, value)
|
|
626
|
+
return value
|
|
627
627
|
},
|
|
628
628
|
(error: unknown) => {
|
|
629
|
-
settle(error ?? new Error('getServerSideProps error'), undefined)
|
|
630
|
-
throw error
|
|
629
|
+
settle(error ?? new Error('getServerSideProps error'), undefined)
|
|
630
|
+
throw error
|
|
631
631
|
},
|
|
632
|
-
) as T
|
|
632
|
+
) as T
|
|
633
633
|
}
|
|
634
|
-
settle(undefined, result)
|
|
635
|
-
return result
|
|
634
|
+
settle(undefined, result)
|
|
635
|
+
return result
|
|
636
636
|
} catch (error) {
|
|
637
|
-
settle(error ?? new Error('getServerSideProps error'), undefined)
|
|
638
|
-
throw error
|
|
637
|
+
settle(error ?? new Error('getServerSideProps error'), undefined)
|
|
638
|
+
throw error
|
|
639
639
|
}
|
|
640
640
|
}
|
|
641
641
|
|
|
@@ -646,7 +646,7 @@ function emitRootLeafSpan(
|
|
|
646
646
|
spanType: string,
|
|
647
647
|
attributes: Record<string, unknown>,
|
|
648
648
|
): void {
|
|
649
|
-
const { api: a } = state
|
|
649
|
+
const { api: a } = state
|
|
650
650
|
const span = a.trace.getTracer('next.js', '0.0.1').startSpan(
|
|
651
651
|
name,
|
|
652
652
|
{
|
|
@@ -658,41 +658,41 @@ function emitRootLeafSpan(
|
|
|
658
658
|
},
|
|
659
659
|
},
|
|
660
660
|
state.rootContext,
|
|
661
|
-
)
|
|
662
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
663
|
-
endSpan(span, 'nodejs')
|
|
661
|
+
)
|
|
662
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
663
|
+
endSpan(span, 'nodejs')
|
|
664
664
|
}
|
|
665
665
|
|
|
666
666
|
/** Discard the route's open render span (see withPagesDataSpan). */
|
|
667
667
|
function discardRenderSpan(state: OtelState): void {
|
|
668
|
-
state.pagesFallback = true
|
|
669
|
-
if (state.renderSpan && !state.renderSpan.ended) state.renderSpan.discarded = true
|
|
668
|
+
state.pagesFallback = true
|
|
669
|
+
if (state.renderSpan && !state.renderSpan.ended) state.renderSpan.discarded = true
|
|
670
670
|
}
|
|
671
671
|
|
|
672
672
|
// gSSP threw: Next renders `/_error` (its own renderDocument span), resolves
|
|
673
673
|
// `/_error`, probes `/500` twice (prod), and the route resolve already fired.
|
|
674
674
|
function emitPagesErrorFallbackSpans(state: OtelState, _route: string): void {
|
|
675
|
-
discardRenderSpan(state)
|
|
675
|
+
discardRenderSpan(state)
|
|
676
676
|
emitRootLeafSpan(state, 'render route (pages) /_error', SPAN_TYPE.renderDocument, {
|
|
677
677
|
'next.route': '/_error',
|
|
678
|
-
})
|
|
678
|
+
})
|
|
679
679
|
emitRootLeafSpan(state, 'resolve page components', SPAN_TYPE.findPageComponents, {
|
|
680
680
|
'next.route': '/_error',
|
|
681
|
-
})
|
|
681
|
+
})
|
|
682
682
|
for (let i = 0; i < 2; i += 1) {
|
|
683
683
|
emitRootLeafSpan(state, 'resolve page components', SPAN_TYPE.findPageComponents, {
|
|
684
684
|
'next.route': '/500',
|
|
685
|
-
})
|
|
685
|
+
})
|
|
686
686
|
}
|
|
687
687
|
}
|
|
688
688
|
|
|
689
689
|
// gSSP returned { notFound: true }: Next serves the prerendered `/_not-found`
|
|
690
690
|
// (prod: a findPageComponents probe only, no render span).
|
|
691
691
|
function emitPagesNotFoundFallbackSpans(state: OtelState, _route: string): void {
|
|
692
|
-
discardRenderSpan(state)
|
|
692
|
+
discardRenderSpan(state)
|
|
693
693
|
emitRootLeafSpan(state, 'resolve page components', SPAN_TYPE.findPageComponents, {
|
|
694
694
|
'next.route': '/_not-found',
|
|
695
|
-
})
|
|
695
|
+
})
|
|
696
696
|
}
|
|
697
697
|
|
|
698
698
|
/**
|
|
@@ -702,9 +702,9 @@ function emitPagesNotFoundFallbackSpans(state: OtelState, _route: string): void
|
|
|
702
702
|
* pipes from the node server even for edge routes.
|
|
703
703
|
*/
|
|
704
704
|
export function emitStartResponseSpan(): void {
|
|
705
|
-
const state = stateOf(getWorkUnit())
|
|
706
|
-
if (state?.pagesFallback || state?.pagesApi) return
|
|
707
|
-
emitNodeLeafSpan('start response', SPAN_TYPE.startResponse, {})
|
|
705
|
+
const state = stateOf(getWorkUnit())
|
|
706
|
+
if (state?.pagesFallback || state?.pagesApi) return
|
|
707
|
+
emitNodeLeafSpan('start response', SPAN_TYPE.startResponse, {})
|
|
708
708
|
}
|
|
709
709
|
|
|
710
710
|
/**
|
|
@@ -714,11 +714,11 @@ export function emitStartResponseSpan(): void {
|
|
|
714
714
|
* emitted for page renders, matching Next.
|
|
715
715
|
*/
|
|
716
716
|
export function emitClientComponentLoadingSpan(count: number): void {
|
|
717
|
-
const state = stateOf(getWorkUnit())
|
|
718
|
-
if (!state?.renderSpan || state.renderSpan.ended) return
|
|
717
|
+
const state = stateOf(getWorkUnit())
|
|
718
|
+
if (!state?.renderSpan || state.renderSpan.ended) return
|
|
719
719
|
emitNodeLeafSpan(SPAN_TYPE.clientComponentLoading, SPAN_TYPE.clientComponentLoading, {
|
|
720
720
|
'next.clientComponentLoadCount': count,
|
|
721
|
-
})
|
|
721
|
+
})
|
|
722
722
|
}
|
|
723
723
|
|
|
724
724
|
function emitNodeLeafSpan(
|
|
@@ -726,11 +726,11 @@ function emitNodeLeafSpan(
|
|
|
726
726
|
spanType: string,
|
|
727
727
|
attributes: Record<string, unknown>,
|
|
728
728
|
): void {
|
|
729
|
-
const state = stateOf(getWorkUnit())
|
|
730
|
-
if (!state) return
|
|
731
|
-
const { api: a } = state
|
|
732
|
-
const render = state.renderSpan
|
|
733
|
-
const parentContext = render && !render.ended ? render.spanContext : state.rootContext
|
|
729
|
+
const state = stateOf(getWorkUnit())
|
|
730
|
+
if (!state) return
|
|
731
|
+
const { api: a } = state
|
|
732
|
+
const render = state.renderSpan
|
|
733
|
+
const parentContext = render && !render.ended ? render.spanContext : state.rootContext
|
|
734
734
|
const span = a.trace.getTracer('next.js', '0.0.1').startSpan(
|
|
735
735
|
name,
|
|
736
736
|
{
|
|
@@ -742,9 +742,9 @@ function emitNodeLeafSpan(
|
|
|
742
742
|
},
|
|
743
743
|
},
|
|
744
744
|
parentContext,
|
|
745
|
-
)
|
|
746
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
747
|
-
endSpan(span, 'nodejs')
|
|
745
|
+
)
|
|
746
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
747
|
+
endSpan(span, 'nodejs')
|
|
748
748
|
}
|
|
749
749
|
|
|
750
750
|
/**
|
|
@@ -757,23 +757,23 @@ function emitNodeLeafSpan(
|
|
|
757
757
|
* unavailable. Does not require an open work-unit root span.
|
|
758
758
|
*/
|
|
759
759
|
export function withMiddlewareSpan<T>(request: Request, fn: () => T): T {
|
|
760
|
-
const a = api()
|
|
761
|
-
if (!a) return fn()
|
|
762
|
-
const method = request.method.toUpperCase()
|
|
763
|
-
let target = ''
|
|
760
|
+
const a = api()
|
|
761
|
+
if (!a) return fn()
|
|
762
|
+
const method = request.method.toUpperCase()
|
|
763
|
+
let target = ''
|
|
764
764
|
try {
|
|
765
|
-
const url = new URL(request.url)
|
|
766
|
-
target = url.pathname + url.search
|
|
765
|
+
const url = new URL(request.url)
|
|
766
|
+
target = url.pathname + url.search
|
|
767
767
|
} catch {
|
|
768
|
-
target = request.url
|
|
768
|
+
target = request.url
|
|
769
769
|
}
|
|
770
|
-
const carrier: Record<string, string> = {}
|
|
770
|
+
const carrier: Record<string, string> = {}
|
|
771
771
|
request.headers.forEach((value, key) => {
|
|
772
|
-
carrier[key] = value
|
|
773
|
-
})
|
|
774
|
-
const parentCtx = a.propagation.extract(a.context.active(), carrier, headerGetter)
|
|
775
|
-
const name = `middleware ${method}
|
|
776
|
-
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
772
|
+
carrier[key] = value
|
|
773
|
+
})
|
|
774
|
+
const parentCtx = a.propagation.extract(a.context.active(), carrier, headerGetter)
|
|
775
|
+
const name = `middleware ${method}`
|
|
776
|
+
const tracer = a.trace.getTracer('next.js', '0.0.1')
|
|
777
777
|
const span = tracer.startSpan(
|
|
778
778
|
name,
|
|
779
779
|
{
|
|
@@ -785,39 +785,39 @@ export function withMiddlewareSpan<T>(request: Request, fn: () => T): T {
|
|
|
785
785
|
},
|
|
786
786
|
},
|
|
787
787
|
parentCtx,
|
|
788
|
-
)
|
|
789
|
-
const spanCtx = a.trace.setSpan(parentCtx, span)
|
|
788
|
+
)
|
|
789
|
+
const spanCtx = a.trace.setSpan(parentCtx, span)
|
|
790
790
|
const settle = (error?: unknown) => {
|
|
791
791
|
if (error !== undefined) {
|
|
792
|
-
span.recordException(error)
|
|
793
|
-
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
792
|
+
span.recordException(error)
|
|
793
|
+
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
794
794
|
} else {
|
|
795
|
-
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
795
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET })
|
|
796
796
|
}
|
|
797
797
|
// Middleware always runs in the edge runtime in Next; pnext's proxy runner
|
|
798
798
|
// already wraps the handler in withRouteRuntime('edge') — the explicit tag
|
|
799
799
|
// makes the exported runtime deterministic regardless of settle timing.
|
|
800
|
-
endSpan(span, 'edge')
|
|
801
|
-
}
|
|
800
|
+
endSpan(span, 'edge')
|
|
801
|
+
}
|
|
802
802
|
try {
|
|
803
|
-
const result = a.context.with(spanCtx, fn)
|
|
803
|
+
const result = a.context.with(spanCtx, fn)
|
|
804
804
|
if (isThenable(result)) {
|
|
805
805
|
return (result as PromiseLike<unknown>).then(
|
|
806
806
|
value => {
|
|
807
|
-
settle()
|
|
808
|
-
return value
|
|
807
|
+
settle()
|
|
808
|
+
return value
|
|
809
809
|
},
|
|
810
810
|
error => {
|
|
811
|
-
settle(error)
|
|
812
|
-
throw error
|
|
811
|
+
settle(error)
|
|
812
|
+
throw error
|
|
813
813
|
},
|
|
814
|
-
) as T
|
|
814
|
+
) as T
|
|
815
815
|
}
|
|
816
|
-
settle()
|
|
817
|
-
return result
|
|
816
|
+
settle()
|
|
817
|
+
return result
|
|
818
818
|
} catch (error) {
|
|
819
|
-
settle(error)
|
|
820
|
-
throw error
|
|
819
|
+
settle(error)
|
|
820
|
+
throw error
|
|
821
821
|
}
|
|
822
822
|
}
|
|
823
823
|
|
|
@@ -829,10 +829,10 @@ export function emitLeafSpan(
|
|
|
829
829
|
kind?: number,
|
|
830
830
|
): void {
|
|
831
831
|
if (spanType === SPAN_TYPE.getLayoutOrPageModule) {
|
|
832
|
-
emitSegmentSpan(name, spanType, attributes, kind)
|
|
833
|
-
return
|
|
832
|
+
emitSegmentSpan(name, spanType, attributes, kind)
|
|
833
|
+
return
|
|
834
834
|
}
|
|
835
|
-
withChildSpan(name, spanType, attributes, () => undefined, kind !== undefined ? { kind } : {})
|
|
835
|
+
withChildSpan(name, spanType, attributes, () => undefined, kind !== undefined ? { kind } : {})
|
|
836
836
|
}
|
|
837
837
|
|
|
838
838
|
function emitSegmentSpan(
|
|
@@ -841,28 +841,28 @@ function emitSegmentSpan(
|
|
|
841
841
|
attributes: Record<string, unknown>,
|
|
842
842
|
kind?: number,
|
|
843
843
|
): void {
|
|
844
|
-
const state = stateOf(getWorkUnit())
|
|
845
|
-
if (state?.pagesFallback) return
|
|
844
|
+
const state = stateOf(getWorkUnit())
|
|
845
|
+
if (state?.pagesFallback) return
|
|
846
846
|
if (!state?.renderSpan || state.renderSpan.ended) {
|
|
847
|
-
withChildSpan(name, spanType, attributes, () => undefined, kind !== undefined ? { kind } : {})
|
|
848
|
-
return
|
|
847
|
+
withChildSpan(name, spanType, attributes, () => undefined, kind !== undefined ? { kind } : {})
|
|
848
|
+
return
|
|
849
849
|
}
|
|
850
|
-
const tree = ensureComponentTreeSpan(state)
|
|
851
|
-
const previous = state.currentContext
|
|
852
|
-
state.currentContext = tree.spanContext
|
|
850
|
+
const tree = ensureComponentTreeSpan(state)
|
|
851
|
+
const previous = state.currentContext
|
|
852
|
+
state.currentContext = tree.spanContext
|
|
853
853
|
try {
|
|
854
|
-
withChildSpan(name, spanType, attributes, () => undefined, kind !== undefined ? { kind } : {})
|
|
854
|
+
withChildSpan(name, spanType, attributes, () => undefined, kind !== undefined ? { kind } : {})
|
|
855
855
|
} finally {
|
|
856
|
-
state.currentContext = previous
|
|
856
|
+
state.currentContext = previous
|
|
857
857
|
}
|
|
858
858
|
}
|
|
859
859
|
|
|
860
860
|
function ensureComponentTreeSpan(state: OtelState) {
|
|
861
|
-
const current = state.componentTreeSpan
|
|
862
|
-
if (current && !current.ended) return current
|
|
863
|
-
const { api: a } = state
|
|
864
|
-
const parentContext = state.renderSpan?.spanContext ?? state.currentContext
|
|
865
|
-
const name = 'build component tree'
|
|
861
|
+
const current = state.componentTreeSpan
|
|
862
|
+
if (current && !current.ended) return current
|
|
863
|
+
const { api: a } = state
|
|
864
|
+
const parentContext = state.renderSpan?.spanContext ?? state.currentContext
|
|
865
|
+
const name = 'build component tree'
|
|
866
866
|
const span = a.trace.getTracer('next.js', '0.0.1').startSpan(
|
|
867
867
|
name,
|
|
868
868
|
{
|
|
@@ -873,72 +873,72 @@ function ensureComponentTreeSpan(state: OtelState) {
|
|
|
873
873
|
},
|
|
874
874
|
},
|
|
875
875
|
parentContext,
|
|
876
|
-
)
|
|
877
|
-
const spanContext = a.trace.setSpan(parentContext, span)
|
|
878
|
-
const next = { span, parentContext, spanContext, ended: false }
|
|
879
|
-
state.componentTreeSpan = next
|
|
880
|
-
return next
|
|
876
|
+
)
|
|
877
|
+
const spanContext = a.trace.setSpan(parentContext, span)
|
|
878
|
+
const next = { span, parentContext, spanContext, ended: false }
|
|
879
|
+
state.componentTreeSpan = next
|
|
880
|
+
return next
|
|
881
881
|
}
|
|
882
882
|
|
|
883
883
|
function endComponentTreeSpan(state: OtelState): void {
|
|
884
|
-
const tree = state.componentTreeSpan
|
|
885
|
-
if (!tree || tree.ended) return
|
|
886
|
-
tree.ended = true
|
|
887
|
-
tree.span.setStatus({ code: state.api.SpanStatusCode.UNSET })
|
|
888
|
-
endSpan(tree.span, childRuntime(state, SPAN_TYPE.createComponentTree))
|
|
889
|
-
if (state.currentContext === tree.spanContext) state.currentContext = tree.parentContext
|
|
884
|
+
const tree = state.componentTreeSpan
|
|
885
|
+
if (!tree || tree.ended) return
|
|
886
|
+
tree.ended = true
|
|
887
|
+
tree.span.setStatus({ code: state.api.SpanStatusCode.UNSET })
|
|
888
|
+
endSpan(tree.span, childRuntime(state, SPAN_TYPE.createComponentTree))
|
|
889
|
+
if (state.currentContext === tree.spanContext) state.currentContext = tree.parentContext
|
|
890
890
|
}
|
|
891
891
|
|
|
892
892
|
const headerGetter = {
|
|
893
893
|
keys(carrier: Record<string, string>): string[] {
|
|
894
|
-
return Object.keys(carrier)
|
|
894
|
+
return Object.keys(carrier)
|
|
895
895
|
},
|
|
896
896
|
get(carrier: Record<string, string>, key: string): string | undefined {
|
|
897
|
-
return carrier[key.toLowerCase()] ?? carrier[key]
|
|
897
|
+
return carrier[key.toLowerCase()] ?? carrier[key]
|
|
898
898
|
},
|
|
899
|
-
}
|
|
899
|
+
}
|
|
900
900
|
|
|
901
901
|
/** Setter for propagation.inject into a plain record carrier. */
|
|
902
902
|
export const carrierSetter = {
|
|
903
903
|
set(carrier: Record<string, string>, key: string, value: string): void {
|
|
904
|
-
carrier[key] = value
|
|
904
|
+
carrier[key] = value
|
|
905
905
|
},
|
|
906
|
-
}
|
|
906
|
+
}
|
|
907
907
|
|
|
908
908
|
function errorMessage(error: unknown): string {
|
|
909
|
-
if (error instanceof Error) return error.message
|
|
910
|
-
return String(error)
|
|
909
|
+
if (error instanceof Error) return error.message
|
|
910
|
+
return String(error)
|
|
911
911
|
}
|
|
912
912
|
|
|
913
913
|
function markSpanError(api: OtelApi, span: OtelSpan, error: unknown): void {
|
|
914
|
-
span.setAttribute('error.type', error instanceof Error ? error.name : typeof error)
|
|
915
|
-
span.recordException(error)
|
|
916
|
-
span.setStatus({ code: api.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
914
|
+
span.setAttribute('error.type', error instanceof Error ? error.name : typeof error)
|
|
915
|
+
span.recordException(error)
|
|
916
|
+
span.setStatus({ code: api.SpanStatusCode.ERROR, message: errorMessage(error) })
|
|
917
917
|
}
|
|
918
918
|
|
|
919
919
|
export function otelExportInProgress(): boolean {
|
|
920
|
-
return spanEndDepth > 0
|
|
920
|
+
return spanEndDepth > 0
|
|
921
921
|
}
|
|
922
922
|
|
|
923
923
|
function endSpan(span: OtelSpan, runtime?: SpanRuntime): void {
|
|
924
|
-
spanEndDepth
|
|
924
|
+
spanEndDepth++
|
|
925
925
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
926
|
-
const previousRuntime = process.env.NEXT_RUNTIME
|
|
926
|
+
const previousRuntime = process.env.NEXT_RUNTIME
|
|
927
927
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
928
|
-
if (runtime) process.env.NEXT_RUNTIME = runtime
|
|
928
|
+
if (runtime) process.env.NEXT_RUNTIME = runtime
|
|
929
929
|
try {
|
|
930
|
-
span.end()
|
|
930
|
+
span.end()
|
|
931
931
|
} finally {
|
|
932
932
|
if (runtime) {
|
|
933
933
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
934
|
-
if (previousRuntime === undefined) delete process.env.NEXT_RUNTIME
|
|
934
|
+
if (previousRuntime === undefined) delete process.env.NEXT_RUNTIME
|
|
935
935
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
936
|
-
else process.env.NEXT_RUNTIME = previousRuntime
|
|
936
|
+
else process.env.NEXT_RUNTIME = previousRuntime
|
|
937
937
|
}
|
|
938
|
-
spanEndDepth
|
|
938
|
+
spanEndDepth--
|
|
939
939
|
}
|
|
940
940
|
}
|
|
941
941
|
|
|
942
942
|
function isThenable(value: unknown): value is PromiseLike<unknown> {
|
|
943
|
-
return typeof (value as { then?: unknown } | null | undefined)?.then === 'function'
|
|
943
|
+
return typeof (value as { then?: unknown } | null | undefined)?.then === 'function'
|
|
944
944
|
}
|