LCOV - code coverage report
Current view: top level - server/logging - PerformanceLogContext.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 26 29 89.7 %
Date: 2022-11-19 15:00:39 Functions: 7 7 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2019 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.ImmutableList;
      18             : import com.google.common.collect.Iterables;
      19             : import com.google.common.flogger.FluentLogger;
      20             : import com.google.gerrit.extensions.registration.DynamicSet;
      21             : import com.google.gerrit.extensions.registration.Extension;
      22             : import org.eclipse.jgit.lib.Config;
      23             : 
      24             : /**
      25             :  * Context for capturing performance log records. When the context is closed the performance log
      26             :  * records are handed over to the registered {@link PerformanceLogger}s.
      27             :  *
      28             :  * <p>Capturing performance log records is disabled if there are no {@link PerformanceLogger}
      29             :  * registered (in this case the captured performance log records would never be used).
      30             :  *
      31             :  * <p>It's important to enable capturing of performance log records in a context that ensures to
      32             :  * consume the captured performance log records. Otherwise captured performance log records might
      33             :  * leak into other requests that are executed by the same thread (if a thread pool is used to
      34             :  * process requests).
      35             :  */
      36             : public class PerformanceLogContext implements AutoCloseable {
      37         105 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      38             : 
      39             :   // Do not use PluginSetContext. PluginSetContext traces the plugin latency with a timer metric
      40             :   // which would result in a performance log and we don't want to log the performance of writing
      41             :   // a performance log in the performance log (endless loop).
      42             :   private final DynamicSet<PerformanceLogger> performanceLoggers;
      43             : 
      44             :   private final boolean oldPerformanceLogging;
      45             :   private final ImmutableList<PerformanceLogRecord> oldPerformanceLogRecords;
      46             : 
      47             :   public PerformanceLogContext(
      48         105 :       Config gerritConfig, DynamicSet<PerformanceLogger> performanceLoggers) {
      49         105 :     this.performanceLoggers = performanceLoggers;
      50             : 
      51             :     // Just in case remember the old state and reset performance log entries.
      52         105 :     this.oldPerformanceLogging = LoggingContext.getInstance().isPerformanceLogging();
      53         105 :     this.oldPerformanceLogRecords = LoggingContext.getInstance().getPerformanceLogRecords();
      54         105 :     LoggingContext.getInstance().clearPerformanceLogEntries();
      55             : 
      56             :     // Do not create performance log entries if performance logging is disabled or if no
      57             :     // PerformanceLogger is registered.
      58         105 :     boolean enablePerformanceLogging =
      59         105 :         gerritConfig.getBoolean("tracing", "performanceLogging", false);
      60         105 :     LoggingContext.getInstance()
      61         105 :         .performanceLogging(
      62         105 :             enablePerformanceLogging && !Iterables.isEmpty(performanceLoggers.entries()));
      63         105 :   }
      64             : 
      65             :   @Override
      66             :   public void close() {
      67         105 :     if (LoggingContext.getInstance().isPerformanceLogging()) {
      68           3 :       runEach(performanceLoggers, LoggingContext.getInstance().getPerformanceLogRecords());
      69             :     }
      70             : 
      71             :     // Restore old state. Required to support nesting of PerformanceLogContext's.
      72         105 :     LoggingContext.getInstance().performanceLogging(oldPerformanceLogging);
      73         105 :     LoggingContext.getInstance().setPerformanceLogRecords(oldPerformanceLogRecords);
      74         105 :   }
      75             : 
      76             :   /**
      77             :    * Invokes all performance loggers.
      78             :    *
      79             :    * <p>Similar to how {@code com.google.gerrit.server.plugincontext.PluginContext} invokes plugins
      80             :    * but without recording metrics for invoking {@link PerformanceLogger}s.
      81             :    *
      82             :    * @param performanceLoggers the performance loggers that should be invoked
      83             :    * @param performanceLogRecords the performance log records that should be handed over to the
      84             :    *     performance loggers
      85             :    */
      86             :   private static void runEach(
      87             :       DynamicSet<PerformanceLogger> performanceLoggers,
      88             :       ImmutableList<PerformanceLogRecord> performanceLogRecords) {
      89           3 :     performanceLoggers
      90           3 :         .entries()
      91           3 :         .forEach(
      92             :             p -> {
      93           3 :               try (TraceContext traceContext = newPluginTrace(p)) {
      94           3 :                 performanceLogRecords.forEach(r -> r.writeTo(p.get()));
      95           0 :               } catch (RuntimeException e) {
      96           0 :                 logger.atWarning().withCause(e).log(
      97           0 :                     "Failure in %s of plugin %s", p.get().getClass(), p.getPluginName());
      98           3 :               }
      99           3 :             });
     100           3 :   }
     101             : 
     102             :   /**
     103             :    * Opens a trace context for a plugin that implements {@link PerformanceLogger}.
     104             :    *
     105             :    * <p>Basically the same as {@code
     106             :    * com.google.gerrit.server.plugincontext.PluginContext#newTrace(Extension<T>)}. We have this
     107             :    * method here to avoid a dependency on PluginContext which lives in
     108             :    * "//java/com/google/gerrit/server". This package ("//java/com/google/gerrit/server/logging")
     109             :    * should have as few dependencies as possible.
     110             :    *
     111             :    * @param extension performance logger extension
     112             :    * @return the trace context
     113             :    */
     114             :   private static TraceContext newPluginTrace(Extension<PerformanceLogger> extension) {
     115           3 :     return TraceContext.open().addPluginTag(extension.getPluginName());
     116             :   }
     117             : }

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