Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions packages/next/src/build/templates/app-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getRevalidateReason } from '../../server/instrumentation/utils' with {
import {
getTracer,
SpanKind,
SpanStatusCode,
type Span,
} from '../../server/lib/trace/tracer' with { 'turbopack-transition': 'next-server-utility' }
import type { RequestMeta } from '../../server/request-meta'
Expand Down Expand Up @@ -191,6 +192,19 @@ function buildCompletedShellCacheKey(
)
}

let srcPage = 'VAR_DEFINITION_PAGE'
// turbopack doesn't normalize `/index` in the page name
// so we need to to process dynamic routes properly
// TODO: fix turbopack providing differing value from webpack
if (process.env.TURBOPACK) {
srcPage = srcPage.replace(/\/index$/, '') || '/'
} else if (srcPage === '/index') {
// we always normalize /index specifically
srcPage = '/'
}

const normalizedSrcPage = normalizeAppPath(srcPage)

export async function handler(
req: IncomingMessage,
res: ServerResponse,
Expand All @@ -208,17 +222,6 @@ export async function handler(
}
const isMinimalMode = Boolean(getRequestMeta(req, 'minimalMode'))

let srcPage = 'VAR_DEFINITION_PAGE'

// turbopack doesn't normalize `/index` in the page name
// so we need to to process dynamic routes properly
// TODO: fix turbopack providing differing value from webpack
if (process.env.TURBOPACK) {
srcPage = srcPage.replace(/\/index$/, '') || '/'
} else if (srcPage === '/index') {
// we always normalize /index specifically
srcPage = '/'
}
const multiZoneDraftMode = process.env
.__NEXT_MULTI_ZONE_DRAFT_MODE as any as boolean

Expand Down Expand Up @@ -258,8 +261,6 @@ export async function handler(
clientAssetToken,
} = prepareResult

const normalizedSrcPage = normalizeAppPath(srcPage)

let { isOnDemandRevalidate } = prepareResult

// We use the resolvedPathname instead of the parsedUrl.pathname because it
Expand Down Expand Up @@ -724,6 +725,16 @@ export async function handler(
'next.rsc': false,
})

if (res.statusCode && res.statusCode >= 500) {
// For 5xx status codes: SHOULD be set to 'Error' span status.
// x-ref: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
span.setStatus({
code: SpanStatusCode.ERROR,
})
// For span status 'Error', SHOULD set 'error.type' attribute.
span.setAttribute('error.type', res.statusCode.toString())
}

