Log
The Log class is Slenix's logging system. It writes daily log files to storage/logs/ using a simple, human-readable format. Each entry records a timestamp, severity level, message, and optional context data in JSON. No external dependencies are required.
Log Format
Every line written to a log file follows this structure:
[2026-04-01 12:00:00] LEVEL: message {"key":"value"}Example output:
[2026-04-24 09:15:42] INFO: User logged in {"user_id":42,"ip":"192.168.1.1"}
[2026-04-24 09:17:03] ERROR: Payment failed {"order_id":991,"reason":"Insufficient funds"}
[2026-04-24 09:17:03] CRITICAL: Database unreachable {"host":"db.internal","port":3306}Log Files
Log files are created daily, named after the channel and the date:
storage/logs/slenix-2026-04-24.log
storage/logs/slenix-2026-04-25.logThe default channel is slenix. This can be changed with Log::setChannel().
Configuration
These methods are typically called once during application bootstrap.
Setting the log directory
Log::setPath('/custom/path/to/logs');If not set, the default directory is storage/logs/ (or relative to the STORAGE_PATH constant if defined).
Setting the channel name
The channel determines the filename prefix. Use different channels to separate logs by context (e.g. app, queue, api).
Log::setChannel('api');
// writes to: storage/logs/api-2026-04-24.logLog Levels
Slenix defines five severity levels, from least to most critical:
| Level | Constant | Method | Typical use |
|---|---|---|---|
| Debug | Log::DEBUG | Log::debug() | Detailed diagnostic information during development |
| Info | Log::INFO | Log::info() | Normal application events (login, order placed) |
| Warning | Log::WARNING | Log::warning() | Unexpected situations that are not errors yet |
| Error | Log::ERROR | Log::error() | Runtime errors that need attention |
| Critical | Log::CRITICAL | Log::critical() | Severe failures requiring immediate action |
Writing Logs
All logging methods accept a message string and an optional context array. The context is appended as JSON at the end of the log line.
Log::debug('Query executed', ['sql' => 'SELECT * FROM users', 'time_ms' => 4.2]);
Log::info('User logged in', ['user_id' => 42, 'ip' => $request->ip()]);
Log::warning('Disk usage above 80%', ['used' => '82%', 'path' => '/var/www']);
Log::error('Payment gateway timeout', ['order_id' => 991, 'gateway' => 'stripe']);
Log::critical('Database connection lost', ['host' => 'db.internal', 'port' => 3306]);Logging exceptions
Log::exception() automatically captures the class, code, file, line, and a trimmed stack trace (up to 8 frames) from any Throwable.
try {
$this->processOrder($order);
} catch (\Throwable $e) {
Log::exception($e); // defaults to ERROR level
Log::exception($e, Log::CRITICAL); // override the level
}Example output:
[2026-04-24 10:02:11] ERROR: Connection refused {"class":"PDOException","code":2002,"file":"/app/Database/Connection.php","line":58,"trace":[...]}Reading Logs
Log::tail(int $lines = 50, ?string $date = null): array
Returns the last N lines from a log file as a plain string array. Defaults to today's file.
$lines = Log::tail(100); // last 100 lines from today
$lines = Log::tail(50, '2026-04-20'); // last 50 lines from a specific dateLog::read(?string $date = null): array
Parses today's (or a given date's) log file and returns an array of structured entries.
$entries = Log::read();
$entries = Log::read('2026-04-20');
foreach ($entries as $entry) {
echo $entry['datetime']; // "2026-04-24 09:15:42"
echo $entry['level']; // "INFO"
echo $entry['message']; // "User logged in"
print_r($entry['context']); // ['user_id' => 42, 'ip' => '...']
}Log::files(): array
Returns the names of all log files available in the log directory.
$files = Log::files();
// → ['slenix-2026-04-22.log', 'slenix-2026-04-23.log', 'slenix-2026-04-24.log']Maintenance
Log::prune(int $days = 30): int
Deletes log files older than the given number of days. Returns the count of removed files. Suitable for scheduled jobs.
$removed = Log::prune(30); // delete files older than 30 days
echo "Removed {$removed} old log files.";Method Reference
| Method | Returns | Description |
|---|---|---|
Log::debug($message, $context) | void | Writes a DEBUG entry |
Log::info($message, $context) | void | Writes an INFO entry |
Log::warning($message, $context) | void | Writes a WARNING entry |
Log::error($message, $context) | void | Writes an ERROR entry |
Log::critical($message, $context) | void | Writes a CRITICAL entry |
Log::exception($e, $level) | void | Logs a Throwable with trace |
Log::tail($lines, $date) | array | Last N raw log lines |
Log::read($date) | array | Parsed log entries as structured array |
Log::files() | array | Lists all log file names |
Log::prune($days) | int | Removes log files older than N days |
Log::setPath($path) | void | Sets a custom log directory |
Log::setChannel($channel) | void | Sets the log channel (filename prefix) |
Complete Example
use Slenix\Supports\Logging\Log;
// Bootstrap (e.g. in config/app.php)
Log::setChannel('app');
// -------------------------------------------------------
// Controller — logging a user action
// -------------------------------------------------------
public function checkout(Request $request, Response $response): void
{
$user = $request->getAttribute('user');
$order = Order::create($request->only('items', 'address'));
Log::info('Order placed', [
'user_id' => $user->id,
'order_id' => $order->id,
'total' => $order->total,
]);
return $response->status(201)->json(['order' => $order]);
}
// -------------------------------------------------------
// Catching and logging exceptions
// -------------------------------------------------------
public function handle(Request $request, Response $response): void
{
try {
$this->paymentGateway->charge($request->input('amount'));
} catch (\Throwable $e) {
Log::exception($e, Log::CRITICAL);
return $response->status(500)->json([
'error' => 'Payment processing failed. Please try again.',
]);
}
}
// -------------------------------------------------------
// Scheduled job — log rotation
// -------------------------------------------------------
public function handle(): void
{
$removed = Log::prune(60); // keep two months of logs
Log::info("Log rotation complete", ['files_removed' => $removed]);
}
// -------------------------------------------------------
// Admin panel — display recent log entries
// -------------------------------------------------------
public function logs(Request $request, Response $response): void
{
$date = $request->get('date', date('Y-m-d'));
$entries = Log::read($date);
$errors = array_filter($entries, fn($e) => in_array($e['level'], ['ERROR', 'CRITICAL']));
return $response->json([
'date' => $date,
'total' => count($entries),
'errors' => count($errors),
'entries' => array_values($errors),
]);
}