cihub / seelog

Seelog is a native Go logging library that provides flexible asynchronous dispatching, filtering, and formatting.
BSD 3-Clause "New" or "Revised" License
1.64k stars 243 forks source link

How to create custom filters? #92

Open jonathankarsh opened 9 years ago

jonathankarsh commented 9 years ago

First off, thanks for a great library!

Not sure if I'm mis-reading the doco, but it seems that I cannot create a custom filter dispatcher which would:

Just wanted to check whether these capabilities are present in seelog?

Cheers

goodsign commented 9 years ago

Hi jonathankarsh!

Thanks!

Currently, this functionality is not implemented: we only have custom formatters and custom receivers. Custom dispatchers are not here yet.

But now I know what to implement next :)

jonathankarsh commented 9 years ago

That would be awesome.. thanks for the quick reply! I was thinking about making public some of filters.. or provide a similar public mechanism. I might dig around a bit. Are you accepting PRs for new features ATM?

goodsign commented 9 years ago

Yeah, I do accept feature PRs! I'll be able to implement something myself in a couple of weeks. Meanwhile you could try to look into it.

However let's discuss it and make sure that it fits in current seelog architecture.

I think that currently custom dispatchers ('filters' and 'splitters' are just examples of a broad category of 'dispatchers', as opposed to 'receivers') should be implemented the same way as custom receivers, but just with different interface. You may refer to this wiki section. I think that the same features as in Scenario 3.1 and Scenario 3.2 should be implemented (in the same way) for custom dispatchers.

At the moment, custom receiver logic is located here. Config parser uses it here. Basically it is all about scenarios 3.1 and 3.2 above. This part in the last link is about scenario 3.2:

if cfg != nil && cfg.CustomReceiverProducers != nil {
        if prod, ok := cfg.CustomReceiverProducers[customName]; ok {
            rec, err := prod(args)
            if err != nil {
                return nil, err
            }
            creceiver, err := newCustomReceiverDispatcherByValue(currentFormat, rec, customName, args)
...
}

And this part is about scenario 3.1:

return newCustomReceiverDispatcher(currentFormat, customName, args)

I believe that the most clean and easy way to add this feature is to create something like custom receiver, but with a little bit different details, like a bit different interface instead of CustomReceiver (It should contain a children parameter in the ReceiveMessage signature) and a little bit different struct instead of customReceiverDispatcher (should contain something like children []dispatcher field). You can have a look at current implementation of splitter and filter and look how they are instantiated by the cfg parser, what they get as parameters, etc. to get the idea.

If that sounds complicated, then I'll think about implementing it myself in ~2 weeks. Feel free to ask any questions. Thanks!

goodsign commented 9 years ago

Maybe, because now we have two different custom nodes, you could just start with renaming current dispatch_custom.go to dispatch_custom_receiver.go (also, rename dispatch_customdispatcher_test.go -> dispatch_custom_receiver_test.go). Just not to confuse them.

After that you could just copypaste the custom receiver code and then change the implementation details in the new dispatch_custom_dispatcher.go according to comments above.

Thanks!

jonathankarsh commented 9 years ago

Nice :-)

All sounds good at a high level, I was also thinking along the lines of custom dispatcher using a different interface.

I'll follow up with questions as soon as I get a chance