OpenTelemetry Tail Sampling: قلل تكلفة الـ Traces بذكاء
هتعرف هنا إزاي تقلل تكلفة الـ traces من غير ما تعمي نفسك عن الأخطاء والطلبات البطيئة. ركز: الهدف مش إنك تجمع بيانات أقل وخلاص، الهدف إنك تجمع البيانات اللي تساعدك وقت العطل.
مستوى القارئ: متوسط
المشكلة باختصار
لو عندك 10 خدمات بتستقبل 1 مليون request يوميًا، وجمعت trace كامل لكل request، هتلاقي الـ observability backend بيكبر بسرعة. المشكلة إن 95% من الطلبات غالبًا ناجحة وسريعة، لكنك بتدفع تخزين ومعالجة عليها كأنها مهمة بنفس درجة طلب فشل في الدفع أو checkout أخذ 8 ثواني.
الطريقة الشائعة الغلط هي إنك تعمل head sampling بنسبة ثابتة، مثل 10% من أول لحظة. الطريقة دي بتفشل في نقطة مهمة: ممكن ترمي request فشل قبل ما تعرف إنه فشل. Tail Sampling يحل النقطة دي لأنه يقرر بعد ما الـ trace يكتمل.
الفكرة الأساسية: القرار بعد اكتمال الـ Trace
في OpenTelemetry، الـ sampling هو آلية لتقليل كمية traces التي يتم إنشاؤها أو إرسالها للـ backend. التوثيق الرسمي يشرح أن head sampling يحصل بدري جدًا، بينما sampling المتأخر ممكن يحصل داخل الـ Collector. هذا مهم لأن Collector يقدر يشوف الصورة كاملة: هل في span عليها ERROR؟ هل الـ latency عدى threshold؟ هل service.criticality تساوي critical؟
مثال بسيط: عندك مطعم توصيل. مش محتاج تسجل فيديو كامل لكل طلب وصل في 12 دقيقة بدون مشاكل. لكن لو طلب اتأخر 55 دقيقة أو فشل الدفع، هنا محتاج التفاصيل. Tail Sampling بيعمل نفس الفكرة للـ distributed tracing.
إعداد عملي بـ OpenTelemetry Collector
الافتراض إنك تستخدم OpenTelemetry Collector contrib، وعندك OTLP receiver، والـ backend بتاعك يستقبل OTLP. المثال التالي يحتفظ بكل traces التي فيها ERROR، وكل traces أبطأ من 2 ثانية، ويأخذ 10% فقط من الطلبات العادية. الرقم تقديري كبداية، مش قانون ثابت.
receivers:
otlp:
protocols:
grpc:
http:
processors:
memory_limiter:
check_interval: 1s
limit_mib: 512
spike_limit_mib: 128
tail_sampling:
decision_wait: 10s
num_traces: 50000
expected_new_traces_per_sec: 500
policies:
- name: keep-errors
type: status_code
status_code:
status_codes: [ERROR]
- name: keep-slow-requests
type: latency
latency:
threshold_ms: 2000
- name: sample-normal-traffic
type: probabilistic
probabilistic:
sampling_percentage: 10
batch:
timeout: 5s
send_batch_size: 8192
exporters:
otlp:
endpoint: tempo.example.com:4317
tls:
insecure: false
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, tail_sampling, batch]
exporters: [otlp]بالظبط، ترتيب processors مهم. OpenTelemetry يوضح أن تعريف processor لا يفعله وحده؛ لازم تضيفه داخل pipeline. هنا وضعنا memory_limiter قبل tail_sampling عشان Collector ما ينهارش وقت الضغط، ثم batch في الآخر لتقليل overhead الإرسال.
الأرقام المتوقعة والقياس
لو عندك 10 مليون span يوميًا، و70% منها طلبات عادية، و20% طلبات عادية لكن طويلة نسبيًا، و10% أخطاء أو slow traces مهمة، فسياسة زي اللي فوق ممكن تخفض الإرسال من 10 مليون إلى حوالي 2.5 أو 3 مليون span. ده تقليل قريب من 70% في حجم البيانات المرسلة. المكسب: تكلفة أقل وضغط أقل على backend. الخسارة: مش هتشوف كل request ناجح وسريع بالتفصيل.
أفضل طريقة للقياس إنك تراقب 3 أرقام لمدة أسبوع: عدد spans قبل Collector، عدد spans المصدرة للـ backend، ونسبة الأخطاء التي ظهرت في backend مقارنة بالـ logs أو metrics. لو الأخطاء قلت في traces عن الواقع، يبقى policy عندك بترمي المهم.
الـ Trade-off هنا
Tail Sampling محتاج يحتفظ بالـ traces في الذاكرة لحد ما يقرر. لو decision_wait يساوي 10 ثواني وtraffic عالي، Collector هيحتاج RAM أكبر. بتكسب قرار أذكى من head sampling، لكن بتخسر بساطة التشغيل وقليل من الذاكرة. OpenTelemetry ينصح بمراقبة metrics مثل otelcol_processor_refused_spans وqueue size عند التوسع، لأن رفض spans معناه إن Collector أصبح bottleneck.
لو عايزها تدعم خدمات حرجة، أضف attribute مثل service.criticality=critical وخليها 100%. توثيق OpenTelemetry demo يعرض مثالًا قريبًا: services حرجة 100%، high بنسبة 50%، medium 10%، وlow 1%. لا تنقل الأرقام كما هي قبل ما تقيس traffic بتاعك.
متى لا تستخدم هذه الطريقة
لا تستخدم Tail Sampling لو عندك خدمة صغيرة وتكلفة traces مقبولة. لا تستخدمه أيضًا لو Collector عندك ضعيف في الذاكرة أو latency حساس جدًا لدرجة إن انتظار 10 ثواني قبل القرار يربك التحقيقات السريعة. وفي بيئات compliance التي تطلب الاحتفاظ بكل trace لفترة محددة، sampling قد يكون غير مناسب أصلًا.
مصادر اعتمدت عليها
- OpenTelemetry Sampling Concepts
- OpenTelemetry Collector Configuration
- OpenTelemetry Collector Processors
- Tail-Based Sampling with service.criticality
- Scaling the OpenTelemetry Collector
الخطوة التالية
الخطوة التالية: شغل Collector في بيئة staging لمدة 48 ساعة بنفس policy، وقارن عدد spans قبل وبعد. لو الأخطاء والطلبات الأبطأ من 2 ثانية ظاهرة كاملة، ابدأ بنسبة 10% للطلبات العادية في production.