notrab / dumbo

A lightweight, friendly PHP framework for HTTP.
MIT License
158 stars 16 forks source link

Custom logger? #29

Closed notrab closed 2 months ago

notrab commented 2 months ago

I was thinking we could do something like this:

<?php

namespace Dumbo\Helpers;

use Dumbo\Context;
use Psr\Http\Message\ResponseInterface;

class Logger
{
    private static function colorizeStatus(int $status): string
    {
        return match (true) {
            $status >= 500 => "\033[31m$status\033[0m", // Red
            $status >= 400 => "\033[33m$status\033[0m", // Yellow
            $status >= 300 => "\033[36m$status\033[0m", // Cyan
            $status >= 200 => "\033[32m$status\033[0m", // Green
            default => "\033[37m$status\033[0m", // White
        };
    }

    private static function formatElapsedTime(float $elapsed): string
    {
        return $elapsed >= 1000
            ? sprintf("%.2fs", $elapsed / 1000)
            : sprintf("%.0fms", $elapsed);
    }

    public static function logger(callable $logFunc = null): callable
    {
        return function (
            Context $c,
            callable $next
        ) use ($logFunc): ResponseInterface {
            $start = microtime(true);
            $method = $c->req->method();
            $path = $c->req->path();

            $defaultLogFunc = function (string $message) {
                error_log($message);
            };

            $log = $logFunc ?? $defaultLogFunc;

            $log(sprintf("<-- %s %s", $method, $path));

            $response = $next($c);

            $status = $response->getStatusCode();
            $elapsed = (microtime(true) - $start) * 1000;
            $colorizedStatus = self::colorizeStatus($status);
            $formattedTime = self::formatElapsedTime($elapsed);

            $logPath = $c->req->routePath() ?: $path;
            $log(
                sprintf(
                    "--> %s %s %s %s",
                    $method,
                    $logPath,
                    $colorizedStatus,
                    $formattedTime
                )
            );

            return $response;
        };
    }
}

Which means it can be used like this:

<?php

require "vendor/autoload.php";

use Dumbo\Dumbo;
use Dumbo\Helpers\Logger;

$app = new Dumbo();

$app->use(Logger::logger());

I do think there's an issue with 404 routes and that those won't be matched so there might need to be some updates to findRoute to render run middleware too.

Nyxalis commented 2 months ago

Could this also be used to log into log files for debugging or finding errors?