التتبع الموزع وOpenTelemetry

الرصد الشامل الموحد

18 دقيقة الدرس 9 من 28

الرصد الشامل الموحد

لديك الآن ثلاثة أركان جاهزة: Prometheus يجمع المقاييس، وLoki يحتضن السجلات، وTempo يخزن آثار التتبع الموزعة. كل ركن يجيب عن أسئلة مختلفة. المقاييس تخبرك أن شيئًا ما خطأ. السجلات تخبرك بما حدث. آثار التتبع تخبرك أين ذهب الوقت وأي خدمة هي المسؤولة. التحول الحقيقي — الذي يُفرّق بين فريق مناوبة يعمل بردود الأفعال وفريق SRE عالي الأداء — هو القدرة على التنقل بين الإشارات الثلاث خلال ثلاثين ثانية، متبعًا خيط السببية الواحد دون نسخ ولصق للمعرّفات أو تبديل الأدوات.

الرصد الشامل الموحد ليس منتجًا تشتريه، بل هو منهجية: أدوات قياس متسقة، وترابط مقصود، وتصميم لوحات بيانات تقودك من الأعراض إلى الجذر دون طرق مسدودة.

نموذج ترابط الأركان الثلاثة

يرتبط الأركان الثلاثة على مستويين: من خلال التسميات/سمات الموارد المشتركة التي تظهر بصورة متطابقة في كل أنواع الإشارات، ومن خلال حقول الربط الصريح — أهمها trace_id الذي يربط سطر السجل بأثر التتبع الذي أنتجه بالضبط.

سمات الموارد هي الأساس. عند تهيئة OTel SDK، يُزيّن كل span، وكل نقطة بيانات مقاييس، وكل سجل بسمات الموارد: service.name وservice.version وdeployment.environment وk8s.pod.name وk8s.namespace.name. تصبح هذه تسميات Prometheus، وتسميات مجاري Loki، وعلامات بحث Tempo. ولأن نفس قيم السمات تظهر في الأنظمة الثلاثة، يمكن للوحة بيانات Grafana التفريع إلى الأنظمة الثلاثة بمتغير واحد مثل ${service}.

الربط الصريح هو معرّف الأثر (trace ID) الذي يُحقن في سجلات JSON المهيكلة. في كل مرة تُصدر خدمتك سطر سجل أثناء معالجة طلب، تُلحق جسر التسجيل في OTel الحقلين trace_id وspan_id. يمكن لـ Grafana Loki حينئذٍ عرض زر "عرض في Tempo" بجانب نتيجة السجل — نقرة واحدة تنتقل بك إلى الأثر المحدد، محددًا مسبقًا لنافذة الوقت الصحيحة.

Three-Pillar Correlation: Metrics, Logs, Traces linked by trace_id and resource attributes Metrics Prometheus / OTEL service.name label Logs Loki / structured JSON trace_id field injected Traces Tempo / Jaeger TraceID + SpanID Shared Resource Attributes service.name · k8s.pod.name · deployment.environment Grafana Unified dashboards + drill-down
تتشارك الأركان الثلاثة سمات الموارد وترتبط بمعرّف الأثر — يتنقل Grafana بينها دون لصق يدوي للمعرّفات.

النماذج التمثيلية (Exemplars): الجسر بين المقاييس وآثار التتبع

النموذج التمثيلي (Exemplar) هو نقطة بيانات عينة مُلصقة بمشاهدة مقياس، تحمل trace_id واختياريًا span_id. هو جواب Prometheus على السؤال: "أخبرتني للتو أن وقت الاستجابة p99 ارتفع إلى 4 ثوانٍ — أرِني طلبًا حقيقيًا كان بهذا البطء." بدون النماذج التمثيلية، ستضطر إلى تخمين نافذة زمنية والبحث في Tempo يدويًا. مع النماذج، تحمل سلة الهستوغرام لوقت الاستجابة مؤشرًا مباشرًا إلى أثر حقيقي وقع في تلك السلة.

