OpenTelemetry Tail Sampling بالعربي: احتفظ بالتريس المهم
مستوى القارئ: متوسط
لو فاتورة الـ tracing بتزيد، المقال ده هيخليك تحتفظ بالـ traces اللي تهمك فعلاً: الأخطاء، الطلبات البطيئة، وجزء صغير من الطبيعي.
المشكلة باختصار
الطريقة الشائعة إنك تعمل head sampling بنسبة ثابتة، مثلاً 10% من أول الطلب. الطريقة دي بتفشل لما الخطأ النادر يحصل في الـ 90% اللي اترموا. ركز: المشكلة مش إن sampling غلط. المشكلة إن القرار اتاخد بدري.
الافتراض إن عندك تطبيق microservices بيستقبل حوالي 2,000 request في الدقيقة، وكل request ينتج 8 إلى 15 span. لو خزنت 100% من التريسز، أنت ممكن تبعت عشرات الآلاف من spans كل دقيقة لمنصة المراقبة. ده مفيد في التحقيق، لكنه مكلف ومزعج.
الفكرة: القرار بعد اكتمال الطلب
Tail Sampling في OpenTelemetry Collector بيستنى شوية لحد ما معظم spans بتاعة trace توصل، وبعدها يقرر: هل التريس ده يستاهل يتخزن ولا لأ. مثال بسيط: لو عندك طلب checkout خلص بنجاح في 180ms، ممكن تحتفظ بـ 5% منه بس. لكن لو نفس الطلب رجع ERROR أو أخد أكثر من 2 ثانية، احتفظ به 100%.
اللي بيحصل فعلاً إن الـ Collector يستخدم processor اسمه tail_sampling. حسب توثيق OpenTelemetry، الـ processor ده موجود في توزيعة contrib وKubernetes Collector، وبيشتغل على traces فقط. إعداد decision_wait يحدد وقت الانتظار قبل القرار، وnum_traces يحدد عدد traces التي تبقى في الذاكرة أثناء الانتظار.
إعداد عملي في OpenTelemetry Collector
أفضل طريقة تبدأ بيها: خلي الأخطاء 100%، والطلبات البطيئة 100%، والباقي نسبة صغيرة. المثال التالي مناسب كبداية لفريق عنده 500 إلى 1,000 trace جديدة في الثانية على gateway collector واحد.
receivers:
otlp:
protocols:
grpc:
http:
processors:
memory_limiter:
check_interval: 1s
limit_mib: 1024
spike_limit_mib: 256
tail_sampling:
decision_wait: 10s
num_traces: 20000
expected_new_traces_per_sec: 1000
policies:
- name: keep-errors
type: status_code
status_code:
status_codes: [ERROR]
- name: keep-slow-requests
type: latency
latency:
threshold_ms: 2000
- name: keep-5-percent-normal
type: probabilistic
probabilistic:
sampling_percentage: 5
batch:
timeout: 5s
send_batch_size: 8192
exporters:
otlp:
endpoint: tempo:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, tail_sampling, batch]
exporters: [otlp]