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

commonMain.com.giancarlobuenaflor.kflogger.KMetadataKey.kt Maven / Gradle / Ivy

package com.giancarlobuenaflor.kflogger

/**
 * Callback interface to handle additional contextual `Metadata` in log statements. This interface
 * is only intended to be implemented by logger backend classes as part of handling metadata, and
 * should not be used in any general application code, other than to implement the
 * [KMetadataKey.emit] method in this class.
 */
public expect interface KMetadataKeyKeyValueHandler {
  /** Handle a single key/value pair of contextual metadata for a log statement. */
  public fun handle(key: String?, value: Any?)
}

/**
 * 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 [MetadataKey] 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 behaviour. 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 prior to being processed by the backend (e.g. rate * limiting), but a metadata entry remains present to record the fact that rate limiting was * enabled. */ public expect open class KMetadataKey { /* TODO /** * Constructor for custom key subclasses. Most use-cases will not require the use of custom keys, * but occasionally it can be useful to create a specific subtype to control the formatting of * values or to have a family of related keys with a common parent type. */ protected constructor(label: String, clazz: java.lang.Class, canRepeat: Boolean) : this( label, clazz, canRepeat, true )*/ /** Cast an arbitrary value to the type of this key. */ public fun cast(value: Any?): T /** Whether this key can be used to set more than one value in the metadata. */ public fun canRepeat(): Boolean /** * Emits one or more key/value pairs for the given metadata value. Call this method in preference * to using [.emitRepeated] directly to protect against unbounded reentrant logging. */ public fun safeEmit(value: T, kvh: KMetadataKeyKeyValueHandler) /** * Emits one or more key/value pairs for a sequence of repeated metadata values. Call this method * in preference to using [.emitRepeated] directly to protect against unbounded reentrant logging. */ public fun safeEmitRepeated(values: Iterator, kvh: KMetadataKeyKeyValueHandler) /** * Override this method to provide custom logic for emitting one or more key/value pairs for a * given metadata value (call [.safeEmit] from logging code to actually emit values). * * By default this method simply emits the given value with this key's label, but it can be * customized key/value pairs if necessary. * * Note that if multiple key/value pairs are emitted, the following best-practice should be * followed: * * Key names should be of the form `"




© 2015 - 2025 Weber Informatics LLC | Privacy Policy