OpenTelemetry Tail Sampling بالعربي: احتفظ بالأخطاء وقلل تكلفة الـ traces
هتعرف هنا إزاي تقلل حجم الـ traces المرسلة للـ backend بدون ما ترمي الأخطاء والطلبات البطيئة اللي محتاجها وقت التحقيق.
مستوى القارئ: متوسط
المشكلة باختصار
لو عندك microservices بتنتج 800 trace في الثانية، وإنت بتبعت 100% من الـ traces إلى Grafana Tempo أو Jaeger أو أي backend مدفوع، فأنت بتدفع على طلبات سليمة مش هتفتحها غالبًا. الطريقة الشائعة هي head sampling من داخل التطبيق. دي بتفشل في نقطة مهمة: القرار بيتاخد في أول الطلب، قبل ما تعرف هل الطلب هيطلع error أو هيعدي 5 ثواني.
Tail Sampling بيأخر القرار لآخر الـ trace تقريبًا. المعنى البسيط: بدل ما تسأل البوابة في أول الدخول “هحتفظ بالزائر ده ولا لأ؟”، تستنى تشوف الرحلة كاملة. لو حصل خطأ في الدفع أو latency عالي، تحتفظ بالرحلة. لو الرحلة عادية، تحتفظ بنسبة صغيرة فقط.
الفكرة الأساسية: القرار بعد ما الصورة تبان
OpenTelemetry Collector فيه processor اسمه tail_sampling. حسب توثيق OpenTelemetry، الـ processors بتغير أو ترشح بيانات القياس داخل pipeline، والـ Tail Sampling Processor موجود في توزيعات contrib وK8s للـ traces. المصدر: OpenTelemetry processors documentation.
الإعدادات المهمة هنا ثلاثة: decision_wait، وnum_traces، وexpected_new_traces_per_sec. توثيق الـ processor يوضح إن decision_wait هو وقت الانتظار قبل قرار العينة، وnum_traces هو عدد الـ traces المحفوظة في الذاكرة، وexpected_new_traces_per_sec يساعد في تجهيز هياكل البيانات. المصدر: Tail Sampling Processor README.
ركز في الرقم ده: لو عندك 800 trace/sec وdecision_wait: 20s، فأنت محتاج تحتفظ تقريبًا بـ 16,000 trace في الذاكرة قبل اتخاذ القرار. ضيف هامش 25% وخلي num_traces حوالي 20,000. الافتراض إن متوسط trace عندك صغير، مثل 8 إلى 15KB، وإن الـ Collector عنده ذاكرة كافية.
إعداد عملي للـ Collector
السيناريو الواقعي: متجر إلكتروني عنده 50K زائر يوميًا. أغلب الطلبات سليمة، لكن وقت الضغط يحصل خطأ في checkout أو طلبات تعدي 3 ثواني. المطلوب: احتفظ بكل الأخطاء، وكل الطلبات الأبطأ من 3000ms، واحتفظ بـ 2% من باقي الطلبات للمراقبة العامة.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
memory_limiter:
check_interval: 5s
limit_percentage: 75
spike_limit_percentage: 20
tail_sampling:
decision_wait: 20s
num_traces: 20000
expected_new_traces_per_sec: 800
policies:
- name: keep-errors
type: status_code
status_code:
status_codes: [ERROR]
- name: keep-slow-requests
type: latency
latency:
threshold_ms: 3000
- name: keep-small-baseline
type: probabilistic
probabilistic:
sampling_percentage: 2
batch:
timeout: 2s
send_batch_size: 1024
exporters:
otlphttp:
endpoint: https://tempo.example.com/otlp
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, tail_sampling, batch]
exporters: [otlphttp]