Comment configurer l'instrumentation avec OpenTelemetry
L'observabilité est cruciale pour comprendre et optimiser le comportement et les performances de votre application Next.js.
À mesure que les applications deviennent plus complexes, il devient de plus en plus difficile d'identifier et de diagnostiquer les problèmes qui peuvent survenir. En utilisant des outils d'observabilité tels que les logs et les métriques, les développeurs peuvent obtenir des insights sur le comportement de leur application et identifier des zones d'optimisation. Avec l'observabilité, les développeurs peuvent résoudre les problèmes de manière proactive avant qu'ils ne deviennent majeurs et offrir une meilleure expérience utilisateur. Par conséquent, il est fortement recommandé d'utiliser l'observabilité dans vos applications Next.js pour améliorer les performances, optimiser les ressources et améliorer l'expérience utilisateur.
Nous recommandons d'utiliser OpenTelemetry pour instrumenter vos applications. C'est une manière agnostique de la plateforme d'instrumenter les applications qui vous permet de changer votre fournisseur d'observabilité sans modifier votre code. Lisez la documentation officielle d'OpenTelemetry pour plus d'informations sur OpenTelemetry et son fonctionnement.
Cette documentation utilise des termes comme Span, Trace ou Exporter tout au long de ce document, tous peuvent être trouvés dans le guide d'observabilité OpenTelemetry.
Next.js prend en charge l'instrumentation OpenTelemetry nativement, ce qui signifie que nous avons déjà instrumenté Next.js lui-même.
Premiers pas
OpenTelemetry est extensible mais sa configuration peut être assez verbeuse.
C'est pourquoi nous avons préparé un package @vercel/otel
qui vous aide à démarrer rapidement.
Utilisation de @vercel/otel
Pour commencer, installez les packages suivants :
Ensuite, créez un fichier personnalisé instrumentation.ts
(ou .js
) dans le répertoire racine du projet (ou dans le dossier src
si vous en utilisez un) :
Consultez la documentation de @vercel/otel
pour les options de configuration supplémentaires.
Bon à savoir :
- Le fichier
instrumentation
doit être à la racine de votre projet et non dans le dossierapp
oupages
. Si vous utilisez le dossiersrc
, placez le fichier danssrc
à côté depages
etapp
.- Si vous utilisez l'option de configuration
pageExtensions
pour ajouter un suffixe, vous devrez également mettre à jour le nom du fichierinstrumentation
pour correspondre.- Nous avons créé un exemple basique with-opentelemetry que vous pouvez utiliser.
Configuration manuelle d'OpenTelemetry
Le package @vercel/otel
fournit de nombreuses options de configuration et devrait couvrir la plupart des cas d'utilisation courants. Mais s'il ne répond pas à vos besoins, vous pouvez configurer OpenTelemetry manuellement.
Tout d'abord, vous devez installer les packages OpenTelemetry :
Maintenant, vous pouvez initialiser NodeSDK
dans votre instrumentation.ts
.
Contrairement à @vercel/otel
, NodeSDK
n'est pas compatible avec le runtime edge, vous devez donc vous assurer que vous les importez uniquement lorsque process.env.NEXT_RUNTIME === 'nodejs'
. Nous recommandons de créer un nouveau fichier instrumentation.node.ts
que vous importez conditionnellement uniquement lors de l'utilisation de node :
Faire cela équivaut à utiliser @vercel/otel
, mais il est possible de modifier et d'étendre certaines fonctionnalités qui ne sont pas exposées par @vercel/otel
. Si le support du runtime edge est nécessaire, vous devrez utiliser @vercel/otel
.
Tester votre instrumentation
Vous avez besoin d'un collecteur OpenTelemetry avec un backend compatible pour tester les traces OpenTelemetry localement. Nous recommandons d'utiliser notre environnement de développement OpenTelemetry.
Si tout fonctionne bien, vous devriez pouvoir voir le span racine du serveur étiqueté comme GET /requested/pathname
.
Tous les autres spans de cette trace particulière seront imbriqués en dessous.
Next.js trace plus de spans que ceux émis par défaut.
Pour voir plus de spans, vous devez définir NEXT_OTEL_VERBOSE=1
.
Déploiement
Utilisation d'OpenTelemetry Collector
Lorsque vous déployez avec OpenTelemetry Collector, vous pouvez utiliser @vercel/otel
.
Cela fonctionnera à la fois sur Vercel et en auto-hébergement.
Déploiement sur Vercel
Nous nous sommes assurés qu'OpenTelemetry fonctionne nativement sur Vercel.
Suivez la documentation Vercel pour connecter votre projet à un fournisseur d'observabilité.
Auto-hébergement
Le déploiement sur d'autres plateformes est également simple. Vous devrez démarrer votre propre OpenTelemetry Collector pour recevoir et traiter les données de télémétrie de votre application Next.js.
Pour ce faire, suivez le guide de démarrage d'OpenTelemetry Collector, qui vous guidera dans la configuration du collecteur et son paramétrage pour recevoir les données de votre application Next.js.
Une fois que votre collecteur est opérationnel, vous pouvez déployer votre application Next.js sur la plateforme de votre choix en suivant leurs guides de déploiement respectifs.
Exportateurs personnalisés
OpenTelemetry Collector n'est pas nécessaire. Vous pouvez utiliser un exportateur OpenTelemetry personnalisé avec @vercel/otel
ou la configuration manuelle d'OpenTelemetry.
Spans personnalisés
Vous pouvez ajouter un span personnalisé avec les API OpenTelemetry.
L'exemple suivant montre une fonction qui récupère les stars GitHub et ajoute un span personnalisé fetchGithubStars
pour suivre le résultat de la requête fetch :
La fonction register
s'exécutera avant que votre code ne s'exécute dans un nouvel environnement.
Vous pouvez commencer à créer de nouveaux spans, et ils devraient être correctement ajoutés à la trace exportée.
Spans par défaut dans Next.js
Next.js instrumente automatiquement plusieurs spans pour vous fournir des insights utiles sur les performances de votre application.
Les attributs sur les spans suivent les conventions sémantiques OpenTelemetry. Nous ajoutons également certains attributs personnalisés sous l'espace de noms next
:
next.span_name
- duplique le nom du spannext.span_type
- chaque type de span a un identifiant uniquenext.route
- Le motif de route de la requête (par exemple,/[param]/user
).next.rsc
(true/false) - Si la requête est une requête RSC, comme un prefetch.next.page
- C'est une valeur interne utilisée par le routeur App.
- Vous pouvez la considérer comme une route vers un fichier spécial (comme
page.ts
,layout.ts
,loading.ts
et autres) - Elle peut être utilisée comme identifiant unique uniquement lorsqu'elle est associée à
next.route
car/layout
peut être utilisé pour identifier à la fois/(groupA)/layout.ts
et/(groupB)/layout.ts
[http.method] [next.route]
next.span_type
:BaseServer.handleRequest
Ce span représente le span racine pour chaque requête entrante dans votre application Next.js. Il suit la méthode HTTP, la route, la cible et le code de statut de la requête.
Attributs :
- Attributs HTTP communs
http.method
http.status_code
- Attributs HTTP serveur
http.route
http.target
next.span_name
next.span_type
next.route
render route (app) [next.route]
next.span_type
:AppRender.getBodyResult
.
Ce span représente le processus de rendu d'une route dans le routeur App.
Attributs :
next.span_name
next.span_type
next.route
fetch [http.method] [http.url]
next.span_type
:AppRender.fetch
.
Ce span représente la requête fetch exécutée dans votre code.
Attributs :
- Attributs HTTP communs
http.method
- Attributs HTTP client
http.url
net.peer.name
net.peer.port
(uniquement si spécifié)
next.span_name
next.span_type
Ce span peut être désactivé en définissant NEXT_OTEL_FETCH_DISABLED=1
dans votre environnement. C'est utile lorsque vous souhaitez utiliser une bibliothèque d'instrumentation fetch personnalisée.
executing api route (app) [next.route]
next.span_type
:AppRouteRouteHandlers.runHandler
.
Ce span représente l'exécution d'un gestionnaire de route API dans le routeur App.
Attributs :
next.span_name
next.span_type
next.route
getServerSideProps [next.route]
next.span_type
:Render.getServerSideProps
.
Ce span représente l'exécution de getServerSideProps
pour une route spécifique.
Attributs :
next.span_name
next.span_type
next.route
getStaticProps [next.route]
next.span_type
:Render.getStaticProps
.
Ce span représente l'exécution de getStaticProps
pour une route spécifique.
Attributs :
next.span_name
next.span_type
next.route
render route (pages) [next.route]
next.span_type
:Render.renderDocument
.
Ce span représente le processus de rendu du document pour une route spécifique.
Attributs :
next.span_name
next.span_type
next.route
generateMetadata [next.page]
next.span_type
:ResolveMetadata.generateMetadata
.
Ce span représente le processus de génération de métadonnées pour une page spécifique (une seule route peut avoir plusieurs de ces spans).
Attributs :
next.span_name
next.span_type
next.page
resolve page components
next.span_type
:NextNodeServer.findPageComponents
.
Ce span représente le processus de résolution des composants de page pour une page spécifique.
Attributs :
next.span_name
next.span_type
next.route
resolve segment modules
next.span_type
:NextNodeServer.getLayoutOrPageModule
.
Ce span représente le chargement des modules de code pour un layout ou une page.
Attributs :
next.span_name
next.span_type
next.segment
start response
next.span_type
:NextNodeServer.startResponse
.
Ce span de durée zéro représente le moment où le premier octet a été envoyé dans la réponse.