post Process
A callback which can be overridden to implement post processing of logging contexts prior to passing them to the backend.
Basic Responsibilities
This method is responsible for:
- Performing any rate limiting operations specific to the extended API.
- Updating per log-site information (e.g. for debug metrics).
- Adding any additional metadata to this context.
- Returning whether logging should be attempted.
Implementations of this method must always call super.postProcess() first with the given log site key:
protected boolean postProcess(@Nullable LogSiteKey logSiteKey) {
boolean shouldLog = super.postProcess(logSiteKey);
// Handle rate limiting if present.
// Add additional metadata etc.
return shouldLog;
}Log Site Keys
If per log-site information is needed during post-processing, it should be stored using a LogSiteMap. This will correctly handle "specialized" log-site keys and remove the risk of memory leaks due to retaining unused log site data indefinitely.
Note that the given logSiteKey can be more specific than the LogSite of a log statement (i.e. a single log statement can have multiple distinct versions of its state). See per for more information.
If a log statement cannot be identified uniquely, then logSiteKey will be
null, and this method must behave exactly as if the corresponding fluent method had not been invoked. On a system in which log site information is unavailable:
logger.atInfo().every(100).withCause(e).log("Some message"); logger.atInfo().withCause(e).log("Some message"); Rate Limiting and Skipped Logs
When handling rate limiting, updateRateLimiterStatus should be called for each active rate limiter. This ensures that even if logging does not occur, the number of "skipped" log statements is recorded correctly and emitted for the next allowed log.
If postProcess() returns false without updating the rate limit status, the log statement may not be counted as skipped. In some situations this is desired, but either way the extended logging API should make it clear to the user (via documentation) what will happen. However in most cases postProcess() is only expected to return false due to rate limiting.
If rate limiters are used there are still situations in which postProcess() can return true, but logging will not occur. This is due to race conditions around the resetting of rate limiter state. A postProcess() method can "early exit" as soon as shouldLog is false, but should assume logging will occur while it remains true.
If a method in the logging chain determines that logging should definitely not occur, it may choose to return the NoOp logging API at that point. However this will bypass any post-processing, and no rate limiter state will be updated. This is sometimes desirable, but the API documentation should make it clear to the user as to which behaviour occurs.
For example, level selector methods (such as atInfo()) return the NoOp API for "disabled" log statements, and these have no effect on rate limiter state, and will not update the "skipped" count. This is fine because controlling logging via log level selection is not conceptually a form of "rate limiting".
The default implementation of this method enforces the rate limits as set by every and atMostEvery.
Return
true if logging should be attempted (usually based on rate limiter state).
Parameters
used to lookup persistent, per log statement, state.