Open-source project
google/flogger avatar
google/flogger

google/flogger: Fluent Java Logging Setup and Usage

A Fluent Logging API for Java

1,481 stars133 forksJavaApache-2.0

At a glance

What is it?
Flogger gives Java applications a fluent logging API, lazy evaluation for expensive values, rate controls, and structured context through chained calls. It is aimed at codebases that want one readable logging surface while retaining a backend.
Who is it for?
Java teams that want a self-documenting logging surface, lazy evaluation, rate limiting, and room for extensions should evaluate Flogger. Projects already standardized on another API should first confirm their existing backend path and migration scope.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The logging consistency problem addressed by Flogger

Flogger addresses a specific Java codebase problem: developers moving between projects can encounter several logging APIs with different calls, capabilities, and failure modes. The README says those differences caused confusion and bugs in Google's large Java codebase. Flogger is intended to provide one recommended API across ordinary Java projects, with the understanding that logging should read as part of the surrounding code rather than as a loosely formatted string assembled elsewhere.

The intended users are Java developers and organizations that want consistency across services or libraries. Its fluent call structure also makes optional logging behavior explicit. A statement can start at a severity level and then add a cause, throttling rule, or lazily evaluated value before supplying the message. This is a different API shape from a conventional logger method that expects callers to pass its level, format string, arguments, and exception according to backend-specific conventions.

Flogger does not attempt to replace application logging through style alone. The README identifies disabled-level cost, performance for enabled statements, extensibility, and reduced reliance on long parameter lists as the principal reasons to adopt it. The strongest practical case is therefore a codebase with many logging call sites, mixed conventions, or a need to keep costly debug instrumentation available without always calculating its values.

Flogger's fluent API and backend boundary

The application-facing object is `FluentLogger`. A typical statement follows a pipeline from severity selection to optional metadata or controls and finally to `log()`. Severity is selected with calls such as `atInfo()` and `atSevere()`. The same chain can add an exception with `withCause(exception)`, apply `atMostEvery(30, SECONDS)`, or defer an expensive value with `lazy(() -> doExpensiveCalculation())`.

The central design choice is the separation between the fluent API and logging backends. Applications use the same call shape while the backend handles emitted records. The README requires `com.google.flogger:flogger` for code that uses the API and `com.google.flogger:flogger-system-backend` for the binary at runtime. In a modularized build, the system backend can be supplied by the root module that builds the application or binary and can use `runtime` scope.

This boundary also explains the repository layout. Directories named `slf4j` and `log4j2` indicate integration areas, while the README specifically describes the system backend for basic use. The README does not document how to select or configure those other integrations, so their setup should not be inferred from directory names alone. For non-Google code, the README recommends `FluentLogger` instead of `GoogleLogger`, which it describes as a minor variant designed for Google's codebase and intended to have a more stable external API.

Dependencies, logger creation, and a first log statement

The documented installation starts with Maven dependencies rather than a command from the repository. Add `com.google.flogger:flogger` to every module that contains code using Flogger. Add the matching `com.google.flogger:flogger-system-backend` dependency to the module that produces the runnable application or binary. The two artifacts must use the same selected version. The README does not provide a complete build file or a command for resolving dependencies, so no unverified Maven or Gradle command is included here.

After declaring the dependencies, import `FluentLogger`. This import is the API entry point used in all subsequent examples from the README.

java
import com.google.common.flogger.FluentLogger;

Create one `private static final` logger instance for the enclosing class. The README recommends using `forEnclosingClass()` rather than choosing a category manually.

java
private static final FluentLogger logger = FluentLogger.forEnclosingClass();

A first real statement can attach a cause and pass a value to a printf-style format specifier. Place the statement in the class that owns the logger, and replace `exception` and `argument` with values available at that call site.

java
logger.atInfo().withCause(exception).log("Log message with: %s", argument);

Flogger accepts Java `Formatter` specifiers, including `%s`, `%d`, and `%016x`. The call should emit an informational record only when the configured backend and level permit it. Flogger also records the associated cause through the fluent API.

The dependency scope distinction matters during verification. Code that imports or calls Flogger needs the API artifact at compile time. A modularized binary may receive `flogger-system-backend` only at runtime from its root module. Omitting the runtime backend can leave compilation successful while preventing the application from producing log output at execution time.

Lazy values and atMostEvery controls in Java logging

Flogger's builder supports behavior that is awkward to express clearly with a conventional logging call. The README combines a severe log level, a rate limit, and a lazy value in one chain. This example demonstrates the intended composition rather than a special case with a separate façade.

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

