Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatter Loader + Handler Loader #10

Merged
merged 1 commit into from
Jun 16, 2015

Conversation

rantonmattei
Copy link
Contributor

Added the FormatterLoader: loads any Monolog Formatter class (implementing the MonoLog\Formatter\FormatterInterface)
Added the HandlerLoader: loads any Monolog Handler class (implementing the MonoLog\Handler\HandlerInterface)

They both extend ClassLoader which was the trouble maker for the previous PR. The reason was a dependency on those extra option handlers in the canHandle method.
This PR contains the tests for ClassLoader as well.

I need to revisit this at some point cause it makes a double dependency that seems unnecessary. I'd like to get those closures out of here (see initExtraOptionsHandlers method).

My favorite reviewers: @mortaliorchard @OrCharles, please review!

Some more info on Monolog:
Monolog Handlers are the handlers attached to you logger. A logger can log to multiple destinations: a simple log file, a stream like stdout or stderr, using an API (Loggly), etc. In order to log into those destination, you need to set up a handler for each of those.
On top of that if you need specific formatter (i.e. formatting each line you log), you need to instantiate a Formatter object and set it in your Handler.
That's why it is kind of tedious to set this manually.

$logger = new \Monolog\Logger();
$f1 = new \Monolog\Formatter\LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n');
$h1 = new \Monolog\Handler\LogglyHandler($myToken, $logLevel);
$h2 = new \Monolog\Handler\StreamHandler('php://stdout');
$h1->setFormatter($f1);
$h2->setFormatter($f1);
$logger->pushHandler($h1);
$logger->pushHandler($h2);

// And then finally
$logger->info('Writing with my logger');
$logger->error('uh oh, something happened');

I used the same formatter for the 2 handlers but this gets much longer if you have multiple handlers with multiple formatter.

The formatter loader takes a set of options for the formatter, typically the formatter section of you yaml file

formatters:
    spaced:
        class: Monolog\Formatter\LineFormatter
        format: "%datetime% %channel%.%level_name%  %message%\n"
        include_stacktraces: true

And it instantiate the corresponding Formatter object with the provided options.

The Handler loader does the same thing for the provided Handlers

handlers:
    console:
        class: Monolog\Handler\StreamHandler
        level: DEBUG
        formatter: spaced
        stream: php://stdout
    info_file_handler:
        class: Monolog\Handler\StreamHandler
        level: INFO
        formatter: dashed
        stream: ./example_info.log

You'll notice that handlers can reference previously defined formatter(s). So, Cascade will load formatters first and then will instantiate the Handlers.

I hope this helps

}

/**
* @expectedException InvalidArgumentException

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated: but damn, it took me a while to realize that this actually end up generating some code that checks if this method throws an exception :|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha, yeah it's almost like a .py decorator :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, kind of python-ish.... 😁
Same apply with @dataProvider which is basically fixtures for your test function. When you want to repeatedly call a test function with different args.

@mortaliorchard
Copy link

Lots of code. But I honestly don't find any issues with it. R+

}

/**
* Loads the closures as option handlers. Add handlers to that function if

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which function is 'that' function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the initExtraOptionsHandlers method

this is where you would add additional closures should you have any custom options handlers.
Those are there in case you cannot pass your options through the constructor directly or if you want to do more complex stuff with your Formatter object. The closure receive the Formatter instance as param, so you can modify that object (if needed) before it gets passed to the handler(s)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, so then you mean 'this' function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, fixed

@rantonmattei rantonmattei force-pushed the loaders branch 2 times, most recently from fb12b1d to a46993f Compare June 16, 2015 14:54
@OrCharles
Copy link

thanks for the pre-emptive explanation.. maybe throw that into README.md ?

R+

@rantonmattei
Copy link
Contributor Author

I'll put together a more detailed doc using ReadTheDoc The REadMe is already a bit long, and I think it should focus on usage more than the implementation details

rantonmattei added a commit that referenced this pull request Jun 16, 2015
Formatter Loader + Handler Loader
@rantonmattei rantonmattei merged commit 9c2c521 into theorchard:master Jun 16, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants