Structured Logging लॉग रिकॉर्ड करने का एक दृष्टिकोण है जहाँ प्रत्येक संदेश कुंजी-मान जोड़े के साथ मशीन-पठनीय प्रारूप में प्रस्तुत किया जाता है, न कि असंरचित पाठ के रूप में। सपाट स्ट्रिंग्स के विपरीत, संरचित लॉग में मेटाडेटा होता है: टाइमस्टैम्प, स्तर, मॉड्यूल, अनुरोध आईडी — और विश्लेषण प्रणालियों द्वारा अनुक्रमित किए जा सकते हैं। O'Reilly Effective Logging के अनुसार, संरचित प्रारूपों में संक्रमण फ़ील्ड द्वारा फ़िल्टर करने की क्षमता के कारण घटना खोज समय को घंटों से मिनटों तक कम कर देता है। यह आधुनिक मोबाइल और सर्वर डेवलपमेंट में वास्तविक मानक है: JSON और logfmt लॉग को आँखों से नहीं बल्कि प्रोग्राम द्वारा प्रोसेस करने की अनुमति देते हैं।
मुख्य बिंदु
Structured Logging लॉग रिकॉर्ड करने की एक विधि है जहाँ प्रत्येक संदेश में नामित फ़ील्ड और टाइप किए गए मान होते हैं। User 42 logged in from device ABC जैसी स्ट्रिंग के बजाय, एक संरचित लॉग फ़ील्ड के सेट जैसा दिखता है: user_id=42, event=login, device_id=ABC, timestamp=2026-07-04T10:30:00Z।
टेक्स्ट लॉग की तुलना में संरचित लॉग का मुख्य लाभ प्रोग्रामेटिक प्रसंस्करण की क्षमता है। टेक्स्ट लॉग को पार्स करने के लिए रेगुलर एक्सप्रेशन और स्ट्रिंग प्रारूप के बारे में अनुमानों की आवश्यकता होती है। संरचित लॉग बिना नुकसान के पार्स किए जाते हैं: प्रत्येक फ़ील्ड का एक ज्ञात प्रकार और नाम होता है, जो अतिरिक्त प्रसंस्करण के बिना उपयोगकर्ता 42 के लिए पिछले एक घंटे में सभी प्रमाणीकरण त्रुटियाँ खोजें जैसे क्वेरी बनाने की अनुमति देता है।
Honeycomb.io (2023) के अनुसार, प्रोडक्शन में structured logging का उपयोग करने वाली टीमें टेक्स्ट लॉग और grep पर निर्भर टीमों की तुलना में औसतन 4 गुना तेजी से घटनाओं का पता लगाती हैं।
Structured Logging कई सीरियलाइज़ेशन प्रारूपों का समर्थन करता है। प्रारूप का चुनाव बुनियादी ढाँचे पर निर्भर करता है: JSON Elasticsearch और क्लाउड सिस्टम के साथ एकीकरण के लिए सुविधाजनक है, logfmt tail और grep के माध्यम से कंसोल व्यूइंग के लिए, Protocol Buffers बैंडविड्थ सीमाओं वाले उच्च-प्रदर्शन सिस्टम के लिए।
| प्रारूप | उदाहरण | कब उपयोग करें |
|---|---|---|
| JSON | {"event":"login","user_id":42} | ELK Stack, क्लाउड कलेक्टर, माइक्रोसर्विसेज़ |
| Logfmt | event=login user_id=42 duration_ms=150 | कंसोल, tail, heroku logs |
| MessagePack | JSON का बाइनरी समतुल्य | उच्च-लोड सिस्टम, IoT |
JSON संरचित लॉग के लिए सबसे सामान्य प्रारूप है। यह सभी संग्रह प्रणालियों द्वारा मूल रूप से समर्थित है: Logstash, Fluentd, Amazon CloudWatch, Google Cloud Logging। JSON लॉग मनुष्यों द्वारा आसानी से पढ़े जा सकते हैं और बिना अतिरिक्त लाइब्रेरी के किसी भी प्रोग्रामिंग भाषा द्वारा पार्स किए जा सकते हैं। मुख्य दोष वर्बोसिटी है: प्रत्येक कुंजी-मान जोड़े को उद्धरण और कोलन की आवश्यकता होती है, जो logfmt की तुलना में संग्रहीत डेटा की मात्रा को 30–50% तक बढ़ा देता है।
Logfmt को Heroku में कंसोल विजिबिलिटी के लिए विकसित किया गया था। यह JSON से अधिक कॉम्पैक्ट है, मानव पठनीयता बनाए रखता है, और cut और awk के साथ आसानी से पार्स किया जा सकता है। उदाहरण: ts=2026-07-04T10:30:00Z level=error module=api status=500. Logfmt को अधिकांश वर्णों के एस्केपिंग की आवश्यकता नहीं होती है और यह कंटेनरों में stdout लॉगिंग के लिए उपयुक्त है।
मोबाइल एप्लिकेशन में, Structured Logging तीन मुख्य समस्याओं को हल करता है: डिवाइस पर पुनरुत्पादन के बिना क्रैश के कारण ढूँढना, उपयोगकर्ता सत्रों को ट्रैक करना, और एप्लिकेशन संस्करणों के अनुसार प्रदर्शन का विश्लेषण करना।
मोबाइल डिवाइसों पर टेक्स्ट लॉग लगभग बेकार हैं — एक डेवलपर उपयोगकर्ता के डिवाइस पर लॉग को grep नहीं कर सकता। संरचित लॉग क्लाउड सिस्टम (Firebase, Sentry, Datadog) को भेजे जाते हैं और वहाँ अनुक्रमित किए जाते हैं। आप iOS 17.4 पर सभी क्रैश दिखाएँ, एप्लिकेशन संस्करण 3.2, चेकआउट मॉड्यूल में जैसा क्वेरी बना सकते हैं और सेकंडों में सटीक चयन प्राप्त कर सकते हैं।
Sentry (2024) के अनुसार, संरचित breadcrumbs का उपयोग करने वाले एप्लिकेशन में प्रत्येक क्रैश रिपोर्ट में केवल त्रुटि टेक्स्ट लॉग करने वाले एप्लिकेशन की तुलना में 60% अधिक संदर्भ होता है। यह सीधे बग फिक्स की गति को प्रभावित करता है।
ELK Stack — Elasticsearch, Logstash, Kibana — संरचित लॉग के साथ काम करने के लिए मानक बुनियादी ढाँचा बना हुआ है। Logstash JSON में लॉग प्राप्त करता है, उन्हें रूपांतरित करता है और इंडेक्सिंग के लिए Elasticsearch को भेजता है, Kibana क्वेरी और डैशबोर्ड के लिए विज़ुअल इंटरफ़ेस प्रदान करता है।
मोबाइल एप्लिकेशन के लिए, क्लाउड समाधान लोकप्रिय हैं: Firebase Crashlytics कस्टम लॉग के साथ, Sentry breadcrumbs के साथ, Datadog APM ट्रैकिंग के साथ। वे सीधे मोबाइल SDK से संरचित लॉग स्वीकार करते हैं और अपना स्वयं का बैकएंड तैनात करने की आवश्यकता नहीं होती है। Firebase क्रैश रिपोर्ट के लिए मुफ्त पैकेज प्रदान करता है, Sentry वितरित ट्रेसिंग जोड़ता है, और Datadog क्लाइंट और सर्वर दोनों पर एक साथ अनुरोध प्रदर्शन को ट्रैक करने के लिए APM के साथ एकीकृत होता है।
Grafana Loki — लॉग के लिए अनुकूलित Elasticsearch का एक विकल्प। Loki डिफ़ॉल्ट रूप से संदेश सामग्री को इंडेक्स नहीं करता बल्कि फ़िल्टरिंग के लिए लेबल का उपयोग करता है। यह भंडारण में काफी सस्ता है और फ़ील्ड के एक निश्चित सेट पर क्वेरी के लिए तेज़ है।
// Swift Logger के माध्यम से JSON में संरचित लॉगिंग
struct StructuredLog {
let event: String
let attributes: [String: Any]
let level: String
func serialize() -> String {
var base = "event=\(event) level=\(level)"
for (key, value) in attributes {
base += " \(key)=\(value)"
}
return base
}
}
संरचित लॉगिंग का पहला नियम: प्रत्येक संदेश में अनुरोध या सत्र पहचानकर्ता होना चाहिए। संदर्भ के बिना, एक व्यक्तिगत लॉग बेकार है — यह निर्धारित करना असंभव है कि यह किस उपयोगकर्ता या अनुरोध से संबंधित है। सत्र शुरू होने पर correlation ID जोड़ें और इसे एप्लिकेशन की सभी परतों के माध्यम से पास करें।
दूसरा नियम: फ़ील्ड टाइपिंग. संख्यात्मक फ़ील्ड (duration_ms, status_code, retry_count) को संख्या के रूप में भेजा जाना चाहिए, स्ट्रिंग के रूप में नहीं। Elasticsearch और समान सिस्टम संख्याओं और स्ट्रिंग्स को अलग-अलग इंडेक्स करते हैं: संख्याओं पर एग्रीगेशन (औसत, माध्यिका, परसेंटाइल) लागू किए जा सकते हैं, स्ट्रिंग्स पूर्ण-पाठ खोज का समर्थन करती हैं। गलत टाइपिंग एनालिटिकल डैशबोर्ड बनाने की क्षमता को छीन लेती है।
तीसरा नियम: नेस्टेड ऑब्जेक्ट से बचें. 2 स्तरों से अधिक गहराई वाले JSON लॉग को फ़िल्टर और विज़ुअलाइज़ करना मुश्किल होता है। {"user": {"name": "Alice", "role": "admin"}} के बजाय, सपाट कुंजियाँ उपयोग करें: user_name=Alice user_role=admin.
// Timber + logfmt के माध्यम से Android पर संरचित लॉगिंग
class StructuredTree : Timber.Tree() {
override fun log(priority: Int, tag: String?,
message: String?, t: Throwable?) {
val level = priorityToLevel(priority)
val logfmt = "level=$level tag=$tag message=$message"
sendToRemote(logfmt)
}
}
प्रत्येक संरचित संदेश के लिए न्यूनतम फ़ील्ड सेट: ISO 8601 में timestamp, level (debug/info/warn/error/fatal), logger (मॉड्यूल या क्लास का नाम), message (घटना का मानव-पठनीय विवरण)। अतिरिक्त: correlation_id, user_id (यदि ज्ञात हो), version (एप्लिकेशन संस्करण), platform (iOS/Android), environment (dev/staging/prod)।
correlation_id के बिना, संरचित लॉग असंबद्ध रिकॉर्ड का संग्रह बन जाते हैं जिन्हें एक उपयोगकर्ता परिदृश्य में नहीं जोड़ा जा सकता। प्रत्येक एप्लिकेशन लॉन्च पर UUID जनरेट करें और इसे सभी सत्र लॉग में जोड़ें। व्यवहार में, correlation_id को सभी परतों के माध्यम से पारित किया जाना चाहिए: UI इवेंट से नेटवर्क अनुरोध और बैकग्राउंड कार्यों तक — अन्यथा कुछ लॉग संदर्भ के बिना रह जाएंगे और एनालिटिक्स में भाग नहीं लेंगे। एंड-टू-एंड ट्रैकिंग के साथ, एक एकल UUID उपयोगकर्ता यात्रा की पूरी तस्वीर एकत्र करने की अनुमति देता है।
iOS पर, संरचित लॉगिंग को os_log के ऊपर एक रैपर के माध्यम से कार्यान्वित किया जा सकता है जो फ़ील्ड को logfmt प्रारूप में सीरियलाइज़ करता है। Android पर, एक कस्टम Tree के साथ Timber के माध्यम से जो सर्वर को भेजने से पहले संदेशों को JSON या logfmt में रूपांतरित करता है।
import OSLog
struct StructuredLogger {
let subsystem: String
let category: String
func log(level: OSLogType,
event: String,
context: [String: Any]) {
let oslogger = Logger(
subsystem: subsystem,
category: category
)
let fields = context.map {
"\($0.key)=\($0.value)"
}.joined(separator: " ")
oslogger.log(level: level,
"\(event) \(fields)")
}
}
संरचित और टेक्स्ट लॉग के बीच चुनाव परियोजना के चरण पर निर्भर करता है। प्रारंभिक विकास चरणों में, टेक्स्ट लॉग सरल और तेज़ होते हैं — डेवलपर बिना अतिरिक्त रैपर के सीधे संदेश लिखता है। लेकिन एक बार परियोजना एक टीम या एक सर्वर की सीमा से परे चली जाती है, तो संरचित लॉग अनिवार्य हो जाते हैं।
| मानदंड | टेक्स्ट लॉग | संरचित लॉग |
|---|---|---|
| पठनीयता | कंसोल में उच्च | मध्यम (pretty-print आवश्यक) |
| खोज | सबस्ट्रिंग द्वारा grep | फ़ील्ड और मान द्वारा क्वेरी |
| एग्रीगेशन | समर्थित नहीं | औसत, माध्यिका, परसेंटाइल |
| एकीकरण | पार्सिंग आवश्यक | ELK/Loki/Datadog में मूल |
| भंडारण आकार | छोटा (मेटाडेटा के बिना) | बड़ा (फ़ील्ड + मान) |
अक्सर पूछे जाने वाले प्रश्न
सर्वर भेजने के लिए, JSON का उपयोग करें — यह Firebase Crashlytics, Sentry और Datadog द्वारा मूल रूप से समर्थित है। Xcode या Android Studio लॉग में स्थानीय देखने के लिए, logfmt का उपयोग करें — यह अधिक कॉम्पैक्ट है और बिना फ़ॉर्मेटिंग के पढ़ा जा सकता है।
हाँ, क्लाइंट पर संरचित लॉग प्रत्येक क्रैश रिपोर्ट में संदर्भ जोड़ने की अनुमति देते हैं: OS संस्करण, नेटवर्क स्थिति, उपयोगकर्ता की अंतिम क्रियाएँ। संरचित breadcrumbs के बिना, क्रैश रिपोर्ट में उपयोगकर्ता परिदृश्य के बिना केवल कॉल स्टैक होता है।
Logfmt अधिक कॉम्पैक्ट (30–50% कम आकार) और टर्मिनल में पढ़ने में आसान है। JSON नेस्टेड ऑब्जेक्ट और ऐरे का समर्थन करता है लेकिन उद्धरण एस्केपिंग की आवश्यकता होती है। चुनाव बुनियादी ढाँचे पर निर्भर करता है: ELK के लिए — JSON, कंसोल व्यूइंग के लिए — logfmt।
एप्लिकेशन लॉन्च पर UUID का एक उदाहरण बनाएँ, इसे सिंगलटन या DI कंटेनर में स्टोर करें, और कंस्ट्रक्टर के माध्यम से सभी लॉगर में पास करें। विकल्प — Kotlin कोरूटीन में थ्रेड-लोकल या Continuation Local Storage का उपयोग करें।
कर सकते हैं, लेकिन अनुशंसित नहीं — मिश्रण करने पर स्वचालित इंडेक्सिंग की क्षमता खो जाती है। यदि कुछ लॉग टेक्स्ट-आधारित हैं, तो उन्हें रेगुलर एक्सप्रेशन से पार्स करना पड़ता है, जो खोज प्रदर्शन और विश्वसनीयता को कम करता है। सभी लॉग को संरचित प्रारूप में माइग्रेट करना बेहतर है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें