diff --git a/apps/app/src/instrumentation.ts b/apps/app/src/instrumentation.ts index bf57f96d9..ce1d8d8c5 100644 --- a/apps/app/src/instrumentation.ts +++ b/apps/app/src/instrumentation.ts @@ -1,7 +1,12 @@ import { diag } from '@opentelemetry/api'; +import { logs } from '@opentelemetry/api-logs'; import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; -import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'; +import { + BatchLogRecordProcessor, + LoggerProvider, + SimpleLogRecordProcessor, +} from '@opentelemetry/sdk-logs'; import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; import { OTLPHttpJsonTraceExporter, registerOTel } from '@vercel/otel'; @@ -11,20 +16,30 @@ export function register() { const otelEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT; const headers = parseHeaders(process.env.OTEL_EXPORTER_OTLP_HEADERS); + const isEdgeRuntime = process.env.NEXT_RUNTIME === 'edge'; - // Configure log export - const logRecordProcessors = - // Logging doesn't currently work on edge with OTel - process.env.NEXT_RUNTIME !== 'edge' && otelEndpoint - ? [ - new BatchLogRecordProcessor( - new OTLPLogExporter({ - url: `${otelEndpoint}/v1/logs`, - headers, - }), - ), - ] - : undefined; + // Configure log export with edge runtime workaround + // See: https://github.com/vercel/otel/issues/104 + // The workaround is to create our own LoggerProvider with empty logRecordLimits + // to avoid "Cannot read properties of undefined (reading 'attributeCountLimit')" error + if (otelEndpoint) { + const logExporter = new OTLPLogExporter({ + url: `${otelEndpoint}/v1/logs`, + headers, + }); + + // Use SimpleLogRecordProcessor for edge (more compatible), BatchLogRecordProcessor for Node.js + const logProcessor = isEdgeRuntime + ? new SimpleLogRecordProcessor(logExporter) + : new BatchLogRecordProcessor(logExporter); + + const loggerProvider = new LoggerProvider({ + // Empty logRecordLimits is the workaround for edge runtime bug + logRecordLimits: {}, + processors: [logProcessor], + }); + logs.setGlobalLoggerProvider(loggerProvider); + } // Configure trace exporter const traceExporter = otelEndpoint @@ -34,23 +49,23 @@ export function register() { }) : undefined; - // Configure metrics exporter - const metricReaders = otelEndpoint - ? [ - new PeriodicExportingMetricReader({ - exporter: new OTLPMetricExporter({ - url: `${otelEndpoint}/v1/metrics`, - headers, + // Configure metrics exporter (metrics not supported on edge runtime) + const metricReaders = + otelEndpoint && !isEdgeRuntime + ? [ + new PeriodicExportingMetricReader({ + exporter: new OTLPMetricExporter({ + url: `${otelEndpoint}/v1/metrics`, + headers, + }), + exportIntervalMillis: 5000, }), - // Logs are also flushed on exit - exportIntervalMillis: 5000, - }), - ] - : undefined; + ] + : undefined; registerOTel({ serviceName: process.env.OTEL_SERVICE_NAME || 'common', - logRecordProcessors, + // Don't pass logRecordProcessors - we've already set up our own LoggerProvider above traceExporter, metricReaders, });