اهمیت Error logging در برنامه نویسی

من در برنامه نویسی PHP همیشه این کد رو ابتدای اسکریپت هام میذاشتم:
error_reporting(E_ALL);
ini_set('display_errors', '1');

این باعث میشه تمام خطاهایی یا هشدارهایی که در سطح PHP رخ میدن در مرورگر نمایش داده بشن. بدیهی است که این امر موقع توسعه و تست برنامه خیلی مهمه و به این شکل میشه اشکالات و باگها رو شناسایی و رفع کرد. اما موقعی که برنامه برای کاربرد واقعی روی سرور میره، نمایش خطاها رو باید خاموش کنیم چون نمایش این خطاهای خام و فنی و زمخت هم از نظر تجربهء کاربری و اعتبار سایت چندان جالب نیست و هم میتونه منبعی برای کمک اطلاعاتی به هکرها باشه.
خاموش کردن خطاها رو میتونیم به این شکل انجام بدیم:
ini_set('display_errors', '0');
اما اخیرا به فکر افتادم که امکان Error logging رو هم در برنامم بذارم.

Error logging یعنی خطاها در یک فایلی دیتابیسی جایی ذخیره بشن تا بعدا بتونیم متوجه اونا بشیم و بهشون رجوع کنیم. مثلا وقتی سایت شما داره کار میکنه و کاربران ازش استفاده میکنن ممکنه هزار و یک جور خطا و مشکل یا رویداد مشکوک رخ بده که اگر Error logging نداشته باشید طبیعتا شما بعنوان برنامه نویس و مسئول سایت ممکنه هیچوقت متوجه اونا نشید یا خیلی دیر متوجه بشید بعد از اینکه برای کاربران و سیستم شما مشکلات زیادی پیش آمده.
این نمونه کدی هست که نشون میده چطور Error logging رو در PHP فعال کنیم:
ini_set('log_errors', 1);
ini_set('error_log', 'error_log.txt');

البته این کد فقط یه نمونه خام هست برای نشون دادن تنظیمات و روش کار کلی. مثلا باید دقت کنید که کسی غیر از شما نتونته فایل لاگ رو از طریق مرورگر مشاهده کنه. برای این هدف مثلا میتونید فایل رو در خارج از www قرار بدید یا بهرصورت به صورت دیگری عمل کنید که جلوی دسترسی عمومی بهش گرفته بشه؛ مثلا با htaccess هم میشه جلوی دسترسی بهش رو گرفت:

<Files "error_log.txt">
Deny from all
</Files>

و اما نکاتی رو تا یادم نرفته اضافه کنم. اینکه میگیم نمایش خطاها به کاربران رو غیرفعال کنیم به این معنی نیست که در هیچ صورتی هیچ خطا و توضیح یا حتی اطلاعات فنی رو به کاربر نشون ندیم. اتفاقا یه برنامهء خوب باید در شرایط خطاهایی که مشکل جدی در سیستم محسوب میشن، به کاربر در این مورد آگاهی رسانی کنه تا کاربر سردرگم و گمراه نشه و بدونه که مشکلی و احتمالا به چه علتی رخ داده (که به این شکل میتونن و ممکنه به مسئولین سایت هم گزارشش کنن). اما اونکه ما با display_errors غیرفعالش میکنیم نمایش خطاها و هشدارهای خام و پر از اطلاعات و جزییات سطح پایین و فنی خود PHP است. این خطاها بطور معمول به درد توسعه و تست و خود برنامه نویس میخورن و نه کاربران عادی! و البته هکرهای محترم هم از دیدن این خطاها معمولا خوشحال میشن چون کارشون رو راحتتر میکنه.

