دليل النشر

Grafana Tempo وOpenTelemetry: التتبع الموزع على VPS

انشر على VPS Cloud ←

دليل عملي

Grafana Tempo وOpenTelemetry: التتبع الموزع على VPS

الأمان والمراقبة12 دقيقةً للقراءةعدد الخطوات: 7

تتبع طلب عبر خدمات متعددة بدون أداة تتبع يعني تصفح آلاف سطور السجلات يدويًا. يشكّل OpenTelemetry وGrafana Tempo ثنائيًا مفتوح المصدر يحوّل هذا التحقيق إلى بضع نقرات. يشرح هذا الدليل كيفية نشر المكدّس الكامل على VPS، وتجهيز تطبيقاتك، واستخدام TraceQL لتشخيص مشاكل الأداء.

المحتويات· لماذا اختيار OpenTelemetry بدلًا من وكيل خاص1/12
  1. 01لماذا اختيار OpenTelemetry بدلًا من وكيل خاص
  2. 02ما توفّره لك مكدّسة OTel + Grafana Tempo
  3. 03متطلبات VPS
  4. 04بنية المكدّس: من span إلى التصوير
  5. 05نشر مكدّس OTel + Tempo في سبع خطوات
  6. 06تهيئة الاحتفاظ بالتتبعات والتخزين
  7. 07تجهيز تطبيق Node.js
  8. 08تجهيز تطبيق Python
  9. 09OTel + Tempo مقابل Jaeger مقابل Zipkin مقابل Datadog APM
  10. 10التنبيهات وـ SLOs في Grafana
  11. 11الجمع بين التتبعات والسجلات والمقاييس في Collector واحد
  12. 12حل المشكلات الشائعة

لماذا اختيار OpenTelemetry بدلًا من وكيل خاص

OpenTelemetry مشروع متخرّج من CNCF يوحّد ركائز المراقبة الثلاث — التتبعات والمقاييس والسجلات — تحت معيار محايد للمورّدين. على عكس وكلاء Datadog أو New Relic الذين يقيّدونك بعقد وصيغة خاصة، يستقبل OTel Collector البيانات ويحوّلها ويصدّرها إلى أي خادم متوافق. يمكنك تغيير التخزين دون تعديل سطر واحد في كود تطبيقك.

تغطّي حزم SDK لغات Node.js وPython وGo وJava وPHP وRuby ومعظم اللغات الحديثة. منتشرات السياق W3C TraceContext وB3 مدمجة: تمرّر trace-id تلقائيًا بين خدماتك الصغيرة عبر رؤوس HTTP دون إعداد إضافي.

ما توفّره لك مكدّسة OTel + Grafana Tempo

  • تتبع موزع بدون فهرس خارجي — يخزّن Grafana Tempo v2.x التتبعات في كتل مضغوطة (parquet) على القرص المحلي أو تخزين الكائنات، بدون Cassandra أو Elasticsearch.
  • استعلامات TraceQL — تتيح لغة Tempo المخصصة تصفية التتبعات حسب المدة والخدمة وحالة الخطأ أو السمات المخصصة في ثوانٍ.
  • توافق متعدد البروتوكولات — يقبل Tempo بروتوكولات OTLP وZipkin وJaeger: تتصل تطبيقاتك الحالية دون إعادة تجهيز كاملة.
  • خفيف على VPS — 2 جيجابايت RAM تكفي لبيئة التطوير أو الاختبار؛ في الإنتاج تحت الحمل، يوفّر 4 جيجابايت هامشًا مريحًا.
  • تكلفة محكومة — VPS بسعر 99 درهم/شهر استضافة ذاتية يحلّ محل اشتراك Datadog APM بحوالي 23 دولارًا لكل مضيف شهريًا.
  • ربط التتبعات بالسجلات والمقاييس — بربط Tempo بـ Loki وPrometheus في Grafana، تنتقل من تتبع إلى سجلاته ومقاييسه بنقرة واحدة.
  • لا قيود على المورّد — إذا انتقلت إلى Jaeger غدًا، تعيد تهيئة مُصدِّر واحد في Collector؛ حزم SDK والكود لا تتغير.

متطلبات VPS

