المراقبة في TypeScript: من الصندوق الأسود إلى نظام شفاف
\n\nتخيل أن تطبيق TypeScript الخاص بك هو آلية معقدة من آلاف التروس. كل شيء يعمل بشكل مثالي حتى يتعطل. وفجأة تتلقى رسالة: "الموقع بطيء". أين تبحث عن المشكلة؟ قاعدة البيانات؟ API؟ أم أن أحد الخدمات المصغرة قد توقف فقط؟
\n\nبدون المراقبة (observability)، ستخمن مثل الشامان بدفّه. مع المراقبة، ترى الصورة كاملة: أين انخفض الأداء، أي طلب تسبب في الخطأ، ولماذا حدث تسرب للذاكرة.
\n\nفي هذه المقالة، سنشرح الأركان الثلاثة للمراقبة — التتبع، المقاييس والسجلات — ونتعلم كيفية دمجها في تطبيقات TypeScript بأمثلة عملية. ستتعلم كيفية تحويل تطبيقك من صندوق أسود إلى نظام شفاف يمكن تشخيصه في دقائق.
\n\nلماذا المراقبة ضرورية لتطبيقات TypeScript؟
\n\nTypeScript ليس مجرد إضافة فوق JavaScript. إنها لغة تُستخدم لكتابة الواجهة الخلفية للأنظمة عالية التحميل، والخدمات المصغرة، وحتى أدوات سطر الأوامر. وكلما كان النظام أكثر تعقيدًا، زادت أهمية فهم ما يحدث داخله.
\n\nالتسجيل التقليدي جيد، لكنه غير كافٍ. عندما يكون لديك 50 خدمة مصغرة، تتحول السجلات إلى ضوضاء بيضاء. أنت بحاجة إلى:
\n\n- \n
- التتبع — لتتبع مسار طلب واحد عبر جميع الخدمات. \n
- المقاييس — لرؤية أن الذاكرة RAM تنمو بسرعة. \n
- السجلات المنظمة — لعدم البحث عن إبرة في كومة قش. \n
لنقم بتطبيق هذا في تطبيق حقيقي.
\n\nالتتبع في TypeScript: OpenTelemetry عمليًا
\n\nالتتبع (Tracing) هو قصة حياة طلب واحد. ترى كم من الوقت استغرق كل خطوة: من طلب HTTP إلى استعلام قاعدة البيانات. في TypeScript، أصبح OpenTelemetry المعيار الفعلي.
\n\nتثبيت وإعداد OpenTelemetry
\n\nnpm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-jaeger\n\nلننشئ ملف tracing.ts لتهيئة التتبع:
import { NodeSDK } from '@opentelemetry/sdk-node';\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\nimport { JaegerExporter } from '@opentelemetry/exporter-jaeger';\nimport { Resource } from '@opentelemetry/resources';\nimport { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';\n\nconst jaegerExporter = new JaegerExporter({\n endpoint: 'http://localhost:14268/api/traces',\n serviceName: 'my-typescript-app',\n});\n\nconst sdk = new NodeSDK({\n resource: new Resource({\n [SemanticResourceAttributes.SERVICE_NAME]: 'my-typescript-app',\n [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',\n }),\n traceExporter: jaegerExporter,\n instrumentations: [getNodeAutoInstrumentations()],\n});\n\nsdk.start();\n\n\nالآن، سيتم تتبع كل طلب HTTP وكل استعلام قاعدة بيانات تلقائيًا. سترى في واجهة Jaeger UI (أو Grafana Tempo) خريطة كاملة للاستدعاءات.
\n\nإنشاء سبان يدويًا
\n\nالأتمتة رائعة، لكن أحيانًا تحتاج إلى إضافة علاماتك الخاصة. على سبيل المثال، قياس وقت تنفيذ منطق أعمال معقد:
\n\nimport { trace } from '@opentelemetry/api';\n\nconst tracer = trace.getTracer('business-logic');\n\nasync function processOrder(orderId: string): Promise<void> {\n const span = tracer.startSpan('process-order', {\n attributes: { 'order.id': orderId },\n });\n\n try {\n // منطق معالجة الطلب الخاص بك\n await validateOrder(orderId);\n await chargePayment(orderId);\n await sendConfirmation(orderId);\n\n span.setStatus({ code: 1 }); // OK\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus