Git Product home page Git Product logo

easy-log-handler's Introduction

EasyLogHandler (human-friendly log files)

Symfony log files are formatted in the same way for all environments. This means that dev.log is optimized for machines instead of humans. The result is a log file bloated with useless information that makes you less productive.

EasyLogHandler is a new Monolog handler that creates human-friendly log files. It's optimized to display the log information in a clear and concise way. Use it in the development environment to become a much more productive developer.

  1. Features
  2. Installation
  3. Configuration and Usage

Features

These are some of the best features of EasyLogHandler and how it compares itself with the default Symfony logs.

Better Log Structure

Symfony log files are a huge stream of text. When you open them, you can't easily tell when a request started or finished and which log messages belong together:

Symfony EasyLogHandler
structure-overview-symfony-mini structure-overview-easylog-mini

EasyLogHandler structures the log files in a different way:

structure-easylog

  • It adds a large header and some new lines to separate each request logs;
  • If the request is less significant (e.g. Assetic requests) the header is more compact and displays less information;
  • Log messages are divided internally so you can better understand their different parts (request, doctrine, security, etc.)

Less Verbose Logs

First of all, EasyLogHandler doesn't display the timestamp in every log message. In the dev environment you shouldn't care about that, so the timestamp is only displayed once for each group of log messages.

Symfony EasyLogHandler
timestamps-symfony timestamps-easylog

The extra information, which some log messages include to add more details about the log, is displayed only when it's different from the previous log. In contrast, Symfony always displays the extra for all logs, generating a lot of duplicated information:

Symfony
extra-symfony
EasyLogHandler
extra-easylog

It's becoming increasingly popular to use placeholders in log messages instead of the actual values (e.g. Matched route "{route}". instead of Matched route "home".) This is great for machines, because they can group similar messages that only vary in the placeholder values.

However, for humans this "feature" is disturbing. That's why EasyLogHandler automatically replaces any placeholder included in the log message:

Symfony
placeholders-symfony
EasyLogHandler
placeholder-easylog

Better Visual Hierarchy

Important elements, such as deprecations and security-related messages, must stand out in log files to help you spot them instantly. However, in Symfony all logs look exactly the same. How can you know which are the important ones?

Symfony
visual-hierarchy-symfony
(all messages look exactly the same)
EasyLogHandler
visual-hierarchy-easylog
(deprecations, warnings, errors and security messages stand out)

Dynamic Variable Inlining

Log messages usually contain related variables in their context and extra properties. Displaying the content of these variables in the log files is always a tough balance between readability and conciseness.

EasyLogHandler decides how to inline these variables dynamically depending on each log message. For example, Doctrine query parameters are always inlined but request parameters are inlined for unimportant requests and nested for important requests:

dynamic-inline-easylog

Stack Traces

When log messages include error stack traces, you definitely want to take a look at them. However, Symfony displays stack traces inlined, making them impossible to inspect. EasyLogHandler displays them as proper stack traces:

Symfony
stack-trace-symfony
EasyLogHandler
stack-trace-easylog

Log Message Grouping

One of the most frustrating experiences when inspecting log files is having lots of repeated or similar consecutive messages. They provide little information and they just distract you. EasyLogHandler process all log messages at once instead of one by one, so it's aware when there are similar consecutive logs.

For example, this is a Symfony log file displaying three consecutive missing translation messages:

translation-group-symfony

And this is how the same messages are displayed by EasyLogHandler:

translation-group-easylog

The difference is even more evident for "event notified" messages, which usually generate tens of consecutive messages:

Symfony
event-group-symfony
EasyLogHandler
event-group-easylog

Installation

This project is distributed as a PHP package instead of a Symfony bundle, so you just need to require the project with Composer:

$ composer require --dev easycorp/easy-log-handler

Configuration and Usage

Step 1

Define a new service in your application for this log handler:

Newer Symfony version:

# config/packages/dev/easy_log_handler.yaml
services:
    EasyCorp\EasyLog\EasyLogHandler:
        public: false
        arguments: ['%kernel.logs_dir%/%kernel.environment%.log']

