All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kiwiproject.logging.LazyLogParameterSupplier Maven / Gradle / Ivy

Go to download

Kiwi is a utility library. We really like Google's Guava, and also use Apache Commons. But if they don't have something we need, and we think it is useful, this is where we put it.

There is a newer version: 4.4.0
Show newest version
package org.kiwiproject.logging;

import static java.util.Objects.isNull;

import lombok.AllArgsConstructor;
import lombok.experimental.UtilityClass;

import java.util.function.Supplier;

/**
 * Provides lazy evaluation of one or more replacement parameters in a logging statement, for example when
 * using SLF4J. This is useful when one or more values might be relatively expensive to compute, such as
 * serializing an object to JSON for DEBUG logging but not wanting to incur to JSON serialization cost at
 * higher log levels.
 * 

* While many log frameworks now provide a way to pass a {@link Supplier} as an argument, not all do (e.g. SLF4J * version 1.7.x and earlier) and not all provide as much flexibility as you might want in order to mix and match * lazy and non-lazy arguments. This simple class lets you mix and match lazy and non-lazy parameters whether the * logging API supports this or not. *

* To use, just statically import methods from {@link LazyLogParameterSupplier} and use them to wrap one or more * replacement parameters in the same logging statement. Note again you do not need to make all the * parameters lazy. *

* Examples: *

 * // Explicitly create the parameter supplier and pass it to the lazy method
 * Supplier<String> jsonSupplier = () -> jsonHelper.toJson(thing);
 * LOG.debug("Thing {} took {} millis to fetch. JSON value: {}",
 *         thing.getId(), fetchMillis, lazy(jsonSupplier));
 *
 * // Pass a Supplier as a lambda to the lazy method for one or more parameters
 * LOG.debug("Thing {} took {} millis to fetch. JSON value: {}",
 *         thing.getId(), fetchMillis, lazy(() -> jsonHelper.toJson(thing)));
 *
 * // If thingToJson converts the thing to JSON it can be a simple lambda...
 * LOG.debug("Thing {} took {} millis to fetch. JSON value: {}",
 *         thing.getId(), fetchMillis, lazy(() -> thingToJson()));
 *
 * // ...or a method reference
 * LOG.debug("Thing {} took {} millis to fetch. JSON value: {}",
 *         thing.getId(), fetchMillis, lazy(this::thingToJson));
 * 
* * @implNote adapted from from my * slf4j-lazy-params repository */ @UtilityClass public class LazyLogParameterSupplier { /** * Delays execution of the {@code original} supplier in a log replacement value. This also permits some * replacement parameters to use delayed (lazy) execution while others can be regular parameters. *

* Example usage (assuming SLF4J API, and using static import and a method reference): *

     * LOG.debug("Foo JSON with id {} is: {}", foo.getId(), lazy(foo::toJson));
     * 
* * @param original supplier of a replacement value that might be expensive to compute, e.g. serialize an * object to JSON * @return a {@link Supplier} that wraps {@code original} */ public static Supplier lazy(Supplier original) { return new ObjectSupplierWrapper(original); } /** * A {@link Supplier} that returns the original object, and whose toString method returns a null-safe * representation of the supplied object. This null-safe toString is what the logging frameworks will * ultimately insert into the logging output. */ @AllArgsConstructor private static class ObjectSupplierWrapper implements Supplier { private final Supplier original; @Override public Object get() { return original.get(); } @Override public String toString() { var value = get(); return isNull(value) ? "null" : value.toString(); } } }