The `atMostEvery(30, SECONDS)` control states that this severe message is limited to once per 30-second interval under Flogger's logging behavior. The supplier passed to `lazy()` represents work that should not be evaluated merely because the call site exists. This is particularly relevant to diagnostic logging in request paths, where `doExpensiveCalculation()` may inspect state that is expensive to retrieve even when nobody reads the log.

These controls still need application review. Rate limiting is appropriate for repeated exceptional conditions, but it can hide changes in frequency when the first occurrence is retained. A developer troubleshooting one request may see no recent line even though the underlying event continues. Likewise, a lazy supplier should be side-effect free. If the calculation mutates shared state, postponing or skipping evaluation changes program behavior beyond logging.

Flogger does not make log output free of all cost. Disabled-level statements are described as effectively free, and enabled statements as having high performance, but the exact cost still depends on the backend, format string, supplied arguments, and the behavior of the logging framework selected by the application.

Backend choice versus direct use of another logging API

The practical alternative is to make an established logging framework, such as the APIs represented by the repository's `slf4j` and `log4j2` directories, the direct interface seen throughout application code. Flogger takes a facade-like approach: developers write against its fluent API, while an integration or backend determines how records are emitted. A conventional approach keeps framework-specific calls at each logging site and relies on that framework's level, parameter, exception, and configuration conventions.

That difference affects consistency as much as syntax. Flogger's calls expose cause attachment, lazy evaluation, and rate control as named stages in one chain. A conventional API may offer comparable capabilities elsewhere, but it does not create the same uniform call surface across every module. Conversely, adopting Flogger means checking how it integrates with the existing logging configuration and deployment environment. The README does not document the configuration keys or initialization sequence for the `slf4j` and `log4j2` integration directories, so those cannot be treated as drop-in instructions.

Flogger is also a poor fit when changing application-facing logging calls is prohibitively expensive or prohibited by library API policy. A library with a stable public surface may need to retain an established logging abstraction. A small project that already uses one logging framework consistently gains less from replacing its call sites, particularly if its current API already covers lazy values and rate controls.

Flogger releases, licensing, and adoption boundaries

The repository is not archived. Its last push was on 2026-10-15, and the listed releases include Flogger 0.9 on 2025-05-16, Flogger 0.8 on 2023-10-17, and Flogger 0.7.4 on 2021-12-20. These release dates show that published versions are not all on the same schedule, so adoption should pin a selected version for the API and system backend rather than combining unrelated artifacts. The README does not document a migration procedure between Flogger versions or a compatibility matrix.

The repository is licensed under Apache-2.0. Teams incorporating the library should review the repository's `LICENSE` file and their own distribution, notice, and dependency obligations. That is an identification of the applicable license, not legal advice about a particular application.

The main adoption cost is not the logger declaration. It is the effort required to locate existing logging calls, translate their level and exception semantics, confirm which artifact supplies the backend at runtime, and check that rate-limited or lazy statements preserve the intended behavior. Flogger's API is most suitable for Java codebases that want consistent calls and can support that migration. It is less suitable for projects committed to direct use of an existing framework or for environments where the runtime backend cannot be included.

Editorial conclusion

Java teams that want a self-documenting logging surface, lazy evaluation, rate limiting, and room for extensions should evaluate Flogger. Projects already standardized on another API should first confirm their existing backend path and migration scope. The first technical check should be whether the API and system backend can both be added at a consistent release version, then whether a minimal logger declaration and one call compile in the application build.

Frequently asked questions

Which Flogger artifact should a Java application include?

Code that uses Flogger depends on `com.google.flogger:flogger`, while the runnable binary also needs `com.google.flogger:flogger-system-backend`. In a modularized build, the root application or binary module can provide the system backend at runtime scope.

How do I create and use a Flogger logger?

Import `FluentLogger`, create a `private static final` instance with `FluentLogger.forEnclosingClass()`, and begin a fluent statement with a method such as `atInfo()` or `atSevere()`.

Can Flogger defer an expensive log value and limit repeated messages?

Yes. The README shows `lazy(() -> doExpensiveCalculation())` for a deferred value and `atMostEvery(30, SECONDS)` as a rate control. Both are composed into the fluent statement before `log()` is called.

Should external Java projects use FluentLogger or GoogleLogger?

The README recommends `FluentLogger` for non-Google code. It describes `GoogleLogger` as a minor variant intended for Google's codebase, while `FluentLogger` is expected to have the more stable API for external users.

Official sources

  1. google/flogger on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/google-flogger.svg)](https://hysenlabs.com/projects/google-flogger)

Was this useful?