Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions apps/app/src/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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
Expand All @@ -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,
});
Expand Down