النماذج التمثيلية جزء من معيار OpenMetrics وتدعمها Prometheus أصلًا منذ الإصدار v2.43. يُصدرها OTel SDK تلقائيًا لمقاييس الهستوغرام عندما يكون span نشطًا. لتفعيلها من جانب Prometheus، مطلوب معاملان:

# prometheus.yml — تفعيل تخزين النماذج التمثيلية global: scrape_interval: 15s storage: exemplars: max_exemplars: 100000 # مخزن حلقي؛ نحو 48 ميغابايت بالحجم المعتاد # يجب أن يكشف هدف السحب عن المقاييس بتنسيق OpenMetrics النصي: scrape_configs: - job_name: 'checkout-service' scrape_interval: 15s scrape_protocols: - OpenMetricsText1.0.0 # يُفعّل تحليل النماذج التمثيلية - PrometheusText0.0.4 static_configs: - targets: ['checkout:9090']

في Grafana، افتح أي لوحة هستوغرام، وبدّل التمثيل البصري إلى خريطة حرارية أو سلسلة زمنية، ثم فعّل خيار "Exemplars". ستظهر نقاط على الرسم البياني عند اللحظات التي سُجّلت فيها نماذج الاستجابة البطيئة. انقر أي نقطة وسيأخذك Grafana مباشرة إلى Tempo مع الأثر محملًا مسبقًا. هذا أسرع مسار من شذوذ في المقياس إلى جذر السبب في الإنتاج — بلا بحث يدوي.

نصيحة احترافية: النماذج التمثيلية عينات — لا يسجّل SDK نموذجًا لكل طلب، بل لمجموعة فرعية تمثيلية فقط. تأكد من أن معدل أخذ عينات آثار التتبع مرتفع بما يكفي لعدم إسقاط الطلبات البطيئة قبل وصولها إلى Tempo. أخذ عينات رأسي (head-based) بنسبة 100% للطلبات التي تتجاوز 1 ثانية، مع معدل ذيل 1% لكل الباقي، استراتيجية إنتاجية شائعة للحفاظ على تكاليف التخزين مع ضمان وجود نماذج لحالات الذيل البطيء.

رسوم بيانات الخدمات (Service Graphs): طبقة الطوبولوجيا

رسم بياني للخدمات هو رسم موجه مشتق من بيانات آثار التتبع، يُظهر الخدمات التي تستدعي أيًا منها مع مقاييس مجمّعة (معدل الطلبات، معدل الأخطاء، مئينيات وقت الاستجابة) على كل حافة. يجيب على الأسئلة التي لا يستطيع مخطط بنيتك الثابتة الإجابة عليها: "ما التبعيات الموجودة فعلًا على المسار الحرج الآن، وأيها يعاني تدهورًا؟"

يشحن Grafana Tempo بمولّد رسوم بيانية خدمات مدمج. يقرأ الـ spans من Tempo، يُحدد علاقات الوالد-الطفل، ويُصدر مقاييس متوافقة مع Prometheus تحت فضاء الأسماء traces_service_graph_*. تخزن تلك المقاييس في Prometheus وتعرضها على لوحة Service Map في Grafana. يتطلب خط الأنابيب بأكمله بضعة أسطر فقط من إعداد Tempo:

# tempo.yaml — تفعيل توليد مقاييس رسم بياني الخدمات metrics_generator: registry: external_labels: source: tempo cluster: prod-us-east-1 storage: path: /var/tempo/wal remote_write: - url: http://prometheus:9090/api/v1/write processors: - service-graphs # يبني طوبولوجيا الاستدعاء - span-metrics # يُصدر مقاييس RED لكل عملية service_graphs: dimensions: - http.method - http.status_code - deployment.environment enable_virtual_node_label: true # يُظهر التبعيات الخارجية (قواعد بيانات، أطراف ثالثة)

