-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First cut of new public API for scoped log contexts.
This is designed to work with gRPC context (which should allow it to work in and outside Google) but it would not be directly compatible with TraceLoggingContext, so there'll need to be a bit of a migration and probably a parallel running period. RELNOTES=Adding initial common API for per-request logging configuration support (implementation to follow). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=283435398
- Loading branch information
Showing
15 changed files
with
2,052 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
api/src/main/java/com/google/common/flogger/context/ContextDataProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright (C) 2019 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.context; | ||
|
||
import static com.google.common.flogger.util.StaticMethodCaller.callGetterFromSystemProperty; | ||
|
||
import java.util.logging.Level; | ||
|
||
/** | ||
* An API for injecting scoped metadata for log statements (either globally or on a per-request | ||
* basis). This class is intended for subclassing by the logging context implementation, which can | ||
* then be installed into fluent loggers by setting the {@code "flogger.context"} system property. | ||
* Thiis class is not a public API and should never need to be invoked directly by application code. | ||
* | ||
* <p>Note that since this class (and any installed implementation sub-class) is loaded when the | ||
* logging platform is loaded, care must be taken to avoid cyclic references during static | ||
* initialisation. This means that no static fields or static initialization can reference fluent | ||
* loggers or the logging platform (either directly or indirectly). | ||
*/ | ||
public abstract class ContextDataProvider { | ||
// Visible only for the no-op implementation. | ||
static final String CONTEXT_PROVIDER_PROPERTY = "flogger.context"; | ||
|
||
/** | ||
* Returns the singleton instance of the context data provider for use by logging platform | ||
* implementations. This method should not be called by general application code, and the {@code | ||
* ContextDataProvider} class should never need to be used directly outside of fluent logger | ||
* platform implementations. | ||
*/ | ||
public static ContextDataProvider getInstance() { | ||
return LazyHolder.INSTANCE; | ||
} | ||
|
||
/** | ||
* Returns the context API with which users can create and modify the state of logging contexts | ||
* within an application. This method should be overridden by subclasses to provide the specific | ||
* implementation of the API. | ||
* | ||
* <p>This method should never be called directly (other than in tests) and users should always go | ||
* via {@link ScopedLoggingContext#getInstance}, without needing to reference this class at all. | ||
* | ||
* <p>If an implementation wishes to allow logging from the context API class, that class must be | ||
* lazily loaded when this method is called (e.g. using a "lazy holder"). Failure to do so is | ||
* likely to result in errors during the initialization of the logging platform classes. | ||
*/ | ||
public abstract ScopedLoggingContext getContextApiSingleton(); | ||
|
||
/** | ||
* Returns whether the given logger should have logging forced at the specified level. When | ||
* logging is forced for a log statement it will be emitted regardless or the normal log level | ||
* configuration of the logger and ignoring any rate limiting or other filtering. | ||
* | ||
* <p>Implementations which do not support forcing logging should return {@code false}. | ||
* | ||
* <p>{@code loggerName} can be used to look up specific configuration, such as log level, for the | ||
* logger, to decide if a log statement should be forced. This information might vary depending on | ||
* the context in which this call is made, so the result should not be cached. | ||
* | ||
* <p>{@code isEnabledByLevel} indicates that the log statement is enabled according to its log | ||
* level, but a {@code true} value does not necessarily indicate that logging will occur, due to | ||
* rate limiting or other conditional logging mechanisms. To bypass conditional logging and ensure | ||
* that an enabled log statement will be emitted, this method should return {@code true} if {@code | ||
* isEnabledByLevel} was {@code true}. | ||
* | ||
* <p>WARNING: This method MUST complete quickly and without allocating any memory. It is invoked | ||
* for every log statement regardless of logging configuration, so any implementation must go to | ||
* every possible length to be efficient. | ||
* | ||
* @param loggerName the fully qualified logger name (e.g. "com.example.SomeClass") | ||
* @param level the level of the log statement being invoked | ||
* @param isEnabledByLevel whether the logger is enabled at the given level | ||
*/ | ||
public abstract boolean shouldForceLogging( | ||
String loggerName, Level level, boolean isEnabledByLevel); | ||
|
||
/** | ||
* Returns a set of tags to be added to a log statement. These tags can be used to provide | ||
* additional contextual metadata to log statements (e.g. request IDs). | ||
* | ||
* <p>Implementations which do not support {@link Tags} should return {@code Tags.empty()}. | ||
*/ | ||
public Tags getTags() { | ||
return Tags.empty(); | ||
} | ||
|
||
private static final class LazyHolder { | ||
private static final ContextDataProvider INSTANCE = loadContext(); | ||
|
||
private static ContextDataProvider loadContext() { | ||
ContextDataProvider ctx = | ||
callGetterFromSystemProperty(CONTEXT_PROVIDER_PROPERTY, ContextDataProvider.class); | ||
return ctx != null ? ctx : new NoOpContextDataProvider(); | ||
} | ||
} | ||
} |
Oops, something went wrong.