Older Symfony version:

# app/config/services.yml
services:
    # ...
    easycorp.easylog.handler:
        class: EasyCorp\EasyLog\EasyLogHandler
        public: false
        arguments:
            - '%kernel.logs_dir%/%kernel.environment%.log'

Step 2

Update your Monolog configuration in the dev environment to define a buffered handler that wraps this new handler service (keep reading to understand why). You can safely copy+paste this configuration:

Newer Symfony version:

# config/packages/dev/monolog.yaml
monolog:
    handlers:
        buffered:
            type:     buffer
            handler:  easylog
            channels: ['!event']
            level:    debug
        easylog:
            type: service
            id:   EasyCorp\EasyLog\EasyLogHandler

Older Symfony version:

# app/config/config_dev.yml
monolog:
    handlers:
        buffered:
            type:     buffer
            handler:  easylog
            channels: ["!event"]
            level:    debug
        easylog:
            type: service
            id:   easycorp.easylog.handler

Most log handlers treat each log message separately. In contrast, EasyLogHandler advanced log processing requires each log message to be aware of the other logs (for example to merge similar consecutive messages). This means that all the logs associated with the request must be captured and processed in batch.

In the above configuration, the buffered handler saves all log messages and then passes them to the EasyLog handler, which processes all messages at once and writes the result in the log file.

Use the buffered handler to configure the channels logged/excluded and the level of the messages being logged.

easy-log-handler's People

Contributors

javiereguiluz avatar nicolas-grekas avatar noniagriconomie avatar oskarstark avatar piotrantosik avatar smithandre avatar szepczynski avatar theofidry avatar tristanbes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

easy-log-handler's Issues

Serialization of 'SplTempFileObject' is not allowed

EasyLog formatter try to serialize an unserialazable object.
Indeed, objects based on Resources can't be serialized.

How can I filter this types of object ?

Trace

Fatal error: Uncaught Exception: Serialization of 'SplTempFileObject' is not allowed in /srv/http/vendor/symfony/yaml/Inline.php:141
Stack trace:
#0 /srv/http/vendor/symfony/yaml/Inline.php(141): serialize(Object(App\Infrastructure\Component\Notification\Message\Mail\Mail))
#1 /srv/http/vendor/symfony/yaml/Dumper.php(62): Symfony\Component\Yaml\Inline::dump(Object(App\Infrastructure\Component\Notification\Message\Mail\Mail), 1)
#2 /srv/http/vendor/symfony/yaml/Dumper.php(105): Symfony\Component\Yaml\Dumper->dump(Object(App\Infrastructure\Component\Notification\Message\Mail\Mail), 1, 0, 1)
#3 /srv/http/vendor/symfony/yaml/Yaml.php(99): Symfony\Component\Yaml\Dumper->dump(Array, 2, 0, 1)
#4 /srv/http/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(369): Symfony\Component\Yaml\Yaml::dump(Array, 2, 2, 1)
#5 /srv/http/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(521): EasyCorp\EasyLog\EasyLogFormatter->formatContext(Array)
#6 /srv/http/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(84): EasyCo in /srv/http/vendor/symfony/yaml/Inline.php on line 141

Environment in documentation

Hi,
In your Readme, you start by talking about changing logs for the dev environment only.
But to achive this, you talk about registering a service for all environment.
Maybe it would be better to install the package in require-dev and to register the service in config_dev.yml to avoid loading your package in production, and register a useless service for no use.

And THANK YOU so much ! your library is such a good idea !

Can logs be rotated using this bundle?

I am wondering if is there any way to rotate logs when I am using this bundle since I'd to get rid of the default config .... maybe this isn't necessary but was the only way to make it work. This is how my setup looks like:

 monolog:
    handlers:
        #main:
        #    type: stream
        #    path: "%kernel.logs_dir%/%kernel.environment%.log"
        #    level: debug
        #    channels: [!event]
        console:
            type:   console
            channels: [!event, !doctrine]
        buffered:
            type:     buffer
            handler:  easylog
            channels: ["!event"]
            level:    debug
        easylog:
            type: service
            id:   easycorp.easylog.handler
        # uncomment to get logging in your browser
        # you may have to allow bigger header sizes in your Web server configuration
        #firephp:
        #    type:   firephp
        #    level:  info
        #chromephp:
        #    type:   chromephp
        #    level:  info