بمجرد تشغيل رسم بياني الخدمات، تُظهر لوحة Service Map في Grafana طوبولوجيا حية. يُلوَّن كل حافة بمعدل الأخطاء: أخضر للصحي، أصفر لمعدل أخطاء مرتفع، أحمر للمتدهور. النقر على أي عقدة أو حافة يفتح لوحة مُصفّاة مسبقًا لتلك الخدمة. هذه هي الشاشة الأولى التي يفتحها معظم مهندسي SRE عند إطلاق تنبيه — فهي تُضيّق على الفور نطاق الضرر.

الفكرة الرئيسية: مقاييس الـ span (التي يُصدرها معالج span-metrics) تمنحك مقاييس RED — المعدل والأخطاء والمدة — لكل خدمة ولكل عملية، مشتقة كليًا من بيانات آثار التتبع. يعني هذا أن حتى الخدمات التي لا تكشف عن نقطة نهاية /metrics (كود خارجي، برامج جاهزة) تحصل على قابلية رصد مجدية طالما تُصدر spans. وهي أيضًا نظام إنذار مبكر: تُحسب مقاييس span في الوقت شبه الفعلي، مما يُظهر المشكلة في الغالب قبل أن تلتقطها دورة سحب PromQL في لوحتك.

ربط مصادر بيانات Grafana عمليًا

القطعة الأخيرة هي إعداد Grafana ليعرف كيف ترتبط مصادر بياناته ببعضها. يتم هذا من خلال الحقول المشتقة في Loki وtrace-to-logs / trace-to-metrics في إعدادات مصدر بيانات Tempo. يبدو ملف توفير Grafana الإنتاجي الأدنى هكذا:

# grafana/provisioning/datasources/observability.yaml apiVersion: 1 datasources: - name: Prometheus type: prometheus url: http://prometheus:9090 isDefault: true jsonData: exemplarTraceIdDestinations: - name: trace_id datasourceUid: tempo-uid # النقر على نموذج تمثيلي يفتح Tempo - name: Loki type: loki url: http://loki:3100 jsonData: derivedFields: - name: TraceID matcherRegex: '"trace_id":"(\w+)"' url: '$${__value.raw}' datasourceUid: tempo-uid # trace_id في سطر السجل يرتبط بـ Tempo - name: Tempo uid: tempo-uid type: tempo url: http://tempo:3200 jsonData: tracesToLogsV2: datasourceUid: loki-uid tags: - key: service.name value: service_name # يُصفّي Loki تلقائيًا حسب الخدمة tracesToMetrics: datasourceUid: prometheus-uid tags: - key: service.name value: job queries: - name: Request rate query: rate(http_server_duration_count{job="$${__tags.job}"}[5m]) serviceMap: datasourceUid: prometheus-uid

بهذا الإعداد، يصبح كل تنبيه نقطة انطلاق لا نهاية. يرى مهندس SRE ارتفاعًا في معدل الأخطاء على لوحة Prometheus، ينقر على نقطة نموذج تمثيلي، يصل إلى Tempo على الأثر المحدد، يرى أي span فشل، ينقر على رابط Loki في ذلك الـ span، يقرأ سطر السجل المحدد للخطأ — كل ذلك في جلسة Grafana واحدة، في أقل من ثلاثين ثانية. هذا هو الرصد الشامل الموحد يعمل كما صُمّم.

فخ إنتاجي — انجراف الساعة يُتلف الترابط: تعتمد روابط النماذج التمثيلية وارتباطات الأثر بالسجل على توافق التوقيت. إذا اختلف طابع زمن استيعاب Loki عن وقت بدء الـ span بأكثر من ثوانٍ قليلة — بسبب انجراف الساعة بين المضيفين، أو التخزين المؤقت في OTel Collector، أو max_chunk_age في Loki — سيفتح رابط الحقل المشتق Loki في نافذة زمنية خاطئة ويعيد نتائج فارغة. فرض NTP على جميع العقد (chrony مع مصدر ثابت)، وإعداد معالج batch في OTel Collector للتفريغ بتكرار (أقل من 5 ثوانٍ). راقب وقت استجابة خط الأنابيب في Collector بمقياس otelcol_processor_batch_timeout_trigger_send.