Structured Logging لاگ ریکارڈ کرنے کا ایک طریقہ ہے جہاں ہر پیغام کلید-قدر کے جوڑوں کے ساتھ مشین پڑھنے کے قابل فارمیٹ میں پیش کیا جاتا ہے، بجائے غیر ساختی متن کے۔ فلیٹ سٹرنگز کے برعکس، ساختی لاگ میں میٹا ڈیٹا ہوتا ہے: ٹائم سٹیمپ، سطح، ماڈیول، درخواست ID — اور تجزیہ کے نظاموں کے ذریعے انڈیکس کیا جا سکتا ہے۔ 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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں