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

com.google.common.flogger.LoggingApi Maven / Gradle / Ivy

There is a newer version: 2.0.31
Show newest version
/*
 * Copyright (C) 2012 The Flogger Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.flogger;

import static com.google.common.flogger.util.Checks.checkNotNull;

import java.util.concurrent.TimeUnit;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

/**
 * The basic logging API. An implementation of this API (or an extension of it) will be
 * returned by any fluent logger, and forms the basis of the fluent call chain.
 * 

* In typical usage each method in the API, with the exception of the terminal {@code log()} * statements, will carry out some simple task (which may involve modifying the context of the log * statement) and return the same API for chaining. The exceptions to this are: *

    *
  • Methods which return a NoOp implementation of the API in order to disable logging. *
  • Methods which return an alternate API in order to implement context specific grammar (though * these alternate APIs should always return the original logging API eventually). *
* A hypothetical example of a context specific grammar might be: *
{@code
 * logger.at(WARNING).whenSystem().isLowOnMemory().log("");
 * }
* In this example the {@code whenSystem()} method would return its own API with several context * specific methods ({@code isLowOnMemory()}, {@code isThrashing()} etc...), however each of these * sub-APIs must eventually return the original logging API. */ // NOTE: new methods to this interface should be coordinated with google-java-format public interface LoggingApi> { /** * Associates a {@link Throwable} instance with the current log statement, to be interpreted as * the cause of this statement. Typically this method will be used from within catch blocks to log * the caught exception or error. If the cause is {@code null} then this method has no effect. *

