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
749 changes: 657 additions & 92 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@
"@netlify/build": "^35.1.7",
"@netlify/config": "^24.0.4",
"@netlify/edge-bundler": "^14.5.5",
"@netlify/edge-functions-bootstrap": "^2.14.0",
"@netlify/edge-functions": "^2.17.1",
"@netlify/edge-functions-bootstrap": "^2.14.0",
"@netlify/eslint-config-node": "^7.0.1",
"@netlify/functions": "^4.3.0",
"@netlify/otel": "^4.3.0",
"@netlify/serverless-functions-api": "^2.5.0",
"@netlify/zip-it-and-ship-it": "^14.1.8",
"@opentelemetry/api": "^1.8.0",
Expand Down
8 changes: 4 additions & 4 deletions src/build/templates/handler-monorepo.tmpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
createRequestContext,
runWithRequestContext,
} from '{{cwd}}/.netlify/dist/run/handlers/request-context.cjs'
import { getTracer } from '{{cwd}}/.netlify/dist/run/handlers/tracer.cjs'
import { getTracer, withActiveSpan } from '{{cwd}}/.netlify/dist/run/handlers/tracer.cjs'

process.chdir('{{cwd}}')

Expand All @@ -15,8 +15,8 @@ export default async function (req, context) {
const tracer = getTracer()

const handlerResponse = await runWithRequestContext(requestContext, () => {
return tracer.withActiveSpan('Next.js Server Handler', async (span) => {
span.setAttributes({
return withActiveSpan(tracer, 'Next.js Server Handler', async (span) => {
span?.setAttributes({
'account.id': context.account.id,
'deploy.id': context.deploy.id,
'request.id': context.requestId,
Expand All @@ -32,7 +32,7 @@ export default async function (req, context) {
cachedHandler = handler
}
const response = await cachedHandler(req, context, span, requestContext)
span.setAttributes({
span?.setAttributes({
'http.status_code': response.status,
})
return response
Expand Down
8 changes: 4 additions & 4 deletions src/build/templates/handler.tmpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
runWithRequestContext,
} from './.netlify/dist/run/handlers/request-context.cjs'
import serverHandler from './.netlify/dist/run/handlers/server.js'
import { getTracer } from './.netlify/dist/run/handlers/tracer.cjs'
import { getTracer, withActiveSpan } from './.netlify/dist/run/handlers/tracer.cjs'

// Set feature flag for regional blobs
process.env.USE_REGIONAL_BLOBS = '{{useRegionalBlobs}}'
Expand All @@ -13,8 +13,8 @@ export default async function handler(req, context) {
const tracer = getTracer()

const handlerResponse = await runWithRequestContext(requestContext, () => {
return tracer.withActiveSpan('Next.js Server Handler', async (span) => {
span.setAttributes({
return withActiveSpan(tracer, 'Next.js Server Handler', async (span) => {
span?.setAttributes({
'account.id': context.account.id,
'deploy.id': context.deploy.id,
'request.id': context.requestId,
Expand All @@ -26,7 +26,7 @@ export default async function handler(req, context) {
cwd: process.cwd(),
})
const response = await serverHandler(req, context, span, requestContext)
span.setAttributes({
span?.setAttributes({
'http.status_code': response.status,
})
return response
Expand Down
32 changes: 16 additions & 16 deletions src/run/handlers/cache.cts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Buffer } from 'node:buffer'
import { join } from 'node:path'
import { join as posixJoin } from 'node:path/posix'

import { type Span } from '@opentelemetry/api'
import type { Span } from '@netlify/otel/opentelemetry'
import type { PrerenderManifest } from 'next/dist/build/index.js'
import { NEXT_CACHE_TAGS_HEADER } from 'next/dist/lib/constants.js'

Expand All @@ -32,7 +32,7 @@ import {
type RevalidateTagDurations,
type TagStaleOrExpiredStatus,
} from './tags-handler.cjs'
import { getTracer, recordWarning } from './tracer.cjs'
import { getTracer, recordWarning, withActiveSpan } from './tracer.cjs'

let memoizedPrerenderManifest: PrerenderManifest

Expand Down Expand Up @@ -74,7 +74,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
private captureResponseCacheLastModified(
cacheValue: NetlifyCacheHandlerValue,
key: string,
getCacheKeySpan: Span,
getCacheKeySpan?: Span,
) {
if (cacheValue.value?.kind === 'FETCH') {
return
Expand Down Expand Up @@ -262,17 +262,17 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
async get(
...args: Parameters<CacheHandlerForMultipleVersions['get']>
): ReturnType<CacheHandlerForMultipleVersions['get']> {
return this.tracer.withActiveSpan('get cache key', async (span) => {
return withActiveSpan(this.tracer, 'get cache key', async (span) => {
const [key, context = {}] = args
getLogger().debug(`[NetlifyCacheHandler.get]: ${key}`)

span.setAttributes({ key })
span?.setAttributes({ key })

const blob = await this.cacheStore.get<NetlifyCacheHandlerValue>(key, 'blobStore.get')

// if blob is null then we don't have a cache entry
if (!blob) {
span.addEvent('Cache miss', { key })
span?.addEvent('Cache miss', { key })
return null
}

Expand All @@ -281,7 +281,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
if (getRequestContext()?.isBackgroundRevalidation && typeof ttl === 'number' && ttl < 0) {
// background revalidation request should allow data that is not yet stale,
// but opt to discard STALE data, so that Next.js generate fresh response
span.addEvent('Discarding stale entry due to SWR background revalidation request', {
span?.addEvent('Discarding stale entry due to SWR background revalidation request', {
key,
ttl,
})
Expand All @@ -303,14 +303,14 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
)

if (expiredByTags) {
span.addEvent('Expired', { expiredByTags, key, ttl })
span?.addEvent('Expired', { expiredByTags, key, ttl })
return null
}

this.captureResponseCacheLastModified(blob, key, span)

if (staleByTags) {
span.addEvent('Stale', { staleByTags, key, ttl })
span?.addEvent('Stale', { staleByTags, key, ttl })
// note that we modify this after we capture last modified to ensure that Age is correct
// but we still let Next.js know that entry is stale
blob.lastModified = -1 // indicate that the entry is stale
Expand All @@ -324,7 +324,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {

switch (blob.value?.kind) {
case 'FETCH':
span.addEvent('FETCH', {
span?.addEvent('FETCH', {
lastModified: blob.lastModified,
revalidate: context.revalidate,
ttl,
Expand All @@ -336,7 +336,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {

case 'ROUTE':
case 'APP_ROUTE': {
span.addEvent(blob.value?.kind, {
span?.addEvent(blob.value?.kind, {
lastModified: blob.lastModified,
status: blob.value.status,
revalidate: blob.value.revalidate,
Expand All @@ -362,7 +362,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
requestContext.pageHandlerRevalidate = revalidate
}

span.addEvent(blob.value?.kind, { lastModified: blob.lastModified, revalidate, ttl })
span?.addEvent(blob.value?.kind, { lastModified: blob.lastModified, revalidate, ttl })

await this.injectEntryToPrerenderManifest(key, blob.value)

Expand All @@ -379,7 +379,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {

const { revalidate, rscData, segmentData, ...restOfPageValue } = blob.value

span.addEvent(blob.value?.kind, { lastModified: blob.lastModified, revalidate, ttl })
span?.addEvent(blob.value?.kind, { lastModified: blob.lastModified, revalidate, ttl })

await this.injectEntryToPrerenderManifest(key, blob.value)

Expand All @@ -400,7 +400,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
}
}
default:
span.recordException(new Error(`Unknown cache entry kind: ${blob.value?.kind}`))
span?.recordException(new Error(`Unknown cache entry kind: ${blob.value?.kind}`))
}
return null
})
Expand Down Expand Up @@ -452,10 +452,10 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions {
}

async set(...args: Parameters<CacheHandlerForMultipleVersions['set']>) {
return this.tracer.withActiveSpan('set cache key', async (span) => {
return withActiveSpan(this.tracer, 'set cache key', async (span?: Span) => {
const [key, data, context] = args
const lastModified = Date.now()
span.setAttributes({ key, lastModified })
span?.setAttributes({ key, lastModified })

getLogger().debug(`[NetlifyCacheHandler.set]: ${key}`)

Expand Down
18 changes: 9 additions & 9 deletions src/run/handlers/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { OutgoingHttpHeaders } from 'http'

import { ComputeJsOutgoingMessage, toComputeResponse, toReqRes } from '@fastly/http-compute-js'
import type { Context } from '@netlify/functions'
import { Span } from '@opentelemetry/api'
import type { Span } from '@netlify/otel/opentelemetry'
import type { WorkerRequestHandler } from 'next/dist/server/lib/types.js'

import { getRunConfig, setRunConfig } from '../config.js'
Expand All @@ -17,7 +17,7 @@ import { nextResponseProxy } from '../revalidate.js'
import { setFetchBeforeNextPatchedIt } from '../storage/storage.cjs'

import { getLogger, type RequestContext } from './request-context.cjs'
import { getTracer, recordWarning } from './tracer.cjs'
import { getTracer, recordWarning, withActiveSpan } from './tracer.cjs'
import { configureUseCacheHandlers } from './use-cache-handler.js'
import { setupWaitUntil } from './wait-until.cjs'
// make use of global fetch before Next.js applies any patching
Expand Down Expand Up @@ -61,13 +61,13 @@ const disableFaultyTransferEncodingHandling = (res: ComputeJsOutgoingMessage) =>
export default async (
request: Request,
_context: Context,
topLevelSpan: Span,
topLevelSpan: Span | undefined,
requestContext: RequestContext,
) => {
const tracer = getTracer()

if (!nextHandler) {
await tracer.withActiveSpan('initialize next server', async () => {
await withActiveSpan(tracer, 'initialize next server', async () => {
const { getMockedRequestHandler } = await nextImportPromise
const url = new URL(request.url)

Expand All @@ -80,7 +80,7 @@ export default async (
})
}

return await tracer.withActiveSpan('generate response', async (span) => {
return await withActiveSpan(tracer, 'generate response', async (span) => {
const { req, res } = toReqRes(request)

// Work around a bug in http-proxy in next@<14.0.2
Expand All @@ -104,7 +104,7 @@ export default async (
getLogger().withError(error).error('next handler error')
console.error(error)
resProxy.statusCode = 500
span.setAttribute('http.status_code', 500)
span?.setAttribute('http.status_code', 500)
resProxy.end('Internal Server Error')
})

Expand All @@ -113,7 +113,7 @@ export default async (
const response = await toComputeResponse(resProxy)

if (requestContext.responseCacheKey) {
topLevelSpan.setAttribute('responseCacheKey', requestContext.responseCacheKey)
topLevelSpan?.setAttribute('responseCacheKey', requestContext.responseCacheKey)
}

const nextCache = response.headers.get('x-nextjs-cache')
Expand All @@ -135,7 +135,7 @@ export default async (

const netlifyVary = response.headers.get('netlify-vary') ?? undefined
const netlifyCdnCacheControl = response.headers.get('netlify-cdn-cache-control') ?? undefined
topLevelSpan.setAttributes({
topLevelSpan?.setAttributes({
'x-nextjs-cache': nextCache ?? undefined,
isServedFromNextCache,
netlifyVary,
Expand All @@ -151,7 +151,7 @@ export default async (
(!isRSCRequest && contentType?.includes('text/html'))) ??
false

topLevelSpan.setAttributes({
topLevelSpan?.setAttributes({
isRSCRequest,
isCacheableAppPage: true,
contentType,
Expand Down
Loading
Loading