OpenTelemetry بالإنتاج: الـ Traces والسياق وشو اللي فعلاً يهم
أنماط OpenTelemetry إنتاجية. نشر السياق عبر الطوابير والـ workers، تتبع استدعاءات LLM، استراتيجيات العينات لأحمال الذكاء الاصطناعي، spans آمنة للخصوصية، وBaggage API.
ليش OpenTelemetry فاز
قبل ثلاث سنوات، مشهد المراقبة كان مفتت. Jaeger للتتبع، Prometheus للمقاييس، Fluentd للسجلات، كل واحد بالـ SDK حقه، البروتوكول حقه، والقفل على بائع محدد. OpenTelemetry وحّدهم بمعيار واحد: SDK واحد، بروتوكول واحد (OTLP)، collector واحد يوجّه لأي backend.
تبنّينا OpenTelemetry عبر أنظمة الإنتاج حقتنا. هالمقال يغطي الأنماط اللي فعلاً تهم بالإنتاج، مو دورة الإعداد. لاستراتيجية المراقبة الأوسع (متى تنبّه، شو تسجّل، كيف تبني المقاييس)، شوف دليل مراقبة الذكاء الاصطناعي. هالمقال يروح أعمق بتنفيذ OpenTelemetry تحديداً.
نشر السياق: الجزء الأصعب
طلب مستخدم واحد ممكن يعبر 5 خدمات، 3 طوابير رسائل، عمليتين worker، واستدعاء LLM. نشر السياق يضمن إنه التتبع يتابع الطلب عبر كلهم.
نشر HTTP (سهل)
OpenTelemetry يعمل instrumentation تلقائي لعملاء وخوادم HTTP. سياق التتبع ينتشر عبر headers الـ traceparent والـ tracestate. هالشي يشتغل من الصندوق.
// Instrumentation تلقائي: ما تحتاج كود لنشر HTTP
// الـ SDK يضيف header الـ traceparent للطلبات الصادرة
// الخدمة المستقبلة تستخرجه وتكمّل التتبع
نشر الطوابير (صعب)
طوابير الرسائل تقطع النشر التلقائي. لما تحط رسالة بالطابور، سياق التتبع لازم يُسلسل بـ headers الرسالة. لما worker يسحبها، السياق لازم يُستخرج والتتبع يكمل.
// المنتج: حقن سياق التتبع بـ headers الرسالة
import { context, propagation } from '@opentelemetry/api';
async function enqueueMessage(queue: string, payload: any) {
const carrier: Record<string, string> = {};
propagation.inject(context.active(), carrier);
await messageQueue.send(queue, {
body: payload,
headers: carrier, // يحتوي traceparent و tracestate
});
}
// المستهلك: استخراج سياق التتبع من headers الرسالة
async function processMessage(message: QueueMessage) {
const parentContext = propagation.extract(context.active(), message.headers);
await context.with(parentContext, async () => {
const span = tracer.startSpan('process_message', {
attributes: {
'messaging.system': 'rabbitmq',
'messaging.operation': 'process',
'messaging.destination': message.queue,
},
});
try {
await handleMessage(message.body);
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
throw error;
} finally {
span.end();
}
});
}
هالنمط يشتغل مع RabbitMQ وKafka وBullMQ وSQS وSymfony Messenger. الـ headers حق الرسالة تحمل سياق التتبع. المستهلك يستخرجه وينشئ child spans تحت التتبع الأصلي.
نشر عمليات الـ Worker
لـ BullMQ workers حق Vendure، وSymfony Messenger workers حق Pimcore، وأنظمة المهام الخلفية المشابهة، النمط نفسه: سلسل السياق بحمولة المهمة، استخرجه على جانب الـ worker.
// BullMQ: أضف سياق التتبع لبيانات المهمة
async function addJob(queue: Queue, data: any) {
const carrier: Record<string, string> = {};
propagation.inject(context.active(), carrier);
await queue.add('process', {
...data,
_traceContext: carrier,
});
}
// BullMQ: استخراج سياق التتبع بالـ worker
worker.on('process', async (job) => {
const parentContext = propagation.extract(context.active(), job.data._traceContext || {});
await context.with(parentContext, async () => {
const span = tracer.startSpan(`job:${job.name}`);
try {
await processJob(job.data);
} finally {
span.end();
}
});
});
تتبع استدعاءات LLM
استدعاءات LLM هي أغلى العمليات بأنظمة الذكاء الاصطناعي. تتبعها مع attributes صحيحة يمكّن تتبع التكاليف، تحليل الكمون، ومراقبة الجودة.
async function tracedLlmCall(prompt: string, options: LlmOptions): Promise<string> {
const span = tracer.startSpan('llm.generate', {
attributes: {
'llm.provider': options.provider, // "openai", "anthropic"
'llm.model': options.model, // "gpt-4o", "claude-sonnet-4-20250514"
'llm.temperature': options.temperature,
'llm.max_tokens': options.maxTokens,
'llm.prompt_tokens': estimateTokens(prompt), // تقدير قبل الاستدعاء
},
});
try {
const response = await llmClient.generate(prompt, options);
span.setAttributes({
'llm.response_tokens': response.usage.completionTokens,
'llm.total_tokens': response.usage.totalTokens,
'llm.finish_reason': response.finishReason,
'llm.cost_usd': calculateCost(response.usage, options.model),
});
span.setStatus({ code: SpanStatusCode.OK });
return response.text;
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
span.setAttribute('llm.error_type', error.constructor.name);
throw error;
} finally {
span.end();
}
}
لا تحط نص الـ prompt بـ span attributes. الـ prompts تحتوي PII. الـ span attributes تنرسل للـ backend حق المراقبة (Jaeger, Grafana Tempo, Datadog). بدلاً من هيك، سجّل hash الـ prompt أو عدد الـ tokens. للبنية الكاملة لتسجيل آمن من PII، شوف دليل منع تسرب بيانات الذكاء الاصطناعي.
اصطلاحات Span Attributes حق LLM
| الخاصية | النوع | مثال |
|---|---|---|
llm.provider | string | "openai" |
llm.model | string | "gpt-4o" |
llm.temperature | float | 0.7 |
llm.prompt_tokens | int | 1250 |
llm.response_tokens | int | 340 |
llm.total_tokens | int | 1590 |
llm.finish_reason | string | "stop" |
llm.cost_usd | float | 0.023 |
llm.error_type | string | "RateLimitError" |
llm.cache_hit | boolean | false |
استراتيجيات العينات
بأنظمة الذكاء الاصطناعي عالية الحجم، تتبع كل طلب مكلف جداً. العينات تقلل الحجم مع الحفاظ على الرؤية للتتبعات المهمة.
العينات بالرأس (Head-Based Sampling)
قرّر ببداية التتبع إذا تاخذ عينة أو لا. بسيط بس يفقد بيانات.
// خذ عينة 10% من كل التتبعات
const sampler = new TraceIdRatioBased(0.1);
// دائماً خذ عينة للأخطاء (تجاوز النسبة لتتبعات الأخطاء)
const compositeSampler = new ParentBasedSampler({
root: new TraceIdRatioBased(0.1),
// الأخطاء دائماً مأخوذة عينتها عبر span processor
});
العينات بالذيل (Tail-Based Sampling) (الموصى به للذكاء الاصطناعي)
قرّر بعد ما يكمل التتبع إذا تحتفظ فيه. يحتفظ بكل التتبعات المهمة (أخطاء، استجابات بطيئة، تكلفة عالية) ويحذف الروتينية.
// OpenTelemetry Collector: إعدادات العينات بالذيل
processors:
tail_sampling:
decision_wait: 10s
policies:
# احتفظ بكل الأخطاء
- name: errors
type: status_code
status_code: { status_codes: [ERROR] }
# احتفظ بالتتبعات البطيئة (أكثر من 5 ثواني)
- name: slow
type: latency
latency: { threshold_ms: 5000 }
# احتفظ باستدعاءات LLM الغالية (أكثر من $0.10)
- name: expensive_llm
type: string_attribute
string_attribute:
key: llm.cost_usd
values: [] # مخصص: فلتر بالـ pipeline
enabled_regex_matching: true
# خذ عينة 5% من كل شي ثاني
- name: baseline
type: probabilistic
probabilistic: { sampling_percentage: 5 }
العينات بالذيل تحتاج OpenTelemetry Collector. الـ collector يخزن التتبعات الكاملة مؤقتاً، يقيّم السياسات، ويمرر بس التتبعات المختارة للـ backend. هالشي يضيف كمون (فترة decision_wait) بس يقلل تكاليف التخزين بشكل كبير مع الاحتفاظ بكل البيانات المهمة.
Spans آمنة للخصوصية
الـ span attributes، أسماء الـ spans، وأحداث الـ spans كلها تنرسل للـ backend حق المراقبة. إذا أي وحدة فيها PII، البنية التحتية للتتبع حقتك تصير مسؤولية حماية بيانات.
// سيء: PII بالـ span attributes
span.setAttribute('user.email', 'sara.mustermann@beispiel.de');
span.setAttribute('user.name', 'Sara Mustermann');
span.setAttribute('request.body', JSON.stringify(requestBody)); // يحتوي PII
// كويس: معرّفات رمزية وبيانات مجمّعة فقط
span.setAttribute('user.id', 'usr_abc123'); // معرّف مبهم، مو PII
span.setAttribute('entities.detected', 3);
span.setAttribute('entities.types', ['person', 'email', 'phone']);
span.setAttribute('policy.applied', 'german-support');
قواعد التتبع الآمن للخصوصية:
- معرّفات المستخدمين: معرّفات مبهمة فقط (مو إيميلات، مو أسماء)
- أجسام الطلبات: لا تضمّن المحتوى الخام أبداً. سجّل عدد الكيانات وأنواعها.
- prompts الـ LLM: لا تضمّنها أبداً. سجّل عدد الـ tokens وhash الـ prompt.
- رسائل الأخطاء: نظّفها قبل ما تربطها بالـ spans. شيل أي بيانات مستخدم.
للمزيد عن حماية البيانات بأنظمة الذكاء الاصطناعي، شوف دليل الامتثال للـ GDPR ودليل حوكمة الذكاء الاصطناعي.
الـ Baggage API
OpenTelemetry Baggage ينقل أزواج مفتاح-قيمة عبر حدود الخدمات. بخلاف span attributes (اللي تبقى على الـ span)، الـ baggage ينتشر لكل الخدمات اللي بعده تلقائياً.
import { propagation, context, baggage } from '@opentelemetry/api';
// حدّد الـ baggage عند الـ API gateway
const bag = propagation.createBaggage({
'tenant.id': { value: 'tenant_acme' },
'request.priority': { value: 'high' },
'feature.flags': { value: 'new-checkout,beta-search' },
});
const ctx = propagation.setBaggage(context.active(), bag);
// الخدمات اللي بعدها تقدر تقرأ الـ baggage
const tenantId = propagation.getBaggage(context.active())?.getEntry('tenant.id')?.value;
مفيد لـ:
- نشر Tenant ID (كل خدمة بعدها تعرف أي tenant)
- Feature flags (انشر تعيينات التجارب عبر الخدمات)
- توجيه الأولويات (الطلبات عالية الأولوية تحصل معاملة طابور مختلفة)
- علامات التصحيح (علّم طلبات محددة لتسجيل مفصّل)
الـ Baggage يسافر مع سياق التتبع بـ HTTP headers وmetadata الرسائل. كل خدمة تستخرج سياق التتبع تحصل على الـ baggage كمان.
بنية الـ Collector
OpenTelemetry Collector هو طبقة التوجيه المركزية بين تطبيقاتك والـ backends حق المراقبة.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Service A │ │ Service B │ │ Worker C │
│ (OTLP gRPC) │ │ (OTLP HTTP) │ │ (OTLP gRPC) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────┐
│ OTel Collector │
│ │
│ Receivers: OTLP (gRPC + HTTP) │
│ Processors: batch, tail_sampling, attributes │
│ Exporters: Tempo, Prometheus, Loki │
└─────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Grafana │ │ Prometheus │ │ Grafana │
│ Tempo │ │ │ │ Loki │
│ (traces) │ │ (metrics) │ │ (logs) │
└──────────────┘ └──────────────┘ └──────────────┘
الـ collector يتعامل مع التجميع (يقلل استدعاءات الشبكة)، العينات (يقلل التخزين)، معالجة الخصائص (يضيف/يشيل attributes)، والتوجيه (إشارات مختلفة لـ backends مختلفة). انشره كـ sidecar أو كخدمة مركزية حسب البنية التحتية حقتك.
لأنماط النشر السحابي بما فيها البنية التحتية للمراقبة، هداك الصفحة تغطي منهجيتنا. شوف كمان دليل بنية الأنظمة لفهم كيف يندمج الـ collector مع البنية العامة.
الأخطاء الشائعة
-
ما في نشر سياق عبر الطوابير. نشر HTTP تلقائي. نشر الطوابير لا. إذا ما حقنت/استخرجت السياق بـ headers الرسائل، التتبعات تنقطع عند كل حدود الطوابير.
-
PII بالـ span attributes. الـ backend حق التتبع يفهرس كل شي. إذا الـ spans فيها إيميلات، أسماء، أو أجسام طلبات، الـ cluster حق Grafana Tempo حقك صار مخزن PII.
-
تتبع كل طلب بالإنتاج. عند 1000 RPS، التتبع الكامل يولّد تيرابايتات من البيانات. استخدم العينات بالذيل للاحتفاظ بالأخطاء، التتبعات البطيئة، والعمليات الغالية.
-
ما في attributes خاصة بالـ LLM. بدون عدد الـ tokens، التكلفة، معرّف النموذج، وسبب الإنهاء على spans الـ LLM، ما تقدر تتبع تكاليف الذكاء الاصطناعي أو تشخّص مشاكل الجودة.
-
العينات بالرأس تحذف الأخطاء. إذا أخذت عينة 10% من التتبعات وخطأ صار بالـ 90% اللي حذفتها، ما بتشوفه أبداً. استخدم العينات بالذيل أو سياسات "دائماً خذ عينة للأخطاء".
-
Baggage لحمولات كبيرة. الـ Baggage يسافر مع كل طلب. القيم الكبيرة تزيد حجم الـ headers بكل استدعاء HTTP. خلّ قيم الـ baggage صغيرة (معرّفات، flags، أولويات).
النقاط الرئيسية
-
نشر السياق عبر الطوابير هو الجزء الأصعب. HTTP تلقائي. الطوابير تحتاج حقن/استخراج يدوي لسياق التتبع بـ headers الرسائل. هنا أغلب تطبيقات التتبع الموزع تنكسر.
-
تتبع استدعاءات LLM مع attributes التكلفة والـ tokens. النموذج، المزود، عدد الـ tokens، التكلفة، سبب الإنهاء. هالخصائص تمكّن لوحات تحكم تكاليف الذكاء الاصطناعي ومراقبة الجودة.
-
العينات بالذيل لأحمال الذكاء الاصطناعي. احتفظ بكل الأخطاء، التتبعات البطيئة، والعمليات الغالية. احذف التتبعات الروتينية. يقلل التخزين بأكثر من 90% مع الاحتفاظ بكل البيانات المهمة.
-
ما في PII بالـ spans. معرّفات مستخدمين مبهمة، عدد كيانات، أنواع tokens. أبداً محتوى خام، إيميلات، أسماء، أو أجسام طلبات.
-
Baggage ينشر سياق الـ tenant. حدّد Tenant ID، feature flags، والأولوية عند الحافة. كل خدمة بعدها تقرأها من الـ baggage بدون تمرير parameters صريح.
ننفذ OpenTelemetry عبر خدمات الذكاء الاصطناعي، البرمجيات المخصصة، والبنية التحتية السحابية حقتنا. إذا تبني مراقبة لنظام موزع، تواصل مع فريقنا أو اطلب عرض سعر.
المواضيع المغطاة
أدلة ذات صلة
الدليل الشامل لأنظمة الذكاء الاصطناعي الوكيلي
دليل تقني لأنظمة الذكاء الاصطناعي الوكيلي في بيئات الأعمال. تعرف على البنية والقدرات والتطبيقات العملية للوكلاء المستقلين.
اقرأ الدليلالتجارة الوكيلية: كيف تخلي وكلاء الذكاء الاصطناعي يشترون بأمان
كيف تصمم تجارة وكيلية محكومة. محركات السياسات، بوابات الموافقة البشرية، إيصالات HMAC، الـ idempotency، عزل المستأجرين، وبروتوكول الدفع الوكيلي الكامل.
اقرأ الدليلالـ 9 أماكن اللي نظام AI تبعك بيسرّب بيانات منها (وكيف تسد كل وحدة)
خارطة منهجية لكل مكان البيانات بتتسرب منه بأنظمة AI. البرومبتات، الـ embeddings، السجلات، استدعاءات الأدوات، ذاكرة الـ agent، رسائل الأخطاء، الكاش، بيانات التدريب، وتسليمات الـ agents.
اقرأ الدليلجاهز لبناء أنظمة ذكاء اصطناعي جاهزة للإنتاج؟
فريقنا متخصص في بناء أنظمة ذكاء اصطناعي جاهزة للإنتاج. خلينا نحكي كيف نقدر نساعد.
ابدأ محادثة