polyfony-inc/polyfony

View on GitHub
Private/Polyfony/Logger.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php

namespace Polyfony;

use \Models\Logs as Logs;
use \Models\Emails as Emails;

class Logger {
    
    // plaintext names for each levels
    const DEBUG     = 0;
    const INFO         = 1;
    const NOTICE     = 2;
    const WARNING     = 3;
    const CRITICAL     = 4;

    // list of level of log messages available
    const LEVELS = [
        0 => 'debug',
        1 => 'info', 
        2 => 'notice', 
        3 => 'warning',
        4 => 'critical'
    ];

    // css classes
    const CLASSES = [
        0 => 'primary',
        1 => 'info', 
        2 => 'info', 
        3 => 'warning',
        4 => 'danger'
    ];

    const MIN_LEVEL_FOR_EMAIL_NOTIFICATION = 3;

    public static function debug(
        $message     = null, 
        $context     = null
    ) :void {
        // forward to the logging method
        self::log(self::DEBUG, $message, $context);
    }

    public static function info(
        $message     = null, 
        $context     = null
    ) :void {
        // forward to the logging method
        self::log(self::INFO, $message, $context);
    }

    public static function notice(
        $message     = null, 
        $context     = null
    ) :void {
        // forward to the logging method
        self::log(self::NOTICE, $message, $context);
    }

    public static function warning(
        $message     = null, 
        $context     = null
    ) :void {
        // forward to the logging method
        self::log(self::WARNING, $message, $context);
    }

    public static function critical(
        $message     = null, 
        $context     = null
    ) :void {
        // forward to the logging method
        self::log(self::CRITICAL, $message, $context);
    }

    private static function log(
        int $level, 
        $message, 
        $context = null
    ) :void {
    
        // if the logger is enabled and the log event level is supposed to be logged
        if(
            Config::get('logger', 'enable') && 
            $level >= Config::get('logger', 'level')
        ) {

            // format the log event
            $log = self::formatLogMessage($level, $message, $context);
            
            // if the profiler is enabled
            if(Config::get('profiler', 'enable')) {
                // send the log event to the profiler
                try { self::toProfiler($log); } catch (Exception $e) {}
            }
            
            // if we want to log to a file
            if(
                Config::get('logger', 'driver') == 'file' && 
                Config::get('logger', 'path')
            ) {
                // format a new line for the log file
                try { self::toFile($log); } catch (Exception $e) {}
            }

            // if we want to log to the database
            if(Config::get('logger', 'driver') == 'database') {
                // insert record in the database
                try { self::toDatabase($log); } catch (Exception $e) {}
            }
            
            // an email reporting address is set and level is above 3
            if(
                Config::get('logger', 'email') && 
                $level > self::MIN_LEVEL_FOR_EMAIL_NOTIFICATION
            ) {
                // send an email notice
                try { self::toEmail($log); } catch (Exception $e) {}
            }

        }

    }

    // format a log message with proper context and additionnal informations
    private static function formatLogMessage(
        int $level, 
        $message, 
        $context = null
    ) :array {

        return [
            'date'            => date('d/m/y H:i:s'),
            'level'            => self::LEVELS[$level],
            'id_level'        => $level,
            'message'        => $message,
            'context'        => $context,
            'creation_date'    => time(),
            'login'            => Security::isAuthenticated() ? Security::getAccount()->get('login') : '',
            'bundle'        => isset(Router::getCurrentRoute()->bundle) ? Router::getCurrentRoute()->bundle : null,
            'controller'    => isset(Router::getCurrentRoute()->controller) ? Router::getCurrentRoute()->controller : null ,
            'method'        => Request::isPost() ? 'post' : 'get',
            'url'            => Format::truncate(Request::getUrl(), 256),
            'ip'            => Format::truncate(Request::server('REMOTE_ADDR'), 15),
            'agent'            => Format::truncate(Request::server('HTTP_USER_AGENT'), 256)
        ];

    }

    private static function toProfiler( array $log ) :void {

        // place a marker and auto release
        Profiler::releaseMarker(
                Profiler::setMarker(
                $log['message'],
                'log',
                $log
            )
        );

    }

    private static function toFile( array $log ) :void {
        // add the context to the message
        $log['message'] .= ' '.json_encode($log['context']);
        // format the log
        unset($log['creation_date'], $log['id_level'], $log['context']);
        // add the debug informations
        // and save it
        file_put_contents(Config::get('logger', 'path'), implode("\t", $log) . "\n", FILE_APPEND);
    }

    private static function toDatabase( array $log ) :void {
        // add the context to the message
        $log['message'] .= ' '.json_encode($log['context']);
        // remove useless element
        unset($log['date'], $log['level'], $log['context']);
        // and insert it
        Logs::create($log);
    }

    private static function toEmail( array $log ) :void {
        // format and send and email with the log element
        (new Emails)
            ->set([
                'to'         => Config::get('logger', 'email'),
                'format'     => 'text',
                'subject'     => ucfirst(self::LEVELS[$log['id_level']]) . " : {$log['message']}",
                'body'         => var_export($log, true),
            ])
            ->send();
    }
    
}

?>