كيفية إعداد التتبع باستخدام OpenTelemetry
المراقبة (Observability) أمر بالغ الأهمية لفهم وتحسين سلوك وأداء تطبيق Next.js الخاص بك.
مع زيادة تعقيد التطبيقات، يصبح من الصعب بشكل متزايد تحديد وتشخيص المشكلات التي قد تنشأ. من خلال استخدام أدوات المراقبة مثل التسجيل والمقاييس، يمكن للمطورين الحصول على رؤى حول سلوك التطبيق وتحديد مجالات التحسين. مع المراقبة، يمكن للمطورين معالجة المشكلات بشكل استباقي قبل أن تصبح مشاكل كبيرة وتقديم تجربة مستخدم أفضل. لذلك، يوصى بشدة باستخدام المراقبة في تطبيقات Next.js لتحسين الأداء وموارد التحسين وتعزيز تجربة المستخدم.
نوصي باستخدام OpenTelemetry لتتبع تطبيقاتك. إنها طريقة محايدة للمنصة لتتبع التطبيقات تتيح لك تغيير مزود المراقبة دون تغيير الكود الخاص بك. اقرأ وثائق OpenTelemetry الرسمية لمزيد من المعلومات حول OpenTelemetry وكيفية عملها.
تستخدم هذه الوثائق مصطلحات مثل Span، Trace أو Exporter في جميع أنحاء هذا المستند، وكلها يمكن العثور عليها في دليل المراقبة الأساسي لـ OpenTelemetry.
يدعم Next.js تتبع OpenTelemetry مباشرة، مما يعني أننا قد قمنا بالفعل بتتبع Next.js نفسه.
البدء
OpenTelemetry قابل للتوسيع ولكن إعداده بشكل صحيح يمكن أن يكون مطولًا جدًا.
لهذا السبب أعددنا حزمة @vercel/otel
التي تساعدك على البدء بسرعة.
استخدام @vercel/otel
للبدء، قم بتثبيت الحزم التالية:
npm install @vercel/otel @opentelemetry/sdk-logs @opentelemetry/api-logs @opentelemetry/instrumentation
بعد ذلك، قم بإنشاء ملف instrumentation.ts
(أو .js
) مخصص في الدليل الجذري للمشروع (أو داخل مجلد src
إذا كنت تستخدم واحدًا):
import { registerOTel } from '@vercel/otel'
export function register() {
registerOTel({ serviceName: 'next-app' })
}
import { registerOTel } from '@vercel/otel'
export function register() {
registerOTel({ serviceName: 'next-app' })
}
راجع وثائق @vercel/otel
لخيارات التكوين الإضافية.
معلومة جيدة:
- يجب أن يكون ملف
instrumentation
في جذر مشروعك وليس داخل مجلدapp
أوpages
. إذا كنت تستخدم مجلدsrc
، فضع الملف داخلsrc
بجانبpages
وapp
.- إذا كنت تستخدم خيار التكوين
pageExtensions
لإضافة لاحقة، فستحتاج أيضًا إلى تحديث اسم ملفinstrumentation
ليتطابق.- لقد أنشأنا مثالًا أساسيًا with-opentelemetry يمكنك استخدامه.
تكوين OpenTelemetry يدويًا
توفر حزمة @vercel/otel
العديد من خيارات التكوين وينبغي أن تخدم معظم حالات الاستخدام الشائعة. ولكن إذا لم تكن مناسبة لاحتياجاتك، يمكنك تكوين OpenTelemetry يدويًا.
أولاً، تحتاج إلى تثبيت حزم OpenTelemetry:
npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http
الآن يمكنك تهيئة NodeSDK
في ملف instrumentation.ts
.
على عكس @vercel/otel
، فإن NodeSDK
غير متوافق مع وقت تشغيل الحافة (edge runtime)، لذا تحتاج إلى التأكد من أنك تقوم باستيرادها فقط عندما يكون process.env.NEXT_RUNTIME === 'nodejs'
. نوصي بإنشاء ملف جديد instrumentation.node.ts
والذي تقوم باستيراده شرطيًا فقط عند استخدام node:
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation.node.ts')
}
}
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation.node.js')
}
}
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { Resource } from '@opentelemetry/resources'
import { NodeSDK } from '@opentelemetry/sdk-node'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node'
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'next-app',
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
})
sdk.start()
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { Resource } from '@opentelemetry/resources'
import { NodeSDK } from '@opentelemetry/sdk-node'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node'
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'next-app',
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
})
sdk.start()
عمل هذا يعادل استخدام @vercel/otel
، ولكن من الممكن تعديل وتوسيع بعض الميزات التي لا يتم كشفها بواسطة @vercel/otel
. إذا كان دعم وقت تشغيل الحافة ضروريًا، فسيتعين عليك استخدام @vercel/otel
.
اختبار التتبع الخاص بك
تحتاج إلى جامع OpenTelemetry مع خلفية متوافقة لاختبار آثار OpenTelemetry محليًا. نوصي باستخدام بيئة تطوير OpenTelemetry الخاصة بنا.
إذا كان كل شيء يعمل بشكل جيد، يجب أن تكون قادرًا على رؤية نطاق الخادم الجذري المسمى كـ GET /requested/pathname
.
جميع النطاقات الأخرى من ذلك الأثر المحدد ستكون متداخلة تحته.
يتتبع Next.js نطاقات أكثر مما يتم إصداره افتراضيًا.
لرؤية المزيد من النطاقات، يجب عليك تعيين NEXT_OTEL_VERBOSE=1
.
النشر
استخدام جامع OpenTelemetry
عند النشر مع جامع OpenTelemetry، يمكنك استخدام @vercel/otel
.
سيعمل هذا على كل من Vercel وعند الاستضافة الذاتية.
النشر على Vercel
لقد تأكدنا من أن OpenTelemetry يعمل مباشرة على Vercel.
اتبع وثائق Vercel لربط مشروعك بمزود المراقبة.
الاستضافة الذاتية
النشر على منصات أخرى هو أيضًا مباشر. ستحتاج إلى تشغيل جامع OpenTelemetry الخاص بك لاستقبال ومعالجة بيانات المراقبة من تطبيق Next.js الخاص بك.
للقيام بذلك، اتبع دليل البدء لجامع OpenTelemetry، والذي سيرشدك خلال إعداد الجامع وتكوينه لاستقبال البيانات من تطبيق Next.js الخاص بك.
بمجرد تشغيل الجامع الخاص بك، يمكنك نشر تطبيق Next.js الخاص بك على المنصة التي تختارها باتباع أدلة النشر الخاصة بها.
المصدرون المخصصون
جامع OpenTelemetry ليس ضروريًا. يمكنك استخدام مصدر OpenTelemetry مخصص مع @vercel/otel
أو تكوين OpenTelemetry يدويًا.
النطاقات المخصصة
يمكنك إضافة نطاق مخصص باستخدام واجهات برمجة تطبيقات OpenTelemetry.
npm install @opentelemetry/api
يوضح المثال التالي دالة تجلب نجوم GitHub وتضيف نطاقًا مخصصًا fetchGithubStars
لتتبع نتيجة طلب الجلب:
import { trace } from '@opentelemetry/api'
export async function fetchGithubStars() {
return await trace
.getTracer('nextjs-example')
.startActiveSpan('fetchGithubStars', async (span) => {
try {
return await getValue()
} finally {
span.end()
}
})
}
سيتم تنفيذ دالة register
قبل تشغيل الكود الخاص بك في بيئة جديدة.
يمكنك البدء في إنشاء نطاقات جديدة، ويجب أن تتم إضافتها بشكل صحيح إلى الأثر المصدر.
النطاقات الافتراضية في Next.js
يقوم Next.js تلقائيًا بتتبع عدة نطاقات لتوفير رؤى مفيدة حول أداء التطبيق الخاص بك.
تتبع السمات على النطاقات الاتفاقيات الدلالية لـ OpenTelemetry. نضيف أيضًا بعض السمات المخصصة تحت مساحة الاسم next
:
next.span_name
- يكرر اسم النطاقnext.span_type
- لكل نوع نطاق معرف فريدnext.route
- نمط المسار للطلب (مثل/[param]/user
).next.rsc
(صحيح/خطأ) - ما إذا كان الطلب هو طلب RSC، مثل الجلب المسبق.next.page
- هذه قيمة داخلية تستخدمها موجه التطبيق.
- يمكنك التفكير فيها كمسار لملف خاص (مثل
page.ts
،layout.ts
،loading.ts
وغيرها) - يمكن استخدامها كمعرف فريد فقط عند اقترانها بـ
next.route
لأن/layout
يمكن استخدامها لتحديد كل من/(groupA)/layout.ts
و/(groupB)/layout.ts
[http.method] [next.route]
next.span_type
:BaseServer.handleRequest
يمثل هذا النطاق النطاق الجذري لكل طلب وارد إلى تطبيق Next.js الخاص بك. يتتبع طريقة HTTP، المسار، الهدف، ورمز حالة الطلب.
السمات:
- سمات HTTP الشائعة
http.method
http.status_code
- سمات HTTP للخادم
http.route
http.target
next.span_name
next.span_type
next.route
render route (app) [next.route]
next.span_type
:AppRender.getBodyResult
.
يمثل هذا النطاق عملية عرض مسار في موجه التطبيق.
السمات:
next.span_name
next.span_type
next.route
fetch [http.method] [http.url]
next.span_type
:AppRender.fetch
.
يمثل هذا النطاق طلب الجلب المنفذ في الكود الخاص بك.
السمات:
- سمات HTTP الشائعة
http.method
- سمات HTTP للعميل
http.url
net.peer.name
net.peer.port
(فقط إذا تم تحديده)
next.span_name
next.span_type
يمكن إيقاف هذا النطاق عن طريق تعيين NEXT_OTEL_FETCH_DISABLED=1
في بيئتك. هذا مفيد عندما تريد استخدام مكتبة تتبع جلب مخصصة.
executing api route (app) [next.route]
next.span_type
:AppRouteRouteHandlers.runHandler
.
يمثل هذا النطاق تنفيذ معالج مسار API في موجه التطبيق.
السمات:
next.span_name
next.span_type
next.route
getServerSideProps [next.route]
next.span_type
:Render.getServerSideProps
.
يمثل هذا النطاق تنفيذ getServerSideProps
لمسار معين.
السمات:
next.span_name
next.span_type
next.route
getStaticProps [next.route]
next.span_type
:Render.getStaticProps
.
يمثل هذا النطاق تنفيذ getStaticProps
لمسار معين.
السمات:
next.span_name
next.span_type
next.route
render route (pages) [next.route]
next.span_type
:Render.renderDocument
.
يمثل هذا النطاق عملية عرض المستند لمسار معين.
السمات:
next.span_name
next.span_type
next.route
generateMetadata [next.page]
next.span_type
:ResolveMetadata.generateMetadata
.
يمثل هذا النطاق عملية إنشاء بيانات وصفية لصفحة معينة (يمكن أن يحتوي مسار واحد على عدة هذه النطاقات).
السمات:
next.span_name
next.span_type
next.page
resolve page components
next.span_type
:NextNodeServer.findPageComponents
.
يمثل هذا النطاق عملية حل مكونات الصفحة لصفحة معينة.
السمات:
next.span_name
next.span_type
next.route
resolve segment modules
next.span_type
:NextNodeServer.getLayoutOrPageModule
.
يمثل هذا النطاق تحميل وحدات الكود لتخطيط أو صفحة.
السمات:
next.span_name
next.span_type
next.segment
start response
next.span_type
:NextNodeServer.startResponse
.
يمثل هذا النطاق ذو الطول الصفر الوقت الذي تم فيه إرسال البايت الأول في الاستجابة.