Logging with Monolog

Florian Engelhardt

Florian Engelhardt

  • Proud dad of four kids
  • Linux and Vim user
  • PHP-Dev since 2k
  • Software Architect
  • works @ Bergfreunde
  • https://dotbox.org

Roadmap

  • Why logging?
  • Story time!
  • What is Monolog ...
  • ... and how to use it?
  • Tipps from the frontline

Name some Logs ...

What do they all have in common?

  • These are services
  • Therfore know nothing about your business logic

Do those logs help you with

  • Customer complaining about no delivery, but a charged credit card?
  • Lawyer who swears he has never ever signed up for your newsletter?
  • Boss wanting to know who changed the price of a specific article?

NO!

→ You have a problem now

Application logging

  • Paper trail for code
  • Look for patterns and trends
  • Quick error isolation and context
  • Helps you with post-mortem analysis
  • Times in logs keep performance prominent
  • Provide direction when picking up an application for the first time

Story time

Monolog!

  • Logging for PHP
  • Inspired by Python Logbook
  • Implements PSR-3 Interface
  • Sends your logs to files, sockets, inboxes, databases, web services

Monolog?

  • Handler (transport record)
  • Formatter (transform record)
  • Processor (enrich record)
  • Record (the logged event)

Handlers

  • Stream (log to file)
  • Slack / HipChat (spam your favourite chat)
  • Loggly / Rollbar (SAAS)
  • FirePHP / ChromePHP (for dev env)

and many many more, just look at the github repo

Formatters

  • Line
  • Html
  • Json
  • Logstash
  • Loggly

many many more and in most cases, that does not concern you

Processors

  • PsrLogMessage
  • Introspection
  • Web
  • Git

many many more, but these are awesome

Log levels

  • debug (detailed debug informations)
  • info (interesting events)
  • notice (normal but significant events)
  • warning (exceptional occurrences)
  • error (runtime errors)
  • critical (application component unavailable)
  • alert (immediate action required)
  • emergency (system unusable)

these are also the method names

Record

$record = [
  'message' => '',
  'level' => 200,
  'level_name' => 'INFO',
  'channel' => 'app',
  'datetime' => DateTime::__set_state([
     'date' => '2018-06-11 18:39:26.353995',
     'timezone_type' => 3,
     'timezone' => 'UTC',
  ]),
  'context' => [],
  'extra' => []
]

Installation

$ composer require monolog/monolog

Init

// create a log channel
$log = new \Monolog\Logger('app');
$log->pushHandler(
    new \Monolog\Handler\StreamHandler(
        'path/to/awesome.log',
        Logger::INFO
    )
);

Or with next OXID-Release

$log = \OxidEsales\Eshop\Core\Registry::getLogger();

Usage

$log->info('user login');
// try login
$log->warn('wrong credentials');
[2018-06-01 19:41:09] app.INFO: user login [] []
[2018-06-01 19:41:09] app.WARN: wrong credentials [] []

Add some context

$user = 'flo';
$log->info('user login', [
    'user' => $user
]);
// try login
$log->warn('wrong credentials', [
    'user' => $user
]);
[2018-06-01 19:41:09] app.INFO: user login {"user":"flo"} []
[2018-06-01 19:41:09] app.WARN: wrong credentials {"user":"flo"} []

FingersCrossed

  • Buffers all log messages
  • Until a record exceeds the defined severity level
  • Than delivery everything to the handler it wraps

FingersCrossed

$log = new Logger('app');
$log->pushHandler(
    new FingersCrossedHandler (
        new StreamHandler (
            'path/to/awesome.log',
            Logger::INFO
        ),
        Logger::WARN
    )
);

$log->info('user login', ['user' => 'username']);
// try login
$log->warn('wrong credentials', ['user' => 'username']);

Tipps from the Frontline

Performance

  20ms per API call (blind guess, SAAS/Chat)
x 20 log messages
= 400 ms tradeoff
  • Better log to AMQP / Redis / SSD (anything fast)
  • And have another tool pick up and deliver the log messages
  • Or use the BufferHandler
  • And always measure your performance impact

What to log?

  • User logs in / out or changes his data
  • Newsletter (un)subscribe
  • Orders, Payments and Refunds
  • Exceptions

Ask your customer service and collegues for typical problems

You should add to your log

  • Request identifier
  • Session identifier
  • User identifier
  • Calling class::method (or file::line)

use a processor for these

You should not log

  • Usernames and passwords to "debug" auth
  • Serialized objects (nobody reads that 80kb log message)
  • Numeric error codes

GDPR?

check with your lawyer

Conclusion

The END

  • Questions?
  • Feedback!

https://dotbox.org