فلسفهٔ لاگ
هر برنامهای که اجرا میشود، هر درخواستی که به یک سرور میرسد و هر تغییری که در یک سیستمعامل رخ میدهد، یک ردپا از خود به جا میگذارد. لاگ، ثبت نظاممند همین ردپاهاست. پرسش این است که چرا انسانها اصلاً به فکر ثبت این ردپاها افتادند.
پاسخ کوتاه این است: سیستمهای پیچیده حافظهٔ کوتاهمدت دارند و انسانها به آنها اعتماد میکنند. لاگ، حافظهٔ بلندمدت و قابل بازبینیِ سیستم است. بدون آن، هر خطا یک راز باقی میماند، هر نفوذ بدون شاهد میماند و هر تصمیم دربارهٔ سلامت زیرساخت بر حدس استوار میشود.
ریشهٔ تاریخی: از دفتر کشتی تا ساختار داده
واژهٔ log از logbook گرفته شده؛ دفتری که ناخدای کشتی سرعت و مسیر و رویدادهای سفر را در آن ثبت میکرد تا بعداً بتواند مسیر طیشده را بازسازی کند. کامپیوترها این واژه را در اوایل دههٔ ۱۹۶۰ وام گرفتند، و نخستین کاربرد ثبتشدهٔ آن در معنای محاسباتی به سال ۱۹۶۳ برمیگردد.
اما لاگ در محاسبات خیلی زود از نقش دفتر خاطرات بیرون آمد. در پایگاههای دادهٔ رابطهای، به یک ساختار دادهٔ بنیادین تبدیل شد؛ مهمتر از همه، لاگ پیشنویسی یا WAL: دنبالهای فقطافزودنی از رکوردها با ترتیب اکیداً صعودی که پس از نوشتن تغییرناپذیر میماند.
همین ساختار ساده، دو مشکل بزرگ را همزمان حل کرد: ترتیب تغییرات و بازسازی وضعیت پس از خرابی. اگر سیستم در میانهٔ کار از کار میافتاد، کافی بود لاگ را از ابتدا بازپخش کند تا به وضعیت پایدار برگردد.
این همان نقطهای است که فلسفهٔ لاگ از «ثبت برای انسان» به «ثبت برای ماشین» تغییر کرد. لاگ دیگر چیزی نبود که آن را میخواندید؛ چیزی شد که آن را دوباره اجرا میکردید.
لاگ پیشنویسی پیش از اعمال تغییری که توصیف میکند روی حافظهٔ پایدار نوشته میشود. همین ترتیب است که بازیابی پس از خرابی را ممکن میکند و دلیل آن این است که ساختار، فقطافزودنی است و در جا بازنویسی نمیشود.
خرابی رخ میدهد و باید بدانیم چرا
قدیمیترین نیاز به لاگ از دل نقص بیرون آمد. برنامهای که کرش میکند، سروری که از دسترس خارج میشود یا درخواستی که با خطا مواجه میشود، هیچکدام توضیح نمیدهند که «چرا». لاگ این توضیح را فراهم میکند.
از منظر مهندسی، لاگ یک ردیابی حسابرسی ایجاد میکند؛ ثبتی زمانمند از آنچه رخ داده و با چه ترتیبی. همین ردیابی است که حدس زدن را به تشخیص تبدیل میکند. وقتی یک سرویس وب پاسخ اشتباه میدهد، توسعهدهنده به لاگ نگاه میکند تا ببیند درخواست چه بوده، چه پارامتری ارسال شده و در کدام مرحله شکست خورده است.
بدون لاگ، فرایند اشکالزدایی به بازسازی حدسیِ شرایط تبدیل میشود که در سیستمهای توزیعشده تقریباً غیرممکن است.
این نیاز به خطا محدود نمیشود. لاگهای عملکردی نشان میدهند کدام بخش از سیستم کند است و لاگهای دسترسی نشان میدهند چه کسی چه کاری انجام داده است. سیستمعاملها از دههٔ ۱۹۵۰ مکانیزمهای لاگ برای کمک به تشخیص سیستم را معرفی کردند و این نیاز از آن زمان تا امروز تغییر نکرده است.
سیستمهای توزیعشده یک حقیقت واحد ندارند
با ظهور سیستمهای توزیعشده، مشکل عمیقتری پدیدار شد. در یک سیستم توزیعشده، هر گره ساعت فیزیکی خودش را دارد و این ساعتها هرگز کاملاً همگام نیستند. اگر رویدادها را فقط بر اساس برچسب زمانی مرتب کنیم، ممکن است ترتیب اشتباهی به دست آید.
اینجاست که لاگ به یک مکانیزم نظمدهی تبدیل میشود. لاگ ترتیبی اکیداً صعودی تحمیل میکند که مستقل از هر ساعت فیزیکی است. اگر دو گره از یک لاگ مشترک تغذیه شوند، هر دو دقیقاً یک ترتیب رویداد را میبینند.
اصل پشت این رفتار تکرار ماشین حالت است: اگر دو فرایند قطعی از یک وضعیت شروع کنند و ورودی یکسان را با ترتیب یکسان دریافت کنند، خروجی یکسان تولید میکنند.
به بیان ساده، لاگ در سیستمهای توزیعشده نقش دفتر ثبت رسمی را بازی میکند. وقتی چند سرویس درگیر یک درخواست واحد هستند، بازسازی آن درخواست بدون یک شناسهٔ همبستگی که در سراسر خطوط لاگ منتقل شود، غیرممکن است.
امنیت بدون شاهد معنا ندارد
در دهههای اخیر، نیاز سومی اضافه شد که ماهیتش با دو نیاز پیشین فرق داشت: امنیت. لاگ دیگر فقط ابزار عیبیابی نبود؛ به شاهد قانونی و ابزار دفاعی تبدیل شد.
نهادهای ملی امنیت سایبری، لاگ کردن را یک کنترل امنیتی با اثر پسنگر میدانند. مرکز امنیت سایبری بریتانیا و کمیسیون ملی انفورماتیک و آزادیهای فرانسه هر دو نگهداری لاگ را یک اقدام ضروری میشمارند. هر دو توصیه میکنند رویدادهای دسترسی، ایجاد، تغییر و حذف دادهها ثبت شوند تا در صورت نفوذ یا استفادهٔ نادرست، بتوان منشأ را شناسایی کرد.
این نیاز، ماهیت لاگ را عوض کرد. اگر قبلاً لاگ برای «فهمیدن» بود، حالا برای «اثبات کردن» هم هست. یک سیستم بدون لاگ امنیتی، در برابر نفوذی که همین حالا در جریان است کور است.
لاگهای نگهداریشده به مدرک قابل استناد تبدیل میشوند و همین آنها را حساس میکند. دسترسی خواندن را محدود کنید، آنها را رمزنگاری کنید و بازهٔ نگهداری را آگاهانه تعیین کنید، نه اینکه بینهایت جمع شوند.
زیرساخت بدون دید، قابل مدیریت نیست
در سطح زیرساخت، لاگها از حالت «فایلهای پراکنده روی سرورهای مختلف» خارج شدند و به یک منبع دانش عملیاتی تبدیل شدند.
وقتی لاگها در یک مکان مرکزی جمعآوری میشوند، مجموعهای پراکنده از پیامها به یک تصویر منسجم تبدیل میشود که تشخیص توزیعشده و تحلیل پس از حادثه را ممکن میکند. این تمرکز، پیچیدگی شناختیِ تحلیل خرابیهای توزیعشده را کم میکند و همبستگی رویدادها را بر اساس زمان و زمینه ممکن میسازد.
از منظر زیرساخت، لاگها سه کارکرد کلیدی دارند:
- پایش سلامت: نشان میدهند سیستم در چه وضعیتی است و چه روندی را طی میکند.
- همبستگی رویدادها: رویدادهایی را که در ظاهر بیربط به نظر میرسند، مثل نوشتن شدید روی دیسک و خطاهای ارتباط با کلاینت، به هم مرتبط میکنند تا علت ریشهای پیدا شود.
- برنامهریزی ظرفیت: الگوهای مصرف و رشد را نشان میدهند تا پیش از بحران تصمیم گرفته شود.
بدون این دید، مدیریت زیرساخت به واکنش به بحرانهای رخداده محدود میشود، نه پیشگیری از آنها.
دو نوع لاگ که نباید اشتباه گرفته شوند
دو چیز متفاوت هر دو «لاگ» نامیده میشوند و به پرسشهای متفاوتی پاسخ میدهند.
لاگ برنامه متنی نیمهساختاریافته است که برنامهنویس برای خواندنِ یک انسان مینویسد. هدفش اشکالزدایی و ردیابی اجرای برنامه است. ابزارهایی مثل log4j یا syslog این نوع لاگ را تولید میکنند.
لاگ داده که ژورنال هم نامیده میشود، دنبالهای ساختاریافته و قابل پردازش ماشین از رکوردها با ترتیب اکید است. هدفش بازسازی وضعیت، همگامسازی و توزیع داده است.
تمایز حیاتی است: لاگ برنامه به سؤال «چه خطایی رخ داد؟» پاسخ میدهد، لاگ داده به این پرسش که «چطور سیستم را به وضعیت پایدار برگردانیم؟».
دو سناریو برای درک عملی
خرید آنلاین و لاگ برنامه
مشتری در یک فروشگاه اینترنتی روی «ثبت سفارش» کلیک میکند و صفحهٔ خطا میبیند. مدیر سیستم نمیداند مشکل از کجاست. آیا موجودی کالا بهروز نبوده؟ آیا درگاه پرداخت پاسخ نداده؟ آیا کد تخفیف نامعتبر بوده؟
اینجاست که لاگ برنامه به کار میآید. اگر برنامهنویس در هر مرحله لاگ نوشته باشد، مدیر میتواند مسیر درخواست را دنبال کند و ببیند در کدام مرحله شکست خورده است. لاگ جملهای دقیق به او میگوید: سفارش شمارهٔ ۸۴۷۲ در ساعت ۱۴:۳۲:۰۵ به درگاه پرداخت ارسال شد و پاسخ ۵۰۳ گرفت.
همین یک جمله، تفاوت میان یک ساعت جستوجوی حدسی و یک دقیقه رفع مشکل است. اگر لاگ برنامه نبود، مدیر باید حدس میزد، سناریوها را بازسازی میکرد و شاید هم مشکل را به گردن بخش اشتباهی میانداخت.
قطعی شبکه در نیمهشب و لاگ داده
فرض کنید یک سرور در تهران لاگهای خود را به یک سرور مرکزی در اصفهان میفرستد. ساعت ۳ بامداد، لینک شبکه قطع میشود. سرور تهران به کار خود ادامه میدهد و لاگ تولید میکند، اما نمیتواند آنها را بفرستد.
اینجاست که لاگ داده به کار میآید. اگر سرور از یک صف دیسکی استفاده کند، پیامها روی دیسک محلی ذخیره میشوند تا لینک برگردد. وقتی شبکه وصل شد، صف تخلیه میشود و تمام پیامهای آن شب به سرور مرکزی میرسند، بدون آنکه حتی یک خط گم شود.
اگر این مکانیزم نبود، پیامهای آن شب برای همیشه از بین میرفتند. صبح روز بعد، تیم امنیت نمیتوانست بررسی کند چه اتفاقی افتاده، و تیم عملیات نمیدانست سیستم در آن بازه چه رفتاری داشته است.
آنچه اینجا نجاتبخش است خود صف دیسکی است، نه TCP بهتنهایی. سیستم syslog روی TCP خالص تأییدیه ندارد، پس فرستندهای که بافرش هنگام قطعی شبکه پر شود پیامها را بیسروصدا دور میریزد. تفاوت انواع صف را در معماری rsyslog توضیح دادهایم.
آنچه لاگ حل نمیکند
ارزیابی صادقانه ایجاب میکند محدودیتها هم دیده شوند. خودِ لاگ کردن یک عمل مصرفکنندهٔ منابع است. ثبت بیش از حد میتواند آنقدر سربار بسازد که اندازهگیری عملکرد را مخدوش کند؛ پدیدهای که در آن هرچه بیشتر اندازه بگیریم، کمتر عملکرد سیستم را درست میفهمیم. به همین دلیل، نمونهگیری و مدیریت سطح لاگ بخشی جداییناپذیر از طراحی یک سیستم لاگ کارآمد است.
همچنین، لاگ بهخودیخود ارزشمند نیست. یک لاگ بدون ساختار، بدون همبستگی و بدون تحلیل، فقط یک فایل بزرگ است. ارزش واقعی وقتی آزاد میشود که لاگها جمعآوری، یکدستسازی و تحلیل شوند. به همین دلیل است که معماریهایی مثل rsyslog، صفهای بافری و سیستمهای مرکزی جمعآوری لاگ به وجود آمدند: نه برای «داشتن لاگ»، بلکه برای «قابل استفاده کردن لاگ».
جمعبندی
فلسفهٔ لاگ در یک جمله خلاصه میشود: سیستمهای پیچیده باید بتوانند دربارهٔ گذشتهٔ خودشان حرف بزنند.
این نیاز در چهار سطح بروز کرده و هر سطح چیز متفاوتی از لاگ میخواهد.
| سطح | نیاز | آنچه لاگ فراهم میکند |
|---|---|---|
| برنامهنویسی | فهم خطا و رفتار برنامه | ردیابی اجرا و زمینهٔ خطا |
| سیستمعامل | تشخیص و بازیابی پس از خرابی | ساختار دادهٔ قابل بازپخش برای بازسازی وضعیت |
| سیستم توزیعشده | نظمدهی و همگامسازی | ترتیب اکید مستقل از ساعت فیزیکی |
| زیرساخت و امنیت | دید، حسابرسی و پاسخ به حادثه | شاهد قابل استناد و همبستگی رویدادها |
لاگ از یک دفتر سادهٔ کشتی شروع شد، به ساختار دادهای برای بقا در پایگاههای داده تبدیل شد، سپس ستون فقرات سیستمهای توزیعشده شد و در نهایت به ابزار دفاعی و عملیاتی زیرساخت رسید. در هر مرحله نیاز عوض شد، اما یک چیز ثابت ماند: بدون ثبت رویدادها، هیچ سیستمی نمیتواند دربارهٔ خودش بیاموزد.