يحتاج VPS إلى 2 جيجابايت RAM على الأقل (يُنصح بـ 4 في الإنتاج) وصلاحية root أو sudo. يجب تثبيت Docker Engine ≥ 24 وDocker Compose v2.

خطّط لنطاق فرعي مخصص — مثلًا grafana.your-domain.com — لعرض واجهة Grafana خلف وكيل عكسي TLS. يجب فتح المنفذَين 4317 (OTLP/gRPC) و4318 (OTLP/HTTP) في جدار الحماية على الجانب الخاص لاستقبال البيانات من تطبيقاتك؛ لا تعرّضهما على الواجهة العامة. تبقى المنافذ 3200 (Tempo) و3000 (Grafana) داخلية في شبكة Docker.

للتخزين، خطّط لـ 10 جيجابايت على الأقل لكتل التتبع. الوحدة الافتراضية في /tmp/tempo لا تبقى بعد إعادة التشغيل: استبدلها بـ Docker volume أو قرص مخصص قبل الإنتاج.

بنية المكدّس: من span إلى التصوير

يتبع تدفق البيانات أربع خطوات:

1. تطبيقك يجهّز طلباته بحزمة OTel SDK ويصدّر الـ spans إلى OTel Collector (OTLP gRPC منفذ 4317 أو HTTP منفذ 4318).
2. OTel Collector يستقبل ويجمّع في دُفعات ثم يصدّر إلى Tempo عبر OTLP gRPC داخلي. يمكنه في آنٍ واحد إرسال المقاييس إلى Prometheus والسجلات إلى Loki.
3. Grafana Tempo يخزّن كتل التتبع المضغوطة على القرص (أو S3). يعرض API لـ TraceQL على المنفذ 3200.
4. Grafana يستعلم Tempo بـ TraceQL، ويعرض flamegraphs ورسوم بيانية للخدمات وSpan metrics.

TraceQL هي لغة استعلام Tempo الأصلية. استعلام نموذجي: {service.name="api" && status=error && duration>500ms}.

Span Metrics خط أنابيب في Tempo يستخرج تلقائيًا مقاييس RED من التتبعات الواردة دون إضافة عدّاد واحد في كودك.

نشر مكدّس OTel + Tempo في سبع خطوات

  1. إنشاء هيكل المجلدات

    أنشئ مجلد otel-stack/ على VPS:

    mkdir -p otel-stack/config
    cd otel-stack

    ستضع هنا ثلاثة ملفات إعداد: tempo.yaml وotel-collector-config.yaml وdocker-compose.yml.

  2. كتابة إعداد Tempo (tempo.yaml)

    أنشئ config/tempo.yaml بخادم تخزين محلي ودعم TraceQL:

    server:
      http_listen_port: 3200
    
    distributor:
      receivers:
        otlp:
          protocols:
            grpc:
              endpoint: 0.0.0.0:4317
    
    ingester:
      max_block_bytes: 1_000_000
      max_block_duration: 5m
    
    compactor:
      compaction:
        block_retention: 168h   # 7 أيام
    
    storage:
      trace:
        backend: local
        wal:
          path: /tmp/tempo/wal
        local:
          path: /tmp/tempo/blocks
  3. كتابة إعداد OTel Collector

    أنشئ config/otel-collector-config.yaml:

    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    
    processors:
      batch:
        timeout: 5s
        send_batch_size: 1000
    
    exporters:
      otlp:
        endpoint: tempo:4317
        tls:
          insecure: true
    
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [otlp]
  4. كتابة ملف docker-compose.yml

    أنشئ docker-compose.yml في جذر otel-stack/:

    services:
      otel-collector:
        image: otel/opentelemetry-collector-contrib:latest
        volumes:
          - ./config/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
        ports:
          - "4317:4317"
          - "4318:4318"
        networks:
          - observability
        depends_on:
          - tempo
    
      tempo:
        image: grafana/tempo:latest
        command: ["-config.file=/etc/tempo.yaml"]
        volumes:
          - ./config/tempo.yaml:/etc/tempo.yaml
          - tempo-data:/tmp/tempo
        ports:
          - "3200:3200"
        networks:
          - observability
    
      grafana:
        image: grafana/grafana:latest
        ports:
          - "3000:3000"
        environment:
          - GF_AUTH_ANONYMOUS_ENABLED=true
          - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
        networks:
          - observability
        depends_on:
          - tempo
    
    volumes:
      tempo-data:
    
    networks:
      observability:

    شغّل المكدّس: docker compose up -d ثم تحقق: docker compose ps.

  5. إعداد Grafana Tempo كمصدر بيانات

    افتح Grafana على http://vps-الخاص-بك:3000. انتقل إلى Connections → Data sources → Add data source واختر Tempo. اضبط URL على http://tempo:3200. فعّل Service graph وSpan metrics. إذا كانت مكدّستك تشمل Loki، اربط مصدرَي البيانات في حقل Linked data sources للتنقل من span إلى سجلاته بنقرة واحدة.

  6. إرسال أول تتبع تجريبي

    اختبر استقبال التتبعات باستخدام telemetrygen:

    docker run --rm --network otel-stack_observability \
      ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest \
      traces \
      --otlp-endpoint otel-collector:4317 \
      --otlp-insecure \
      --duration 5s \
      --rate 10

    في Grafana، افتح Explore، اختر مصدر بيانات Tempo، ونفّذ الاستعلام {} لرؤية جميع التتبعات المستقبَلة.

  7. استعلام التتبعات بـ TraceQL

    في لوحة Explore بـ Grafana، أدخل استعلام TraceQL لتصفية تتبعاتك:

    - {service.name="my-api"} — جميع تتبعات الخدمة
    - {status=error} — جميع التتبعات الخاطئة
    - {duration>1s && service.name="my-api"} — التتبعات البطيئة
    - {span.http.route="/api/orders" && status=error} — أخطاء مسار محدد

    انقر على أي تتبع لفتح flamegraph التفصيلي.

تهيئة الاحتفاظ بالتتبعات والتخزين

يوفّر Tempo خيارَي تخزين رئيسيَّين.

التخزين المحلي على Docker volume: الخيار الموصى به لـ VPS مستقل. اضبط block_retention في tempo.yaml حسب الحاجة: 72 ساعة لبيئة الاختبار، 168 إلى 720 ساعة للإنتاج. كل ساعة من التتبعات المضغوطة تشغل حوالي 100–300 ميجابايت.

تخزين كائنات متوافق مع S3: لمكدّس متعدد العقد أو تخزين غير محدود. Tempo متوافق مع AWS S3 وMinIO وScaleway Object Storage. تبقى WAL دائمًا على القرص المحلي لضمان متانة التتبعات قيد الاستيعاب.

يدمج المضغّط كتلًا صغيرة ويطبّق سياسة الاحتفاظ تلقائيًا كل 5 دقائق.

تجهيز تطبيق Node.js

يلتقط التجهيز التلقائي لـ OTel في Node.js استدعاءات HTTP والطلبات وقواعد البيانات دون تعديل منطق الأعمال.

ثبّت الحزم:

npm install @opentelemetry/sdk-node \
             @opentelemetry/auto-instrumentations-node \
             @opentelemetry/exporter-trace-otlp-grpc

أنشئ tracing.js:

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'grpc://localhost:4317',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

شغّل التطبيق:

export OTEL_SERVICE_NAME=my-api
export OTEL_EXPORTER_OTLP_ENDPOINT=http://your-vps:4317
node --require ./tracing.js app.js

تجهيز تطبيق Python

تثبيت وإعداد:

pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

تشغيل التطبيق:

export OTEL_SERVICE_NAME=my-python-service
export OTEL_EXPORTER_OTLP_ENDPOINT=http://your-vps:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
opentelemetry-instrument python app.py

يتم تجهيز Django وFlask وFastAPI وSQLAlchemy وعملاء HTTP تلقائيًا. للتجهيز اليدوي:

from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("process-order") as span:
    span.set_attribute("order.id", order_id)

OTel + Tempo مقابل Jaeger مقابل Zipkin مقابل Datadog APM

مرّر الجدول أفقيًا

المعيارOTel + Grafana TempoJaegerDatadog APM
التكلفة الشهريةالاستضافة فقط (99 درهم/شهر VPS)الاستضافة فقط (مماثل)~23 دولار لكل مضيف شهريًا
خادم التخزينمحلي، S3، GCS، Azure BlobCassandra، Elasticsearch، BadgerSaaS مُدار (مغلق)
لغة الاستعلامTraceQL (أصلية، قوية)Jaeger Query UI (أساسية)لغة خاصة بـ Datadog
التجهيز التلقائيحزمة OTel SDK عالميةمكتبات Jaeger أو OTelوكيل Datadog الخاص
ربط التتبعات بالسجلاتنعم (Loki + Grafana)محدودنعم (مدمج، مدفوع)
Span Metrics (RED)نعم (خط أنابيب Tempo أصلي)غير أصلينعم (يحسبه Datadog)
القيود على المورّدلا شيء (معيار CNCF)منخفض (متوافق مع OTel)قوي (وكيل وصيغة خاصة)
تعقيد التثبيتمتوسط (3 حاويات)منخفض إلى متوسطمنخفض (وكيل تلقائي)

التنبيهات وـ SLOs في Grafana

يتيح Grafana 10+ تعريف تنبيهات على المقاييس المشتقة من التتبعات. تولّد Span Metrics في Tempo ثلاثة مقاييس تلقائيًا لكل خدمة: معدل الطلبات وتوزيع زمن الاستجابة وعدّاد الأخطاء.

لإنشاء SLO على معدل الخطأ، اذهب إلى Alerting → Alert rules → New alert rule في Grafana، اختر مصدر بيانات Prometheus، وأدخل استعلامًا يحسب نسبة الأخطاء. اضبط الحد (مثلًا > 0.05 لمعدل خطأ فوق 5%) ونافذة التقييم. هيّئ نقطة اتصال: Alertmanager أو PagerDuty أو Slack أو webhook. التنبيهات المبنية على التتبعات أدق بكثير من التنبيهات على مقاييس اصطناعية.

الجمع بين التتبعات والسجلات والمقاييس في Collector واحد

OTel Collector ليس حصرًا للتتبعات. بإضافة filelog receiver، تجمع سجلات حاويات Docker وترسلها إلى Loki. وprometheus receiver يجمع نقاط /metrics ويصدّرها إلى Prometheus. عملية واحدة تدير كل بيانات المراقبة على VPS.

في Grafana، اربط Tempo وLoki عبر derived fields: عندما يحتوي سجل على trace_id، رابط قابل للنقر يأخذك مباشرة إلى flamegraph المقابل. هذا التنقل المتقاطع يقلّص وقت التشخيص بشكل ملحوظ.

حل المشكلات الشائعة

لا spans تصل إلى Tempo. تحقق أولًا من أن OTel Collector قابل للوصول من تطبيقك (telnet your-vps 4317). راجع سجلات Collector: خطأ connection refused على tempo:4317 يعني أن Tempo لم يبدأ بعد أو منفذه الداخلي غير مكشوف على شبكة Docker.

رفض الاتصال من التطبيق إلى Collector. في UFW أو firewalld، اسمح بالمنفذَين 4317 و4318 لعناوين IP تطبيقاتك فقط. في الإنتاج، ضع التطبيقات والـ Collector على نفس الشبكة الخاصة.

تتبعات مقطوعة أو spans مفقودة. قد يستغرق الـ batch processor حتى 5 ثوانٍ قبل الإرسال. للتطوير، قلّل timeout: 1s. إذا كانت spans غائبة باستمرار، تحقق من تفعيل منتشر السياق W3CTraceContextPropagator في SDK.

Tempo يستهلك مساحة كبيرة. قلّل block_retention وأعد تشغيل Tempo. سيطبّق المضغّط السياسة الجديدة في الدورة القادمة.

Grafana لا يجد تتبعات من سجلات Loki. تحقق من أن تطبيقاتك تحقن trace_id في السجلات وأن Derived fields في مصدر بيانات Loki يشير إلى النمط الصحيح.

استضف مكدّس المراقبة على VPS

ابدأ من 99 درهم/شهر — وصول root كامل، تخزين SSD، بدون قيود على المزود.

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة