Faragiri

همهٔ زبان‌ها

آموزش لاگ‌گیریاشکال‌زدایی

یک سطر به‌جای print، و بعد می‌شود صدای یک ماژول را جدا بالا برد بدون آنکه بقیه برنامه پرحرف شود. سطح را رویداد تعیین می‌کند، نه اهمیتش.

۴بخش
۳دقیقه خواندن
۴عمق

پنج پله، هرکدام یک پرسش

هر سطر روی کدام پله می‌نشیند، بر اساس اینکه چه اتفاقی افتاد

پله را جالب بودن سطر تعیین نمی‌کند؛ اینکه کار تمام شد یا نه، و اینکه کسی باید کاری بکند یا نه.

  1. ۰۵CRITICALبرنامه نمی‌تواند ادامه دهد، و پله بالاتری وجود نداردتوقف
  2. ۰۴ERRORاین عملیات شکست خورد. بدون exc_info قاب‌ها از بین می‌روندتمام نشد
  3. ۰۳WARNINGسنجه مقدار نامعتبر داد، برنامه کنار آمد، و کسی باید بداندمدیریت‌شده
  4. ۰۲INFOاجرا شروع شد، فایل نوشته شد. چیزی برای اقدام نیستتایید
  5. ۰۱DEBUGمقدارهایی که وگرنه چاپشان می‌کردید، و حجمش اجازه دارد زیاد باشددر محیط اصلی خاموش

این نردبان درباره حجم چیزی نمی‌گوید، که نصف دیگر یک لاگ قابل استفاده است. یک سطر DEBUG در حلقه‌ای روی چهارصد ایستگاه چهارصد سطر است، و فقط به این دلیل قابل تحمل است که از بیرون خاموش می‌شود.

تفاوت لاگ و print در قالب خروجی نیست، در این است که لاگ را می‌شود از بیرون خاموش و روشن کرد. کلیدش یک سطر است، در هر فایل، بدون هیچ تغییر دیگری:

  • log = logging.getLogger(__name__)

حالا نام لاگر همان نام ماژول است و سلسله‌مراتب دارد. با logging.getLogger("payesh.sanjeh").setLevel(logging.DEBUG) فقط همان یک ماژول پرحرف می‌شود و بقیه برنامه در سطح قبلی می‌مانند. اگر همه‌جا print نوشته باشید این کار ممکن نیست و تنها انتخابتان همه یا هیچ است.

خروجی نمونه با سطح INFO و قالب پیش‌فرضی که خودتان تعیین می‌کنید:

  • INFO __main__ ejra shoro shod, 4 istgah
  • DEBUG payesh.sanjeh meghdar kham = -999.0
  • WARNING __main__ istgah Astara meghdar nadarad

سطر دوم فقط به این دلیل چاپ شد که همان یک لاگر بالا برده شده بود؛ سطر هم‌سطح آن در ماژول اصلی چاپ نشد.

سطح را رویداد تعیین می‌کند، نه اهمیت آن برای شما

پرسشی که سطح را مشخص می‌کند دو تاست: آیا کار تمام شد، و آیا کسی باید کاری بکند. هشدار یعنی برنامه با یک وضعیت غیرعادی کنار آمد و ادامه داد. خطا یعنی همان عملیات تمام نشد. اگر بین این دو مانده‌اید، بپرسید آیا نتیجه‌ای که کاربر گرفت کامل بود.

در سطح خطا حتما exc_info=True بدهید، وگرنه فقط پیام شما ثبت می‌شود و قاب‌ها از بین می‌روند؛ همان قاب‌هایی که سطری که مهم است معمولاً سطر اول نیست درباره خواندنشان است. و هیچ‌وقت پیام را با چسباندن رشته نسازید: log.info("%s satr khande shod", n) قالب‌بندی را تا وقتی سطح روشن نباشد اصلا انجام نمی‌دهد.

چه چیزی نباید در لاگ باشد

رمز، توکن، شماره کارت و کد ملی هیچ‌وقت. لاگ معمولا جایی می‌رود که دسترسی به آن از دسترسی به پایگاه داده آسان‌تر است و مدت بیشتری هم می‌ماند. اگر لازم است بدانید کدام کاربر بود، شناسه‌اش را ثبت کنید و نه مشخصاتش.

و در مقابل، دو چیز تقریبا همیشه جا می‌مانند و هر دو ارزان‌اند: شناسه‌ای که همه سطرهای یک درخواست را به هم وصل می‌کند، و مقدار ورودی‌ای که تصمیم بر اساس آن گرفته شد. بدون اولی، در سروری که ده درخواست هم‌زمان دارد سطرها در هم می‌روند و هیچ‌کدام معنی ندارند: دو کار هم‌زمان، و باگ‌هایی که فقط از همین می‌آیند.

جایی که کار گیر می‌کند، سروری است که کسی لاگش را نمی‌خواند

در بسیاری از پروژه‌های کوچک، لاگ روی سرور در یک فایل انباشته می‌شود و تا روزی که دیسک پر شود کسی بازش نمی‌کند. مشکل ابزار نیست، این است که نوشتن لاگ بدون تصمیم درباره چرخش و نگهداری، فقط یک بمب ساعتی روی دیسک است. حداقل کاری که ارزشش را دارد یک بار تنظیم چرخش فایل بر اساس اندازه است، که در خود کتابخانه استاندارد هست و به هیچ سرویسی نیاز ندارد. و برای اینکه لاگ واقعا خوانده شود، همان روز اول یک دستور جست‌وجو برای خودتان بنویسید که فقط سطرهای هشدار و خطای امروز را بیرون بکشد.

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶ ماژول logging در کتابخانه استاندارد و رایگان است و جای print را می‌گیرد، با این تفاوت اصلی که سطحش را می‌شود از بیرون عوض کرد. برای چرخش فایل، logging.handlers.RotatingFileHandler در همان ماژول است و جای اسکریپت کرون برای پاک کردن فایل لاگ را می‌گیرد. اگر لاگ قرار است به‌شکل ماشین‌خوان جمع شود، قالب JSON با یک قالب‌بند سفارشی چند سطر است و هیچ بسته بیرونی نمی‌خواهد، که وقتی نصب وابستگی خودش یک مرحله است ارزش دارد.

پرسش بعدی این است که وقتی لاگ می‌گوید کجا شکسته و هنوز نمی‌دانید چرا، چطور همان‌جا بایستید و مقدارها را ببینید، که متوقف کردن برنامه، و نگاه کردن به دور و برش است. و در استقرار واقعی، همین سطرها باید جایی جمع شوند که بشود جست‌وجویشان کرد: چه نگه داریم، و پیدا کردن یک سطر میان میلیون‌ها.

کنار این

بالای این