Node.js बैकएंड विकास बूटकैंप · पाठ

OpenTelemetry स्पैन से वितरित ट्रेसिंग

सेवा सीमाओं के पार विलंबता दिखाने वाले स्पैन बनाने के लिए सेवाओं में स्वचालित और मैन्युअल इंस्ट्रुमेंटेशन कीजिए।

पाठ 2, कुल 4 में से13 चरण

OpenTelemetry स्पैन से वितरित ट्रेसिंग, CoddyKit पर Node.js बैकएंड विकास बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह Node.js बैकएंड विकास बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

वितरित अनुरेखण क्यों?

माइक्रोसर्विस सिस्टम में एक उपयोगकर्ता अनुरोध API गेटवे, ऑर्डर सेवा, भुगतान सेवा और डेटाबेस से होकर गुजर सकता है। जब वह अनुरोध धीमा हो, तो किसी एक सेवा के लॉग यह नहीं बता सकते कि समय कहाँ लगा।

वितरित अनुरेखण पूरी यात्रा को जोड़ देता है। काम की हर इकाई एक स्पैन बन जाती है, स्पैन मिलकर एक ट्रेस बनाते हैं और यह ट्रेस हर सेवा सीमा के पार लगने वाला समय दिखाता है।

  • ट्रेस: आरंभ से अंत तक पूरा अनुरोध, जिसकी पहचान traceId से होती है।
  • स्पैन: एक कार्य (जैसे HTTP कॉल या डेटाबेस क्वेरी), जिसमें प्रारंभ समय, अवधि और पैरेंट होता है।
  • संदर्भ प्रसार: सेवा सीमाओं के पार traceId और spanId भेजना, आमतौर पर HTTP हेडर के माध्यम से।

OpenTelemetry (OTel), Node.js में इन स्पैन को बनाने का विक्रेता-निरपेक्ष मानक है।

स्पैन की संरचना

स्पैन, ट्रेस की मूल निर्माण इकाई है। हर स्पैन में वही ट्रेस पहचान होती है, लेकिन उसकी अपनी पहचान और समय-संबंधी जानकारी होती है।

  • traceId: 16 बाइट, ट्रेस के हर स्पैन में साझा।
  • spanId: 8 बाइट, इस स्पैन के लिए अद्वितीय।
  • parentSpanId: इस स्पैन को उस कार्य से जोड़ता है जिसने इसे शुरू किया।
  • name, startTime, endTime (अवधि = end - start)।
  • विशेषताएँ: http.method या db.system जैसे कुंजी/मान टैग।
  • स्थिति: OK, ERROR या UNSET।

पैरेंट और चाइल्ड के लिंक एक वृक्ष बनाते हैं। रूट स्पैन पूरा अनुरोध होता है; चाइल्ड स्पैन उन कॉल को दर्शाते हैं जो वह करता है। दृश्य रूप में यह वृक्ष Jaeger या Tempo में दिखाई देने वाला परिचित वॉटरफॉल बन जाता है।

Node SDK के साथ स्वचालित इंस्ट्रूमेंटेशन

स्पैन प्राप्त करने का सबसे तेज़ तरीका स्वचालित इंस्ट्रूमेंटेशन है। OTel Node SDK लोकप्रिय लाइब्रेरी (http, Express, pg, ioredis आदि) में इस तरह बदलाव करता है कि वे आपके द्वारा अनुरेखण कोड लिखे बिना स्पैन उत्पन्न करें।

एक tracing.js फ़ाइल बनाएँ, जो SDK को बाकी सब चीज़ों से पहले शुरू करे। फिर अपना ऐप node -r ./tracing.js app.js के साथ चलाएँ, ताकि यह फ़ाइल सबसे पहले लोड हो।

// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');

