Flogger Metadata Key
Key for logging semi-structured metadata values.
Metadata keys can be used to provide log statements with strongly typed values which can be read and interpreted by logging backends or other logs related tools. This mechanism is intended for values with specific semantics and should not be seen as a replacement for logging arguments as part of a formatted log message.
Examples of where using MetadataKey is suitable are:
- Logging a value with special semantics (e.g. values that are handled specially by the logger backend).
- Passing configuration to a specific logger backend to modify behaviour for individual log statements or all log statements in a
ScopedLoggingContext. - Logging a structured value in many places with consistent formatting (e.g. so it can later be re-parsed by logs related tools).
If you just want to log an general "key value pair" in a small number of log statements, it is still better to just do something like log("key=%s", value).
Metadata keys are expected to be singleton constants, and should never be allocated at the log site itself. Even though they are expected to be singletons, comparing keys should be done via equals() (rather than '==') since this will be safe in cases where non-singleton keys exist, and is just as fast if the keys are singletons.
It is strongly recommended that any public FloggerMetadataKey instances are defined as public static final fields in a top-level or nested class, which does no logging. Ideally a separate class would be defined to hold only the keys, since this allows keys to be loaded very early in the logging Platform lifecycle without risking any static initialization issues.
Custom subclasses of MetadataKey which override either of the protected emit methods should take care to avoid calling any code which might trigger logging since this could lead to unexpected recusrion, especially if the key is being logged as part of a
ScopedLoggingContext. While there is protection against unbounded reentrant logging in Flogger, it is still best practice to avoid it where possible.
Metadata keys are passed to a log statement via the with() method, so it can aid readability to choose a name for the constant field which reads "fluently" as part of the log statement. For example:
// Prefer this...
logger.atInfo().with(FILE_LOGGING_FOR, user).log("User specific log message...");
// to...
logger.atInfo().with(SET_LOGGING_TO_USER_FILE, user).log("User specific log message...");
Logger backends can act upon metadata present in log statements to modify behavior. Any metadata entries that are not handled by a backend explicitly are, by default, rendered as part of the log statement in a default format.
Note that some metadata entries are handled before being processed by the backend (e.g. rate limiting), but a metadata entry remains present to record the that rate limiting was enabled.
See also
Original Java code of Google Flogger