How does one extend the fluent API for domain-specific attributes?

328 vues
Accéder directement au premier message non lu

Jon Wolski

non lue,
22 mai 2019, 11:21:0522/05/2019
à Flogger Discuss
Suppose in my domain, every log statement occurs in the context of a Web request and every request has the context of a user ID, session ID, and cart ID.

Rather than log something like the following:

logger.atInfo().log("User %s (session: %s) added product %s to cart %s.", userId, sessionId, productId, cartId);


I would prefer something more structured like the following:

logger.atInfo().forUser(userId).withSession(sessionId).withCart(cartId).log("product added to cart: %s", productId);

or better yet

logger.atInfo().forUser(userId).withSession(sessionId).withCart(cartId).product(productId).action(PRODUCT_ADDED).log();

https://google.github.io/flogger/benefits#extensibility seems to imply this is possible, but I don't see where.

My hope is that my logging back-end can send a JSON serialization of this info to my ELK stack.

Flogger Discuss

non lue,
22 mai 2019, 20:18:5022/05/2019
à Flogger Discuss
Structured logging support is built into the design of Flogger, and there are two ways you can achieve this (with and without a custom logger).

In the lastest version of Flogger you should see the new "with(MetadataKey<T>, T)" method in the API. This is the generic way to add custom metadata to a log statement.

Right now (assuming you've defined the appropriate keys) you should be able to do:
   logger.atInfo().with(USER, userId).with(SESSION, sessionId).with(CART, cartId).with(PRODUCT, productId).with(ACTION, PRODUCT_ADDED).log("Please still put some basic message here...");

If you really want to go for extending the API, you need to make a new custom logger (the logger is a "factory" for the logging API and to avoid a _lot_ of confusion, it's strongly recommended that each logger implementation produces a single, concrete API).
Your custom logger should extend the "base" API and can then add its own fluent methods.
If you look at FluentLogger, it's really just a "custom" logger with no additional methods in, so start with a copy of that class, introduce the new API sub-type and start adding methods to it.

However the logging backend doesn't know what to do with any other this metadata, so you'd have to extend an existing backend to understand the LogData structure and extract the key/value pairs.
Right now it just formats the key/value pairs in the log statement (though it does to it in an easy to parse/grep manner).

My recommendation would be to start with the with() method approach and see how it goes. Then get a custom backend up if you want, and once all that's working, consider if you still want a whole new logger for a custom API.
Also, only use metadata keys/values for truly structured data you understand the semantics of. There's still perfectly good value in having just a formatted message string; don't make _everything_ metadata.

Finally - and it's something I'm trying to work on in the next few weeks - I am hoping to introduce a properly generic mechanism for injecting tags in some "scope".
This lets you set up a request scope with tags like session ID (things that would be the same for all log statements in a request) and have that information added to every log statement automatically.
You'll be able to nest scopes too, so a "session" scope could contain a "cart" scope for when the cart is being manipulated etc.

So you _might_ want to wait for that, since it's a slightly different mechanism (for performance reasons) than the generic metadata key thing!

HTH,
    David

jsalc...@gmail.com

non lue,
11 juil. 2019, 03:27:5811/07/2019
à Flogger Discuss
Hi David!

That's sounds great. Do you know how is progressing that new feature?

Thanks,
Répondre à tous
Répondre à l'auteur
Transférer
0 nouveau message