google/flogger

Extensibility How to

sysmat opened this issue · 9 comments

  • flogger:0.7.4

For example, consider a mechanism for emitting per-user log statements which get written out separately from the main logs. > > >Currently this requires a separate supporting class. With Flogger a UserLogger class could be written with an extended API:

logger.at(INFO).forUserId(id).log("Message: %s", param);
  • which class to extend?
import com.google.common.flogger.FluentLogger; // is final can not be extend


public class MyLogger extends FluentLogger {}

You can just use a MetadataKey<UserId> and then your log statement will look like:

logger.atInfo().with(USER, id).log("Message: %s", param);

the key can just be:

public static final MetadataKey<UserId> USER = MetadataKey.single("user_id", UserId.class);

Then you can make a custom LoggerBackend which can recognize the USER key specially and do whatever it needs to do.

The reason that the FluentLogger API is final is because by extending it you can change things like the format string it uses. It would be very unpleasant for users if you could have a Supplier<FluentLogger> where you don't know if the instance you got uses printf formatting or brace-style formatting (or something else). These core parts of functionality need to be baked into the choice of logger implementation you are using.

Making a new logging API that extends the existing LoggingApi and a new logger class (subclass of AbstractLogger) is easy if you need to do that, but in your case you don't need to go down that route.

https://github.com/google/flogger/blob/master/api/src/main/java/com/google/common/flogger/MetadataKey.java

Oh and with this approach (if you use gRPC contexts) you can set that metadata once for a whole task, so you don't even need to set it on each log statement.

See: https://github.com/google/flogger/blob/master/api/src/main/java/com/google/common/flogger/context/ScopedLoggingContext.java

  • I try with this: public static final MetadataKey<Integer> ID = MetadataKey.single("id", Integer.class);
  • flogger-slf4j-backend:0.74
  • System.setProperty("flogger.backend_factory", "com.google.common.flogger.backend.slf4j.Slf4jBackendFactory#getInstance");
 logger.at(Level.INFO)
               .with(ID, 12)
               .log("query=%s ,limit=%d, currentPage=%d, useLimit=%s", query, limit, currentPage, useLimit);
  • getting error: Caused by: java.lang.NoSuchFieldError: ID

  • deployed on glassfish & java 8

  • I'll stick with slf4j and now is slf4j 2.0.0
  • lack of documentation(not up to date)

Can you let us know what's not up to date ?

  • Extensibility should be more explicit how to create forUserId extension
  • backend for slf4j should have which version of slf4j and how to activate
  • Logger Config on net I see some code snippets, but LoggerConfig is not part of lib, so is it possible to change log lavel at runtime?
  • If you have examples in repository with what is possible this project will have more stars and attraction

Thanks for the feedback. LoggerConfig is no longer part of Flogger because Flogger is a facade and can emit logs to many different logging systems (each with their own configuration mechanism). LoggerConfig was JDK logger specific and thus useless to most other backends and it was a mistake to have packaged it as part of Flogger originally.

I definitely agree that the user-facing documents regarding what you can do with Flogger are very limited at the moment, and we'll try to improve that.