rgoers opened a new pull request, #2438: URL: https://github.com/apache/logging-log4j2/pull/2438
This adds support for a ScopedContext and a ResourceLogger as requested in https://github.com/apache/logging-log4j-kotlin/issues/71 and similar to https://github.com/apache/logging-log4j2/discussions/2214 Support for running child threads and propagating the ThreadContext and ScopedContext was added. ThreadContext, ScopedContext, and custom ContextDataProviders can all be accessed via ContextData.getValue(key) in log4j-api. This necessitated moving ContextDataProvider support into the API. Example usage for wrapping a simple code block. ScopedContext.where("id", UUID.randomUUID()) .where("ipAddress", request.getRemoteAddr()) .where("loginId", session.getAttribute("loginId")) .where("hostName", request.getServerName()) .run(new Worker()); private class Worker implements Runnable { private static final Logger LOGGER = LogManager.getLogger(Worker.class); public void run() { LOGGER.debug("Performing work"); String loginId = ScopedContext.get("loginId"); } } Creating Threads: BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(5); ExecutorService executorService = new ThreadPoolExecutor(1, 2, 30, TimeUnit.SECONDS, workQueue); Future<?> future = ScopedContext.where("id", UUID.randomUUID()) .where("ipAddress", request.getRemoteAddr()) .where("loginId", session.getAttribute("loginId")) .where("hostName", request.getServerName()) .run(executorService, new Worker()); try { future.get(); } catch (ExecutionException ex) { logger.warn("Exception in worker thread: {}", ex.getMessage()); } Note that this syntax supports virtual threads. ResourceLogger can be used to include resource data in all log events coming from a specific Logger. private class User { private final String loginId; private final String role; private int loginAttempts; private final ResourceLogger logger; public User(final String loginId, final String role) { this.loginId = loginId; this.role = role; logger = ResourceLogger.newBuilder() .withClass(this.getClass()) .withSupplier(new UserSupplier()) .build(); } public void login() throws Exception { ++loginAttempts; try { authenticator.authenticate(loginId); logger.info("Login succeeded"); } catch (Exception ex) { logger.warn("Failed login"); throw ex; } } private class UserSupplier implements Supplier<Map<String, String>> { public Map<String, String> get() { Map<String, String> map = new HashMap<>(); map.put("LoginId", loginId); map.put("Role", role); map.put("Count", Integer.toString(loginAttempts)); return map; } } } Data from the UserSupplier will appear as context data in every log event that uses the Logger. ResourceLogger is able to do this by using a ScopedContext internally. Note that instead of ContextDataProviders returning their respective maps, the context map being constructed is now passed to each provider to add its own keys and values. This inherently makes building the context map garbage free, which was creating a spaghetti nightmare previously. With the move of ContextDataProvider to the API ContextDataInjectors are no longer needed. They are deprecated in this PR to be removed in 3.0.0. Note that with this PR they are never used unless a user specifies the system property to declare one. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