* If this method is called multiple times for a single log statement, the last invocation will * take precedence. */ API withCause(@NullableDecl Throwable cause); /** * Modifies the current log statement to be emitted at most one-in-N times. The specified count * must be greater than zero and it is expected, but not required, that it is constant. In the * absence of any other rate limiting, this method always allows the first invocation of any log * statement to be emitted. * *

Notes

* * If multiple rate limiters are used for a single log statement, that log statement will * only be emitted once all rate limiters have reached their threshold, and when a log statement * is emitted all the rate limiters are reset. In particular for {@code every(N)} this means that * logs need not always be emitted at multiples of {@code N} if other rate limiters are active, * though it will always be at least {@code N}. *

* When rate limiting is active, a {@code "skipped"} count is added to log statements to indicate * how many logs were disallowed since the last log statement was emitted. *

* If this method is called multiple times for a single log statement, the last invocation will * take precedence. * * @param n the factor by which to reduce logging frequency. * @throws IllegalArgumentException if {@code n} is not positive. */ API every(int n); /** * Modifies the current log statement to be emitted with likelihood 1 in {@code n}. For example, * inserting {@code onAverageEvery(20)} into a call chain results in approximately 5% as many * messages being emitted as before. Unlike the other rate-limiting options, there is no * guarantee about when the first such message will be emitted, though it becomes highly likely as * the number of calls reaches several times {@code n}. * *

Notes

* * If multiple rate limiters are used for a single log statement, that log statement will * only be emitted once all rate limiters have reached their threshold, and when a log statement * is emitted all the rate limiters are reset. In particular for {@code onAverageEvery(N)} this * means that logs may occurs less frequently than one-in-N if other rate limiters are active. *

* When rate limiting is active, a {@code "skipped"} count is added to log statements to indicate * how many logs were disallowed since the last log statement was emitted. *

* If this method is called multiple times for a single log statement, the last invocation will * take precedence. * * @param n the factor by which to reduce logging frequency; a value of {@code 1} has no effect. * @throws IllegalArgumentException if {@code n} is not positive. */ API onAverageEvery(int n); /** * Modifies the current log statement to be emitted at most once per specified time period. The * specified duration must not be negative, and it is expected, but not required, that it is * constant. In the absence of any other rate limiting, this method always allows the first * invocation of any log statement to be emitted. *

* Note that for performance reasons {@code atMostEvery()} is explicitly not intended to * perform "proper" rate limiting to produce a limited average rate over many samples. * *

Behaviour

* * A call to {@code atMostEvery()} will emit the current log statement if: *
{@code
   *   currentTimestampNanos >= lastTimestampNanos + unit.toNanos(n)
   * }
* where {@code currentTimestampNanos} is the timestamp of the current log statement and * {@code lastTimestampNanos} is a time stamp of the last log statement that was emitted. *

* The effect of this is that when logging invocation is relatively infrequent, the period * between emitted log statements can be higher than the specified duration. For example * if the following log statement were called every 600ms: *

{@code
   *   logger.atFine().atMostEvery(2, SECONDS).log(...);
   * }
* logging would occur after {@code 0s}, {@code 2.4s} and {@code 4.8s} (not {@code 4.2s}), * giving an effective duration of {@code 2.4s} between log statements over time. *

* Providing a zero length duration (ie, {@code n == 0}) disables rate limiting and makes this * method an effective no-op. * *

Granularity

* * Because the implementation of this feature relies on a nanosecond timestamp provided by the * backend, the actual granularity of the underlying clock used may vary, and it is possible to * specify a time period smaller than the smallest visible time increment. If this occurs, then * the effective rate limit applied to the log statement will be the smallest available time * increment. For example, if the system clock granularity is 1 millisecond, and a * log statement is called with {@code atMostEvery(700, MICROSECONDS)}, the effective rate of * logging (even averaged over long periods) could never be more than once every millisecond. * *

Notes

* * If multiple rate limiters are used for a single log statement, that log statement will * only be emitted once all rate limiters have reached their threshold, and when a log statement * is emitted all the rate limiters are reset. So even if the rate limit duration has expired, it * does not mean that logging will occur. *

* When rate limiting is active, a {@code "skipped"} count is added to log statements to indicate * how many logs were disallowed since the last log statement was emitted. *

* If this method is called multiple times for a single log statement, the last invocation will * take precedence. * * @param n the minimum number of time units between emitted log statements * @param unit the time unit for the duration * @throws IllegalArgumentException if {@code n} is negative. */ API atMostEvery(int n, TimeUnit unit); /** * Aggregates stateful logging with respect to a given {@code key}. * *

Normally log statements with conditional behaviour (e.g. rate limiting) use the same state * for each invocation (e.g. counters or timestamps). This method allows an additional qualifier * to be given which allows for different conditional state for each unique qualifier. * *

This only makes a difference for log statements which use persistent state to control * conditional behaviour (e.g. {@code atMostEvery()} or {@code every()}). * *

This is the most general form of log aggregation and allows any keys to be used, but it * requires the caller to have chosen a bucketing strategy. Where it is possible to refactor code * to avoid passing keys from an unbounded space into the {@code per(...)} method (e.g. by * mapping cases to an {@code Enum}), this is usually preferable. * * When using this method, a bucketing strategy is needed to reduce the risk of leaking memory. * Consider the alternate API: * *

{@code
   * // Rate limit per unique error message ("No such file", "File corrupted" etc.).
   * logger.atWarning().per(error.getMessage()).atMostEvery(30, SECONDS).log(...);
   * }
* *

A method such as the one above would need to store some record of all the unique messages it * has seen in order to perform aggregation. This means that the API would suffer a potentially * unbounded memory leak if a timestamp were included in the message (since all values would now * be unique and need to be retained). * *

To fix (or at least mitigate) this issue, a {@link LogPerBucketingStrategy} is passed to * provide a mapping from "unbounded key space" (e.g. arbitrary strings) to a bounded set of * "bucketed" values. In the case of error messages, you might implement a bucketing strategy to * classify error messages based on the type of error. * *

This method is most useful in helping to avoid cases where a rare event might never be * logged due to rate limiting. For example, the following code will cause log statements with * different types of {@code errorMessage}s to be rate-limited independently of each other. * *

{@code
   * // Rate limit for each type of error (FileNotFoundException, CorruptedFileException etc.).
   * logger.atInfo().per(error, byClass()).atMostEvery(30, SECONDS).log(...);
   * }
* *

If a user knows that the given {@code key} values really do form a strictly bounded set, * the {@link LogPerBucketingStrategy#knownBounded()} strategy can be used, but it should always * be documented as to why this is safe. * *

The {@code key} passed to this method should always be a variable (passing a constant value * has no effect). If a {@code null} key is passed, this call has no effect (e.g. rate limiting * will apply normally, without respect to any specific scope). * *

If multiple aggregation keys are added to a single log statement, then they all take effect * and logging is aggregated by the unique combination of keys passed to all "per" methods. */ API per(@NullableDecl T key, LogPerBucketingStrategy strategy); /** * Aggregates stateful logging with respect to the given enum value. * *

Normally log statements with conditional behaviour (e.g. rate limiting) use the same state * for each invocation (e.g. counters or timestamps). This method allows an additional qualifier * to be given which allows for different conditional state for each unique qualifier. * *

This only makes a difference for log statements which use persistent state to control * conditional behaviour (e.g. {@code atMostEvery()} or {@code every()}). * *

This method is most useful in helping to avoid cases where a rare event might never be * logged due to rate limiting. For example, the following code will cause log statements with * different {@code taskType}s to be rate-limited independently of each other. * *

{@code
   * // We want to rate limit logging separately for all task types.
   * logger.at(INFO).per(taskType).atMostEvery(30, SECONDS).log("Start task: %s", taskSpec);
   * }
* *

The {@code key} passed to this method should always be a variable (passing a constant value * has no effect). If {@code null} is passed, this call has no effect (e.g. rate limiting will * apply normally, without respect to any specific scope). * *

If multiple aggregation keys are added to a single log statement, then they all take effect * and logging is aggregated by the unique combination of keys passed to all "per" methods. */ API per(@NullableDecl Enum key); /** * Aggregates stateful logging with respect to a scoped context determined by the given scope * provider. * *

When {@link com.google.common.flogger.context.ScopedLoggingContext ScopedLoggingContext} is * used to create a context, it can be bound to a {@link * com.google.common.flogger.context.ScopeType ScopeType}. For example: * *

{@code
   * ScopedLoggingContexts.newContext(REQUEST).run(() -> scopedMethod(x, y, z));
   * }
* * where {@link com.google.common.flogger.context.ScopeType#REQUEST REQUEST} defines the scope * type for the context in which {@code scopedMethod()} is called. Within this context, the scope * associated with the {@code REQUEST} type can then be used to aggregate logging behavior: * *
{@code
   * logger.atInfo().atMostEvery(5, SECONDS).per(REQUEST).log("Some message...");
   * }
* *

New scope types can be created for specific subtasks using {@link * com.google.common.flogger.context.ScopeType#create ScopeType.create("")} but it is * recommended to use shared constants (such as {@code ScopeType.REQUEST}) wherever feasible to * avoid confusion. * *

Note that in order for the request scope to be applied to a log statement, the {@code * per(REQUEST)} method must still be called; just being inside the request scope isn't enough. * *

Unlike other {@code per()} methods, this method is expected to be given a constant value. * This is because the given value provides the current scope, rather than being * the current scope. * *

If a log statement using this method is invoked outside a context of the given type, this * call has no effect (e.g. rate limiting will apply normally, without respect to any specific * scope). * *

If multiple aggregation keys are added to a single log statement, then they all take effect * and logging is aggregated by the unique combination of keys passed to all "per" methods. * * @param scopeProvider a constant used to defined the type of the scope in which logging is * aggregated. */ API per(LoggingScopeProvider scopeProvider); /** * Creates a synthetic exception and attaches it as the "cause" of the log statement as a way to * provide additional context for the logging call itself. The exception created by this method is * always of the type {@link LogSiteStackTrace}, and its message indicates the stack size. * *

If the {@code withCause(e)} method is also called for the log statement (either before or * after) {@code withStackTrace()}, the given exception becomes the cause of the synthetic * exception. * * @param size the maximum size of the stack trace to be generated. */ API withStackTrace(StackSize size); /** * Associates a metadata key constant with a runtime value for this log statement in a structured * way that is accessible to logger backends. * *

This method is not a replacement for general parameter passing in the {@link #log()} method * and should be reserved for keys/values with specific semantics. Examples include: *

    *
  • Keys that are recognised by specific logger backends (typically to control logging * behaviour in some way). *
  • Key value pairs which are explicitly extracted from logs by tools. *
* *

Metadata keys can support repeated values (see {@link MetadataKey#canRepeat()}), and if a * repeatable key is used multiple times in the same log statement, the effect is to collect all * the given values in order. If a non-repeatable key is passed multiple times, only the last * value is retained (though callers should not rely on this behavior and should simply avoid * repeating non-repeatable keys). * *

If {@code value} is {@code null}, this method is a no-op. This is useful for specifying * conditional values (e.g. via {@code logger.atInfo().with(MY_KEY, getValueOrNull()).log(...)}). * * @param key the metadata key (expected to be a static constant) * @param value a value to be associated with the key in this log statement. Null values are * allowed, but the effect is always a no-op * @throws NullPointerException if the given key is null * @see MetadataKey */ API with(MetadataKey key, @NullableDecl T value); /** * Sets a boolean metadata key constant to {@code true} for this log statement in a structured way * that is accessible to logger backends. * *

This method is not a replacement for general parameter passing in the {@link #log()} method * and should be reserved for keys/values with specific semantics. Examples include: * *

    *
  • Keys that are recognised by specific logger backends (typically to control logging * behaviour in some way). *
  • Key value pairs which are explicitly extracted from logs by tools. *
* *

This method is just an alias for {@code with(key, true)} to improve readability. * * @param key the boolean metadata key (expected to be a static constant) * @throws NullPointerException if the given key is null * @see MetadataKey */ API with(MetadataKey key); /** * Sets the log site for the current log statement. Explicit log site injection is very rarely * necessary, since either the log site is injected automatically, or it is determined at runtime * via stack analysis. The one use case where calling this method explicitly may be useful is when * making logging helper methods, where some common project specific logging behavior is * enshrined. For example, you can write: * *

{@code
   * public void logStandardWarningAt(LogSite logSite, String message, Object... args) {
   *   logger.atWarning()
   *       .withInjectedLogSite(logSite)
   *       .atMostEvery(5, MINUTES)
   *       .logVarargs(message, args);
   * }
   * }
* * and then code can do: * *
{@code
   * import static com.google.common.flogger.LogSites.logSite;
   * }
* * and elsewhere: * *
{@code
   * logStandardWarningAt(logSite(), "Badness");
   * ...
   * logStandardWarningAt(logSite(), "More badness: %s", getData());
   * }
* *

Now each of the call sites for the helper method is treated as if it were in the logging * API, and things like rate limiting work separately for each, and the location in the log * statement will be the point at which the helper method was called. * *

It is very important to note that the {@code logSite()} call can be very slow, since * determining the log site can involve stack trace analysis. It is only recommended in cases * where logging is expected to occur (e.g. {@code WARNING} level or above). Luckily, there is * typically no need to implement helper methods for {@code FINE} logging, since it's usually less * structured and doesn't normally need to follow any specific "best practice" behavior. * *

Note however that any stack traces generated by {@link #withStackTrace(StackSize)} will * still contain the complete stack, including the call to the logger itself inside the helper * method. * *

This method must only be explicitly called once for any log statement, and if this method is * called multiple times the first invocation will take precedence. This is because log site * injection (if present) is expected to occur just before the final {@code log()} call and must * be overrideable by earlier (explicit) calls. A null argument has no effect. * * @param logSite Log site which uniquely identifies any per-log statement resources. */ API withInjectedLogSite(@NullableDecl LogSite logSite); /** * Internal method not for public use. This method is only intended for use by the logger * agent and related classes and should never be invoked manually. * * @param internalClassName Slash separated class name obtained from the class constant pool. * @param methodName Method name obtained from the class constant pool. * @param encodedLineNumber line number and per-line log statement index encoded as a single * 32-bit value. The low 16-bits is the line number (0 to 0xFFFF inclusive) and the high * 16 bits is a log statement index to distinguish multiple statements on the same line * (this becomes important if line numbers are stripped from the class file and everything * appears to be on the same line). * @param sourceFileName Optional base name of the source file (this value is strictly for * debugging and does not contribute to either equals() or hashCode() behavior). */ API withInjectedLogSite( String internalClassName, String methodName, int encodedLineNumber, @NullableDecl String sourceFileName); /** * Returns true if logging is enabled at the level implied for this API, according to the current * logger backend. For example: *

{@code
   *   if (logger.atFine().isEnabled()) {
   *     // Do non-trivial argument processing
   *     logger.atFine().log("Message: %s", value);
   *   }
   * }
*

* Note that if logging is enabled for a log level, it does not always follow that the log * statement will definitely be written to the backend (due to the effects of other methods in * the fluent chain), but if this method returns {@code false} then it can safely be assumed that * no logging will occur. *

* This method is unaffected by additional methods in the fluent chain and should only ever be * invoked immediately after the level selector method. In other words, the expression: *

{@code logger.atFine().every(100).isEnabled()}
* is incorrect because it will always behave identically to: *
{@code logger.atFine().isEnabled()}
*

*

Implementation Note

* By avoiding passing a separate {@code Level} at runtime to determine "loggability", this API * makes it easier to coerce bytecode optimizers into doing "dead code" removal on sections * guarded by this method. *

* If a proxy logger class is supplied for which: *

{@code logger.atFine()}
* unconditionally returns the "NoOp" implementation of the API (in which {@code isEnabled()} * always returns {@code false}), it becomes simple for bytecode analysis to determine that: *
{@code logger.atFine().isEnabled()}
* always evaluates to {@code false} . */ boolean isEnabled(); /** * Logs a formatted representation of values in the given array, using the specified message * template. * *

This method is only expected to be invoked with an existing varargs array passed in from * another method. Unlike {@link #log(String, Object)}, which would treat an array as a single * parameter, this method will unwrap the given array. * * @param message the message template string containing an argument placeholder for each element * of {@code varargs}. * @param varargs the non-null array of arguments to be formatted. */ void logVarargs(String message, @NullableDecl Object[] varargs); /** * Terminal log statement when a message is not required. A {@code log} method must terminate all * fluent logging chains and the no-argument method can be used if there is no need for a log * message. For example: *

{@code
   * logger.at(INFO).withCause(error).log();
   * }
*

* However as it is good practice to give all log statements a meaningful log message, use of this * method should be rare. */ void log(); /** * Logs the given literal string without interpreting any argument placeholders. *

* Important: This is intended only for use with hard-coded, literal strings which cannot * contain user data. If you wish to log user generated data, you should do something like: *

{@code
   * log("user data=%s", value);
   * }
* This serves to give the user data context in the log file but, more importantly, makes it * clear which arguments may contain PII and other sensitive data (which might need to be * scrubbed during logging). This recommendation also applies to all the overloaded {@code log()} * methods below. */ void log(String msg); // ---- Overloads for object arguments (to avoid vararg array creation). ---- /** * Logs a formatted representation of the given parameter, using the specified message template. * The message string is expected to contain argument placeholder terms appropriate to the * logger's choice of parser. *

