@interfere/next 11.0.0-canary.5 → 11.0.0-canary.6
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 +3 -7
- package/dist/config.mjs +1 -1
- package/dist/instrumentation.edge.mjs +1 -1
- package/dist/instrumentation.mjs +1 -1
- package/dist/internal/build/configure-build.d.mts +1 -0
- package/dist/internal/build/configure-build.mjs +1 -1
- package/dist/internal/server/capture.d.mts +1 -1
- package/dist/internal/server/capture.mjs +1 -1
- package/dist/internal/server/server-flush.d.mts +5 -0
- package/dist/internal/server/server-flush.mjs +1 -0
- package/dist/package.mjs +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<a href="https://interfere.com">
|
|
3
3
|
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://
|
|
5
|
-
<img src="https://
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://images.interfere.com/cdn-cgi/imagedelivery/ZQ3TDZdJHXvYNyL5BNulpQ/v2/header/logo-dark/format=auto">
|
|
5
|
+
<img src="https://images.interfere.com/cdn-cgi/imagedelivery/ZQ3TDZdJHXvYNyL5BNulpQ/v2/header/logo-light/format=auto" height="64" alt="Interfere">
|
|
6
6
|
</picture>
|
|
7
7
|
</a>
|
|
8
8
|
<h1 align="center">@interfere/next</h1>
|
|
@@ -19,11 +19,7 @@
|
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
21
|
<p align="center">
|
|
22
|
-
<a href="https://
|
|
23
|
-
·
|
|
24
|
-
<a href="https://support.interfere.com/roadmap">Feature Requests</a>
|
|
25
|
-
·
|
|
26
|
-
<a href="https://support.interfere.com/requests">Report a Bug</a>
|
|
22
|
+
<a href="https://interfere.com/docs">Documentation</a>
|
|
27
23
|
·
|
|
28
24
|
<a href="mailto:support@interfere.com">Get Help</a>
|
|
29
25
|
</p>
|
package/dist/config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{configureBuild}from"./internal/build/configure-build.mjs";import{readInterfereEnv}from"./internal/env.mjs";import{FatalError,log}from"./internal/logger.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{readNextMajorVersion,warnIfServerInstrumentationMissing}from"./internal/setup-warnings.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{classifyReleasePipelineError,diagnoseRelease,isInterfereApiKey}from"@interfere/types/sdk/build-diagnostics";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{PHASE_PRODUCTION_BUILD}from"next/constants.js";const CLIENT_TRACE_METADATA_KEYS=[`traceparent`,`baggage`],DIAGNOSTIC_CONTEXT={publicKeyEnvVar:`INTERFERE_PUBLIC_KEY`};function reportReleaseDiagnostic(code,input){let diagnostic=diagnoseRelease(code,DIAGNOSTIC_CONTEXT,input),lines=[...diagnostic.details];if(diagnostic.severity===`fatal`){log.fatal(diagnostic.title,lines);return}log.warn(diagnostic.title,lines)}function withInterfere(nextConfig={}){let{interfere,env:userEnv,webpack,turbopack,compiler,productionBrowserSourceMaps,...rest}=nextConfig;if(interfere&&`buildId`in interfere&&interfere.buildId!==void 0)return log.fatal(`Removed: interfere.buildId`,["`interfere.buildId` was removed in SDK 10. It only worked at build time, so server-side spans drifted from the bundle's slug.","Override the commit SHA via the `INTERFERE_SOURCE_ID` env var on both build and runtime envs instead."]);let projectDir=process.cwd(),config=resolveBuildConfig(),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,build=configureBuild({existingWebpack:webpack,existingTurbopack:turbopack,projectDir,values:{__INTERFERE_RELEASE_SLUG__:forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug,...config.publicKey&&{__INTERFERE_PROXY_MODE__:!0,__INTERFERE_PUBLIC_KEY__:config.publicKey},...config.environment&&{__INTERFERE_ENVIRONMENT__:config.environment},...forceEnable&&{__INTERFERE_FORCE_ENABLE__:!0}}});if(config.publicKey!==null&&!build.
|
|
1
|
+
import{configureBuild}from"./internal/build/configure-build.mjs";import{readInterfereEnv}from"./internal/env.mjs";import{FatalError,log}from"./internal/logger.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{readNextMajorVersion,warnIfServerInstrumentationMissing}from"./internal/setup-warnings.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{classifyReleasePipelineError,diagnoseRelease,isInterfereApiKey}from"@interfere/types/sdk/build-diagnostics";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{PHASE_PRODUCTION_BUILD}from"next/constants.js";const CLIENT_TRACE_METADATA_KEYS=[`traceparent`,`baggage`],DIAGNOSTIC_CONTEXT={publicKeyEnvVar:`INTERFERE_PUBLIC_KEY`};function reportReleaseDiagnostic(code,input){let diagnostic=diagnoseRelease(code,DIAGNOSTIC_CONTEXT,input),lines=[...diagnostic.details];if(diagnostic.severity===`fatal`){log.fatal(diagnostic.title,lines);return}log.warn(diagnostic.title,lines)}function withInterfere(nextConfig={}){let{interfere,env:userEnv,webpack,turbopack,compiler,productionBrowserSourceMaps,...rest}=nextConfig;if(interfere&&`buildId`in interfere&&interfere.buildId!==void 0)return log.fatal(`Removed: interfere.buildId`,["`interfere.buildId` was removed in SDK 10. It only worked at build time, so server-side spans drifted from the bundle's slug.","Override the commit SHA via the `INTERFERE_SOURCE_ID` env var on both build and runtime envs instead."]);let projectDir=process.cwd(),config=resolveBuildConfig(),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,build=configureBuild({existingWebpack:webpack,existingTurbopack:turbopack,projectDir,values:{__INTERFERE_RELEASE_SLUG__:forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug,...config.publicKey&&{__INTERFERE_PROXY_MODE__:!0,__INTERFERE_PUBLIC_KEY__:config.publicKey},...config.environment&&{__INTERFERE_ENVIRONMENT__:config.environment},...forceEnable&&{__INTERFERE_FORCE_ENABLE__:!0}}});if(config.publicKey!==null&&!build.clientInstrumentationApplies)return log.fatal(`Missing instrumentation client`,[`INTERFERE_PUBLIC_KEY is set but no instrumentation-client file was found.`,`Create an instrumentation-client.ts file in your project root or src/ directory.`]);config.publicKey!==null&&warnIfServerInstrumentationMissing(projectDir);let nextMajor=readNextMajorVersion(projectDir),experimental=interfereExperimentalConfig({existing:rest.experimental,instrumentationHook:nextMajor===null||nextMajor<=14,traceMetadata:config.publicKey!==null||forceEnable}),existingHook=compiler?.runAfterProductionCompile,browserSourceMaps=config.apiKey===null?productionBrowserSourceMaps:!0;return config.apiKey!==null&&productionBrowserSourceMaps===!1&&log.warn(`Forcing productionBrowserSourceMaps`,[`withInterfere() requires production source maps to symbolicate errors.`,"Your `productionBrowserSourceMaps: false` was overridden to `true`."]),{...rest,...userEnv?{env:userEnv}:{},compiler:{...omitUndefined(compiler??{}),async runAfterProductionCompile(context){existingHook&&await existingHook(context);try{await runBuildReleasePipeline(context,config)}catch(error){if(error instanceof FatalError)throw error;let message=error instanceof Error?error.message:String(error);log.warn(`Skipping release pipeline`,[`Interfere encountered an unexpected error.`,`Build will continue, but this release's data will be ingested, but ignored as finding when generating insights.`,`Error: ${message}`])}}},...omitUndefined({productionBrowserSourceMaps:browserSourceMaps,turbopack:build.turbopack,webpack:build.webpack}),...experimental?{experimental}:{}}}function interfereExperimentalConfig({existing,instrumentationHook,traceMetadata}){let merged={...existing,...instrumentationHook?{instrumentationHook:!0}:{},...traceMetadata?{clientTraceMetadata:[...new Set([...existing?.clientTraceMetadata??[],...CLIENT_TRACE_METADATA_KEYS])]}:{}};return Object.keys(merged).length>0?merged:void 0}function resolveBuildConfig(){let{apiKey,apiUrl,publicKey}=readInterfereEnv(),{commitSha,slug}=resolveReleaseSlug(),environment=process.env.NEXT_PHASE===PHASE_PRODUCTION_BUILD?resolveDeployEnvironment(process.env):null;return{apiKey:apiKey??null,apiUrl,buildId:commitSha,environment,publicKey:publicKey??null,releaseSlug:slug}}async function runBuildReleasePipeline(context,config){let{apiKey,buildId,releaseSlug}=config;if(!apiKey)return log.fatal(`API key not set`,[`withInterfere() requires an API key to publish release metadata during production builds.`,`Set the INTERFERE_API_KEY environment variable, or remove withInterfere() from your Next.js config.`,`See: https://interfere.com/docs/guides/next-js`]);if(!isInterfereApiKey(apiKey))return reportReleaseDiagnostic(`API_KEY_WRONG_PREFIX`,{apiKey});if(!(buildId&&releaseSlug))return log.fatal(`Commit SHA missing`,[`Could not resolve a commit SHA from environment variables or git.`,"Set `INTERFERE_SOURCE_ID`, ensure your CI exposes its git SHA env var (e.g. `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`), or run inside a git checkout."]);let{runBuildPipeline}=await import(`./internal/build/pipeline.mjs`);try{let result=await runBuildPipeline(context,{...config,apiKey,buildId,releaseSlug});if(!result.ready){log.warn(`Skipping`,[`No source maps found`]);return}log.info(`Completed`,[`https://interfere.com/~/${result.config?.org.slug}/surfaces/${result.config?.surface.slug}`,`Release: ${result.release?.destination.slug??`Unknown`}`,`Build: ${result.buildId}`,`Artifacts: ${result.fileCount} source maps`])}catch(error){let message=error instanceof Error?error.message:String(error);reportReleaseDiagnostic(classifyReleasePipelineError(error),{errorMessage:message});return}}export{withInterfere};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readInterfereEnv}from"./internal/env.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{FetchTraceExporter}from"./internal/server/edge-exporter.mjs";import{withPublicKey}from"./internal/url.mjs";import{onRequestError}from"./internal/server/capture.mjs";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{trace}from"@opentelemetry/api";import{resourceFromAttributes}from"@opentelemetry/resources";import{BasicTracerProvider,SimpleSpanProcessor}from"@opentelemetry/sdk-trace-base";let registered=!1;function register(opts={}){if(registered)return Promise.resolve();let env=readInterfereEnv();if(!env.publicKey)return Promise.resolve();let releaseSlug=process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE?LOCAL_DEV_RELEASE_SLUG:null;releaseSlug||console.warn(`[interfere] edge runtime has no build-baked release.slug; the collector will reject edge spans until one is wired (production follow-up).`);let sinkUrl=withPublicKey(`${env.apiUrl}/v2/sink`,env.publicKey),provider=new BasicTracerProvider({resource:resourceFromAttributes({"service.name":opts.serviceName??`interfere-sdk-next-edge`,"service.namespace":`interfere`,"deployment.environment.name":env.nodeEnvironment,"telemetry.sdk.language":`nodejs`,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,...releaseSlug?{"release.slug":releaseSlug}:{}}),spanProcessors:[new SimpleSpanProcessor(new FetchTraceExporter(sinkUrl,{"x-interfere-producer-version":PRODUCER_VERSION}))]});return trace.setGlobalTracerProvider(provider),registered=!0,Promise.resolve()}function buildInterfereOtelKit(_opts={}){return null}export{buildInterfereOtelKit,onRequestError,register};
|
|
1
|
+
import{readInterfereEnv}from"./internal/env.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{FetchTraceExporter}from"./internal/server/edge-exporter.mjs";import{setServerFlush}from"./internal/server/server-flush.mjs";import{withPublicKey}from"./internal/url.mjs";import{onRequestError}from"./internal/server/capture.mjs";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{trace}from"@opentelemetry/api";import{resourceFromAttributes}from"@opentelemetry/resources";import{BasicTracerProvider,SimpleSpanProcessor}from"@opentelemetry/sdk-trace-base";let registered=!1;function register(opts={}){if(registered)return Promise.resolve();let env=readInterfereEnv();if(!env.publicKey)return Promise.resolve();let releaseSlug=process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE?LOCAL_DEV_RELEASE_SLUG:null;releaseSlug||console.warn(`[interfere] edge runtime has no build-baked release.slug; the collector will reject edge spans until one is wired (production follow-up).`);let sinkUrl=withPublicKey(`${env.apiUrl}/v2/sink`,env.publicKey),provider=new BasicTracerProvider({resource:resourceFromAttributes({"service.name":opts.serviceName??`interfere-sdk-next-edge`,"service.namespace":`interfere`,"deployment.environment.name":env.nodeEnvironment,"telemetry.sdk.language":`nodejs`,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,...releaseSlug?{"release.slug":releaseSlug}:{}}),spanProcessors:[new SimpleSpanProcessor(new FetchTraceExporter(sinkUrl,{"x-interfere-producer-version":PRODUCER_VERSION}))]});return trace.setGlobalTracerProvider(provider),setServerFlush(()=>provider.forceFlush()),registered=!0,Promise.resolve()}function buildInterfereOtelKit(_opts={}){return null}export{buildInterfereOtelKit,onRequestError,register};
|
package/dist/instrumentation.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readInterfereEnv}from"./internal/env.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{withPublicKey}from"./internal/url.mjs";import{fetchAndCacheRemoteConfig}from"./internal/server/remote-config.mjs";import{onRequestError}from"./internal/server/capture.mjs";import{bridgeConsoleToOtel}from"./internal/server/console-bridge.mjs";import{installGlobalHandlers}from"./internal/server/global-handlers.mjs";import{PrerenderSafeIdGenerator}from"./internal/server/id-generator.mjs";import{metrics,propagation}from"@opentelemetry/api";import{resourceFromAttributes}from"@opentelemetry/resources";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{AggregationTemporalityPreference,OTLPMetricExporter}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{UndiciInstrumentation}from"@opentelemetry/instrumentation-undici";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";let registered=!1,tracerProvider=null,loggerProvider=null,meterProvider=null;async function flush(){await Promise.all([tracerProvider?.forceFlush(),loggerProvider?.forceFlush(),meterProvider?.forceFlush()])}function matchesAny(url,patterns){for(let pattern of patterns)if(pattern instanceof RegExp?pattern.test(url):url.includes(pattern))return!0;return!1}function buildInterfereOtelKit(opts={}){let env=readInterfereEnv();if(!env.publicKey)return null;let{slug:releaseSlug}=resolveReleaseSlug();releaseSlug||console.warn("[interfere] No commit SHA available; server spans will ship without `release.slug`. Set `INTERFERE_SOURCE_ID` (or any of `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`) on the runtime env.");let sinkUrl=withPublicKey(`${env.apiUrl}/v2/sink`,env.publicKey),ignoreUrls=[sinkUrl,...opts.ignoreUrls??[]],propagateContextUrls=opts.propagateContextUrls??[],exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION};return{resourceAttributes:{"service.name":opts.serviceName??`interfere-sdk-next-server`,"service.namespace":`interfere`,"deployment.environment.name":env.nodeEnvironment,"telemetry.sdk.language":`nodejs`,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,...releaseSlug?{"release.slug":releaseSlug}:{}},spanProcessors:[new BaggageSpanProcessor(()=>!0),new BatchSpanProcessor(new OTLPTraceExporter({url:sinkUrl,headers:exporterHeaders})),...opts._internalAdditionalSpanProcessors??[]],logRecordProcessors:[new BatchLogRecordProcessor(new OTLPLogExporter({url:sinkUrl,headers:exporterHeaders})),...opts._internalAdditionalLogRecordProcessors??[]],metricReaders:[new PeriodicExportingMetricReader({exporter:new OTLPMetricExporter({url:sinkUrl,headers:exporterHeaders,temporalityPreference:AggregationTemporalityPreference.DELTA}),exportIntervalMillis:3e4}),...opts._internalAdditionalMetricReaders??[]],propagators:[new W3CBaggagePropagator],instrumentations:[new UndiciInstrumentation({ignoreRequestHook:req=>matchesAny(`${req.origin}${req.path}`,ignoreUrls),requestHook:(span,req)=>{matchesAny(`${req.origin}${req.path}`,propagateContextUrls)&&span.setAttribute(`interfere.propagated`,!0)}})],enableConsoleBridge:()=>bridgeConsoleToOtel(),fetchRemoteConfig:()=>fetchAndCacheRemoteConfig()}}async function register(opts={}){if(registered)return;let kit=buildInterfereOtelKit(opts);if(!kit)return;let resource=resourceFromAttributes(kit.resourceAttributes);tracerProvider=new NodeTracerProvider({resource,spanProcessors:kit.spanProcessors,idGenerator:new PrerenderSafeIdGenerator}),propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,...kit.propagators]})),tracerProvider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),loggerProvider=new LoggerProvider({resource,processors:kit.logRecordProcessors});let{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider),meterProvider=new MeterProvider({resource,readers:kit.metricReaders}),metrics.setGlobalMeterProvider(meterProvider),registerInstrumentations({tracerProvider,meterProvider,instrumentations:kit.instrumentations}),opts.consoleBridge!==!1&&kit.enableConsoleBridge(),installGlobalHandlers({captureUncaughtException:opts.captureUncaughtException??!0,captureUnhandledRejection:opts.captureUnhandledRejection??!0,exitOnUncaughtException:process.env.NODE_ENV===`production`,flush}),registered=!0,await kit.fetchRemoteConfig()}export{PrerenderSafeIdGenerator,buildInterfereOtelKit,flush,onRequestError,register};
|
|
1
|
+
import{readInterfereEnv}from"./internal/env.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{setServerFlush}from"./internal/server/server-flush.mjs";import{withPublicKey}from"./internal/url.mjs";import{fetchAndCacheRemoteConfig}from"./internal/server/remote-config.mjs";import{onRequestError}from"./internal/server/capture.mjs";import{bridgeConsoleToOtel}from"./internal/server/console-bridge.mjs";import{installGlobalHandlers}from"./internal/server/global-handlers.mjs";import{PrerenderSafeIdGenerator}from"./internal/server/id-generator.mjs";import{metrics,propagation}from"@opentelemetry/api";import{resourceFromAttributes}from"@opentelemetry/resources";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{AggregationTemporalityPreference,OTLPMetricExporter}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{UndiciInstrumentation}from"@opentelemetry/instrumentation-undici";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";let registered=!1,tracerProvider=null,loggerProvider=null,meterProvider=null;async function flush(){await Promise.all([tracerProvider?.forceFlush(),loggerProvider?.forceFlush(),meterProvider?.forceFlush()])}function matchesAny(url,patterns){for(let pattern of patterns)if(pattern instanceof RegExp?pattern.test(url):url.includes(pattern))return!0;return!1}function buildInterfereOtelKit(opts={}){let env=readInterfereEnv();if(!env.publicKey)return null;let{slug:releaseSlug}=resolveReleaseSlug();releaseSlug||console.warn("[interfere] No commit SHA available; server spans will ship without `release.slug`. Set `INTERFERE_SOURCE_ID` (or any of `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`) on the runtime env.");let sinkUrl=withPublicKey(`${env.apiUrl}/v2/sink`,env.publicKey),ignoreUrls=[sinkUrl,...opts.ignoreUrls??[]],propagateContextUrls=opts.propagateContextUrls??[],exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION};return{resourceAttributes:{"service.name":opts.serviceName??`interfere-sdk-next-server`,"service.namespace":`interfere`,"deployment.environment.name":env.nodeEnvironment,"telemetry.sdk.language":`nodejs`,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,...releaseSlug?{"release.slug":releaseSlug}:{}},spanProcessors:[new BaggageSpanProcessor(()=>!0),new BatchSpanProcessor(new OTLPTraceExporter({url:sinkUrl,headers:exporterHeaders})),...opts._internalAdditionalSpanProcessors??[]],logRecordProcessors:[new BatchLogRecordProcessor(new OTLPLogExporter({url:sinkUrl,headers:exporterHeaders})),...opts._internalAdditionalLogRecordProcessors??[]],metricReaders:[new PeriodicExportingMetricReader({exporter:new OTLPMetricExporter({url:sinkUrl,headers:exporterHeaders,temporalityPreference:AggregationTemporalityPreference.DELTA}),exportIntervalMillis:3e4}),...opts._internalAdditionalMetricReaders??[]],propagators:[new W3CBaggagePropagator],instrumentations:[new UndiciInstrumentation({ignoreRequestHook:req=>matchesAny(`${req.origin}${req.path}`,ignoreUrls),requestHook:(span,req)=>{matchesAny(`${req.origin}${req.path}`,propagateContextUrls)&&span.setAttribute(`interfere.propagated`,!0)}})],enableConsoleBridge:()=>bridgeConsoleToOtel(),fetchRemoteConfig:()=>fetchAndCacheRemoteConfig()}}async function register(opts={}){if(registered)return;let kit=buildInterfereOtelKit(opts);if(!kit)return;let resource=resourceFromAttributes(kit.resourceAttributes);tracerProvider=new NodeTracerProvider({resource,spanProcessors:kit.spanProcessors,idGenerator:new PrerenderSafeIdGenerator}),propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,...kit.propagators]})),tracerProvider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),loggerProvider=new LoggerProvider({resource,processors:kit.logRecordProcessors});let{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider),meterProvider=new MeterProvider({resource,readers:kit.metricReaders}),metrics.setGlobalMeterProvider(meterProvider),registerInstrumentations({tracerProvider,meterProvider,instrumentations:kit.instrumentations}),opts.consoleBridge!==!1&&kit.enableConsoleBridge(),installGlobalHandlers({captureUncaughtException:opts.captureUncaughtException??!0,captureUnhandledRejection:opts.captureUnhandledRejection??!0,exitOnUncaughtException:process.env.NODE_ENV===`production`,flush}),setServerFlush(flush),registered=!0,await kit.fetchRemoteConfig()}export{PrerenderSafeIdGenerator,buildInterfereOtelKit,flush,onRequestError,register};
|
|
@@ -15,6 +15,7 @@ interface ConfigureBuildInput {
|
|
|
15
15
|
readonly values: InterfereInjectedValues;
|
|
16
16
|
}
|
|
17
17
|
interface ConfigureBuildOutput {
|
|
18
|
+
readonly clientInstrumentationApplies: boolean;
|
|
18
19
|
readonly turbopack: NextConfig["turbopack"] | undefined;
|
|
19
20
|
readonly webpack: NextConfig["webpack"] | undefined;
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync}from"node:fs";import{basename,dirname,join,normalize,resolve}from"node:path";import{fileURLToPath}from"node:url";const INSTRUMENTATION_CLIENT_FILES=[`instrumentation-client.ts`,`instrumentation-client.tsx`,`instrumentation-client.js`,`instrumentation-client.jsx`,`src/instrumentation-client.ts`,`src/instrumentation-client.tsx`,`src/instrumentation-client.js`,`src/instrumentation-client.jsx`],INSTRUMENTATION_SERVER_FILES=[`instrumentation.ts`,`instrumentation.tsx`,`instrumentation.js`,`instrumentation.jsx`,`src/instrumentation.ts`,`src/instrumentation.tsx`,`src/instrumentation.js`,`src/instrumentation.jsx`],LOADER_FILE_CANDIDATES=[`value-injection-loader.ts`,`value-injection-loader.js`,`value-injection-loader.mjs`,`value-injection-loader.cjs`];function configureBuild({existingWebpack,existingTurbopack,projectDir,values}){let clientPath=resolveFirstExisting(projectDir,INSTRUMENTATION_CLIENT_FILES),targets=[clientPath,resolveFirstExisting(projectDir,INSTRUMENTATION_SERVER_FILES)].filter(path=>path!==null);return{webpack:buildWebpackHook(existingWebpack,
|
|
1
|
+
import{existsSync}from"node:fs";import{basename,dirname,join,normalize,resolve}from"node:path";import{fileURLToPath}from"node:url";const INSTRUMENTATION_CLIENT_FILES=[`instrumentation-client.ts`,`instrumentation-client.tsx`,`instrumentation-client.js`,`instrumentation-client.jsx`,`src/instrumentation-client.ts`,`src/instrumentation-client.tsx`,`src/instrumentation-client.js`,`src/instrumentation-client.jsx`],INSTRUMENTATION_SERVER_FILES=[`instrumentation.ts`,`instrumentation.tsx`,`instrumentation.js`,`instrumentation.jsx`,`src/instrumentation.ts`,`src/instrumentation.tsx`,`src/instrumentation.js`,`src/instrumentation.jsx`],LOADER_FILE_CANDIDATES=[`value-injection-loader.ts`,`value-injection-loader.js`,`value-injection-loader.mjs`,`value-injection-loader.cjs`];function configureBuild({existingWebpack,existingTurbopack,projectDir,values}){let clientPath=resolveFirstExisting(projectDir,INSTRUMENTATION_CLIENT_FILES),targets=[clientPath,resolveFirstExisting(projectDir,INSTRUMENTATION_SERVER_FILES)].filter(path=>path!==null),clientInstrumentationApplies=!!(clientPath&&hasInjectedMetadata(values));return{clientInstrumentationApplies,webpack:buildWebpackHook(existingWebpack,targets,values,clientInstrumentationApplies),turbopack:buildTurbopackConfig(existingTurbopack,targets,values,clientInstrumentationApplies)}}function hasInjectedMetadata(metadata){return metadata.__INTERFERE_RELEASE_SLUG__!==null||metadata.__INTERFERE_PUBLIC_KEY__!==void 0}function buildWebpackHook(existingWebpack,targets,values,injectionApplies){if(!injectionApplies)return existingWebpack;let normalizedTargets=new Set(targets.map(path=>normalize(path))),injectionLoaderPath=resolveLoaderPath();return(webpackConfig,options)=>{let outputConfig=existingWebpack?existingWebpack(webpackConfig,options):webpackConfig,mutableConfig=outputConfig;return mutableConfig.module??={},mutableConfig.module.rules??=[],mutableConfig.module.rules.push({test:resource=>!!resource&&normalizedTargets.has(normalize(resource)),use:[{loader:injectionLoaderPath,options:{values}}]}),outputConfig}}function buildTurbopackConfig(existingTurbopack,targets,values,injectionApplies){let baseConfig=existingTurbopack??{},debugIds=baseConfig.debugIds??!0;if(!injectionApplies)return existingTurbopack===void 0&&debugIds===baseConfig.debugIds?existingTurbopack:{...baseConfig,debugIds};let rules={...baseConfig.rules},loaderPath=resolveLoaderPath();for(let target of targets){let ruleKey=`**/${basename(target)}`;rules[ruleKey]=appendTurbopackLoader(rules[ruleKey],{loader:loaderPath,options:{serializedValues:JSON.stringify(values)}})}return{...baseConfig,debugIds,rules}}function appendTurbopackLoader(existing,loader){let rule=existing??{},loaders=Array.isArray(rule.loaders)?rule.loaders:[];return{...rule,loaders:[...loaders,loader]}}function resolveFirstExisting(projectDir,candidates){for(let candidate of candidates){let filePath=resolve(projectDir,candidate);if(existsSync(filePath))return filePath}return null}function resolveLoaderPath(){let directory=resolve(dirname(fileURLToPath(import.meta.url)));for(let candidate of LOADER_FILE_CANDIDATES){let filePath=join(directory,candidate);if(existsSync(filePath))return filePath}return join(directory,`value-injection-loader.js`)}export{configureBuild};
|
|
@@ -9,6 +9,6 @@ interface OnRequestErrorRequest {
|
|
|
9
9
|
}
|
|
10
10
|
declare function onRequestError(error: Error & {
|
|
11
11
|
digest?: string;
|
|
12
|
-
}, request: OnRequestErrorRequest | undefined, context: OnRequestErrorContext): void
|
|
12
|
+
}, request: OnRequestErrorRequest | undefined, context: OnRequestErrorContext): Promise<void>;
|
|
13
13
|
//#endregion
|
|
14
14
|
export { captureError, onRequestError };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isEnabledOnServer}from"../env.mjs";import{isPluginEnabled}from"./remote-config.mjs";import{readServerAction}from"./server-action-marker.mjs";import{SpanKind,SpanStatusCode,trace}from"@opentelemetry/api";import{MECHANISM_TYPE,isNonErrorException,toException}from"@interfere/types/sdk/errors";const ON_REQUEST_ERROR_MECHANISM={type:MECHANISM_TYPE.nextjs.onRequestError,handled:!1,synthetic:!1},SERVER_ACTION_MECHANISM={type:MECHANISM_TYPE.nextjs.serverAction,handled:!1,synthetic:!1},DEFAULT_CAPTURE_ERROR_MECHANISM={type:MECHANISM_TYPE.nextjs.captureError,handled:!0},seen=new WeakSet;function buildAttrs(value,mechanism,context){let attrs={"interfere.exception.mechanism":mechanism.type,"interfere.exception.handled":mechanism.handled},digest=context?.nextjs?.errorDigest;if(digest&&(attrs[`interfere.error.digest`]=digest),context?.nextjs?.requestMethod&&(attrs[`http.request.method`]=context.nextjs.requestMethod),context?.nextjs?.requestPath&&(attrs[`url.path`]=context.nextjs.requestPath),context?.nextjs?.routePath&&(attrs[`http.route`]=context.nextjs.routePath),context?.nextjs?.routeType===`route`&&!mechanism.handled&&(attrs[`http.response.status_code`]=500),context?.serverAction&&(attrs[`interfere.server_action.name`]=context.serverAction.name,context.serverAction.argsShape&&(attrs[`interfere.server_action.args_shape`]=context.serverAction.argsShape)),context?.requestHeaders)for(let[name,headerValue]of Object.entries(context.requestHeaders))attrs[`http.request.header.${name}`]=headerValue;return isNonErrorException(value)?(attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`,attrs):(attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack),attrs)}function recordException({error,mechanism,context}){let value=toException(error),attrs=buildAttrs(value,mechanism,context),tracer=trace.getTracer(`@interfere/next/server`),active=trace.getActiveSpan();if(active?.isRecording()){active.addEvent(`exception`,attrs),mechanism.handled||active.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message});return}let span=tracer.startSpan(`interfere.captureError`,{kind:SpanKind.INTERNAL});span.addEvent(`exception`,attrs),mechanism.handled||span.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message}),span.end()}function captureError(error,_request,context){if(isEnabledOnServer()&&isPluginEnabled(`errors`)){if(error instanceof Error){if(seen.has(error))return;seen.add(error)}recordException({error,mechanism:context?.mechanism??DEFAULT_CAPTURE_ERROR_MECHANISM,context})}}const CAPTURED_REQUEST_HEADERS=[`accept`,`accept-language`,`content-length`,`content-type`,`host`,`referer`,`user-agent`,`x-forwarded-for`,`x-forwarded-host`,`x-forwarded-proto`,`x-vercel-id`];function pickAllowedHeaders(headers){if(!headers)return;let picked={};for(let name of CAPTURED_REQUEST_HEADERS){let value=headers[name];typeof value==`string`&&(picked[name]=value)}return Object.keys(picked).length>0?picked:void 0}function onRequestError(error,request,context){if(seen.has(error)||(seen.add(error),!isEnabledOnServer())||!isPluginEnabled(`errors`))return;let action=readServerAction(error),mechanism=action?SERVER_ACTION_MECHANISM:
|
|
1
|
+
import{isEnabledOnServer}from"../env.mjs";import{flushServerTelemetry}from"./server-flush.mjs";import{isPluginEnabled}from"./remote-config.mjs";import{readServerAction}from"./server-action-marker.mjs";import{SpanKind,SpanStatusCode,trace}from"@opentelemetry/api";import{MECHANISM_TYPE,isNonErrorException,toException}from"@interfere/types/sdk/errors";const ON_REQUEST_ERROR_MECHANISM={type:MECHANISM_TYPE.nextjs.onRequestError,handled:!1,synthetic:!1},SERVER_ACTION_MECHANISM={type:MECHANISM_TYPE.nextjs.serverAction,handled:!1,synthetic:!1},ROUTE_HANDLER_MECHANISM={type:MECHANISM_TYPE.nextjs.routeHandler,handled:!1,synthetic:!1},DEFAULT_CAPTURE_ERROR_MECHANISM={type:MECHANISM_TYPE.nextjs.captureError,handled:!0},CONTROL_FLOW_DIGEST_PREFIXES=[`NEXT_REDIRECT`,`NEXT_NOT_FOUND`,`NEXT_HTTP_ERROR_FALLBACK`];function isNextControlFlowError(error){if(!(error instanceof Error))return!1;let digest=error.digest;return typeof digest==`string`&&CONTROL_FLOW_DIGEST_PREFIXES.some(prefix=>digest.startsWith(prefix))}const seen=new WeakSet;function buildAttrs(value,mechanism,context){let attrs={"interfere.exception.mechanism":mechanism.type,"interfere.exception.handled":mechanism.handled},digest=context?.nextjs?.errorDigest;if(digest&&(attrs[`interfere.error.digest`]=digest),context?.nextjs?.requestMethod&&(attrs[`http.request.method`]=context.nextjs.requestMethod),context?.nextjs?.requestPath&&(attrs[`url.path`]=context.nextjs.requestPath),context?.nextjs?.routePath&&(attrs[`http.route`]=context.nextjs.routePath),context?.nextjs?.routeType===`route`&&!mechanism.handled&&(attrs[`http.response.status_code`]=500),context?.serverAction&&(attrs[`interfere.server_action.name`]=context.serverAction.name,context.serverAction.argsShape&&(attrs[`interfere.server_action.args_shape`]=context.serverAction.argsShape)),context?.requestHeaders)for(let[name,headerValue]of Object.entries(context.requestHeaders))attrs[`http.request.header.${name}`]=headerValue;return isNonErrorException(value)?(attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`,attrs):(attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack),attrs)}function recordException({error,mechanism,context}){let value=toException(error),attrs=buildAttrs(value,mechanism,context),tracer=trace.getTracer(`@interfere/next/server`),active=trace.getActiveSpan();if(active?.isRecording()){active.addEvent(`exception`,attrs),mechanism.handled||active.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message});return}let span=tracer.startSpan(`interfere.captureError`,{kind:SpanKind.INTERNAL});span.addEvent(`exception`,attrs),mechanism.handled||span.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message}),span.end()}function captureError(error,_request,context){if(isEnabledOnServer()&&isPluginEnabled(`errors`)&&!isNextControlFlowError(error)){if(error instanceof Error){if(seen.has(error))return;seen.add(error)}recordException({error,mechanism:context?.mechanism??DEFAULT_CAPTURE_ERROR_MECHANISM,context})}}const CAPTURED_REQUEST_HEADERS=[`accept`,`accept-language`,`content-length`,`content-type`,`host`,`referer`,`user-agent`,`x-forwarded-for`,`x-forwarded-host`,`x-forwarded-proto`,`x-vercel-id`];function pickAllowedHeaders(headers){if(!headers)return;let picked={};for(let name of CAPTURED_REQUEST_HEADERS){let value=headers[name];typeof value==`string`&&(picked[name]=value)}return Object.keys(picked).length>0?picked:void 0}async function onRequestError(error,request,context){if(isNextControlFlowError(error)||seen.has(error)||(seen.add(error),!isEnabledOnServer())||!isPluginEnabled(`errors`))return;let action=readServerAction(error),mechanism=ON_REQUEST_ERROR_MECHANISM;action?mechanism=SERVER_ACTION_MECHANISM:context.routeType===`route`&&(mechanism=ROUTE_HANDLER_MECHANISM);let requestHeaders=pickAllowedHeaders(request?.headers);recordException({error,mechanism,context:{mechanism,nextjs:{...context,...request?.method?{requestMethod:request.method}:{},...request?.path?{requestPath:request.path}:{},...error.digest?{errorDigest:error.digest}:{}},...requestHeaders?{requestHeaders}:{},...action?{serverAction:action}:{}}});try{await flushServerTelemetry()}catch{return}}export{captureError,onRequestError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let flushFn=null;function setServerFlush(fn){flushFn=fn}function flushServerTelemetry(){return flushFn?flushFn():Promise.resolve()}export{flushServerTelemetry,setServerFlush};
|
package/dist/package.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var name=`@interfere/next`,version=`11.0.0-canary.
|
|
1
|
+
var name=`@interfere/next`,version=`11.0.0-canary.6`;export{name,version};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/next",
|
|
3
|
-
"version": "11.0.0-canary.
|
|
3
|
+
"version": "11.0.0-canary.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Build software that never breaks.",
|
|
6
6
|
"keywords": [
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
"typecheck": "tsgo --noEmit"
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
-
"@interfere/constants": "^9.0.2-canary.
|
|
102
|
-
"@interfere/helpers": "^9.0.
|
|
103
|
-
"@interfere/react": "^11.0.0-canary.
|
|
104
|
-
"@interfere/sdk": "^11.0.0-canary.
|
|
105
|
-
"@interfere/types": "^
|
|
101
|
+
"@interfere/constants": "^9.0.2-canary.2",
|
|
102
|
+
"@interfere/helpers": "^9.0.1-canary.1",
|
|
103
|
+
"@interfere/react": "^11.0.0-canary.6",
|
|
104
|
+
"@interfere/sdk": "^11.0.0-canary.6",
|
|
105
|
+
"@interfere/types": "^10.0.0-canary.5",
|
|
106
106
|
"@opentelemetry/api": "^1.9.1",
|
|
107
107
|
"@opentelemetry/api-logs": "^0.219.0",
|
|
108
108
|
"@opentelemetry/baggage-span-processor": "^0.5.0",
|
|
@@ -138,8 +138,8 @@
|
|
|
138
138
|
}
|
|
139
139
|
},
|
|
140
140
|
"devDependencies": {
|
|
141
|
-
"@interfere/test-utils": "^9.0.0",
|
|
142
|
-
"@interfere/typescript-config": "^9.0.0",
|
|
141
|
+
"@interfere/test-utils": "^9.0.1-canary.0",
|
|
142
|
+
"@interfere/typescript-config": "^9.0.1-canary.0",
|
|
143
143
|
"@types/node": "^26.0.0",
|
|
144
144
|
"@types/react": "19.2.17",
|
|
145
145
|
"@types/react-dom": "19.2.3",
|