OpenTelemetry के साथ वितरित ट्रेसिंग
FastAPI में स्वचालित इंस्ट्रुमेंटेशन कीजिए और डाउनस्ट्रीम HTTP तथा डेटाबेस कॉल के माध्यम से ट्रेस संदर्भ प्रसारित कीजिए।
OpenTelemetry के साथ वितरित ट्रेसिंग, CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
वितरित ट्रेसिंग क्यों?
किसी माइक्रोसर्विस या यहाँ तक कि ऐसी एकल बैकएंड सेवा में भी, जो अन्य HTTP API और डेटाबेस से बात करती है, एक उपयोगकर्ता अनुरोध कई कार्रवाइयों में फैल जाता है। जब कुछ धीमा हो या विफल हो जाए, तो केवल लॉग प्रक्रिया की सीमाओं के पार मौजूद कारण-श्रृंखला नहीं दिखा सकते।
वितरित ट्रेसिंग हर अनुरोध को एक साझा trace_id देकर और कार्य को नेस्टेड स्पैन में बाँटकर इस समस्या का समाधान करती है:
- ट्रेस = एक अनुरोध की पूरी यात्रा।
- स्पैन = समय से मापी गई कार्य की एक इकाई (HTTP हैंडलर, DB क्वेरी या बाहर जाने वाला कॉल)।
- स्पैन में
parent_span_idहोता है, जिससे एक ट्री बनता है।
OpenTelemetry (OTel) विक्रेता-निरपेक्ष मानक और SDK है, जिसका उपयोग हम FastAPI से ये ट्रेस बनाने और उन्हें Jaeger, Tempo या OTLP कलेक्टर जैसे बैकएंड तक भेजने के लिए करते हैं।
OpenTelemetry का डेटा मॉडल
कुछ भी जोड़ने से पहले, उन मुख्य ऑब्जेक्ट को समझें जिन्हें आप कोड में कॉन्फ़िगर करेंगे:
- TracerProvider — ट्रेसर बनाने वाला फ़ैक्टरी ऑब्जेक्ट; इसे स्टार्टअप पर एक बार कॉन्फ़िगर किया जाता है।
- Tracer — प्रोवाइडर से प्राप्त किया जाता है और स्पैन शुरू करने के लिए उपयोग होता है।
- Span — इसमें नाम, शुरू और समाप्त होने का समय,
attributes(कुंजी/वैल्यू टैग),eventsऔरstatusहोते हैं। - SpanProcessor — समाप्त हो चुके स्पैन को बैच में सँभालता है (उत्पादन में
BatchSpanProcessorका उपयोग करें)। - एक्सपोर्टर — स्पैन को क्रमबद्ध करके बाहर भेजता है (gRPC/HTTP के ज़रिए OTLP)।
- कॉन्टेक्स्ट — थ्रेड या टास्क-स्थानीय वाहक, जो वर्तमान सक्रिय स्पैन को रखता है।
प्रवाह इस प्रकार है: TracerProvider → Tracer → Span → SpanProcessor → Exporter → backend।
SDK इंस्टॉल करना और प्रारंभिक सेटअप
FastAPI बैकएंड के लिए SDK, OTLP एक्सपोर्टर और इंस्ट्रुमेंटेशन पैकेज इंस्टॉल करें:
opentelemetry-sdk,opentelemetry-apiopentelemetry-exporter-otlpopentelemetry-instrumentation-fastapi,-httpx,-sqlalchemy
स्टार्टअप के समय ऐसी TracerProvider बनाएँ जिसमें आपकी सेवा का नाम बताने वाला Resource हो, OTLP एक्सपोर्टर को समेटने वाला BatchSpanProcessor जोड़ें, फिर उसे वैश्विक रूप से पंजीकृत करें। service.name एट्रिब्यूट बहुत महत्वपूर्ण है — इसी से आपका ट्रेसिंग बैकएंड स्पैन को समूहों में बाँटता है।
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
OTLPSpanExporter,
)
def configure_tracing() -> None:
resource = Resource.create({
"service.name": "orders-api",
"service.version": "1.4.0",
"deployment.environment": "production",
})
provider = TracerProvider(resource=resource)
exporter = OTLPSpanExporter(endpoint="http://otel-collector:4317")
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)FastAPI में स्वचालित इंस्ट्रुमेंटेशन
FastAPIInstrumentor आपके ऐप को इस तरह लपेटता है कि हर आने वाला अनुरोध अपने-आप एक सर्वर स्पैन बन जाता है। यह रूट, विधि और स्थिति कोड पढ़ता है और — सबसे महत्वपूर्ण रूप से — अनुरोध हेडर से आने वाला ट्रेस कॉन्टेक्स्ट निकालता है, ताकि इस सेवा के स्पैन कॉल करने वाले के ट्रेस से जुड़ें।
पहले configure_tracing() कॉल करें, फिर ऐप इंस्टेंस बनाने के तुरंत बाद उसमें इंस्ट्रुमेंटेशन जोड़ें। क्रम महत्वपूर्ण है: इंस्ट्रुमेंटेशन द्वारा उसे पढ़े जाने से पहले प्रोवाइडर को वैश्विक रूप से सेट किया जाना चाहिए।
from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from .tracing import configure_tracing
configure_tracing()
app = FastAPI(title="orders-api")
FastAPIInstrumentor.instrument_app(app)
@app.get("/orders/{order_id}")
async def get_order(order_id: int):
# This handler already runs inside an auto-created server span.
return {"order_id": order_id, "status": "shipped"}ट्रेस कॉन्टेक्स्ट प्रसार: W3C traceparent हेडर
सेवाओं के बीच स्पैन को जोड़ने वाला तंत्र कॉन्टेक्स्ट प्रसार है। OpenTelemetry डिफ़ॉल्ट रूप से W3C Trace Context मानक का उपयोग करता है, जिसमें traceparent HTTP हेडर होता है:
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
00— संस्करण4bf9...4736— 16-बाइट का trace-id (सभी सेवाओं में साझा)00f0...02b7— कॉल करने वाले का मूल span-id01— ट्रेस फ़्लैग (सैंपल किया गया बिट)
बाहर जाते समय इंस्ट्रुमेंट किए गए HTTP क्लाइंट इस हेडर को जोड़ते हैं। अंदर आते समय सर्वर इंस्ट्रुमेंटेशन इसे निकालता है। इसी तरह नेटवर्क के पार भी ट्रेस बिना टूटे बना रहता है।
बाहर जाने वाले HTTP कॉल के माध्यम से प्रसार
जब आपका FastAPI हैंडलर किसी बाद की सेवा को कॉल करता है, तो आपको इंस्ट्रुमेंट किए गए HTTP क्लाइंट का उपयोग करना चाहिए, ताकि traceparent हेडर अपने-आप जोड़ा जा सके। httpx के साथ स्टार्टअप पर एक बार HTTPXClientInstrumentor सक्षम करें।
अब हर बाहर जाने वाला अनुरोध एक क्लाइंट स्पैन बनाता है, जो वर्तमान सर्वर स्पैन का चाइल्ड होता है, और बाद की सेवा उसी ट्रेस को जारी रखती है।
import httpx
from fastapi import FastAPI
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
HTTPXClientInstrumentor().instrument()
app = FastAPI()
@app.get("/orders/{order_id}/full")
async def get_full_order(order_id: int):
async with httpx.AsyncClient(base_url="http://payments") as client:
# traceparent is injected automatically on this request.
resp = await client.get(f"/charges/{order_id}")
return {"order_id": order_id, "payment": resp.json()}डेटाबेस कॉल के माध्यम से प्रसार
डेटाबेस क्वेरी अक्सर किसी अनुरोध का सबसे धीमा हिस्सा होती हैं, इसलिए आप उन्हें भी स्पैन के रूप में देखना चाहेंगे। SQLAlchemy के लिए SQLAlchemyInstrumentor हर स्टेटमेंट के लिए एक स्पैन बनाता है और SQL तथा DB सिस्टम को एट्रिब्यूट के रूप में रिकॉर्ड करता है।
आपको इंजन में इंस्ट्रुमेंटेशन जोड़ना होगा (सिंक्रोनस के लिए engine=... दें, या असिंक्रोनस इंजन के पीछे वाले सिंक्रोनस इंजन का उपयोग करें)। ये DB स्पैन सक्रिय अनुरोध स्पैन के चाइल्ड बन जाते हैं, इसलिए धीमी क्वेरी उस हैंडलर के नीचे नेस्टेड दिखाई देती है जिसने उसे शुरू किया था।
from sqlalchemy.ext.asyncio import create_async_engine
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
engine = create_async_engine("postgresql+asyncpg://app:secret@db/orders")
# For async engines, instrument the underlying sync engine.
SQLAlchemyInstrumentor().instrument(engine=engine.sync_engine)
# Every statement run through this engine now emits a DB span
# nested under the current request span automatically.व्यावसायिक तर्क के लिए मैन्युअल स्पैन बनाना
स्वचालित इंस्ट्रुमेंटेशन इनपुट/आउटपुट की सीमाओं को कवर करता है, लेकिन आपका अपना तर्क दिखाई नहीं देता। समय कहाँ जा रहा है, यह देखने के लिए अर्थपूर्ण कार्य-इकाइयों के चारों ओर मैन्युअल स्पैन जोड़ें। वैश्विक प्रोवाइडर से ट्रेसर प्राप्त करें और उसे कॉन्टेक्स्ट मैनेजर के रूप में उपयोग करें।
स्पैन सक्रिय अनुरोध कॉन्टेक्स्ट के भीतर शुरू होता है, इसलिए वह अपने-आप अनुरोध स्पैन के अंदर नेस्ट हो जाता है — मूल स्पैन को हाथ से जोड़ने की आवश्यकता नहीं होती।
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def price_order(items: list[dict]) -> float:
with tracer.start_as_current_span("price_order") as span:
span.set_attribute("order.item_count", len(items))
subtotal = sum(i["price"] * i["qty"] for i in items)
tax = round(subtotal * 0.20, 2)
total = subtotal + tax
span.set_attribute("order.total", total)
return totalएट्रिब्यूट, घटनाओं और स्थिति से स्पैन को समृद्ध करना
जब स्पैन में कॉन्टेक्स्ट होता है, तब वह उपयोगी बनता है। इनका उपयोग करें:
- खोजे जा सकने वाले टैग (उपयोगकर्ता ID, टेनेंट, आइटम की संख्या) के लिए
set_attribute(key, value)। जहाँ उपलब्ध हों, वहाँ OTel की सिमेंटिक परंपराओं का पालन करें। - समय-चिह्नित संकेतकों (जैसे "cache_miss") के लिए
add_event(name, attributes)। - कुछ विफल होने पर
set_status(Status(StatusCode.ERROR))औरrecord_exception(exc), ताकि आपके बैकएंड में स्पैन लाल दिखाई दे।
एट्रिब्यूट में कभी भी गुप्त जानकारी या पूरी PII न रखें — ट्रेस को बहुत से लोग पढ़ सकते हैं।
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
tracer = trace.get_tracer(__name__)
def reserve_stock(sku: str, qty: int, available: int) -> None:
with tracer.start_as_current_span("reserve_stock") as span:
span.set_attribute("inventory.sku", sku)
span.set_attribute("inventory.requested_qty", qty)
if qty > available:
span.add_event("stock_shortfall", {"available": available})
exc = ValueError(f"Only {available} of {sku} in stock")
span.record_exception(exc)
span.set_status(Status(StatusCode.ERROR))
raise exc
span.set_status(Status(StatusCode.OK))सैंपलिंग: ट्रेस की मात्रा नियंत्रित करना
हर अनुरोध को पूरी मात्रा में ट्रेस करना महँगा होता है। सैंपलिंग तय करती है कि कौन-से ट्रेस रखने हैं। सुझाया गया हेड-आधारित सैंपलर ParentBasedTraceIdRatioBased है:
- यदि आने वाले अनुरोध में पहले से सैंपलिंग का निर्णय मौजूद है (
traceparentमें01फ़्लैग), तो उसका सम्मान किया जाता है — इसलिए हर सेवा में ट्रेस को एकसमान रूप से रखा या हटाया जाता है। - नए मूल अनुरोधों के लिए यह एक निश्चित अनुपात (जैसे 10%) का सैंपल लेता है।
इसी एकरूपता के कारण मूल-आधारित सैंपलिंग महत्वपूर्ण है: आप नहीं चाहेंगे कि सेवा A कोई स्पैन रखे, जबकि सेवा B उसके चाइल्ड को हटा दे और ट्रेस टूट जाए।
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.sampling import (
ParentBasedTraceIdRatioBased,
)
# Keep ~10% of root traces; honor upstream sampling decisions.
sampler = ParentBasedTraceIdRatioBased(rate=0.10)
provider = TracerProvider(sampler=sampler)लॉग को ट्रेस से जोड़ना
ट्रेस और लॉग साथ मिलकर सबसे अधिक शक्तिशाली होते हैं। हर लॉग पंक्ति में वर्तमान trace_id और span_id जोड़ें, ताकि आप लॉग प्रविष्टि से सीधे पूरे ट्रेस तक पहुँच सकें।
सक्रिय स्पैन कॉन्टेक्स्ट को trace.get_current_span().get_span_context() से पढ़ा जाता है। लॉगिंग इंस्ट्रुमेंटेशन सक्षम होने पर OTel इन फ़ील्ड को मानक लॉगिंग रिकॉर्ड में अपने-आप भी जोड़ सकता है।
import logging
from opentelemetry import trace
logger = logging.getLogger("orders")
def log_with_trace(message: str) -> None:
ctx = trace.get_current_span().get_span_context()
trace_id = format(ctx.trace_id, "032x")
span_id = format(ctx.span_id, "016x")
logger.info("%s", message, extra={
"trace_id": trace_id,
"span_id": span_id,
})त्वरित जाँच: सेवाओं के बीच प्रसार
सेवा A (FastAPI) को एक अनुरोध मिलता है और वह HTTP के ज़रिए सेवा B को कॉल करती है। आप चाहते हैं कि B के स्पैन A के स्पैन वाले उसी ट्रेस के अंतर्गत दिखाई दें। यह किस तंत्र से संभव होता है?
पुनरावलोकन
अब आप वितरित ट्रेसिंग के लिए FastAPI बैकएंड में शुरू से अंत तक इंस्ट्रुमेंटेशन जोड़ सकते हैं:
Resource(जिसमेंservice.nameसेट हो),BatchSpanProcessorऔर OTLP एक्सपोर्टर के साथTracerProviderका प्रारंभिक सेटअप करें।FastAPIInstrumentorसे ऐप में स्वचालित इंस्ट्रुमेंटेशन जोड़ें, ताकि हर अनुरोध एक सर्वर स्पैन बने और आने वाला कॉन्टेक्स्ट निकाला जा सके।- बाद की HTTP सेवा (
HTTPXClientInstrumentor) और डेटाबेस (SQLAlchemyInstrumentor) तक कॉन्टेक्स्ट पहुँचाएँ — W3Ctraceparentहेडर ट्रेस को बिना टूटे बनाए रखता है। - अपने व्यावसायिक तर्क के लिए मैन्युअल स्पैन, एट्रिब्यूट, घटनाओं, स्थिति और रिकॉर्ड किए गए अपवादों से उसे समृद्ध करें।
- एकसमान और किफायती ट्रेस के लिए
ParentBasedTraceIdRatioBasedसे सैंपलिंग करें और सक्रियtrace_id/span_idके ज़रिए लॉग को जोड़ें।
परिणाम यह है: एक क्लिक से आप धीमे अनुरोध से उस सटीक नेस्टेड स्पैन तक पहुँच सकते हैं — हैंडलर, HTTP कॉल या क्वेरी — जिसके कारण वह धीमा हुआ।
एआई शिक्षक के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखें — निःशुल्क
अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।
- पाठ्यक्रम
- 21
- पाठ
- 84
अक्सर पूछे जाने वाले प्रश्न
क्या “OpenTelemetry के साथ वितरित ट्रेसिंग” पाठ निःशुल्क है?
हाँ — FastAPI बैकएंड डेवलपमेंट बूटकैंप अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “OpenTelemetry के साथ वितरित ट्रेसिंग” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
“OpenTelemetry के साथ वितरित ट्रेसिंग” में मैं क्या सीखूँगा?
FastAPI में स्वचालित इंस्ट्रुमेंटेशन कीजिए और डाउनस्ट्रीम HTTP तथा डेटाबेस कॉल के माध्यम से ट्रेस संदर्भ प्रसारित कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।
क्या FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?
पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।
“OpenTelemetry के साथ वितरित ट्रेसिंग” पाठ पूरा करने में कितना समय लगता है?
CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।
क्या मैं इस FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में कोड लिख और चला सकता हूँ?
हाँ। हर FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।
इस पाठ्यक्रम के सभी पाठ
- संरचित JSON लॉगिंग और सहसंबंध ID
- OpenTelemetry के साथ वितरित ट्रेसिंग
- Prometheus मेट्रिक्स और RED/USE डैशबोर्ड
- SLO और त्रुटि बजट पर चेतावनी