Can I rotate logs? How?

PHP Fatal Error in 1.0.4: Uncaught Exception: Serialization of 'Closure' is not allowed

Since upgrading to 1.0.4 while using this handler, I receive a fatal error about serialization of closures when running tests. Rolling back to 1.0.3 removes this fatal error.

Exception: Serialization of 'Closure' is not allowed in /Users/tim/Sites/invocation/vendor/symfony/symfony/src/Symfony/Component/Yaml/Inline.php on line 173

Call Stack:
    0.0002     395520   1. {main}() /Users/tim/Sites/invocation/vendor/phpunit/phpunit/phpunit:0
    0.0168    1478592   2. PHPUnit\TextUI\Command::main() /Users/tim/Sites/invocation/vendor/phpunit/phpunit/phpunit:53
    0.0168    1478704   3. PHPUnit\TextUI\Command->run() /Users/tim/Sites/invocation/vendor/phpunit/phpunit/src/TextUI/Command.php:148
    0.0383    3363632   4. PHPUnit\TextUI\TestRunner->doRun() /Users/tim/Sites/invocation/vendor/phpunit/phpunit/src/TextUI/Command.php:195
   11.2136   77690776   5. Monolog\Handler\BufferHandler->close() /Users/tim/Sites/invocation/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php:0
   11.2136   77690776   6. Monolog\Handler\BufferHandler->flush() /Users/tim/Sites/invocation/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php:106
   11.2136   77690776   7. EasyCorp\EasyLog\EasyLogHandler->handleBatch() /Users/tim/Sites/invocation/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php:90
   11.2136   77690776   8. EasyCorp\EasyLog\EasyLogFormatter->formatBatch() /Users/tim/Sites/invocation/vendor/easycorp/easy-log-handler/src/EasyLogHandler.php:38
   11.3118   78437600   9. EasyCorp\EasyLog\EasyLogFormatter->formatRecord() /Users/tim/Sites/invocation/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php:84
   11.3118   78438304  10. EasyCorp\EasyLog\EasyLogFormatter->formatContext() /Users/tim/Sites/invocation/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php:483
   11.3118   78438704  11. Symfony\Component\Yaml\Yaml::dump() /Users/tim/Sites/invocation/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php:368
   11.3119   78438760  12. Symfony\Component\Yaml\Dumper->dump() /Users/tim/Sites/invocation/vendor/symfony/symfony/src/Symfony/Component/Yaml/Yaml.php:120
   11.3119   78438800  13. Symfony\Component\Yaml\Dumper->dump() /Users/tim/Sites/invocation/vendor/symfony/symfony/src/Symfony/Component/Yaml/Dumper.php:120
   11.3119   78438800  14. Symfony\Component\Yaml\Inline::dump() /Users/tim/Sites/invocation/vendor/symfony/symfony/src/Symfony/Component/Yaml/Dumper.php:93
   11.3119   78438800  15. serialize() /Users/tim/Sites/invocation/vendor/symfony/symfony/src/Symfony/Component/Yaml/Inline.php:173

Uncaught TypeError

Just noticed that I'm getting following within my tests:

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to EasyCorp\EasyLog\EasyLogFormatter::formatThrowable() must be an instance of EasyCorp\EasyLog\Throwable, instance of Symfony\Component\Security\Core\Exception\AccessDeniedException given, called in /home/wunder/projects/symfony-flex-backend/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php on line 397 and defined in /home/wunder/projects/symfony-flex-backend/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php:405
Stack trace:
#0 /home/wunder/projects/symfony-flex-backend/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(397): EasyCorp\EasyLog\EasyLogFormatter->formatThrowable(Object(Symfony\Component\Security\Core\Exception\AccessDeniedException))
#1 [internal function]: EasyCorp\EasyLog\EasyLogFormatter->EasyCorp\EasyLog\{closure}(Object(Symfony\Component\Security\Core\Exception\AccessDeniedException), 'exception')
#2 /home/wunder/projects/symfony-flex-backend/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(400): array_walk_recursive(Arr in /home/wunder/projects/symfony-flex-backend/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php on line 405