const rootSpanAttributes = tracer.getRootSpanAttributes()
// We were unable to get attributes, probably OTEL is not enabled
if (!rootSpanAttributes) {
Expand Down
111 changes: 64 additions & 47 deletions packages/next/src/build/templates/app-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import {
setRequestMeta,
type RequestMeta,
} from '../../server/request-meta'
import { getTracer, type Span, SpanKind } from '../../server/lib/trace/tracer'
import {
getTracer,
type Span,
SpanKind,
SpanStatusCode,
} from '../../server/lib/trace/tracer'
import { setManifestsSingleton } from '../../server/app-render/manifests-singleton'
import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'
import { NodeNextRequest, NodeNextResponse } from '../../server/base-http/node'
Expand Down Expand Up @@ -286,51 +291,6 @@ export async function handler(

try {
let parentSpan: Span | undefined
const invokeRouteModule = async (span?: Span) => {
return routeModule.handle(nextReq, context).finally(() => {
if (!span) return

span.setAttributes({
'http.status_code': res.statusCode,
'next.rsc': false,
})

const rootSpanAttributes = tracer.getRootSpanAttributes()
// We were unable to get attributes, probably OTEL is not enabled
if (!rootSpanAttributes) {
return
}

if (
rootSpanAttributes.get('next.span_type') !==
BaseServerSpan.handleRequest
) {
console.warn(
`Unexpected root span type '${rootSpanAttributes.get(
'next.span_type'
)}'. Please report this Next.js issue https://github.com/vercel/next.js`
)
return
}

const route = rootSpanAttributes.get('next.route') || normalizedSrcPage
const name = `${method} ${route}`

span.setAttributes({
'next.route': route,
'http.route': route,
'next.span_name': name,
})
span.updateName(name)

// Propagate http.route to the parent span if one exists (e.g.
// a platform-created HTTP span in adapter deployments).
if (parentSpan && parentSpan !== span) {
parentSpan.setAttribute('http.route', route)
parentSpan.updateName(name)
}
})
}

const handleResponse = async (currentSpan?: Span) => {
const responseGenerator: ResponseGenerator = async ({
Expand All @@ -350,7 +310,7 @@ export async function handler(
return null
}

const response = await invokeRouteModule(currentSpan)
const response = await routeModule.handle(nextReq, context)

;(req as any).fetchMetrics = (context.renderOpts as any).fetchMetrics
let pendingWaitUntil = context.renderOpts.pendingWaitUntil
Expand Down Expand Up @@ -447,6 +407,63 @@ export async function handler(
)
}
throw err
} finally {
// An IIFE to make early returns easier.
;(() => {
if (!currentSpan) {
return
}
currentSpan.setAttributes({
'http.status_code': res.statusCode,
'next.rsc': false,
})

if (res.statusCode && res.statusCode >= 500) {
// For 5xx status codes: SHOULD be set to 'Error' span status.
// x-ref: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
currentSpan.setStatus({
code: SpanStatusCode.ERROR,
})
// For span status 'Error', SHOULD set 'error.type' attribute.
currentSpan.setAttribute('error.type', res.statusCode.toString())
}

const rootSpanAttributes = tracer.getRootSpanAttributes()
// We were unable to get attributes, probably OTEL is not enabled
if (!rootSpanAttributes) {
return
}

if (
rootSpanAttributes.get('next.span_type') !==
BaseServerSpan.handleRequest
) {
console.warn(
`Unexpected root span type '${rootSpanAttributes.get(
'next.span_type'
)}'. Please report this Next.js issue https://github.com/vercel/next.js`
)
return
}

const route =
rootSpanAttributes.get('next.route') || normalizedSrcPage
const name = `${method} ${route}`

currentSpan.setAttributes({
'next.route': route,
'http.route': route,
'next.span_name': name,
})
currentSpan.updateName(name)

// Propagate http.route to the parent span if one exists (e.g.
// a platform-created HTTP span in adapter deployments).
if (parentSpan && parentSpan !== currentSpan) {
parentSpan.setAttribute('http.route', route)
parentSpan.updateName(name)
}
})()
}
}

Expand Down
17 changes: 16 additions & 1 deletion packages/next/src/build/templates/edge-ssr-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import * as pageMod from 'VAR_USERLAND'
import { setManifestsSingleton } from '../../server/app-render/manifests-singleton'
import * as cacheHandlers from '../../server/use-cache/handlers'
import { BaseServerSpan } from '../../server/lib/trace/constants'
import { getTracer, SpanKind, type Span } from '../../server/lib/trace/tracer'
import {
getTracer,
SpanKind,
SpanStatusCode,
type Span,
} from '../../server/lib/trace/tracer'
import { WebNextRequest, WebNextResponse } from '../../server/base-http/web'
import type { NextFetchEvent } from '../../server/web/spec-extension/fetch-event'
import type {
Expand Down Expand Up @@ -303,6 +308,16 @@ async function requestHandler(
'next.rsc': false,
})

if (finalStatus && finalStatus >= 500) {
// For 5xx status codes: SHOULD be set to 'Error' span status.
// x-ref: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
span.setStatus({
code: SpanStatusCode.ERROR,
})
// For span status 'Error', SHOULD set 'error.type' attribute.
span.setAttribute('error.type', finalStatus.toString())
}

const rootSpanAttributes = tracer.getRootSpanAttributes()
// We were unable to get attributes, probably OTEL is not enabled
if (!rootSpanAttributes) {
Expand Down
17 changes: 16 additions & 1 deletion packages/next/src/build/templates/edge-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import { WebNextRequest, WebNextResponse } from '../../server/base-http/web'
import type { NextFetchEvent } from '../../server/web/spec-extension/fetch-event'
import type RenderResult from '../../server/render-result'
import type { RenderResultMetadata } from '../../server/render-result'
import { getTracer, SpanKind, type Span } from '../../server/lib/trace/tracer'
import {
getTracer,
SpanKind,
SpanStatusCode,
type Span,
} from '../../server/lib/trace/tracer'
import { BaseServerSpan } from '../../server/lib/trace/constants'
import { HTML_CONTENT_TYPE_HEADER } from '../../lib/constants'
import type { RequestMeta } from '../../server/request-meta'
Expand Down Expand Up @@ -267,6 +272,16 @@ async function requestHandler(
'next.rsc': false,
})

if (finalStatus && finalStatus >= 500) {
// For 5xx status codes: SHOULD be set to 'Error' span status.
// x-ref: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
span.setStatus({
code: SpanStatusCode.ERROR,
})
// For span status 'Error', SHOULD set 'error.type' attribute.
span.setAttribute('error.type', finalStatus.toString())
}

const rootSpanAttributes = tracer.getRootSpanAttributes()
// We were unable to get attributes, probably OTEL is not enabled
if (!rootSpanAttributes) {
Expand Down
16 changes: 15 additions & 1 deletion packages/next/src/build/templates/pages-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { hoist } from './helpers'

// Import the userland code.
import * as userland from 'VAR_USERLAND'
import { getTracer, SpanKind } from '../../server/lib/trace/tracer'
import {
getTracer,
SpanKind,
SpanStatusCode,
} from '../../server/lib/trace/tracer'
import { BaseServerSpan } from '../../server/lib/trace/constants'
import type { InstrumentationOnRequestError } from '../../server/instrumentation/types'
import {
Expand Down Expand Up @@ -120,6 +124,16 @@ export async function handler(
'next.rsc': false,
})

if (res.statusCode && res.statusCode >= 500) {
// For 5xx status codes: SHOULD be set to 'Error' span status.
// x-ref: https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
span.setStatus({
code: SpanStatusCode.ERROR,
})
// For span status 'Error', SHOULD set 'error.type' attribute.
span.setAttribute('error.type', res.statusCode.toString())
}

const rootSpanAttributes = tracer.getRootSpanAttributes()
// We were unable to get attributes, probably OTEL is not enabled
if (!rootSpanAttributes) {
Expand Down
Loading
Loading