From d1da366e142fcf58e69b3387ec2a4e81f91422f3 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Thu, 6 Feb 2025 22:14:14 +0100 Subject: [PATCH 1/2] initial stuff --- src/run/handlers/cache.cts | 47 ++++++++++++++++------------ src/run/handlers/pc-client.cts | 55 +++++++++++++++++++++++++++++++++ src/run/headers.ts | 5 ++- src/run/next.cts | 35 ++++++++++----------- src/run/regional-blob-store.cts | 11 ------- 5 files changed, 102 insertions(+), 51 deletions(-) create mode 100644 src/run/handlers/pc-client.cts delete mode 100644 src/run/regional-blob-store.cts diff --git a/src/run/handlers/cache.cts b/src/run/handlers/cache.cts index c00a4d5e14..471c8703cc 100644 --- a/src/run/handlers/cache.cts +++ b/src/run/handlers/cache.cts @@ -5,7 +5,6 @@ import { Buffer } from 'node:buffer' import { join } from 'node:path' import { join as posixJoin } from 'node:path/posix' -import { Store } from '@netlify/blobs' import { purgeCache } from '@netlify/functions' import { type Span } from '@opentelemetry/api' import type { PrerenderManifest } from 'next/dist/build/index.js' @@ -22,8 +21,8 @@ import { type NetlifyCacheHandlerValue, type NetlifyIncrementalCacheValue, } from '../../shared/cache-types.cjs' -import { getRegionalBlobStore } from '../regional-blob-store.cjs' +import { getFromProgrammableCache, setInProgrammableCache } from './pc-client.cjs' import { getLogger, getRequestContext } from './request-context.cjs' import { getTracer } from './tracer.cjs' @@ -36,14 +35,12 @@ const purgeCacheUserAgent = `${nextRuntimePkgName}@${nextRuntimePkgVersion}` export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { options: CacheHandlerContext revalidatedTags: string[] - blobStore: Store tracer = getTracer() tagManifestsFetchedFromBlobStoreInCurrentRequest: TagManifestBlobCache constructor(options: CacheHandlerContext) { this.options = options this.revalidatedTags = options.revalidatedTags - this.blobStore = getRegionalBlobStore({ consistency: 'strong' }) this.tagManifestsFetchedFromBlobStoreInCurrentRequest = {} } @@ -206,12 +203,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { const blobKey = await this.encodeBlobKey(key) span.setAttributes({ key, blobKey }) - const blob = (await this.tracer.withActiveSpan('blobStore.get', async (blobGetSpan) => { - blobGetSpan.setAttributes({ key, blobKey }) - return await this.blobStore.get(blobKey, { - type: 'json', - }) - })) as NetlifyCacheHandlerValue | null + const blob = (await getFromProgrammableCache(blobKey)) as NetlifyCacheHandlerValue | null // if blob is null then we don't have a cache entry if (!blob) { @@ -338,10 +330,16 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { // and we didn't yet capture cache tags, we try to get cache tags from freshly produced cache value this.captureCacheTags(value, key) - await this.blobStore.setJSON(blobKey, { + const cacheEntry = { lastModified, value, - }) + } satisfies NetlifyCacheHandlerValue + + await setInProgrammableCache( + blobKey, + cacheEntry, + this.getCacheTagsFromCacheEntry(cacheEntry, context.tags), + ) if (data?.kind === 'PAGE' || data?.kind === 'PAGES') { const requestContext = getRequestContext() @@ -399,7 +397,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { await Promise.all( tags.map(async (tag) => { try { - await this.blobStore.setJSON(await this.encodeBlobKey(tag), data) + await setInProgrammableCache(await this.encodeBlobKey(tag), data) } catch (error) { getLogger().withError(error).log(`Failed to update tag manifest for ${tag}`) } @@ -418,10 +416,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { this.tagManifestsFetchedFromBlobStoreInCurrentRequest = {} } - /** - * Checks if a cache entry is stale through on demand revalidated tags - */ - private async checkCacheEntryStaleByTags( + private getCacheTagsFromCacheEntry( cacheEntry: NetlifyCacheHandlerValue, tags: string[] = [], softTags: string[] = [], @@ -439,7 +434,21 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { ) { cacheTags = (cacheEntry.value.headers?.[NEXT_CACHE_TAGS_HEADER] as string)?.split(/,|%2c/gi) || [] - } else { + } + + return cacheTags + } + + /** + * Checks if a cache entry is stale through on demand revalidated tags + */ + private async checkCacheEntryStaleByTags( + cacheEntry: NetlifyCacheHandlerValue, + tags: string[] = [], + softTags: string[] = [], + ) { + const cacheTags = this.getCacheTagsFromCacheEntry(cacheEntry, tags, softTags) + if (cacheTags.length === 0) { return false } @@ -474,7 +483,7 @@ export class NetlifyCacheHandler implements CacheHandlerForMultipleVersions { tagManifestPromise = this.encodeBlobKey(tag).then((blobKey) => { return this.tracer.withActiveSpan(`get tag manifest`, async (span) => { span.setAttributes({ tag, blobKey }) - return this.blobStore.get(blobKey, { type: 'json' }) + return getFromProgrammableCache(blobKey) }) }) diff --git a/src/run/handlers/pc-client.cts b/src/run/handlers/pc-client.cts new file mode 100644 index 0000000000..79dc2d44d8 --- /dev/null +++ b/src/run/handlers/pc-client.cts @@ -0,0 +1,55 @@ +// const fetchBeforeNextPatchedIt = globalThis.fetch + +import { getTracer } from './tracer.cjs' + +const CACHE_NAME = 'next-runtime' + +const fetchBeforeNextPatchedIt = globalThis.fetch + +function getURL(key: string) { + return new URL(key, 'https://n.org') +} + +export async function getFromProgrammableCache(key: string) { + return await getTracer().withActiveSpan('pc.get', async (span) => { + const url = getURL(key) + span.setAttributes({ key, url: url.href }) + + const cache = await caches.open(CACHE_NAME) + const previousFetch = globalThis.fetch + globalThis.fetch = fetchBeforeNextPatchedIt + const response = await cache.match(url) + + console.log({ response }) + globalThis.fetch = previousFetch + return response?.json() + }) +} + +export async function setInProgrammableCache(key: string, value: any, tags?: string[]) { + return await getTracer().withActiveSpan('pc.set', async (span) => { + const url = getURL(key) + span.setAttributes({ key, url: url.href }) + + const cache = await caches.open(CACHE_NAME) + + const headers: HeadersInit = { + 'Content-Type': 'application/json', + 'Cache-Control': 'max-age=3600', + } + + // ignore for now + // if (tags && tags.length !== 0) { + // headers['Cache-Tag'] = tags.join(',') + // } + const previousFetch = globalThis.fetch + globalThis.fetch = fetchBeforeNextPatchedIt + await cache.put( + url, + new Response(JSON.stringify(value), { + headers, + }), + ) + globalThis.fetch = previousFetch + }) +} diff --git a/src/run/headers.ts b/src/run/headers.ts index c93c0a605b..2c92381406 100644 --- a/src/run/headers.ts +++ b/src/run/headers.ts @@ -5,7 +5,7 @@ import { encodeBlobKey } from '../shared/blobkey.js' import { getLogger, RequestContext } from './handlers/request-context.cjs' import type { RuntimeTracer } from './handlers/tracer.cjs' -import { getRegionalBlobStore } from './regional-blob-store.cjs' +import { getFromProgrammableCache } from './handlers/pc-client.cjs' const ALL_VARIATIONS = Symbol.for('ALL_VARIATIONS') interface NetlifyVaryValues { @@ -167,7 +167,6 @@ export const adjustDateHeader = async ({ warning: true, }) - const blobStore = getRegionalBlobStore({ consistency: 'strong' }) const blobKey = await encodeBlobKey(key) // TODO: use metadata for this @@ -178,7 +177,7 @@ export const adjustDateHeader = async ({ key, blobKey, }) - const blob = (await blobStore.get(blobKey, { type: 'json' })) ?? {} + const blob = (await getFromProgrammableCache(blobKey)) ?? {} getBlobForDateSpan.addEvent(blob ? 'Cache hit' : 'Cache miss') return blob.lastModified diff --git a/src/run/next.cts b/src/run/next.cts index 17859c4835..f2315fb725 100644 --- a/src/run/next.cts +++ b/src/run/next.cts @@ -6,7 +6,6 @@ import { patchFs } from 'fs-monkey' import { getRequestContext } from './handlers/request-context.cjs' import { getTracer } from './handlers/tracer.cjs' -import { getRegionalBlobStore } from './regional-blob-store.cjs' // https://github.com/vercel/next.js/pull/68193/files#diff-37243d614f1f5d3f7ea50bbf2af263f6b1a9a4f70e84427977781e07b02f57f1R49 // This import resulted in importing unbundled React which depending if NODE_ENV is `production` or not would use @@ -96,23 +95,23 @@ export async function getMockedRequestHandler(...args: Parameters { - return getDeployStore({ - ...args, - fetch: fetchBeforeNextPatchedIt, - region: process.env.USE_REGIONAL_BLOBS?.toUpperCase() === 'TRUE' ? undefined : 'us-east-2', - }) -} From bb8e9c296c1699df5108aa1138c0588aa85d5b80 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Mon, 10 Feb 2025 12:16:08 +0100 Subject: [PATCH 2/2] otel-http-instrumentation-attempt --- package-lock.json | 221 ++++++++++++++++++++++++++++++------ package.json | 2 + src/run/handlers/tracing.ts | 6 + 3 files changed, 196 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ef9bd3734..7fdf7e1b51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,8 @@ "@netlify/zip-it-and-ship-it": "^9.41.0", "@opentelemetry/api": "^1.8.0", "@opentelemetry/exporter-trace-otlp-http": "^0.51.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/instrumentation-http": "^0.57.1", "@opentelemetry/resources": "^1.24.0", "@opentelemetry/sdk-node": "^0.51.0", "@opentelemetry/sdk-trace-node": "^1.24.0", @@ -5902,14 +5904,15 @@ } }, "node_modules/@opentelemetry/instrumentation": { - "version": "0.51.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.51.1.tgz", - "integrity": "sha512-JIrvhpgqY6437QIqToyozrUG1h5UhwHkaGK/WAX+fkrpyPtc+RO5FkRtUd9BH0MibabHHvqsnBGKfKVijbmp8w==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.1.tgz", + "integrity": "sha512-SgHEKXoVxOjc20ZYusPG3Fh+RLIZTSa4x8QtD3NfgAUDyqdFFS9W1F2ZVbZkqDCdyMcQG02Ok4duUGLHJXHgbA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.51.1", - "@types/shimmer": "^1.0.2", - "import-in-the-middle": "1.7.4", + "@opentelemetry/api-logs": "0.57.1", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" @@ -5921,23 +5924,71 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.1.tgz", + "integrity": "sha512-ThLmzAQDs7b/tdKI3BV2+yawuF09jF111OFsovqT1Qj3D8vjwKBwhi/rDE5xethwn4tSXtZcJ9hBsVAlWFQZ7g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.1", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/instrumentation/node_modules/@opentelemetry/api-logs": { - "version": "0.51.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.1.tgz", - "integrity": "sha512-E3skn949Pk1z2XtXu/lxf6QAZpawuTM/IUEXcAzpiUkTd73Hmvw26FiN3cJuTmkpM5hZzHwkomVdtrh/n/zzwA==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.1.tgz", + "integrity": "sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" }, "engines": { "node": ">=14" } }, "node_modules/@opentelemetry/instrumentation/node_modules/import-in-the-middle": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.4.tgz", - "integrity": "sha512-Lk+qzWmiQuRPPulGQeK5qq0v32k2bHnWrRPFgqyvhw7Kkov5L6MOLOIU3pcWeujc9W4q54Cp3Q2WV16eQkc7Bg==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.12.0.tgz", + "integrity": "sha512-yAgSE7GmtRcu4ZUSFX/4v69UGXwugFFSdIQJ14LHPOPPQrWv8Y7O9PHsw8Ovk7bKCLe4sjXMbZFqGFcLHpZ89w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", @@ -6333,6 +6384,27 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/instrumentation": { + "version": "0.51.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.51.1.tgz", + "integrity": "sha512-JIrvhpgqY6437QIqToyozrUG1h5UhwHkaGK/WAX+fkrpyPtc+RO5FkRtUd9BH0MibabHHvqsnBGKfKVijbmp8w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.51.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.4", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/otlp-exporter-base": { "version": "0.51.1", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.51.1.tgz", @@ -6454,6 +6526,19 @@ "@opentelemetry/api": ">=1.0.0 <1.9.0" } }, + "node_modules/@opentelemetry/sdk-node/node_modules/import-in-the-middle": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.4.tgz", + "integrity": "sha512-Lk+qzWmiQuRPPulGQeK5qq0v32k2bHnWrRPFgqyvhw7Kkov5L6MOLOIU3pcWeujc9W4q54Cp3Q2WV16eQkc7Bg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/@opentelemetry/sdk-trace-base": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.22.0.tgz", @@ -7091,10 +7176,11 @@ "dev": true }, "node_modules/@types/shimmer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.5.tgz", - "integrity": "sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/statuses": { "version": "2.0.4", @@ -12256,6 +12342,13 @@ "node": ">=12.20.0" } }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "dev": true, + "license": "MIT" + }, "node_modules/fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -40251,32 +40344,32 @@ } }, "@opentelemetry/instrumentation": { - "version": "0.51.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.51.1.tgz", - "integrity": "sha512-JIrvhpgqY6437QIqToyozrUG1h5UhwHkaGK/WAX+fkrpyPtc+RO5FkRtUd9BH0MibabHHvqsnBGKfKVijbmp8w==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.1.tgz", + "integrity": "sha512-SgHEKXoVxOjc20ZYusPG3Fh+RLIZTSa4x8QtD3NfgAUDyqdFFS9W1F2ZVbZkqDCdyMcQG02Ok4duUGLHJXHgbA==", "dev": true, "requires": { - "@opentelemetry/api-logs": "0.51.1", - "@types/shimmer": "^1.0.2", - "import-in-the-middle": "1.7.4", + "@opentelemetry/api-logs": "0.57.1", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" }, "dependencies": { "@opentelemetry/api-logs": { - "version": "0.51.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.1.tgz", - "integrity": "sha512-E3skn949Pk1z2XtXu/lxf6QAZpawuTM/IUEXcAzpiUkTd73Hmvw26FiN3cJuTmkpM5hZzHwkomVdtrh/n/zzwA==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.1.tgz", + "integrity": "sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg==", "dev": true, "requires": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" } }, "import-in-the-middle": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.4.tgz", - "integrity": "sha512-Lk+qzWmiQuRPPulGQeK5qq0v32k2bHnWrRPFgqyvhw7Kkov5L6MOLOIU3pcWeujc9W4q54Cp3Q2WV16eQkc7Bg==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.12.0.tgz", + "integrity": "sha512-yAgSE7GmtRcu4ZUSFX/4v69UGXwugFFSdIQJ14LHPOPPQrWv8Y7O9PHsw8Ovk7bKCLe4sjXMbZFqGFcLHpZ89w==", "dev": true, "requires": { "acorn": "^8.8.2", @@ -40287,6 +40380,36 @@ } } }, + "@opentelemetry/instrumentation-http": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.1.tgz", + "integrity": "sha512-ThLmzAQDs7b/tdKI3BV2+yawuF09jF111OFsovqT1Qj3D8vjwKBwhi/rDE5xethwn4tSXtZcJ9hBsVAlWFQZ7g==", + "dev": true, + "requires": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.1", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "dependencies": { + "@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "dev": true, + "requires": { + "@opentelemetry/semantic-conventions": "1.28.0" + } + }, + "@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "dev": true + } + } + }, "@opentelemetry/otlp-exporter-base": { "version": "0.49.1", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.49.1.tgz", @@ -40560,6 +40683,20 @@ "@opentelemetry/sdk-trace-base": "1.24.1" } }, + "@opentelemetry/instrumentation": { + "version": "0.51.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.51.1.tgz", + "integrity": "sha512-JIrvhpgqY6437QIqToyozrUG1h5UhwHkaGK/WAX+fkrpyPtc+RO5FkRtUd9BH0MibabHHvqsnBGKfKVijbmp8w==", + "dev": true, + "requires": { + "@opentelemetry/api-logs": "0.51.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.4", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + } + }, "@opentelemetry/otlp-exporter-base": { "version": "0.51.1", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.51.1.tgz", @@ -40637,6 +40774,18 @@ "@opentelemetry/resources": "1.24.1", "@opentelemetry/semantic-conventions": "1.24.1" } + }, + "import-in-the-middle": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.4.tgz", + "integrity": "sha512-Lk+qzWmiQuRPPulGQeK5qq0v32k2bHnWrRPFgqyvhw7Kkov5L6MOLOIU3pcWeujc9W4q54Cp3Q2WV16eQkc7Bg==", + "dev": true, + "requires": { + "acorn": "^8.8.2", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } } } }, @@ -41112,9 +41261,9 @@ "dev": true }, "@types/shimmer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.5.tgz", - "integrity": "sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", "dev": true }, "@types/statuses": { @@ -44732,6 +44881,12 @@ "fetch-blob": "^3.1.2" } }, + "forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "dev": true + }, "fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", diff --git a/package.json b/package.json index 6a5779e5e1..69fe13088c 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,8 @@ "@netlify/zip-it-and-ship-it": "^9.41.0", "@opentelemetry/api": "^1.8.0", "@opentelemetry/exporter-trace-otlp-http": "^0.51.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/instrumentation-http": "^0.57.1", "@opentelemetry/resources": "^1.24.0", "@opentelemetry/sdk-node": "^0.51.0", "@opentelemetry/sdk-trace-node": "^1.24.0", diff --git a/src/run/handlers/tracing.ts b/src/run/handlers/tracing.ts index c10724b3ef..21ff44145b 100644 --- a/src/run/handlers/tracing.ts +++ b/src/run/handlers/tracing.ts @@ -1,4 +1,6 @@ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http' +import { registerInstrumentations } from '@opentelemetry/instrumentation' +import { HttpInstrumentation } from '@opentelemetry/instrumentation-http' import { Resource } from '@opentelemetry/resources' import { NodeSDK } from '@opentelemetry/sdk-node' import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node' @@ -24,6 +26,10 @@ const sdk = new NodeSDK({ }), ), }) + +registerInstrumentations({ + instrumentations: [new HttpInstrumentation()], +}) export default sdk // gracefully shut down the SDK on process exit