المشكلة
في مشروع Entegrasys، تُدار عشر شركات شحن وأربعة أنظمة ERP عبر طبقة تنسيق واحدة. وعند إنشاء طلب، يمرّ الطلب بسبع خدمات في المتوسط: بوابة الواجهات البرمجية، وخدمة المصادقة، وخدمة الطلبات، وموصّل ERP، ومحوّل شركة الشحن.
وحين يبطؤ شيء في هذه السلسلة أو يخفق، كان تحديد موضعه بدقة — مع استخدام كل خدمة صيغة سجلات خاصة بها — يستغرق ساعات. وقد حلّ OpenTelemetry هذه المشكلة.
ما هو OpenTelemetry (وما ليس هو)
OpenTelemetry (اختصارًا OTel) معيار محايد تجاه المورّدين لإنتاج بيانات القياس عن بُعد — التتبعات والمقاييس والسجلات — وجمعها وتصديرها. وهو ليس أداة تخزين ولا تصوير بياني؛ بل يعمل في الجانب المنتِج من خط المعالجة.
والأثر العملي لذلك: أي خدمة مزوّدة بأدوات OTel تستطيع إرسال تتبعاتها إلى Jaeger أو Grafana Tempo أو Datadog. وتغيير المورّد لا يتطلب أي تعديل في الشيفرة.
استراتيجية التزويد بالأدوات
التزويد التلقائي مقابل اليدوي
في خدمات Node.js، تزوّد حزمة التزويد التلقائي من OTel بروتوكولات HTTP و gRPC واستعلامات قواعد البيانات وكثيرًا من المكتبات الشائعة تلقائيًا:
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT }),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
هذا الملف الواحد يحوّل كل شيء — من نقاط نهاية Express إلى استعلامات Prisma — إلى مقاطع تتبع تلقائيًا.
أما التزويد اليدوي فضروري لإضافة رؤية داخل منطق الأعمال:
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('order-service', '1.0.0');
async function processOrder(orderId: string) {
return tracer.startActiveSpan('order.process', async (span) => {
span.setAttribute('order.id', orderId);
span.setAttribute('order.source', 'api');
try {
const result = await doWork(orderId);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (err) {
span.recordException(err as Error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw err;
} finally {
span.end();
}
});
}
نقل السياق
نقل السياق هو شريان الحياة في التتبع الموزّع. فمع انتقال الطلب من خدمة إلى أخرى، ينتقل معرّف التتبع ومعرّف المقطع في ترويسات HTTP (traceparent و tracestate).
ويتولى OTel هذا النقل تلقائيًا — لكن إن كسرت طبقة في السلسلة هذا النقل (وكيل عكسي، أو طابور رسائل، أو حزمة تطوير من طرف ثالث)، انكسرت السلسلة.
مزلق شائع
العمليات غير المتزامنة عبر طوابير الرسائل (Kafka و RabbitMQ) لا تحمل سياق التتبع تلقائيًا. فعليكم كتابة شيفرة صريحة لإرفاق traceparent بترويسات الرسالة واستعادته في جانب المستهلك.
إعداد المُجمِّع
يتلقى مُجمِّع OTel التتبعات والمقاييس والسجلات من الخدمات، ويعالجها، ثم يمرّرها إلى التخزين الخلفي. وفي Entegrasys بنينا خط المعالجة التالي:
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
send_batch_size: 1024
memory_limiter:
limit_mib: 512
resource:
attributes:
- key: deployment.environment
value: production
action: upsert
exporters:
otlp/tempo:
endpoint: tempo:4317
tls:
insecure: true
prometheus:
endpoint: "0.0.0.0:8889"
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch, resource]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]
استراتيجية أخذ العينات
تخزين كل تتبع في بيئة الإنتاج مكلف وغير ضروري في آن. لذلك حدّدنا استراتيجية ذكية لأخذ العينات:
- أخذ عينات عند البداية: 10% عشوائيًا كخط أساس لجميع الخدمات
- أخذ عينات عند النهاية: كل الطلبات التي تتجاوز 500 ميلي ثانية تُخزَّن بنسبة 100%
- عينات الأخطاء: كل التتبعات التي تتضمن أخطاءً تُخزَّن بنسبة 100%
- عينات الأعمال: المسارات الحرجة (المدفوعات والطلبات) تُؤخذ عيناتها بنسبة 100%
وطُبّق أخذ العينات عند النهاية على مستوى مُجمِّع OTel، بحيث تتوفر معلومات التتبع الكاملة قبل اتخاذ القرار.
التصوير البياني عبر Grafana Tempo
استخدمنا Grafana Tempo لتخزين التتبعات. ويتيح لنا تكامله الأصلي مع Prometheus عرض التتبعات والمقاييس جنبًا إلى جنب في Grafana.
وأثمن خاصية فيه: الانتقال من تنبيه في Prometheus مباشرة إلى التتبع المعني. فحين يقفز زمن الاستجابة عند المئين 99 لنقطة نهاية، تكفي نقرة واحدة من الرسم البياني إلى التتبع.
النتائج
بعد نقل OTel إلى بيئة الإنتاج:
- انخفض متوسط زمن اكتشاف الحوادث من 47 دقيقة إلى 8 دقائق
- حُدِّدت موصّلات ERP البطيئة من بيانات حقيقية؛ وعُثر على مشكلات استعلام من نوع N+1 في ثلاثة محوّلات لشركات شحن
- تقلّص زمن تهيئة المطورين الجدد: صار سلوك النظام قابلًا للقراءة من التتبعات
الخلاصة
OpenTelemetry معيار ناضج وجاهز لبيئة الإنتاج. ويمكن إعداده دون ارتهان لمورّد، ودعم منظومته الواسع يعني أنكم تستطيعون البدء سريعًا. وإن كنتم تعملون بالخدمات المصغّرة أو الأنظمة الموزّعة، فنوصي بنقل OTel من قائمة «تحسينات مستقبلية» إلى بنيتكم التحتية اليوم.

