امیر کارآموز پیاچپی در کوئرا است. اخیرا طراحی یکی از سیستمهای کوئرا را به امیر سپردن اما از آنجایی که این پروژه، اولین پروژه بزرگ امیر هستش، در عیبیابی پروژه دچار مشکل شده است.
امیر از محمدمهدی که از برنامهنویسای قدیمی کوئراست راهنمایی خواست و محمدمهدی هم به امیر توضیح داد که لاگ و سیستم ثبت لاگ چیه و پیشنهاد داد که امیر برای پروژهاش یک سیستم ثبت لاگ طراحی کند و برای عیبیابی از آن استفاده کند.
محمدمهدی یک پروژه اولیه هم برای طراحی سیستم ثبت لاگ به امیر ارسال کرد و به او گفت که اگر میخواهد سیستم ثبت لاگ خوبی داشته باشد، باید این پروژه را کامل کند.
اما از آنجایی که امیر هنوز به پیاچپی مسلط نیست، از شما برای انجام این کار کمک خواسته است.
# پروژه اولیه
پروژه اولیه را از
[اینجا](https://quera.ir/qbox/download/mPrO3CZCxJ/logger.zip)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
logger
├── LogException.php
├── Logger.php
└── LoggerInterface.php
```
# جزئیات
### کلاسها
#### `\Quera\LoggerInterface`
این کلاس `interface`ای است که کلاس `Logger` باید آن را پیادهسازی کند.
این کلاس از `PHP Standards Recommendations` برداشته شدهاست.
#### `\Quera\Logger`
این کلاس کلاسِ اصلی ما است که دارای توابع زیر است:
- تابع کانستراکتور : دو ورودی میگیرد که اولی آدرسی است که لاگ باید در آن ذخیره شود و دومی گزینههای مرتبط با روش ذخیره است.
آدرس میتواند لینک یک `API` یا آدرس کامل یک فایل باشد که از طریق `type` در گزینهها مشخص میشود.
آرایهی گزینهها میتواند شامل موارد زیر باشد:
> `type`: نشاندهنده نوع ذخیره لاگ هست که میتواند `file` یا `api` باشد و در صورتی که هیچکدام از این دو نباشد تابع باید یک خطا از نوع `LogException` پرتاب کند.
> `dateFormat`: فرمت مورد نظر برای درج تاریخ در لاگ را نشان میدهد و از نوع [فرمت استاندارد در پیاچپی]( https://www.php.net/manual/en/datetime.formats.php
) است.
> `logFormat`: فرمت مورد نظر برای ذخیره لاگ را نشان میدهد. این فرمت میتواند دارای متغیرهایی باشد که میتوانند `date`, `level` و `message` باشند یا از طریق متغیر `context` در توابع لاگ ارسال شوند. همچنین ممکن است در `message` نیز مانند `logFormat` متغیر وجود داشته باشد.
`date` با تاریخ با فرمت مورد نظر در `dateFormat` جایگزین میشود. `level` با اهمیت لاگ با حروف بزرگ جایگزین میشود. `message` با پیام ارسالی هنگام فراخوانی توابع لاگ جایگزین میشود. متغیرها با علامت `{}` دورشان مشخص میشوند.
> `threshold`: نشاندهنده حداقل اهمیت مورد نیاز لاگ برای ذخیره شدن است. اهمیت لاگها به ترتیب از زیاد به کم از چپ به راست بهصورت `EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG` است. اگر برابر `ALL` قرار داده شود همه سطوح را ذخیره میکند. اگر مقداری متفاوت از ۹ مقدار ذکر شده قرار داده شود، باید یک خطا از نوع `LogException` پرتاب کند.
> `append`: در صورت انتخاب شدن نوع `file`، اگر مقدار این متغیر برابر `true` باشد، لاگها را به انتهای فایل مشخص شده اضافه میکند و در غیر این صورت از ابتدای فایل شروع به نوشتن لاگها میکند.
در صورتی که هرکدام از متغیرها در آرایه ورودی وجود نداشته باشد، مقدار آن از روی جدول زیر باید تعیین شود.
|کلید |مقدار پیشفرض در صورت تعیین نشدن |
|-----------|:-----------------------------------|
| type | `'file'` |
| dateFormat| `'Y-m-d H'` |
| logFormat | `'[{date}]-[{level}]-{message}'` |
| threshold | `'ALL'` |
| append | `true` |
- توابع موجود در `LoggerInterface` که شامل `emergency`, `alert`, `critical`, `error`, `warning`, `notice`, `info`, `debug` که هر کدام یک لاگ با سطح متفاوت ذخیره میکنند، میباشد.
علاوه بر آنها تابع `log` نیز مانند آنها وجود دارد با این تفاوت که سطح لاگ را با حروف بزرگ به عنوان ورودی دریافت میکند.
با صدا شدن هرکدام ازین ۹ تابع مرتبط به لاگ، باید لاگ در همان زمان طبق گزینههای انتخاب شده در کانستراکتور کلاس، در فایل ذخیره شده یا به فرمت `POST` به `API` ارسال شود.
#### `\Quera\LogException`
این کلاس خطایی است که در صورت وجود اشتباه در آپشنهای ورودی سازنده کلاس `Logger` پرتاب میشود.
## مثال
یک نمونه از اجرای این کلاس به شکل زیر است:
```php
$options = [
'dateFormat' => 'Y-m-d H',
'logFormat' => '[{date}] {level}-{message}',
'threshold' => 'ERROR',
'append' => true,
];
$logger = new Quera\Logger("~/debug.log", $options);
$logger->critical('oh oh');
$logger->emergency('system is down');
$logger->notice('change variable name');
$logger->log('ERROR', 'error in line 2');
$logger->error('error in line {variable1}', ['variable1' => '6']);
/* file ~/debug.log:
[2019-10-03 10] CRITICAL-oh oh
[2019-10-03 10] EMERGENCY-system is down
[2019-10-03 10] ERROR-error in line 2
[2019-10-03 10] ERROR-error in line 6
*/
```
# نکات
- پروژه اولیه دارای ۳ فایل است که شما تنها میتوانید در فایل `Logger.php` تغییرات ایجاد کنید.
- کلاس `Logger` لزوما باید `LoggerInterface` را پیادهسازی کند.
- `TimeZone` را `Asia/Tehran` قرار دهید.
- در هنگام ارسال به `API` پیام باید با عنوان `message` ارسال شود، به شکلی که با استفاده از `$_POST['message']` قابل دسترسی باشد و برای مثال با فرمت اولیه، اگر به شکل
```php
$logger->emergency('something went wrong...')
```
فراخوانی شده باشد محتوای `$_POST['message']` به شکل
```
[2019-10-02 21]-[EMERGENCY]-something went wrong...
```
دریافت میشود.
# بارگذاری
در انتها فایل های زیر را به صورت یک فایل `zip` آپلود نمایید. نام فایل `zip` اهمیتی ندارد.
```
[your-zip-file-name].zip
├── LogException.php
├── Logger.php
└── LoggerInterface.php
```