OpenTelemetry Tail Sampling: قلل تكلفة الـ traces من غير ما تعمي نفسك
مستوى القارئ: متوسط
هتخرج من المقال بإعداد عملي يقلل حجم الـ traces اللي بتتبعت للـ backend، مع الاحتفاظ بالأخطاء والطلبات البطيئة اللي تهمك فعلاً.
المشكلة باختصار
لو عندك 8 خدمات بتستقبل 2 مليون request يوميًا، وإنت بتصدر 100% من الـ traces، تكلفة التخزين والبحث هتزيد بسرعة. الطريقة الشائعة هي head sampling بنسبة ثابتة، مثلاً 10%. الطريقة دي سهلة، لكنها بتفشل في نقطة مهمة: ممكن ترمي trace فيه error لأن القرار اتاخد في أول الطلب قبل ما تعرف نهايته.
الافتراض هنا إن عندك microservices بتصدر traces عبر OTLP، وعندك OpenTelemetry Collector قبل Jaeger أو Tempo أو vendor مدفوع. لو الـ traffic عندك أقل من 20 ألف request يوميًا، غالبًا مش محتاج التعقيد ده دلوقتي.
الفكرة: القرار يتاخد بعد ما التريس يخلص
Tail Sampling معناه إن قرار الاحتفاظ بالـ trace بيتاخد بعد ما Collector يشوف كل أو معظم الـ spans. ركز في الفرق: بدل ما تقول من البداية “خد 10% وخلاص”، تقول “احتفظ بكل الأخطاء، واحتفظ بكل request أبطأ من 5 ثواني، وخد 5% من الطلبات السليمة”.
مثال بسيط: عندك checkout service. من 100 ألف trace في الساعة، 97 ألف ناجحين وسريعين، 2500 بطيئين، و500 فيهم أخطاء. بدل ما تخزن 100 ألف، ممكن تخزن 8 آلاف تقريبًا: كل الأخطاء، كل البطيء، وعينة صغيرة من السليم. المكسب تقديريًا 92% تقليل في حجم التريس. الخسارة إنك مش هتشوف كل request ناجح سريع بالتفصيل.
إعداد عملي لـ OpenTelemetry Collector
أفضل طريقة تبدأ بيها هي gateway collector واحد أو أكثر قدام الـ backend. استخدم memory_limiter قبل tail_sampling، واستخدم batch بعده. المثال التالي يحتفظ بالأخطاء، والطلبات فوق 5 ثواني، و5% من الباقي.
receivers:
otlp:
protocols:
grpc:
http:
processors:
memory_limiter:
check_interval: 1s
limit_mib: 1024
tail_sampling:
decision_wait: 10s
num_traces: 50000
policies:
- name: keep-errors
type: status_code
status_code:
status_codes: [ERROR]
- name: keep-slow-traces
type: latency
latency:
threshold_ms: 5000
- name: keep-small-baseline
type: probabilistic
probabilistic:
sampling_percentage: 5
batch:
exporters:
otlp:
endpoint: tempo:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, tail_sampling, batch]
exporters: [otlp]