Next.js Instrumentation on instrumentation.ts-tiedostoon perustuva sisäänrakennettu mekanismi, joka ajaa mielivaltaisen alustuskoodin ennen kuin ensimmäistäkään pyyntöä käsitellään. Käytännössä se on ainoa oikea paikka rekisteröidä OpenTelemetry-SDK, initialisoida Sentry tai käynnistää tietokantayhteysaltaan lämmitys. Yhdistettynä @vercel/otel-pakettiin ja onRequestError-koukkuun se antaa App Routerissa täyden jäljityksen server-komponenteista Server Actioneihin, middlewareen ja Route Handlereihin. Käyn tässä oppaassa läpi tuotantokelpoisen konfiguraation, jonka olen itse ajanut sisään monorepossa staff-eng-tason tiimissä (ja josta löytyy ne muutamat kompastuskivet, joista dokumentaatio vaikenee).
instrumentation.ts ajetaan kerran per Node.js- tai Edge-runtime-instanssi, ei per pyyntö. Se on rekisteröintipiste, ei middleware.
@vercel/otel (v1.13+) tarjoaa nollakonfiguraation OpenTelemetry-integraation kaikille App Routerin renderöintitiloille, mukaan lukien PPR ja Cache Components.
onRequestError-koukku (Next.js 15+) välittää palvelinvirheet strukturoidusti Sentryyn, Datadogiin tai omaan lokijärjestelmään ilman try/catch-boilerplaatteja.
Edge Runtime tukee OpenTelemetryä vain rajatusti. Pelkkä fetch-instrumentointi ja manuaaliset spanit toimivat, koska Node.js-natiiviperformancesta puuttuu API:ta.
Server Actionit jäljitetään automaattisesti spanina executeMutationAction, mutta niiden metatietoihin (form data, referrer) pitää lisätä käyttäjän oma attribuuttilogiikka.
OTLP-endpointin ympäristömuuttujat kannattaa asettaa next.config.ts:n serverExternalPackages-listalle, jotta Turbopack ei bundlaa OpenTelemetry-natiivimoduuleja.
Miksi Next.js instrumentation on välttämätön tuotannossa
Kun App Router siirtyi oletuksena palvelinkomponentteihin, jäljitys muuttui kertaheitolla vaikeammaksi. Yksi HTTP-pyyntö voi laukaista kymmeniä rinnakkaisia fetch-kutsuja, kolme Server Actionia, kaksi middleware-suoritusta ja useita use cache-välimuistihakuja. Ja kaikki tämä pyörii eri process-runtimeissa. Ilman keskitettyä instrumentointia jokainen kirjastototeutus (Prisma, Drizzle, Auth.js, react-query) joutuu itse patchaamaan omat kutsunsa, ja jäljityskonteksti katkeaa Server Componentin ja Client Componentin rajapinnalla.
Käytännössä olen nähnyt kolme oiretta, joita instrumentation korjaa. Ensinnäkin Vercel-lokeissa näkyy 500-virhe ilman stack tracea, koska React on jo ehtinyt flushata vastauksen suoratoistona. Toiseksi Server Action epäonnistuu, mutta client näkee vain geneerisen "Something went wrong" -viestin. Kolmanneksi välimuistihäkkyrä ei paljasta, mikä fetch-kutsu oikeasti osui verkkoon versus mikä palautui use cache-tulosjoukosta. OpenTelemetry ratkaisee kaikki kolme, koska se propagoi traceparent-header-kontekstia läpi koko renderöinnin.
Ja tässä on staff-eng-tason vinkki: älä yritä rakentaa observoitavuutta jälkikäteen kunkin palvelun sisään. Rekisteröi yksi OTLP-eksportteri instrumentation.ts:ssä, ja päädyt siihen, että Turbopack-buildisi, monorepo-jaetut kirjastosi ja jokainen React Server Component tuottaa spanit samaan taustajärjestelmään ilman ylimääräistä koodia.
Miten instrumentation.ts toimii App Routerissa
instrumentation.ts on Next.js:n konventio. Sijoita tiedosto projektin juureen (tai src/-hakemiston juureen, jos käytät sitä), vie register-funktio, ja Next.js kutsuu sitä täsmälleen kerran per Node.js- tai Edge-instanssi ennen ensimmäistä pyyntöä. Ei per request. Ei per renderöinti. Kerran per prosessi.
Vähimmäistoteutus näyttää tältä:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation-node');
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('./instrumentation-edge');
}
}
Dynaaminen import() ei ole tyylivalinta, vaan pakko. Jos importaat OpenTelemetry-Node-SDK:n staattisesti moduulin ylätasolla, Turbopack yrittää bundlata sen myös Edge Runtimeen ja saat rakennusvirheen Module not found: Can't resolve 'perf_hooks'. Runtime-tarkistus varmistaa, että vain oikea toteutus latautuu. Törmäsin tähän itse ensimmäisessä produktioviikossa, joten säästä itseltäsi tunti debuggausta.
Toinen olennainen asia. register-funktio saa palauttaa Promise:n, ja Next.js odottaa sen ratkeamista ennen kuin ensimmäinen pyyntö menee läpi. Tämä on ainoa hetki, jolloin sinulla on synkroninen, deterministinen alustusikkuna. Käytä sitä hyväksi: rekisteröi tracer provider, aloita OpenTelemetry SDK, lämmitä connection pool, lataa feature-flag-cache. Kaikki tapahtuu ennen liikennettä.
OpenTelemetry-integraatio askel askeleelta
Suositelluin tapa vuonna 2026 on käyttää Vercelin virallista @vercel/otel-pakettia, joka kääntää raaka-OpenTelemetryn Next.js-konventioihin. Se konfiguroi automaattisesti fetch-instrumentoinnin, propagoi traceparent-headeria, ja lisää spanit jokaiselle App Routerin renderöintivaiheelle. Katso yksityiskohdat Next.js:n virallisesta OpenTelemetry-oppaasta.
Jos jätät serverExternalPackages-listan pois, Turbopack yrittää staattisesti analysoida require-in-the-middle:a (kirjastoa, joka koukkaa Node.js:n require-funktion) ja koko build kaatuu. Tämä on yleisin syy, miksi ihmiset raportoivat "OpenTelemetry ei toimi Next.js 15/16:ssa". Honestly, tästä olisi voinut säästyä puolen päivän issue-linjauksen, jos dokumentaatio olisi maininnut sen etusivulla.
onRequestError-koukku ja virheiden jäljitys
Next.js 15 esitteli onRequestError-koukun, joka on vastaus vanhaan ongelmaan. Server-komponentin virhe ei koskaan päädy client-puolen error boundaryyn samassa muodossa, ja perinteinen Express-tyylinen error middleware ei toimi RSC-mallissa. Koukku ajetaan aina, kun renderöinti heittää poikkeuksen. Server Componentissa, Server Actionissa, Route Handlerissa tai middlewaressa.
Kolme asiaa, jotka on helppo unohtaa. Ensinnäkin digest-kenttä on ainoa vakaa tunniste, joka näkyy myös client-puolen error boundaryssa. Kirjaa se aina, jotta support voi yhdistää käyttäjän raportin oikeaan lokiriviin. Toiseksi routeType: 'action' tarkoittaa Server Actionia, ja näiden virheet on usein liiketoimintakriittisiä ja ansaitsevat oman hälytyskynnyksen. Kolmanneksi keepalive: true on välttämätön Vercelin serverlessissä, muuten function-instanssi voi sammua ennen kuin logi ehtii lähteä. Menetin viime projektissa noin 2 % virhelogeista ennen kuin lisäsin tuon flagin.
Server Actionien ja middlewaren jäljitys
Server Actions on käytännössä RPC. Client kutsuu server-funktiota multipart-POST:in kautta, ja OpenTelemetry näkee tämän automaattisesti spanina nimeltä executeMutationAction. Oletusattribuutit ovat kuitenkin niukat, käytännössä pelkkä actionin ID-hash. Jotta jäljitteet ovat käyttökelpoisia tuotannossa, kannattaa rikastaa spania manuaalisesti:
Middlewaren jäljitys on hankalampi tapaus. Middleware ajetaan aina Edge Runtimessa, jossa OpenTelemetry Node SDK ei toimi. Käytännössä ratkaisu on kaksitasoinen. Ensin middleware asettaa traceparent-headerin manuaalisesti pyyntöön, jotta downstream Node.js-renderöinnit saavat oikean parent context -kontekstin. Sen jälkeen middlewaren omat metriikat (esim. autentikointitarkistuksen latenssi) lähetetään suoraan OTLP HTTP -endpointille fetch:n avulla.
Jos rakennat middlewareen esimerkiksi rate-limitin tai autentikointikerroksen kuten olen käsitellyt Next.js Proxy -oppaassa, kannattaa lisätä jokaiseen päätökseen (allow, deny, redirect) oma metriikka. Muuten hylätyt pyynnöt eivät koskaan päädy Node.js-runtimen jäljitteisiin ja jäät sokeaksi.
Datadog, Sentry ja Vercelin oma observoitavuus
OTLP-standardi tarkoittaa, että sama instrumentation.ts voi lähettää dataa useaan taustajärjestelmään ilman koodimuutoksia. Vain ympäristömuuttujat vaihtuvat. Alla vertailu vaihtoehdoista, joita olen käyttänyt tuotannossa:
Ominaisuus
Vercel Observability
Datadog
Sentry
OTLP-tuki
Natiivi, ei konfiguraatiota
OTLP HTTP + Agent
OTLP + oma SDK
Server Actions -spanit
Automaattinen
Vaatii @vercel/otel:n
Sentry SDK v8+ automaattinen
Virhejäljitys
Vercel Log Drains
APM Error Tracking
Ensiluokkainen, source maps
Hinta (2026, arvio)
Sisältyy Pro-tasoon
$31/host/kk
$26/kk 100k errors
Edge Runtime
Täysi tuki
Rajattu (fetch-only)
Täysi tuki v8+
Setup-aika
~5 min
~30 min (Agent-asennus)
~15 min
Ihanteellinen käyttötapaus
Vercel-only stack
Multi-cloud, k8s
Frontend + backend virheet
Käytännön suositus staff-eng-tiimille: aloita Vercel Observabilityllä, koska se ei vaadi omaa infra-tiimiä. Kun liikenne kasvaa ja tarvitset custom dashboardeja, siirry Datadogiin tai Grafana Cloudiin. Sentry on erikoistapaus. Se on ylivoimainen virhejäljityksessä, mutta ei kilpaile täysimittaisen APM:n kanssa. Yhdistelmä Sentry (virheet) + Datadog (metriikat/spanit) on tavallinen tuotantosetup, ja olen itsekin ajanut sen jo kahdessa työpaikassa.
Jos käytät Vercelin natiivialustaa, katso Vercel OpenTelemetry -dokumentaatio. Sieltä löytyvät valmiit konfiguraatiot yleisimmille taustajärjestelmille.
Edge Runtime -rajoitteet ja kiertotiet
Edge Runtime on rajattu V8-isolaatti, joka ei tarjoa perf_hooks-, fs- tai diagnostics_channel-API:ta. Käytännössä tämä tarkoittaa, että OpenTelemetryn Node SDK ei käynnisty ollenkaan Edge-ympäristössä. Jos yrität importata sen, saat build-virheen. Middleware, Edge Route Handlerit ja Edge Server Componentit vaativat kevyemmän lähestymistavan.
Käytännössä toimivin ratkaisu on @opentelemetry/api-paketti (pelkkä API, ei SDK:ta) yhdistettynä omaan OTLP HTTP -eksportteriin:
// instrumentation-edge.ts
import { trace, context, SpanKind } from '@opentelemetry/api';
// Kevyt manuaalinen tracer, joka lähettää OTLP HTTP -formaatissa
export function register() {
// Minimaalinen tracer-toteutus, vain fetch-instrumentaatio ja manuaaliset spanit
// ...
}
Vaihtoehtoisesti, jos observoitavuus ei ole kriittistä middlewaressa, voit hyväksyä sokean pisteen ja luottaa siihen, että onRequestError-koukku ottaa kiinni virheet myös Edge-runtimessa. OpenTelemetryn spesifikaatio kuvaa vähimmäisvaatimukset manuaaliselle tracer-toteutukselle.
Tuotannon checklist ja yleiset virheet
Kun otin instrumentation-järjestelmän tuotantoon monorepossa, jossa on kolme Next.js-appia ja jaettu design-system-paketti, törmäsin kolmeen ei-ilmeiseen ongelmaan. Näiden ratkaisut kannattaa tarkistaa ennen deployta:
Duplikaatit spanit Vercelillä. Jos rekisteröit sekä @vercel/otel:n että Vercelin sisäisen instrumentaation, saat jokaisesta fetch-kutsusta kaksi spania. Ratkaisu: aseta propagators: []-optio registerOTel-kutsuun, jos Vercelin oma propagaatio on käytössä.
Monorepon jaetut kirjastot menettävät kontekstin. Jos design-system-paketti tekee omia fetch-kutsuja (esim. analytiikkaa varten), ne eivät automaattisesti liity vanhemman spanin kontekstiin, ellei paketti käytä @opentelemetry/api:a itsenäisesti. Ratkaisu: propagoi context eksplisiittisesti tai käytä context.with()-wrapperia.
Turbopack ja instrumentation.ts hot reload. Kehityksessä instrumentation.ts saatetaan ajaa useasti hot reloadin yhteydessä, mikä johtaa moninkertaisiin tracer provider -rekisteröinteihin ja muistivuotoihin dev-serverillä. Suojaa singleton-tarkistuksella: if (globalThis.__otelRegistered) return; globalThis.__otelRegistered = true;.
Kun observoitavuus on paikoillaan, saat myös hyvän lähtökohdan välimuistin analysointiin. Jokainen use cache-hit näkyy omana spaninaan, ja voit vertailla latenssia välimuistin osumien ja miss-tapausten välillä. Jos vielä opettelet direktiivin toimintaa, katso oppaani Next.js 16 Cache Components ja use cache -direktiivi.
Usein kysytyt kysymykset
Toimiiko OpenTelemetry Next.js 16:n kanssa suoraan ilman lisäasennuksia?
Ei kokonaan. Next.js 16 tunnistaa instrumentation.ts-tiedoston ja ajaa register-funktion automaattisesti, mutta OpenTelemetry SDK:n asennus ja konfigurointi on tehtävä itse tai @vercel/otel-paketin avulla. Vercel-hosting lisää lisäksi omat automaattiset spanit ilman erillistä setupia.
Voiko Next.js instrumentation.ts:ää käyttää Sentryn kanssa?
Kyllä. Sentry SDK v8+ tarjoaa @sentry/nextjs-paketin, joka tekee automaattisen integraation instrumentation.ts:n kautta. Alusta Sentry register-funktiossa Node-runtimelle ja käytä onRequestError-koukkua kutsumaan Sentry.captureRequestError.
Miksi instrumentation.ts ei toimi Edge Runtimessa?
Se toimii, mutta rajatusti. Edge Runtime on V8-isolaatti ilman Node.js-natiivimoduuleja, joten OpenTelemetryn Node SDK ei käynnisty. Käytä pelkkää @opentelemetry/api-pakettia ja lähetä spanit manuaalisesti OTLP HTTP -endpointille, tai vaihda middleware Node.js-runtimeen (v15.3+).
Miten jäljitän Server Actionin epäonnistumisen tuotannossa?
Rekisteröi onRequestError-koukku, joka tarkistaa context.routeType === 'action'. Kirjaa myös error.digest-arvo, sillä se on ainoa tunniste, jonka client näkee, ja sen avulla voit yhdistää käyttäjän ilmoituksen palvelinlokiin.
Kannattaako käyttää @vercel/otel vai raaka OpenTelemetry SDK?
Käytä @vercel/otel:iä oletuksena, koska se abstraktoi Next.js:n renderöintielinkaaren ja lisää oikeat propagaattorit. Siirry raa'an OpenTelemetry SDK:n käyttöön vasta jos tarvitset custom-samplereja, exotic-eksporttereja tai integroit ei-Vercel-hostattuun infrastruktuuriin, jossa haluat täyden hallinnan.
Auth.js v5 (NextAuth) ja Next.js 16: täydellinen App Router -autentikointiopas. Asennus, OAuth-providerit, Credentials, proxy.ts-suojaus, roolipohjaiset oikeudet ja Edge-runtime-yhteensopivuus. Mukana toimivat koodiesimerkit Server Componenteille ja Server Actioneille.