نکتهء دیگر اینکه دو نوع خطا و گزارش خطا داریم، یعنی دو سطح داره، یکی خطاهایی که در سطح PHP رخ میدن و دیگری خطاهایی که در سطح برنامهء خودتون رخ میدن یعنی مثلا در منطق برنامهء شما اشکال و خطای خاصی رخ میده (که اینطور خطاها لزوما در سطح PHP تاثیر نمیذاره موجب تولید پیام خطا و هشداری توسط PHP نمیشه ولی در بعضی موارد میتونه هم که بصورت غیرمستقیم موجب بشه). طبیعتا لاگ کردن هر دوی این نوع خطاها برای نظارت و اطمینان نسبت به کارکرد صحیح برنامه و کشف باگها و پیدا کردن علت و رفع اونها مهم هستن. بنابراین ما باید سعی کنیم هردوی این خطاها رو لاگ کنیم. لاگ کردن خطاهای در سطح PHP که نشون دادیم و ساده تره، چون خود PHP اونا رو شناسایی و مدیریت میکنه و نیازی نیست ما کار خاصی بکنیم کد و شرط خاصی بنویسیم، ولی لاگ کردن خطاهای در سطح برنامه و بخصوص خطاهای منطقی و اینها نیاز به کدنویسی و چک کردن ها و تمهیدات و طراحی توسط خودمون داره. البته شاید صرف نکنه تمام این خطاها و احتمالات و موارد مشکوک چک و شناسایی و لاگ بشن، ولی حداقل باید سعی کنیم اونایی رو که مهم هستن و میشه با هزینه ای که به صرفه باشه اونا رو شناسایی کرد هندل کنیم. ضمنا میتونیم این خطاها رو هم توسط همون سیستم لاگ PHP و در یک مکان مشترک با خطاها و هشدارهای PHP ذخیره کنیم که اینطوری کارمون کمتر و راحتتر میشه. البته شاید این ایدهء خیلی خوبی نباشه اما بهرحال راه دسته و از هیچی خیلی بهتره. ما برای اینکه خطاهای سطح برنامهء خودمون رو به سیستم لاگینگ PHP هدایت کنیم میتونیم از تابع trigger_error استفاده کنیم. مثلا:
trigger_error('reg8log: some error message...', E_USER_WARNING);
این الان موجب ایجاد یک پیام هشدار در سطح PHP میشه که در نتیجه توسط PHP به فایل گزارش خطا فرستاده میشه. ضمنا میتونید مثل من به ابتدای این پیامها یک چیزی مثلا اسم برنامهء خودتون رو اضافه کنید یا بهرصورت به هر شکل خاصی که با پیامهای استاندارد PHP متفاوت باشه فرمت کنید تا توی فایل گزارش خطاها بتونید خطاهای در سطح برنامهء خودتون رو از خطاهای در سطح PHP براحتی تشخیص بدید (همچنین شاید لازم بشه برنامه و کدی بنویسید که این دو نوع پیام رو بصورت خودکار از هم تشخیص بده و جدا کنه).
خب این تا اینجا چندین نکته!
و اما یه چیز جالب بگم اینکه خود من موقعی که Error logging رو در برنامم فعال کردم تازه متوجه یکسری باگها در برنامم شدم که تا اون موقع متوجهشون نشده بودم حتی با وجودی که نمایش خطاها در مرورگر روشن بود و موقع توسعه و تست هم این خطاها رخ میدادن! چرا؟ به دلیل اینکه بعضی وقتا پیامهایی که تولید میشن با اینکه به مرورگر ارسال میشن ولی عملا امکان مشاهدهء اونا وجود نداره! بطور مثال موقعی که یک صفحه عملیات هایی انجام میده که در جریان اونها پیام خطا یا هشداری تولید میشه ولی در عین حال با هدر Location مرورگر رو به صفحهء دیگری ریدایرکت میکنه، پیامهایی که در صفحهء اولیه تولید شدن در مرورگر دیده نخواهند شد و بنابراین ما متوجه بروز این خطاها و هشدارها و وجود باگ در کدمون نخواهیم شد! یک مورد دیگر مثلا موقعی هست که خطاهای تولید شده بعد از تگ پایانی HTML واقع میشن که به این شکل هم این پیامها رو مرورگر نشون نمیده. من در برنامم هردوی این حالت ها رو شاهد بودم و به این شکل فهمیدم که برای برنامه نویسی حرفه ای چقدر این لاگ کردن ها مهمه!
شما هم اگر Error logging رو در برنامتون فعال کنید به احتمال زیاد چنین مواردی رو که تاحالا متوجه نشده بودید شاهد خواهید بود! ضمنا بهرحال کاربر اصلی Error logging اینه که هر موقعی که خطا در برنامه رخ داد بعدا شما بتونید متوجه اون بشید چون شما که همیشه سر برنامه نیستید و تنها کسی که با سیستم کار میکنه هم نیستید و خیلی خطاها و شرایط ممکنه در جریان توسعه و تست های شما رخ ندن.

ضمنا بعنوان یک نکتهء جانبی و مکمل عرض کنم که طبیعی است که باید استفاده از عملگر @ رو هم به حداقل ممکن برسونید، چون این عملگر باعث میشه خطاها شناسایی و گزارش نشن و ما متوجه بروز خطا یا موارد مشکوک در برنامه نشیم و باگهای احتمالی از زیر چشممون در برن!

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

*

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>