const sdk = new NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'orders-service',
  }),
  traceExporter: new OTLPTraceExporter({
    url: 'http://localhost:4318/v1/traces',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

स्वचालित इंस्ट्रूमेंटेशन से आपको क्या मिलता है

SDK लोड होने पर आने वाला HTTP अनुरोध अपने-आप रूट स्पैन बन जाता है और कोई भी आउटगोइंग http/fetch कॉल या pg क्वेरी उसके नीचे चाइल्ड स्पैन बन जाती है।

  • इनबाउंड Express रूट → सर्वर स्पैन, जिसमें http.method, http.route, http.status_code होते हैं।
  • आउटबाउंड HTTP कॉल → क्लाइंट स्पैन; हेडर अपने-आप जोड़े जाते हैं।
  • डेटाबेस क्वेरी → क्लाइंट स्पैन, जिसमें db.system और स्टेटमेंट होता है।

इससे सीमाएँ बिना अतिरिक्त प्रयास के कवर हो जाती हैं। लेकिन स्वचालित इंस्ट्रूमेंटेशन आपके व्यावसायिक तर्क—मूल्य-निर्धारण नियम, कैश संबंधी निर्णय और बैच लूप—को नहीं समझता। इनके लिए आपको स्पैन मैन्युअली जोड़ने होंगे।

ट्रेसर प्राप्त करना

स्पैन मैन्युअली बनाने के लिए पहले वैश्विक ट्रेस API से एक ट्रेसर प्राप्त करें। इसका नाम उस मॉड्यूल या लाइब्रेरी के नाम पर रखें जो स्पैन बना रही है; संस्करण वैकल्पिक है, लेकिन इंस्ट्रूमेंटेशन की समस्या खोजते समय उपयोगी होता है।

ट्रेसर आपके सभी मैन्युअल स्पैन का फ़ैक्टरी है।

const { trace } = require('@opentelemetry/api');

// Name + version identify the instrumentation scope
const tracer = trace.getTracer('orders-service', '1.0.0');

// Later, anywhere in the code:
// const span = tracer.startSpan('chargeCustomer');

startActiveSpan: मानक तरीका

startSpan() के बजाय tracer.startActiveSpan() को प्राथमिकता दें। startActiveSpan अपने कॉलबैक की अवधि के लिए नए स्पैन को सक्रिय स्पैन बना देता है, इसलिए उसके अंदर बनाए गए चाइल्ड स्पैन (स्वचालित इंस्ट्रूमेंटेशन वाले भी) अपने-आप चाइल्ड के रूप में जुड़ जाते हैं।

मुख्य नियम: finally ब्लॉक में हमेशा span.end() कॉल करें और विफलता होने पर त्रुटियाँ तथा ERROR स्थिति दर्ज करें।

const { trace, SpanStatusCode } = require('@opentelemetry/api');
const tracer = trace.getTracer('orders-service');

async function processOrder(order) {
  return tracer.startActiveSpan('processOrder', async (span) => {
    try {
      span.setAttribute('order.id', order.id);
      span.setAttribute('order.items', order.items.length);
      const result = await chargeAndShip(order); // child spans nest here
      span.setStatus({ code: SpanStatusCode.OK });
      return result;
    } catch (err) {
      span.recordException(err);
      span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
      throw err;
    } finally {
      span.end();
    }
  });
}

विशेषताएँ, घटनाएँ और स्थिति

स्पैन में अतिरिक्त जानकारी जोड़ने पर वे उपयोगी बनते हैं। इसके लिए तीन साधन हैं:

  • विशेषताएँ — खोजे जा सकने वाले कुंजी/मान टैग। अर्थपूर्ण परंपराओं (http.method, db.system, messaging.system) का उपयोग करें, ताकि बैकएंड उन्हें समझ सकें।
  • घटनाएँ — स्पैन के अंदर स्थित समय-मुद्रित लॉग पंक्तियाँ, जैसे span.addEvent('cache.miss')।
  • स्थिति — ERROR केवल वास्तविक विफलताओं पर सेट करें; सफलता को UNSET या OK रहने दें।

कार्डिनैलिटी को उचित रखें: यदि आपका बैकएंड किसी उच्च-ट्रैफ़िक विशेषता को अनुक्रमित करता है, तो उसमें कभी भी कच्ची उपयोगकर्ता ID या लिटरल वाले पूरे SQL को न डालें—इससे स्टोरेज बहुत तेज़ी से बढ़ सकता है।

function readFromCache(span, key) {
  const hit = cache.has(key);
  if (hit) {
    span.addEvent('cache.hit', { 'cache.key': key });
  } else {
    span.addEvent('cache.miss', { 'cache.key': key });
  }
  span.setAttribute('cache.hit', hit);
  return hit ? cache.get(key) : null;
}

सेवाओं के बीच संदर्भ प्रसार

ट्रेस तभी सेवाओं के बीच फैलता है, जब ट्रेस संदर्भ अनुरोध के साथ आगे जाए। W3C का traceparent हेडर traceId, पैरेंट spanId और सैंपलिंग फ़्लैग रखता है।

मानक HTTP पर स्वचालित इंस्ट्रूमेंटेशन आपके लिए इस हेडर को अपने-आप जोड़ता और निकालता है। जब आप कोई गैर-मानक तरीका अपनाते हैं (जैसे कस्टम ट्रांसपोर्ट या संदेश कतार), तो प्रोपेगेशन API से इसे मैन्युअली जोड़ें और निकालें।

const { context, propagation, trace } = require('@opentelemetry/api');

// SENDER: inject current context into outgoing carrier (e.g. message headers)
function publish(queue, payload) {
  const headers = {};
  propagation.inject(context.active(), headers);
  queue.send({ payload, headers }); // traceparent now travels with the message
}

// RECEIVER: extract context and continue the trace
function onMessage(msg) {
  const parentCtx = propagation.extract(context.active(), msg.headers);
  const tracer = trace.getTracer('worker');
  context.with(parentCtx, () => {
    tracer.startActiveSpan('handleMessage', (span) => {
      handle(msg.payload);
      span.end();
    });
  });
}

traceparent हेडर पढ़ना

traceparent हेडर का एक निश्चित और विश्लेषण योग्य प्रारूप होता है। इसे समझने से टूटा हुआ अनुरेखण ठीक करने में मदद मिलती है (यदि चाइल्ड गायब हो, तो आमतौर पर हेडर कहीं छूट गया है)।

प्रारूप: version-traceId-parentId-flags, जैसे
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

  • 00 — संस्करण
  • 32 हेक्स वर्ण — traceId
  • 16 हेक्स वर्ण — पैरेंट spanId
  • 01 — फ़्लैग (बिट 0 = सैंपल किया गया)

संरचना को स्पष्ट रूप से समझने के लिए यहाँ एक छोटा स्वतंत्र पार्सर दिया गया है।

function parseTraceparent(header) {
  const parts = header.split('-');
  if (parts.length !== 4) throw new Error('invalid traceparent');
  const [version, traceId, parentId, flags] = parts;
  return {
    version,
    traceId,
    parentId,
    sampled: (parseInt(flags, 16) & 1) === 1,
  };
}

const h = '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01';
console.log(parseTraceparent(h));
// { version: '00', traceId: '4bf9...4736', parentId: '00f0...02b7', sampled: true }

लागत नियंत्रित करने के लिए सैंपलिंग

अधिक ट्रैफ़िक में हर अनुरोध का अनुरेखण करना महँगा होता है। सैंपलर तय करते हैं कि कौन-से ट्रेस सुरक्षित रखने हैं। यह निर्णय traceparent के सैंपल किए गए फ़्लैग के माध्यम से आगे जाता है, इसलिए सभी सेवाओं में किसी ट्रेस को एकसमान रूप से रखा या हटाया जाता है।

  • AlwaysOnSampler — सब कुछ रखें (विकास/कम ट्रैफ़िक)।
  • TraceIdRatioBasedSampler — एक निश्चित अंश रखें, जैसे 10%।
  • ParentBasedSampler — अपस्ट्रीम निर्णय का सम्मान करें; नए रूट को अनुपात के आधार पर सैंपल करें। यह उत्पादन का डिफ़ॉल्ट है।

सरलता के लिए हेड सैंपलिंग (शुरुआत में निर्णय) का उपयोग करें, या सभी त्रुटियों और धीमे ट्रेस को रखने के लिए कलेक्टर में टेल सैंपलिंग अपनाएँ।

const { ParentBasedSampler, TraceIdRatioBasedSampler } = require('@opentelemetry/sdk-trace-base');

// Keep 10% of new root traces; honor upstream decisions for the rest
const sampler = new ParentBasedSampler({
  root: new TraceIdRatioBasedSampler(0.1),
});

// Pass to the NodeSDK: new NodeSDK({ sampler, ... });

विलंबता खोजने के लिए वॉटरफॉल पढ़ना

जब स्पैन किसी बैकएंड (Jaeger, Tempo, Honeycomb) तक पहुँचते हैं, तो आप ट्रेस को वॉटरफॉल की तरह पढ़ते हैं। हर पट्टी एक स्पैन होती है; उसकी चौड़ाई उसकी अवधि दर्शाती है और इंडेंटेशन पैरेंट/चाइल्ड संबंध दिखाता है।

अड़चन कैसे खोजें:

  • सबसे चौड़ी चाइल्ड पट्टी खोजें — वही कार्य अनुरोध के अधिकांश समय के लिए ज़िम्मेदार है।
  • पैरेंट और उसके पहले चाइल्ड के बीच रिक्त स्थान देखें — आमतौर पर ये कतार में प्रतीक्षा, GC विराम या ऐसे काम को दर्शाते हैं जिसके लिए इंस्ट्रूमेंटेशन नहीं हुआ है।
  • जो क्रमिक पट्टियाँ समानांतर चल सकती थीं, वे Promise.all के उपयोग का अवसर दिखाती हैं।
  • ERROR स्थिति वाला लाल स्पैन सीधे विफल सीमा की ओर संकेत करता है।

सेवाओं के बीच इसका लाभ यह है कि आप देख सकते हैं कि 900ms के अनुरोध का 80% समय आपके अपने कोड में नहीं, बल्कि डाउनस्ट्रीम भुगतान सेवा में लगा।

त्वरित जाँच: सक्रिय स्पैन का नेस्टिंग

आप किसी फ़ंक्शन को मैन्युअल रूप से tracer.startActiveSpan('outer', cb) में रैप करते हैं। कॉलबैक के अंदर, आपका स्वचालित इंस्ट्रूमेंटेशन वाला HTTP क्लाइंट बाहर जाने वाली कॉल करता है। इनमें से कौन-सा कथन सही है?

पुनरावृत्ति और मुख्य बातें

अब आप ऐसे स्पैन बना सकते हैं जो सेवाओं की सीमाओं के पार लेटेंसी दिखाते हैं:

  • ट्रेस = कई स्पैन, जिनमें एक ही traceId साझा होता है; हर स्पैन का अपना spanId और एक parentSpanId होता है।
  • स्वचालित इंस्ट्रूमेंटेशन (NodeSDK + auto-instrumentations-node, जिसे node -r के साथ लोड किया जाता है) HTTP, DB और कतार की सीमाओं को बिना अतिरिक्त प्रयास के कवर करता है।
  • मैन्युअल स्पैन tracer.startActiveSpan() के साथ व्यावसायिक तर्क को कैप्चर करते हैं; हमेशा finally में end() करें और अपवाद होने पर ERROR स्थिति सेट करें।
  • कार्डिनैलिटी पर नज़र रखते हुए, एट्रिब्यूट और इवेंट से स्पैन को अधिक जानकारी दें।
  • W3C के traceparent हेडर के माध्यम से कॉन्टेक्स्ट प्रसार से ट्रेस सेवाओं के बीच पहुँचते हैं; गैर-HTTP ट्रांसपोर्ट के लिए इन्हें मैन्युअल रूप से इंजेक्ट और एक्सट्रैक्ट करें।
  • सैंपलिंग (ParentBased + अनुपात) सेवाओं के बीच निर्णयों को एकसमान रखते हुए लागत नियंत्रित करती है।
  • वॉटरफ़ॉल पढ़ें: सबसे चौड़ी पट्टियाँ, अंतराल और क्रमिक कॉल वास्तविक बाधा को उजागर करते हैं।
शुरुआत निःशुल्क

एआई शिक्षक के साथ JavaScript सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
22
पाठ
92

अक्सर पूछे जाने वाले प्रश्न

क्या “OpenTelemetry स्पैन से वितरित ट्रेसिंग” पाठ निःशुल्क है?

हाँ—“OpenTelemetry स्पैन से वितरित ट्रेसिंग” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। Node.js बैकएंड विकास बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“OpenTelemetry स्पैन से वितरित ट्रेसिंग” में मैं क्या सीखूँगा?

सेवा सीमाओं के पार विलंबता दिखाने वाले स्पैन बनाने के लिए सेवाओं में स्वचालित और मैन्युअल इंस्ट्रुमेंटेशन कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ Node.js बैकएंड विकास बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या Node.js बैकएंड विकास बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर Node.js बैकएंड विकास बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“OpenTelemetry स्पैन से वितरित ट्रेसिंग” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस Node.js बैकएंड विकास बूटकैंप पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर Node.js बैकएंड विकास बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. सहसंबंध आईडी के साथ संरचित लॉगिंग
  2. OpenTelemetry स्पैन से वितरित ट्रेसिंग
  3. ऐप्लिकेशन मेट्रिक्स उजागर करना और RED पद्धति
  4. AsyncLocalStorage से संदर्भ प्रसार
← Node.js बैकएंड विकास बूटकैंप पर वापस जाएँ