* Note that printf-style loggers are always expected to accept the standard Java printf * formatting characters (e.g. "%s", "%d" etc...) and all flags unless otherwise stated. * Null arguments are formatted as the literal string {@code "null"} regardless of * formatting flags. * * @param msg the message template string containing a single argument placeholder. */ void log(String msg, @NullableDecl Object p1); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8, @NullableDecl Object p9); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8, @NullableDecl Object p9, @NullableDecl Object p10); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8, @NullableDecl Object p9, @NullableDecl Object p10, Object... rest); // ---- Overloads for a single argument (to avoid auto-boxing and vararg array creation). ---- /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1); // ---- Overloads for two arguments (to avoid auto-boxing and vararg array creation). ---- /* * It may not be obvious why we need _all_ combinations of fundamental types here (because some * combinations should be rare enough that we can ignore them). However due to the precedence in * the Java compiler for converting fundamental types in preference to auto-boxing, and the need * to preserve information about the original type (byte, short, char etc...) when doing unsigned * formatting, it turns out that all combinations are required. */ /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, @NullableDecl Object p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, @NullableDecl Object p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, boolean p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, char p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, byte p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, short p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, int p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, long p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, float p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, boolean p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, char p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, byte p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, short p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, int p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, long p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, float p1, double p2); /** Logs a message with formatted arguments (see {@link #log(String, Object)} for details). */ void log(String msg, double p1, double p2); /** * An implementation of {@link LoggingApi} which does nothing and discards all parameters. *

* This class (or a subclass in the case of an extended API) should be returned whenever logging * is definitely disabled (e.g. when the log level is too low). */ public static class NoOp> implements LoggingApi { @SuppressWarnings("unchecked") protected final API noOp() { return (API) this; } @Override public API withInjectedLogSite(LogSite logSite) { return noOp(); } @Override public API withInjectedLogSite( String internalClassName, String methodName, int encodedLineNumber, @NullableDecl String sourceFileName) { return noOp(); } @Override public final boolean isEnabled() { return false; } @Override public final API with(MetadataKey key, @NullableDecl T value) { // Identical to the check in LogContext for consistency. checkNotNull(key, "metadata key"); return noOp(); } @Override public final API with(MetadataKey key) { // Do this inline rather than calling with(key, true) to keep no-op minimal. checkNotNull(key, "metadata key"); return noOp(); } @Override public API per(@NullableDecl T key, LogPerBucketingStrategy strategy) { return noOp(); } @Override public API per(@NullableDecl Enum key) { return noOp(); } @Override public API per(LoggingScopeProvider scopeProvider) { return noOp(); } @Override public final API withCause(@NullableDecl Throwable cause) { return noOp(); } @Override public final API every(int n) { return noOp(); } @Override public final API onAverageEvery(int n) { return noOp(); } @Override public final API atMostEvery(int n, TimeUnit unit) { checkNotNull(unit, "time unit"); return noOp(); } @Override public API withStackTrace(StackSize size) { // Don't permit null since NONE is the right thing to use. checkNotNull(size, "stack size"); return noOp(); } @Override public final void logVarargs(String msg, Object[] params) {} @Override public final void log() {} @Override public final void log(String msg) {} @Override public final void log(String msg, @NullableDecl Object p1) {} @Override public final void log(String msg, @NullableDecl Object p1, @NullableDecl Object p2) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8, @NullableDecl Object p9) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8, @NullableDecl Object p9, @NullableDecl Object p10) {} @Override public final void log( String msg, @NullableDecl Object p1, @NullableDecl Object p2, @NullableDecl Object p3, @NullableDecl Object p4, @NullableDecl Object p5, @NullableDecl Object p6, @NullableDecl Object p7, @NullableDecl Object p8, @NullableDecl Object p9, @NullableDecl Object p10, Object... rest) {} @Override public final void log(String msg, char p1) {} @Override public final void log(String msg, byte p1) {} @Override public final void log(String msg, short p1) {} @Override public final void log(String msg, int p1) {} @Override public final void log(String msg, long p1) {} @Override public final void log(String msg, @NullableDecl Object p1, boolean p2) {} @Override public final void log(String msg, @NullableDecl Object p1, char p2) {} @Override public final void log(String msg, @NullableDecl Object p1, byte p2) {} @Override public final void log(String msg, @NullableDecl Object p1, short p2) {} @Override public final void log(String msg, @NullableDecl Object p1, int p2) {} @Override public final void log(String msg, @NullableDecl Object p1, long p2) {} @Override public final void log(String msg, @NullableDecl Object p1, float p2) {} @Override public final void log(String msg, @NullableDecl Object p1, double p2) {} @Override public final void log(String msg, boolean p1, @NullableDecl Object p2) {} @Override public final void log(String msg, char p1, @NullableDecl Object p2) {} @Override public final void log(String msg, byte p1, @NullableDecl Object p2) {} @Override public final void log(String msg, short p1, @NullableDecl Object p2) {} @Override public final void log(String msg, int p1, @NullableDecl Object p2) {} @Override public final void log(String msg, long p1, @NullableDecl Object p2) {} @Override public final void log(String msg, float p1, @NullableDecl Object p2) {} @Override public final void log(String msg, double p1, @NullableDecl Object p2) {} @Override public final void log(String msg, boolean p1, boolean p2) {} @Override public final void log(String msg, char p1, boolean p2) {} @Override public final void log(String msg, byte p1, boolean p2) {} @Override public final void log(String msg, short p1, boolean p2) {} @Override public final void log(String msg, int p1, boolean p2) {} @Override public final void log(String msg, long p1, boolean p2) {} @Override public final void log(String msg, float p1, boolean p2) {} @Override public final void log(String msg, double p1, boolean p2) {} @Override public final void log(String msg, boolean p1, char p2) {} @Override public final void log(String msg, char p1, char p2) {} @Override public final void log(String msg, byte p1, char p2) {} @Override public final void log(String msg, short p1, char p2) {} @Override public final void log(String msg, int p1, char p2) {} @Override public final void log(String msg, long p1, char p2) {} @Override public final void log(String msg, float p1, char p2) {} @Override public final void log(String msg, double p1, char p2) {} @Override public final void log(String msg, boolean p1, byte p2) {} @Override public final void log(String msg, char p1, byte p2) {} @Override public final void log(String msg, byte p1, byte p2) {} @Override public final void log(String msg, short p1, byte p2) {} @Override public final void log(String msg, int p1, byte p2) {} @Override public final void log(String msg, long p1, byte p2) {} @Override public final void log(String msg, float p1, byte p2) {} @Override public final void log(String msg, double p1, byte p2) {} @Override public final void log(String msg, boolean p1, short p2) {} @Override public final void log(String msg, char p1, short p2) {} @Override public final void log(String msg, byte p1, short p2) {} @Override public final void log(String msg, short p1, short p2) {} @Override public final void log(String msg, int p1, short p2) {} @Override public final void log(String msg, long p1, short p2) {} @Override public final void log(String msg, float p1, short p2) {} @Override public final void log(String msg, double p1, short p2) {} @Override public final void log(String msg, boolean p1, int p2) {} @Override public final void log(String msg, char p1, int p2) {} @Override public final void log(String msg, byte p1, int p2) {} @Override public final void log(String msg, short p1, int p2) {} @Override public final void log(String msg, int p1, int p2) {} @Override public final void log(String msg, long p1, int p2) {} @Override public final void log(String msg, float p1, int p2) {} @Override public final void log(String msg, double p1, int p2) {} @Override public final void log(String msg, boolean p1, long p2) {} @Override public final void log(String msg, char p1, long p2) {} @Override public final void log(String msg, byte p1, long p2) {} @Override public final void log(String msg, short p1, long p2) {} @Override public final void log(String msg, int p1, long p2) {} @Override public final void log(String msg, long p1, long p2) {} @Override public final void log(String msg, float p1, long p2) {} @Override public final void log(String msg, double p1, long p2) {} @Override public final void log(String msg, boolean p1, float p2) {} @Override public final void log(String msg, char p1, float p2) {} @Override public final void log(String msg, byte p1, float p2) {} @Override public final void log(String msg, short p1, float p2) {} @Override public final void log(String msg, int p1, float p2) {} @Override public final void log(String msg, long p1, float p2) {} @Override public final void log(String msg, float p1, float p2) {} @Override public final void log(String msg, double p1, float p2) {} @Override public final void log(String msg, boolean p1, double p2) {} @Override public final void log(String msg, char p1, double p2) {} @Override public final void log(String msg, byte p1, double p2) {} @Override public final void log(String msg, short p1, double p2) {} @Override public final void log(String msg, int p1, double p2) {} @Override public final void log(String msg, long p1, double p2) {} @Override public final void log(String msg, float p1, double p2) {} @Override public final void log(String msg, double p1, double p2) {} } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy