لاگ گرفتن

عملیات logging بهترین کار برای این است که اطلاعات حیاتی و مهم برنامه در حین اجرا را در خروجی نمایش دهیم. بررسی log ها به ما این امکان را میدهد که بفهمیم برنامه ی ما در حالت واقعی چطور کار میکند. همچنین در زمان اتفاق خطا در زمان اجرای برنامه log ها تنها راه یافتن مشکل اتفاق افتاده هستند. هیچوقت نمیتوانید روی سیستم خودتان بفهمید که برنامه هفته ی پیش روی سرور یا روی سیستم مشتری چگونه کار میکرده است؛ یا چرا برنامه روی سیستم من کار میکند اما 8 روز پیش در ساعت 2 بامداد باعث انفجار سیستم مشتری شد؟!

در کنار این مسئله باید دقت کنید که چه اطلاعاتی را به عنوان log نگهداری میکنید! مثلا در یک سیستم بانکی نباید اطلاعات جزییات حساب مشتریان در log ها ذخیره شوند یا اگر قرار است ذخیره شوند باید کاملا مخصی و غیر قابل بازگشت رمزنگاری شوند. دریافت درست و اصولی log ها علاوه بر برنامه نویسی یک هنر و مهارت مهم است.

میتوانیم از دستور print نیز در برنامه استفاده کنیم و از طریق آن لاگ بگیریم! این کار برای پروژه های کوچک بسیار مناسب است اما اگر حجم پروژه بزرگ باشد یا یکی از موارد زیر در پروژه وجود داشته باشد، باید استفاده از print را فراموش کنید:

  • برنامه Multithread باشد: ماژول logging این شرایط را در نظر گرفته و پشتیبانی میکند. در صورت استفاده از print در این شرایط دچار قطعی و وقفه در داده ها( interleaved data) می شویم.
  • نیاز به دسته بندی و سطح بندی log ها وجود داشته باشد: وقتی از print استفاده کنیم هیچ راهی برای نشان دادن تفاوت اهمیت log ها وجود ندارد. ماژول logging اما این امکان را به صورت پیشفرض در خود دارد.
  • نیاز به تغییر ساختار logging در پروژه داشته باشیم: به تغییر و تنظیم logging در طول برنامه مدیریت logging stack گفته میشود. با این ویژگی یک برنامه نویس منظم و مسلط به لاگ گرفتن، میتواند در تمام طول برنامه به درستی کنترل کاملی روی log ها داشته باشد.
  • نیاز به انعطاف پذیری: این صفحه از داکیومنتیشن پایتون فقط به همین مسئله پرداخته است!

کلاس اصلی ماژول logging از کتابخانه های استاندارد، logger نام دارد. با logger میتوان تمام کارهای مرسوم برای logging را انجام داد و آبجکت های این کلاس معمولا با دستور زیر اجرا می شوند:

import logging

logger = logging.getLogger(<logger name>)

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

logging types
  • دیباگ( debug ): پیام هایی که بعدا برای دیباگ و رفع مشکلات برنامه بکار میبریم. مثلا در وب اپلیکیشن ها، درخواست های ورودی باید در این لاگ قرار بگیرند.
  • اطلاعات( info ): پیام های مهمی که روند و شرایط اپلیکیشن را نشان میدهند. مثلا در توسعه ی وب سرور ها باید اطلاعات ورودی و خروجی را در این بخش طبقه بندی کنیم.
  • هشدار( warning ): پیام هایی که حاکی از وجود وضعیت احتمالا نامناسب و خطرناک برای برنامه هستند. مثلا در یک وب اپلیکیشن به مشکل خوردن بازکردن داده ی ورودی نادرست JSON نتیجه ی خوشایندی ندارد و رفتار آن شبیه error خواهد بود. اگر ندانیم که این ورودی نادرست بوده ممکن است فکر کنیم ایراد از برنامه ی وب اپلیکیشن است و نتوانیم بفهمیم که دیتای ورودی نادرست به برنامه ارسال شده است. اما اگر بتوانیم تفاوتی بین خطای واقعی و این خطای ظاهری قائل شویم(با لاگ درست) میتوانیم فرستنده ی دیتا را از خطای خود آگاه کنیم.
  • خطا( error ): زمانی که برنامه ی ما دچار خطا می شود اما برنامه میتواند به عملکرد خود ادامه دهد. این لاگ به توسعه دهنده ها این امکان را میدهد که پس از دریافت لاگ از ایجاد یک خطا در روند اجرای برنامه به رفع آن بپردازند.
  • ناپایدار( fatal ): امیدواریم هیچوقت این لاگ را نبینید! این دسته از لاگ ها را برای این منظور به کار میبریم که اعلام کنیم مشکل پیش آمده باعث توقف روند برنامه شده است. وضعیت ناپایدار شرایط اضطراری را میطلبد و باید سریعا به آن رسیدگی کرد. ضمنا در محیط واقعی معمولا برنامه قطع میشود و توسط نرم افزار مدیریت کانتینر(داکر، کوبرنتیز و ...) مجددا اجرا می شود و به وضعیت اولیه بر میگردد اما برای جلوگیری از ناپدید شدن داده ها باید برای لاگ های fatal فکری کنید! (نکته ی پایین فراموش نشود)

نکته:

لاگ fatal ممکن است در آینده حذف شود و در حال حاضر از critical به جای fatal استفاده میکنیم.