BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Google Releases New Java Logging Framework

Google Releases New Java Logging Framework

Leia em Português

This item in japanese

Bookmarks

Google recently announced the release of a new open-source Java logging framework called Flogger. Acknowledging that "[t]he field of open-source Java logging APIs is already extremely crowded", Google asserts that Flogger offers "many benefits over existing logging APIs". These improvements include reducing the cost of disabled log statements, increasing overall readability, and allowing extensibility.

Flogger, a portmanteau of fluent and logger, argues that one of its main benefits is "[l]ogging at disabled levels is effectively free." Whereas other logging frameworks may generate bytecode for disabled logging statements, Flogger aims to completely avoid it.

More specifically, logging frameworks typically utilize varargs to accommodate the unknown number of parameters in a logging method call rather than having hundreds or even thousands of different and unpredictable method signatures. This use of varargs results in additional bytecode, particularly to allocate an Object[] for storing the varargs. While additional bytecode doesn’t typically warrant concern, it becomes particularly important in applications with very fine-grained logging statements or logging statements that occur in loops.

Flogger avoids this cost through the design of its API. The fluent call chain always begins with a selector for a particular log level, for instance atInfo(). This selector returns an implementation to log at that level and in the case of disabled log statements, a singleton, no-op implementation, can be returned.

Readability is another area that Flogger is making strides to improve. According to Google, Flogger allows for more "self-documenting log statements" through the use of its more expressive fluent API. As an example, consider a typical logging statement which logs an error along with its exception

log.error("The arg, '{}' caused an error", arg, exception)

This same statement can be expressed in Flogger using

logger.atError()
      .withCause(exception)
      .log("The arg, ‘%s’ caused an error", arg);

In addition to the improvements in readability, Flogger was designed with extensibility in mind and allows for custom extensions. Using Flogger, it’s "possible to locally extend the logging API and add methods in the fluent chain".

At this time, documentation and examples of custom extensions are limited but one such example, given by Google, is creating a UserLogger that logs on a per-user basis that gets written out separately from the main log.

logger.at(INFO)
      .forUserId(id)
      .log("Message: %s", param);

Additional information about Flogger can be found on its Github page along with a getting started guide and documentation on best practices.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

  • A good start, but a bit naive

    by Cameron Purdy,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Most of the cost of logging (for well done logging) is in the assembly of the things that are being logged. The examples given here pretend that you're logging something like "param", which is a zero-cost local variable. But what happens when the thing that comprises the parameter of the log message is itself expensive to assemble? Ultimately, being able to represent the information-to-potentially-log as a function with captures (e.g. a lambda) is critical.

    I suppose, though, if you're just logging shit-tons of noise, it doesn't really make a difference.

  • Re: A good start, but a bit naive

    by Dustin Schultz,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Thanks for your comments! Although not covered specifically in this article, Flogger does support lazy evaluation. Albeit it's not unique to Flogger (e.g. Log4j2 supports lazy eval).

    Using Flogger


    log.atSevere()
    .atMostEvery(30, SECONDS)
    .log("Value: %s", lazy(() -> doExpensiveCalculation()));

  • Re: A good start, but a bit naive

    by Cameron Purdy,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    Definitely worth highlighting as a best practice in the documentation! I sometimes have log items that would use hundreds of MB of RAM and tens of MS to put together the log message; they're important, but they're usually disabled.

  • slf4j-fluent mimics the same api

    by Federico Fissore,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    I've stumbled on Flogger some time ago and reproduced its API with github.com/ffissore/slf4j-fluent
    If you wish to have a fluent API with lazy arguments evaluation and you don't want to change logging framework, you might find slf4j-fluent useful

  • Cool framework but limited configurable

    by Anil Kurmi,

    Your message is awaiting moderation. Thank you for participating in the discussion.

    I tried to use the framework but support very limited configurations. Object logging becomes bit easy but still expensive to log whole object.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT