@interfere/next 12.2.0 → 12.3.1
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 +11 -10
- package/dist/config.d.mts +2 -0
- 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/injected-values.d.mts +12 -0
- package/dist/internal/build/injected-values.mjs +1 -0
- package/dist/internal/build/value-injection-loader.mjs +1 -1
- package/dist/internal/env.d.mts +1 -0
- package/dist/internal/env.mjs +1 -1
- package/dist/internal/release-slug.mjs +1 -1
- package/dist/internal/server/instrumentation-options.d.mts +2 -4
- package/dist/package.mjs +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -84,6 +84,16 @@ export default function RootLayout({
|
|
|
84
84
|
|
|
85
85
|
`InterfereProvider` captures render errors by default and rethrows them so your host error boundary keeps control of the fallback. Set `captureRenderErrors={false}` to disable this capture. The deprecated `errorBoundary` prop remains supported; `captureRenderErrors` takes precedence when both are set.
|
|
86
86
|
|
|
87
|
+
### Service identity
|
|
88
|
+
|
|
89
|
+
`withInterfere` uses the application's unscoped `package.json` name as the default `service.name` for browser, server, and edge telemetry. For example, `@profound/platform` becomes `platform`. A build-time `OTEL_SERVICE_NAME` overrides the package name, or set a shared default explicitly:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
export default withInterfere({ serviceName: "platform" }, config);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
An explicit `serviceName` passed to browser `init()` or server/edge `register()` takes precedence. Server and edge runtimes also honor `OTEL_SERVICE_NAME` ahead of the build default. If no name can be inferred or configured, OpenTelemetry's unknown-service fallback remains.
|
|
96
|
+
|
|
87
97
|
### Environment Variables
|
|
88
98
|
|
|
89
99
|
| Variable | Required | Description |
|
|
@@ -141,16 +151,7 @@ Secret keys that were created for one app keep working. New secret keys belong t
|
|
|
141
151
|
|
|
142
152
|
The standard instrumentation export works on Vercel and other Next.js hosts. In `full` mode, Interfere exports application spans directly. When the build config selects `drain`, the Node SDK initializes `@vercel/otel` with its default processors so Vercel can forward application spans through the configured Trace Drain. Platform spans and application spans remain separate observations.
|
|
143
153
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
```ts
|
|
147
|
-
import { register as registerInterfere } from "@interfere/next/instrumentation";
|
|
148
|
-
|
|
149
|
-
export const register = () => registerInterfere({ serverTracing: "full" });
|
|
150
|
-
export { onRequestError } from "@interfere/next/instrumentation";
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
The explicit option takes precedence over build-injected and environment settings. Edge always exports directly because Vercel does not forward custom Edge spans through Trace Drains. Edge reads the build-injected release identity, falling back to the configured commit SHA.
|
|
154
|
+
The mode and the hosting platform come only from the surface configuration that the build injects. When that configuration reports the Vercel platform (the Surface is linked to a Vercel project), direct trace and log exports are capped at 2 s so a flush cannot hold the invocation open. Edge always exports directly because Vercel does not forward custom Edge spans through Trace Drains. Edge reads the build-injected release identity, falling back to the configured commit SHA.
|
|
154
155
|
|
|
155
156
|
### Composing with an existing Vercel OTel setup
|
|
156
157
|
|
package/dist/config.d.mts
CHANGED
|
@@ -26,6 +26,8 @@ export interface NextConfigWithInterfere extends NextConfig {
|
|
|
26
26
|
* config so SDK options never collide with Next's own keys.
|
|
27
27
|
*/
|
|
28
28
|
export interface NextPluginConfig {
|
|
29
|
+
/** Default service name for browser, server, and edge telemetry. Falls back to OTEL_SERVICE_NAME, then the app package name without its scope. */
|
|
30
|
+
readonly serviceName?: string;
|
|
29
31
|
readonly sourceMaps?: {
|
|
30
32
|
/** Upload source maps to Interfere. Defaults to true. Release registration and telemetry stay enabled when false. */
|
|
31
33
|
readonly upload?: boolean;
|
package/dist/config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{configureBuild}from"./internal/build/configure-build.mjs";import{runGitCommand}from"./internal/build/release/git.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{
|
|
1
|
+
import{configureBuild}from"./internal/build/configure-build.mjs";import{runGitCommand}from"./internal/build/release/git.mjs";import{interfereInjectedValues}from"./internal/build/injected-values.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{resolveBuildServiceName}from"@interfere/build/service-name";import{API_URL}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{checkReleaseConfig,diagnoseRelease}from"@interfere/types/sdk/build-diagnostics";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{BUILD_MARKER_GLOBAL,DISABLED_GLOBAL,RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{PHASE_PRODUCTION_BUILD}from"next/constants.js";const CLIENT_TRACE_METADATA_KEYS=[`traceparent`,`tracestate`,`baggage`],DIAGNOSTIC_CONTEXT={publicKeyEnvVar:`INTERFERE_PUBLIC_KEY`,docsUrl:`https://interfere.com/docs/sdk/next-js`};function isThenable(value){return typeof value==`object`&&!!value&&`then`in value&&typeof value.then==`function`}function withInterfere(...args){let[settings,nextConfig]=args.length===2?[args[0],args[1]]:[{},args[0]??{}];return(phase,context)=>{let resolved=typeof nextConfig==`function`?nextConfig(phase,context??{defaultConfig:{}}):nextConfig;return isThenable(resolved)?Promise.resolve(resolved).then(config=>buildInterfereConfig(phase,settings,config)):buildInterfereConfig(phase,settings,resolved)}}function interfereCompilerConfig(compiler,config){let existingHook=compiler?.runAfterProductionCompile;return omitUndefined({...compiler,async runAfterProductionCompile(context){existingHook&&await existingHook(context),config.publicKey===null&&log.warn(`Public key not set`,[`INTERFERE_PUBLIC_KEY is not set, so this build sends no events.`,`Set it on builds that you deploy.`]);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}`])}}})}function resolveBrowserSourceMaps(config,productionBrowserSourceMaps){let releasing=config.apiKey!==null&&config.uploadSourceMaps;return releasing&&productionBrowserSourceMaps===!1&&log.warn(`Forcing productionBrowserSourceMaps`,[`withInterfere() requires production source maps to symbolicate errors.`,"Your `productionBrowserSourceMaps: false` was overridden to `true`."]),releasing?!0:productionBrowserSourceMaps}function disabledInterfereConfig(nextConfig){let{interfere:_interfere,webpack,turbopack,...rest}=nextConfig,projectDir=process.cwd(),build=configureBuild({existingTurbopack:turbopack,existingWebpack:webpack,nextMajor:readNextMajorVersion(projectDir),projectDir,remoteConfigFetch:void 0,values:{[BUILD_MARKER_GLOBAL]:!0,[DISABLED_GLOBAL]:!0,[RELEASE_SLUG_GLOBAL]:null}});return omitUndefined({...rest,turbopack:build.turbopack,webpack:build.webpack})}function buildInterfereConfig(phase,settings,nextConfig){if(settings.disable)return disabledInterfereConfig(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(settings,phase),apiHost=resolveBrowserApiHost(interfere?.apiHost,config.apiUrl),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,nextMajor=readNextMajorVersion(projectDir),build=configureBuild({existingTurbopack:turbopack,existingWebpack:webpack,nextMajor,projectDir,remoteConfigFetch:resolveRemoteConfigFetch(config,phase),values:interfereInjectedValues(config,apiHost,forceEnable,resolveBuildServiceName({root:projectDir,option:settings.serviceName}))});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 experimental=interfereExperimentalConfig({existing:rest.experimental,instrumentationHook:nextMajor===null||nextMajor<=14,traceMetadata:config.publicKey!==null||forceEnable});return omitUndefined({...rest,env:userEnv,compiler:interfereCompilerConfig(compiler,config),productionBrowserSourceMaps:resolveBrowserSourceMaps(config,productionBrowserSourceMaps),turbopack:build.turbopack,webpack:build.webpack,experimental})}function interfereExperimentalConfig({existing,instrumentationHook,traceMetadata}){let merged={...existing};return instrumentationHook&&(merged.instrumentationHook=!0),traceMetadata&&(merged.clientTraceMetadata=[...new Set([...existing?.clientTraceMetadata??[],...CLIENT_TRACE_METADATA_KEYS])]),Object.keys(merged).length>0?merged:void 0}function resolveBrowserApiHost(apiHost,apiUrl){let host=apiHost??apiUrl;if(host!==API_URL)return normalizeHost(host)}function normalizeHost(host){try{return new URL(host).origin}catch{return log.fatal(`Invalid apiHost`,[`interfere.apiHost must be a full URL, e.g. "https://in.yourapp.com".`,`Received: ${host}`])}}function resolveBuildConfig(settings,phase){let{apiKey,apiUrl,publicKey}=readInterfereEnv(),{commitSha,slug}=resolveReleaseSlug(runGitCommand),environment=phase===PHASE_PRODUCTION_BUILD?resolveDeployEnvironment(process.env):null;return{apiKey:apiKey??null,apiUrl,buildId:commitSha,environment,publicKey:publicKey??null,purgeSourceMaps:settings.sourceMaps?.purge??!0,uploadSourceMaps:settings.sourceMaps?.upload??!0,releaseSlug:slug}}function resolveRemoteConfigFetch(config,phase){if(phase===PHASE_PRODUCTION_BUILD&&config.publicKey)return{apiUrl:config.apiUrl,cacheScope:crypto.randomUUID(),publicKey:config.publicKey}}async function runBuildReleasePipeline(context,config){let release=checkReleaseConfig(DIAGNOSTIC_CONTEXT,{apiKey:config.apiKey,commitSha:config.buildId,releaseSlug:config.releaseSlug});if(release.status===`skip`){log.warn(release.title,[...release.details]);return}if(release.status===`fail`)return log.fatal(release.title,[...release.details]);let{runBuildPipeline}=await import(`./internal/build/pipeline.mjs`);try{let result=await runBuildPipeline(context,{...config,apiKey:release.apiKey,buildId:release.commitSha,releaseSlug:release.releaseSlug});if(!result.accepted){result.reason===`no_source_maps`&&log.warn(`Release remains unready`,[`No source maps found. Enable source-map generation and upload them during the build.`]);return}log.info(`Completed`,[`https://interfere.com/~/${result.config.org.slug}/apps/${result.config.surface.slug}`,`Release: ${result.release.destination.slug}`,`Build: ${result.buildId}`,config.uploadSourceMaps?`Artifacts: ${result.fileCount} source maps`:`Source-map uploads disabled`])}catch(error){let diagnostic=diagnoseRelease(DIAGNOSTIC_CONTEXT,error);log[diagnostic.severity](diagnostic.title,[...diagnostic.details])}}export{withInterfere};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readInterfereEnv}from"./internal/env.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{FetchTraceExporter}from"./internal/server/exporters/edge-exporter.mjs";import{setServerFlush}from"./internal/server/exporters/server-flush.mjs";import{onRequestError}from"./internal/server/capture/capture.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{getStringFromEnv}from"@opentelemetry/core";import{createUrlRedactionSpanProcessor,resolveUrlRedaction}from"@interfere/types/sdk/url-redaction";import{trace}from"@opentelemetry/api";import{defaultServiceName,resourceFromAttributes}from"@opentelemetry/resources";import{BasicTracerProvider,SimpleSpanProcessor}from"@opentelemetry/sdk-trace-base";let registered=!1;async 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:resolveReleaseSlug().slug;releaseSlug||console.warn(`[interfere] edge runtime has no release.slug; configure a build release or INTERFERE_SOURCE_ID.`);let provider=new BasicTracerProvider({resource:resourceFromAttributes(omitUndefined({"deployment.environment.name":env.nodeEnvironment,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,"service.name":opts.serviceName||getStringFromEnv(`OTEL_SERVICE_NAME`)||defaultServiceName(),"service.namespace":opts.serviceNamespace,"telemetry.sdk.language":`nodejs`,"release.slug":releaseSlug||void 0})),spanProcessors:[createUrlRedactionSpanProcessor(resolveUrlRedaction(opts.privacy?.urls)),new SimpleSpanProcessor(new FetchTraceExporter({baseUrl:env.apiUrl,publicKeyHeader:{apiKey:env.publicKey},headers:{"x-interfere-producer-version":PRODUCER_VERSION}}))]});return trace.setGlobalTracerProvider(provider),setServerFlush(async()=>provider.forceFlush({timeoutMillis:75e3})),registered=!0,Promise.resolve()}function buildInterfereOtelKit(_opts={}){return null}export{buildInterfereOtelKit,onRequestError,register};
|
|
1
|
+
import{readInterfereEnv}from"./internal/env.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{FetchTraceExporter}from"./internal/server/exporters/edge-exporter.mjs";import{setServerFlush}from"./internal/server/exporters/server-flush.mjs";import{onRequestError}from"./internal/server/capture/capture.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{getStringFromEnv}from"@opentelemetry/core";import{createUrlRedactionSpanProcessor,resolveUrlRedaction}from"@interfere/types/sdk/url-redaction";import{trace}from"@opentelemetry/api";import{defaultServiceName,resourceFromAttributes}from"@opentelemetry/resources";import{BasicTracerProvider,SimpleSpanProcessor}from"@opentelemetry/sdk-trace-base";let registered=!1;async 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:resolveReleaseSlug().slug;releaseSlug||console.warn(`[interfere] edge runtime has no release.slug; configure a build release or INTERFERE_SOURCE_ID.`);let provider=new BasicTracerProvider({resource:resourceFromAttributes(omitUndefined({"deployment.environment.name":env.nodeEnvironment,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,"service.name":opts.serviceName||getStringFromEnv(`OTEL_SERVICE_NAME`)||env.serviceName||defaultServiceName(),"service.namespace":opts.serviceNamespace,"telemetry.sdk.language":`nodejs`,"release.slug":releaseSlug||void 0})),spanProcessors:[createUrlRedactionSpanProcessor(resolveUrlRedaction(opts.privacy?.urls)),new SimpleSpanProcessor(new FetchTraceExporter({baseUrl:env.apiUrl,publicKeyHeader:{apiKey:env.publicKey},headers:{"x-interfere-producer-version":PRODUCER_VERSION}}))]});return trace.setGlobalTracerProvider(provider),setServerFlush(async()=>provider.forceFlush({timeoutMillis:75e3})),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{setServerFlush}from"./internal/server/exporters/server-flush.mjs";import{fetchAndCacheRemoteConfig}from"./internal/server/remote-config.mjs";import{onRequestError}from"./internal/server/capture/capture.mjs";import{CacheSafeTraceContextPropagator}from"./internal/server/tracing/cache-safe-trace-context.mjs";import{bridgeConsoleToOtel}from"./internal/server/capture/console-bridge.mjs";import{FreshnessStampingPropagator}from"./internal/server/tracing/freshness-propagator.mjs";import{installGlobalHandlers}from"./internal/server/capture/global-handlers.mjs";import{PrerenderSafeIdGenerator}from"./internal/server/tracing/id-generator.mjs";import{drainUrl}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{CompositePropagator,W3CBaggagePropagator,getStringFromEnv}from"@opentelemetry/core";import{createUrlRedactionSpanProcessor,resolveUrlRedaction}from"@interfere/types/sdk/url-redaction";import{ProxyTracerProvider,propagation,trace}from"@opentelemetry/api";import{defaultServiceName,resourceFromAttributes}from"@opentelemetry/resources";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{readLogSourcingMode}from"@interfere/types/sdk/log-sourcing";import{
|
|
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/exporters/server-flush.mjs";import{fetchAndCacheRemoteConfig}from"./internal/server/remote-config.mjs";import{onRequestError}from"./internal/server/capture/capture.mjs";import{CacheSafeTraceContextPropagator}from"./internal/server/tracing/cache-safe-trace-context.mjs";import{bridgeConsoleToOtel}from"./internal/server/capture/console-bridge.mjs";import{FreshnessStampingPropagator}from"./internal/server/tracing/freshness-propagator.mjs";import{installGlobalHandlers}from"./internal/server/capture/global-handlers.mjs";import{PrerenderSafeIdGenerator}from"./internal/server/tracing/id-generator.mjs";import{drainUrl}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{CompositePropagator,W3CBaggagePropagator,getStringFromEnv}from"@opentelemetry/core";import{createUrlRedactionSpanProcessor,resolveUrlRedaction}from"@interfere/types/sdk/url-redaction";import{ProxyTracerProvider,propagation,trace}from"@opentelemetry/api";import{defaultServiceName,resourceFromAttributes}from"@opentelemetry/resources";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{readLogSourcingMode}from"@interfere/types/sdk/log-sourcing";import{VERCEL_EXPORT_TIMEOUT_MS,readServerTracing}from"@interfere/types/sdk/server-tracing";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{CompressionAlgorithm}from"@opentelemetry/otlp-exporter-base";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";const FLUSH_TIMEOUT_MS=75e3;function exportTimeouts(vercel){return vercel?{attempt:VERCEL_EXPORT_TIMEOUT_MS,batch:VERCEL_EXPORT_TIMEOUT_MS,flush:VERCEL_EXPORT_TIMEOUT_MS}:{attempt:65e3,batch:7e4,flush:FLUSH_TIMEOUT_MS}}let flushTimeoutMs=FLUSH_TIMEOUT_MS;function canFlush(provider){return`forceFlush`in provider&&typeof provider.forceFlush==`function`}let registered=!1,tracerProvider=null,loggerProvider=null;async function flush(){await Promise.all([tracerProvider?.forceFlush({timeoutMillis:flushTimeoutMs}),loggerProvider?.forceFlush({timeoutMillis:flushTimeoutMs})])}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 tracesUrl=drainUrl(env.apiUrl,`traces`,env.publicKey),logsUrl=drainUrl(env.apiUrl,`logs`,env.publicKey),exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION},resourceAttributes=omitUndefined({"deployment.environment.name":env.nodeEnvironment,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,"service.name":opts.serviceName||getStringFromEnv(`OTEL_SERVICE_NAME`)||env.serviceName||defaultServiceName(),"service.namespace":opts.serviceNamespace,"telemetry.sdk.language":`nodejs`,"release.slug":releaseSlug||void 0}),compression=opts.compression===`gzip`?CompressionAlgorithm.GZIP:CompressionAlgorithm.NONE,tracing=readServerTracing(),isDrainMode=tracing.mode===`drain`,timeouts=exportTimeouts(tracing.vercel),spanProcessors=[createUrlRedactionSpanProcessor(resolveUrlRedaction(opts.privacy?.urls)),new BaggageSpanProcessor(()=>!0),...isDrainMode?[]:[new BatchSpanProcessor(new OTLPTraceExporter({compression,headers:exporterHeaders,timeoutMillis:timeouts.attempt,url:tracesUrl}),{exportTimeoutMillis:timeouts.batch})],...opts._internalAdditionalSpanProcessors??[]],isLogDrainMode=readLogSourcingMode()===`drain`,logRecordProcessors=[...isLogDrainMode?[]:[new BatchLogRecordProcessor({exportTimeoutMillis:timeouts.batch,exporter:new OTLPLogExporter({compression,headers:exporterHeaders,timeoutMillis:timeouts.attempt,url:logsUrl})})],...opts._internalAdditionalLogRecordProcessors??[]];return{enableConsoleBridge:()=>isLogDrainMode?()=>{}:bridgeConsoleToOtel(),fetchRemoteConfig:async()=>fetchAndCacheRemoteConfig(),idGenerator:new PrerenderSafeIdGenerator,instrumentations:[],traceContextPropagator:new CacheSafeTraceContextPropagator,logRecordProcessors,propagators:[new FreshnessStampingPropagator,new W3CBaggagePropagator],resourceAttributes,spanProcessors}}async function register(opts={}){if(registered)return;let tracing=readServerTracing(),drainMode=tracing.mode===`drain`;if(flushTimeoutMs=exportTimeouts(tracing.vercel).flush,drainMode&&process.env.OTEL_SDK_DISABLED?.trim())return;let kit=buildInterfereOtelKit(opts);if(!kit)return;let resource=resourceFromAttributes(kit.resourceAttributes);if(drainMode){let{registerOTel}=await import(`@vercel/otel`);registerOTel({serviceName:String(kit.resourceAttributes[`service.name`]),attributes:kit.resourceAttributes,idGenerator:kit.idGenerator,instrumentations:kit.instrumentations,propagators:[`auto`,kit.traceContextPropagator,...kit.propagators],spanProcessors:[`auto`,...kit.spanProcessors]});let provider=trace.getTracerProvider(),delegate=provider instanceof ProxyTracerProvider?provider.getDelegate():provider;if(!canFlush(delegate))throw Error(`Interfere could not register the Vercel tracer provider. Use buildInterfereOtelKit with an existing OpenTelemetry bootstrap.`);tracerProvider=delegate}else{let provider=new NodeTracerProvider({idGenerator:kit.idGenerator,resource,spanProcessors:kit.spanProcessors});propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[kit.traceContextPropagator,...kit.propagators]})),provider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),tracerProvider=provider}loggerProvider=new LoggerProvider({processors:kit.logRecordProcessors,resource});let{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider),registerInstrumentations({instrumentations:kit.instrumentations,tracerProvider:trace.getTracerProvider()}),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}export{PrerenderSafeIdGenerator,buildInterfereOtelKit,flush,onRequestError,register};
|
|
@@ -8,6 +8,7 @@ interface InterfereInjectedValues {
|
|
|
8
8
|
readonly __INTERFERE_FORCE_ENABLE__?: boolean;
|
|
9
9
|
readonly __INTERFERE_PUBLIC_KEY__?: string;
|
|
10
10
|
readonly __INTERFERE_RELEASE_SLUG__: string | null;
|
|
11
|
+
readonly __INTERFERE_SERVICE_NAME__?: string;
|
|
11
12
|
}
|
|
12
13
|
/** Build-time `/v3/config` request options for remote SDK configuration. */
|
|
13
14
|
export interface RemoteConfigFetch {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ResolvedBuildConfig } from "../../config.mjs";
|
|
2
|
+
//#region src/internal/build/injected-values.d.ts
|
|
3
|
+
export declare function interfereInjectedValues(config: ResolvedBuildConfig, apiHost: string | undefined, forceEnable: boolean, serviceName: string | undefined): import("@interfere/helpers/omit-undefined").OmitUndefined<{
|
|
4
|
+
__INTERFERE_SERVICE_NAME__: string | undefined;
|
|
5
|
+
__INTERFERE_RELEASE_SLUG__: (`rel_${string}` & import("zod").$brand<"ReleaseSlug">) | null;
|
|
6
|
+
__INTERFERE_BUILD__: boolean;
|
|
7
|
+
__INTERFERE_PUBLIC_KEY__: string | undefined;
|
|
8
|
+
__INTERFERE_API_URL__: string | undefined;
|
|
9
|
+
__INTERFERE_ENVIRONMENT__: string | undefined;
|
|
10
|
+
__INTERFERE_FORCE_ENABLE__: boolean | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{omitUndefined}from"@interfere/helpers/omit-undefined";import{API_URL_GLOBAL,BUILD_MARKER_GLOBAL,ENVIRONMENT_GLOBAL,FORCE_ENABLE_GLOBAL,PUBLIC_KEY_GLOBAL,RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{SERVICE_NAME_GLOBAL}from"@interfere/types/sdk/service-name";function interfereInjectedValues(config,apiHost,forceEnable,serviceName){let releaseSlug=forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug;return omitUndefined({[SERVICE_NAME_GLOBAL]:serviceName,[RELEASE_SLUG_GLOBAL]:releaseSlug,[BUILD_MARKER_GLOBAL]:!0,[PUBLIC_KEY_GLOBAL]:config.publicKey||void 0,[API_URL_GLOBAL]:config.publicKey&&apiHost?apiHost:void 0,[ENVIRONMENT_GLOBAL]:config.environment||void 0,[FORCE_ENABLE_GLOBAL]:forceEnable?!0:void 0})}export{interfereInjectedValues};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{log}from"../logger.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{INGEST_URL_GLOBAL}from"@interfere/types/sdk/injected-globals";import{PLUGINS_GLOBAL}from"@interfere/types/sdk/remote-config";import{LOG_SOURCING_GLOBAL}from"@interfere/types/sdk/log-sourcing";import{SERVER_TRACING_GLOBAL}from"@interfere/types/sdk/server-tracing";import{callbackify}from"node:util";import{createBuildConfigResolver}from"@interfere/build/config";let remoteConfigFallbackLogged=!1;const resolveBuildConfig=createBuildConfigResolver(result=>{result.status!==`fallback`||remoteConfigFallbackLogged||(remoteConfigFallbackLogged=!0,log.warn(`Using default SDK settings`,[`Could not load SDK settings from Interfere. The build continues with the default settings.`]))});function valueInjectionLoader(userCode){let options=this.getOptions(),callback=this.async(),values=resolveValues(options);callbackify(async()=>{let globals=await resolveRemoteConfig(resolveFetch(options)).catch(()=>({}));return render({...values,...globals},userCode)})(callback)}function remoteGlobals(config){return omitUndefined({[SERVER_TRACING_GLOBAL]:config.serverTracing,[LOG_SOURCING_GLOBAL]:config.logSourcing,[INGEST_URL_GLOBAL]:config.ingestUrl,[PLUGINS_GLOBAL]:config.plugins})}function render(values,userCode){let lines=Object.entries(values).map(([key,value])=>`globalThis[${JSON.stringify(key)}] = ${JSON.stringify(value)};`);return lines.length===0?userCode:`${lines.join(`
|
|
1
|
+
import{log}from"../logger.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{INGEST_URL_GLOBAL}from"@interfere/types/sdk/injected-globals";import{PLUGINS_GLOBAL}from"@interfere/types/sdk/remote-config";import{LOG_SOURCING_GLOBAL}from"@interfere/types/sdk/log-sourcing";import{SERVER_TRACING_GLOBAL}from"@interfere/types/sdk/server-tracing";import{callbackify}from"node:util";import{createBuildConfigResolver}from"@interfere/build/config";import{PLATFORM_GLOBAL}from"@interfere/types/integrations/platforms/hosting";let remoteConfigFallbackLogged=!1;const resolveBuildConfig=createBuildConfigResolver(result=>{result.status!==`fallback`||remoteConfigFallbackLogged||(remoteConfigFallbackLogged=!0,log.warn(`Using default SDK settings`,[`Could not load SDK settings from Interfere. The build continues with the default settings.`]))});function valueInjectionLoader(userCode){let options=this.getOptions(),callback=this.async(),values=resolveValues(options);callbackify(async()=>{let globals=await resolveRemoteConfig(resolveFetch(options)).catch(()=>({}));return render({...values,...globals},userCode)})(callback)}function remoteGlobals(config){return omitUndefined({[SERVER_TRACING_GLOBAL]:config.serverTracing,[LOG_SOURCING_GLOBAL]:config.logSourcing,[PLATFORM_GLOBAL]:config.platform,[INGEST_URL_GLOBAL]:config.ingestUrl,[PLUGINS_GLOBAL]:config.plugins})}function render(values,userCode){let lines=Object.entries(values).map(([key,value])=>`globalThis[${JSON.stringify(key)}] = ${JSON.stringify(value)};`);return lines.length===0?userCode:`${lines.join(`
|
|
2
2
|
`)}\n${userCode}`}async function resolveRemoteConfig(fetchOptions){return fetchOptions?resolveBuildConfig(fetchOptions.apiUrl,fetchOptions.publicKey,fetchOptions.cacheScope).then(remoteGlobals):{}}function parseJson(text){if(typeof text==`string`)try{return JSON.parse(text)}catch{return}}function resolveFetch(options){let parsed=parseJson(options.serializedFetch);return isRemoteConfigFetch(parsed)?parsed:null}function isRemoteConfigFetch(value){return isRecord(value)&&typeof value.apiUrl==`string`&&typeof value.publicKey==`string`&&(value.cacheScope===void 0||typeof value.cacheScope==`string`)}function resolveValues(options){let parsed=parseJson(options.serializedValues);return isRecord(parsed)?parsed:{}}function isRecord(value){return typeof value==`object`&&!!value&&!Array.isArray(value)}export{valueInjectionLoader as default};
|
package/dist/internal/env.d.mts
CHANGED
package/dist/internal/env.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{interfereDisabled}from"./build-marker-guard.mjs";import{API_URL}from"@interfere/constants/api";import{ENVIRONMENT_GLOBAL}from"@interfere/types/sdk/injected-globals";import{getStringGlobal}from"@interfere/react/util/global";import{parseEnvValue}from"@interfere/types/sdk/env";import{resolveEnvironment}from"@interfere/types/sdk/runtime";function isEnabledOnServer(){return interfereDisabled()?!1:process.env.NODE_ENV===`production`||!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function readInterfereEnv(){let nodeEnvironment=resolveEnvironment({env:process.env,explicit:getStringGlobal(ENVIRONMENT_GLOBAL)});return{apiKey:parseEnvValue(process.env.INTERFERE_API_KEY),apiUrl:parseEnvValue(process.env.INTERFERE_API_URL)??API_URL,nextRuntime:parseEnvValue(process.env.NEXT_RUNTIME),nodeEnvironment,publicKey:interfereDisabled()?null:parseEnvValue(process.env.INTERFERE_PUBLIC_KEY),release:{destinationId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_RELEASE_ID),sourceId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_BUILD_ID)}}}export{isEnabledOnServer,readInterfereEnv};
|
|
1
|
+
import{interfereDisabled}from"./build-marker-guard.mjs";import{API_URL}from"@interfere/constants/api";import{ENVIRONMENT_GLOBAL}from"@interfere/types/sdk/injected-globals";import{SERVICE_NAME_GLOBAL}from"@interfere/types/sdk/service-name";import{getStringGlobal}from"@interfere/react/util/global";import{parseEnvValue}from"@interfere/types/sdk/env";import{resolveEnvironment}from"@interfere/types/sdk/runtime";function isEnabledOnServer(){return interfereDisabled()?!1:process.env.NODE_ENV===`production`||!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function readInterfereEnv(){let nodeEnvironment=resolveEnvironment({env:process.env,explicit:getStringGlobal(ENVIRONMENT_GLOBAL)});return{serviceName:getStringGlobal(SERVICE_NAME_GLOBAL)??null,apiKey:parseEnvValue(process.env.INTERFERE_API_KEY),apiUrl:parseEnvValue(process.env.INTERFERE_API_URL)??API_URL,nextRuntime:parseEnvValue(process.env.NEXT_RUNTIME),nodeEnvironment,publicKey:interfereDisabled()?null:parseEnvValue(process.env.INTERFERE_PUBLIC_KEY),release:{destinationId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_RELEASE_ID),sourceId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_BUILD_ID)}}}export{isEnabledOnServer,readInterfereEnv};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{deriveReleaseSlug,releaseSlugSchema}from"@interfere/types/releases/slug";import{resolveReleaseCommitSha}from"@interfere/types/sdk/github-source";const noGit=()=>null;function readBakedReleaseSlug(){let globals=globalThis;if(!(RELEASE_SLUG_GLOBAL in globals))return null;let parsed=releaseSlugSchema.safeParse(globals[RELEASE_SLUG_GLOBAL]);return parsed.success?parsed.data:null}function resolveReleaseSlug(runGit=noGit){let baked=readBakedReleaseSlug();if(baked)return{commitSha:null,slug:baked};let commitSha=resolveReleaseCommitSha(process.env,runGit);return{commitSha,slug:commitSha?deriveReleaseSlug(commitSha):null}}export{resolveReleaseSlug};
|
|
@@ -63,13 +63,11 @@ export interface ServerInstrumentationOptions {
|
|
|
63
63
|
urls?: UrlRedactionOption;
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
|
-
* Application service name. Defaults to `OTEL_SERVICE_NAME`, then
|
|
67
|
-
*
|
|
66
|
+
* Application service name. Defaults to `OTEL_SERVICE_NAME`, then the
|
|
67
|
+
* build-inferred app name, then OpenTelemetry's unknown-service fallback.
|
|
68
68
|
*/
|
|
69
69
|
serviceName?: string;
|
|
70
70
|
/** Optional application namespace for grouping related services. */
|
|
71
71
|
serviceNamespace?: string;
|
|
72
|
-
/** Overrides build-injected and environment tracing settings. Use full for direct export during local development. */
|
|
73
|
-
serverTracing?: "full" | "drain";
|
|
74
72
|
}
|
|
75
73
|
//#endregion
|
package/dist/package.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var name=`@interfere/next`,version=`12.
|
|
1
|
+
var name=`@interfere/next`,version=`12.3.1`;export{name,version};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/next",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.3.1",
|
|
4
4
|
"description": "Build software that never breaks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"error-tracking",
|
|
@@ -97,12 +97,12 @@
|
|
|
97
97
|
"typecheck": "bun check"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@interfere/build": "^0.
|
|
100
|
+
"@interfere/build": "^0.4.1",
|
|
101
101
|
"@interfere/constants": "^9.3.0",
|
|
102
102
|
"@interfere/helpers": "^9.3.0",
|
|
103
|
-
"@interfere/javascript": "^0.3.
|
|
104
|
-
"@interfere/react": "^12.
|
|
105
|
-
"@interfere/types": "^10.
|
|
103
|
+
"@interfere/javascript": "^0.3.1",
|
|
104
|
+
"@interfere/react": "^12.3.1",
|
|
105
|
+
"@interfere/types": "^10.5.1",
|
|
106
106
|
"@opentelemetry/api": "1.9.1",
|
|
107
107
|
"@opentelemetry/api-logs": "0.222.0",
|
|
108
108
|
"@opentelemetry/baggage-span-processor": "0.5.0",
|