Quickstart for using OpenTelemetry with Vercel Functions
Drains are available on Enterprise and Pro plans
Vercel supports OpenTelemetry traces. OpenTelemetry is an open standard for collecting traces from your application.
With OpenTelemetry on Vercel, you can:
- Export traces to your preferred observability provider using Vercel Drains.
- Automatically instrument Vercel infrastructure and fetch requests from Vercel Functions.
- Collect traces and spans you create with the OpenTelemetry SDK.
- Store traces on Vercel that are created with Session Tracing.
For JavaScript and Typescript users on Vercel, you can use the
@vercel/otelpackage to call the correct OpenTelemetry SDK for you.Install the OpenTelemetry JavaScript SDK and
@vercel/otel:pnpm i @opentelemetry/api @vercel/otelCreate an
instrumentation.tsfile in the root of your project, or, on Next.js it must be placed in thesrcdirectory if you are using one. Add the following code to initialize and configure OTel using@vercel/otel.instrumentation.tsimport { registerOTel } from '@vercel/otel'; export function register() { registerOTel({ serviceName: 'your-project-name' }); } // NOTE: You can replace `your-project-name` with the actual name of your projectBefore receiving traces from an APM vendor (such as DataDog), it may be necessary to first create the service you intend to use as a
serviceNamewithin the service catalog. Refer to the APM vendor's documentation for specific requirements.You can use standard OpenTelemetry SDK to send traces to our collector. List of all supported languages by OpenTelemetry and their SDK can be found in OpenTelemetry docs.
Begin by installing the following packages:
pnpm i @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http @opentelemetry/sdk-trace-nodeNext, create an
instrumentation.tsfile in the root of your project and add the following code to initialize and configure OTel.instrumentation.tsimport { NodeSDK } from '@opentelemetry/sdk-node'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { Resource } from '@opentelemetry/resources'; import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node'; export async function register() { const sdk = new NodeSDK({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: 'your-project-name', // NOTE: You can replace `your-project-name` with the actual name of your project }), spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()), }); await sdk.start(); }The provided service name will be used in your OpenTelemetry backend to distinguish traces from different services. You need to specify what you want to do with generated spans, there are two types of span processors:
SimpleSpanProcessor: sends each span to the collector right away. This type is shown in code aboveBatchSpanProcessor: collects a number of spans and sends them together to the collector. If you choose this type, you'll need to callprocessor.forceFlush()at the end of the invocation to immediately export all spans
A span processor needs to know what to do with processed traces. In order to export traces to Vercel OpenTelemetry collector, you need to use one of these exporters:
@opentelemetry/exporter-trace-otlp-http@opentelemetry/exporter-trace-otlp-grpc
Next.js 13.4+ supports auto-instrumentation which means you no longer have to create a span for each request. To use this feature in Next.js 13 & 14, you must explicitly opt-in by adding
experimental.instrumentationHook = trueto yournext.config.js. This is not required in Next.js 15+.For more information, please refer to the Next.js docs for auto-instrumentation.
For non-Next.js frameworks or Next.js version older than
13.4, you will need to manually create spans for each request.import { trace, context, propagation, SpanStatusCode } from '@opentelemetry/api'; export default async function getUser(request, response) { const incomingContext = propagation.extract(context.active(), request.headers); const tracer = trace.getTracer('your-project-name'); return tracer.startActiveSpan('get-user', async (span) => { try { const result = someFnThatMightThrowError(span); span.end(); return result; } catch (e) { span.recordException(e); span.setStatus({ code: SpanStatusCode.ERROR, message: e.message }); throw e; } }, incomingContext); }In the code above we are importing the OTel tracer to the
pages/api/get-user.tsfile to create spans for tracking performance. You'll need to include this import to any file that uses the tracer.
If you are using Sentry v8+, follow the Sentry documentation to learn how to use your existing custom OpenTelemetry setup.
Using Vercel OTel instead of Sentry: If you prefer to use Vercel's
OpenTelemetry setup instead of Sentry's OTel instrumentation, add
skipOpenTelemetrySetup: true to your Sentry initialization in your
instrumentation.ts file. This resolves conflicts between Vercel's OTel and
Sentry v8+ that can prevent traces from reaching downstream providers.
Was this helpful?