LCOV - code coverage report
Current view: top level - server/logging - LoggingContextAwareCallable.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 22 24 91.7 %
Date: 2022-11-19 15:00:39 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2018 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.logging;
      16             : 
      17             : import com.google.common.collect.ImmutableSetMultimap;
      18             : import com.google.common.flogger.FluentLogger;
      19             : import java.util.concurrent.Callable;
      20             : 
      21             : /**
      22             :  * Wrapper for a {@link Callable} that copies the {@link LoggingContext} from the current thread to
      23             :  * the thread that executes the callable.
      24             :  *
      25             :  * <p>The state of the logging context that is copied to the thread that executes the callable is
      26             :  * fixed at the creation time of this wrapper. If the callable is submitted to an executor and is
      27             :  * executed later this means that changes that are done to the logging context in between creating
      28             :  * and executing the callable do not apply.
      29             :  *
      30             :  * <p>See {@link LoggingContextAwareRunnable} for an example.
      31             :  *
      32             :  * @see LoggingContextAwareRunnable
      33             :  */
      34             : class LoggingContextAwareCallable<T> implements Callable<T> {
      35          87 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      36             : 
      37             :   private final Callable<T> callable;
      38             :   private final Thread callingThread;
      39             :   private final ImmutableSetMultimap<String, String> tags;
      40             :   private final boolean forceLogging;
      41             :   private final boolean performanceLogging;
      42             :   private final MutablePerformanceLogRecords mutablePerformanceLogRecords;
      43             :   private final boolean aclLogging;
      44             :   private final MutableAclLogRecords mutableAclLogRecords;
      45             : 
      46             :   /**
      47             :    * Creates a LoggingContextAwareCallable that wraps the given {@link Callable}.
      48             :    *
      49             :    * @param callable Callable that should be wrapped.
      50             :    * @param mutablePerformanceLogRecords instance of {@link MutablePerformanceLogRecords} to which
      51             :    *     performance log records that are created from the runnable are added
      52             :    * @param mutableAclLogRecords instance of {@link MutableAclLogRecords} to which ACL log records
      53             :    *     that are created from the runnable are added
      54             :    */
      55             :   LoggingContextAwareCallable(
      56             :       Callable<T> callable,
      57             :       MutablePerformanceLogRecords mutablePerformanceLogRecords,
      58          87 :       MutableAclLogRecords mutableAclLogRecords) {
      59          87 :     this.callable = callable;
      60          87 :     this.callingThread = Thread.currentThread();
      61          87 :     this.tags = LoggingContext.getInstance().getTagsAsMap();
      62          87 :     this.forceLogging = LoggingContext.getInstance().isLoggingForced();
      63          87 :     this.performanceLogging = LoggingContext.getInstance().isPerformanceLogging();
      64          87 :     this.mutablePerformanceLogRecords = mutablePerformanceLogRecords;
      65          87 :     this.aclLogging = LoggingContext.getInstance().isAclLogging();
      66          87 :     this.mutableAclLogRecords = mutableAclLogRecords;
      67          87 :   }
      68             : 
      69             :   @Override
      70             :   public T call() throws Exception {
      71          87 :     if (callingThread.equals(Thread.currentThread())) {
      72             :       // propagation of logging context is not needed
      73           0 :       return callable.call();
      74             :     }
      75             : 
      76          87 :     LoggingContext loggingCtx = LoggingContext.getInstance();
      77             : 
      78          87 :     if (!loggingCtx.isEmpty()) {
      79           0 :       logger.atWarning().log("Logging context is not empty: %s", loggingCtx);
      80             :     }
      81             : 
      82             :     // propagate logging context
      83          87 :     loggingCtx.setTags(tags);
      84          87 :     loggingCtx.forceLogging(forceLogging);
      85          87 :     loggingCtx.performanceLogging(performanceLogging);
      86          87 :     loggingCtx.setMutablePerformanceLogRecords(mutablePerformanceLogRecords);
      87          87 :     loggingCtx.aclLogging(aclLogging);
      88          87 :     loggingCtx.setMutableAclLogRecords(mutableAclLogRecords);
      89             :     try {
      90          87 :       return callable.call();
      91             :     } finally {
      92             :       // Cleanup logging context. This is important if the thread is pooled and reused.
      93          87 :       loggingCtx.clear();
      94             :     }
      95             :   }
      96             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750