Any ideas what is causing this?

Uncaught exception

When I use die(dump('text here')); in a Symfony command I get:

string(9) "text here" PHP Fatal error: Uncaught exception 'Symfony\Component\Debug\Exception\ContextErrorException' with message 'Notice: Use of undefined constant ARRAY_FILTER_USE_KEY - assumed 'ARRAY_FILTER_USE_KEY'' in /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php:494 Stack trace: #0 /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(494): Symfony\Component\Debug\ErrorHandler->handleError(8, 'Use of undefine...', '/srv/spencer-bl...', 494, Array) #1 /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(267): EasyCorp\EasyLog\EasyLogFormatter->filterVariablesUsedAsPlaceholders('The Sonata\Medi...', Array) #2 /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(337): EasyCorp\EasyLog\EasyLogFormatter->formatContext(Array) #3 /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php(60): EasyCorp\EasyLog\EasyLogFormatter->formatRecord(Array, 0) #4 /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogHandler.php(29): EasyCo in /srv/spencer-blue/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php on line 494

Buffered handler and messenger long running process

Hello and thank you for this beautiful handler :-)

In the doc it is advised to define a buffered handler in monolog config but I think this sort of handler is tricky to use for long running process such as Messenger worker no?

I did not try it yes I am considering a solution that would involved having a custom middleware that would flush all Resetable monolog Logger found in the container.

WDYT? Am I missing something?

Log immediately

This logger/formatter outputs logs only on request end (probably on kernel::shutdown. This is not usable for console workers running indefinitely. In that case nothing is logged to the output at all!

You should allow stream type in configuration which solves this problem.

Easy log handler not logging

I've installed the bundle and replaced the logging config in my config_dev, but now it isn't logging at all anymore. Is there a way to debug it to see what's going on?

I'm using following Symfony version:

"name": "symfony/symfony", "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/symfony.git", "reference": "df02dd5d3f7decb3a05c6d0f31054b4263625dcb" }

Error with Yaml constant

Hello there,

I got the error below when I installed this package on version v1.0.7 which uses YAML 2.3 but that class hasn't constant DUMP_OBJECT.

Yaml package v2.3.42

PHP Fatal error: Undefined class constant 'DUMP_OBJECT' in /var/www/oferplan-front/vendor/easycorp/easy-log-handler/src/EasyLogFormatter.php on line 369

I solved it installing v.1.0.4, I think the Formatter change occurs in this commit.

Thanks, Antonio.

need information how to handle

hi i'm use on project SF 3 and now SF4.3.

i dont know how i can use with my old code :

     grouped_critical:
            type:           group
            members:        [streamed_critical, buffered_critical]

        streamed_critical:
            type:           rotating_file
            max_files:      15
            path:           "%kernel.logs_dir%/%"

        buffered:
            type:     buffer
            handler:  easylog
            channels: ["!event"]
            level:    debug

        easylog:
            type: service
            id:   easycorp.easylog.handler

        buffered_critical:
            type:           buffer
            handler:        swift_critical
            formatter:      monolog.formatter.html

        swift_critical:
            type:           swift_mailer
            from_email:     "%email%"
            to_email:       "webmaster@%web_address%"
            subject:        Une erreur critique est survenue !
            level:          info
            formatter:      monolog.formatter.html
            content_type:   text/html

thank for helping

DateTime logged as 'null' in Doctrine query log

It seems that a DateTime in the query is logged as null. Is this expected behaviour?

Log:

WHERE t0.requested_date = ? AND ((t0.deleted_at IS NULL)) --> 'query params': [null]

I would expect something like:

WHERE t0.requested_date = ? AND ((t0.deleted_at IS NULL)) --> 'query params': [2016-07-24 07:55:56]

screen shot 2016-08-26 at 08 48 27

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.