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

          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.auto.value.AutoValue;
      18             : import com.google.common.base.MoreObjects;
      19             : import com.google.common.base.MoreObjects.ToStringHelper;
      20             : import com.google.common.collect.ImmutableList;
      21             : import com.google.common.flogger.LazyArg;
      22             : import com.google.common.flogger.LazyArgs;
      23             : import com.google.gerrit.common.Nullable;
      24             : import java.lang.reflect.InvocationTargetException;
      25             : import java.lang.reflect.Method;
      26             : import java.lang.reflect.Modifier;
      27             : import java.util.Arrays;
      28             : import java.util.Comparator;
      29             : import java.util.Optional;
      30             : 
      31             : /** Metadata that is provided to {@link PerformanceLogger}s as context for performance records. */
      32             : @AutoValue
      33         154 : public abstract class Metadata {
      34             :   /** The numeric ID of an account. */
      35             :   public abstract Optional<Integer> accountId();
      36             : 
      37             :   /**
      38             :    * The type of an action (ACCOUNT_UPDATE, CHANGE_UPDATE, GROUP_UPDATE, INDEX_QUERY,
      39             :    * PLUGIN_UPDATE).
      40             :    */
      41             :   public abstract Optional<String> actionType();
      42             : 
      43             :   /** An authentication domain name. */
      44             :   public abstract Optional<String> authDomainName();
      45             : 
      46             :   /** The name of a branch. */
      47             :   public abstract Optional<String> branchName();
      48             : 
      49             :   /** Key of an entity in a cache. */
      50             :   public abstract Optional<String> cacheKey();
      51             : 
      52             :   /** The name of a cache. */
      53             :   public abstract Optional<String> cacheName();
      54             : 
      55             :   /** The name of the implementation class. */
      56             :   public abstract Optional<String> className();
      57             : 
      58             :   /**
      59             :    * The reason of a request cancellation (CLIENT_CLOSED_REQUEST, CLIENT_PROVIDED_DEADLINE_EXCEEDED,
      60             :    * SERVER_DEADLINE_EXCEEDED).
      61             :    */
      62             :   public abstract Optional<String> cancellationReason();
      63             : 
      64             :   /** The numeric ID of a change. */
      65             :   public abstract Optional<Integer> changeId();
      66             : 
      67             :   /**
      68             :    * The type of change ID which the user used to identify a change (e.g. numeric ID, triplet etc.).
      69             :    */
      70             :   public abstract Optional<String> changeIdType();
      71             : 
      72             :   /** The cause of an error. */
      73             :   public abstract Optional<String> cause();
      74             : 
      75             :   /** Side where the comment is written: <= 0 for parent, 1 for revision. */
      76             :   public abstract Optional<Integer> commentSide();
      77             : 
      78             :   /** The SHA1 of a commit. */
      79             :   public abstract Optional<String> commit();
      80             : 
      81             :   /** Diff algorithm used in diff computation. */
      82             :   public abstract Optional<String> diffAlgorithm();
      83             : 
      84             :   /** The type of an event. */
      85             :   public abstract Optional<String> eventType();
      86             : 
      87             :   /** The value of the @Export annotation which was used to register a plugin extension. */
      88             :   public abstract Optional<String> exportValue();
      89             : 
      90             :   /** Path of a file in a repository. */
      91             :   public abstract Optional<String> filePath();
      92             : 
      93             :   /** Garbage collector name. */
      94             :   public abstract Optional<String> garbageCollectorName();
      95             : 
      96             :   /** Git operation (CLONE, FETCH). */
      97             :   public abstract Optional<String> gitOperation();
      98             : 
      99             :   /** The numeric ID of an internal group. */
     100             :   public abstract Optional<Integer> groupId();
     101             : 
     102             :   /** The name of a group. */
     103             :   public abstract Optional<String> groupName();
     104             : 
     105             :   /** The group system being queried. */
     106             :   public abstract Optional<String> groupSystem();
     107             : 
     108             :   /** The UUID of a group. */
     109             :   public abstract Optional<String> groupUuid();
     110             : 
     111             :   /** HTTP status response code. */
     112             :   public abstract Optional<Integer> httpStatus();
     113             : 
     114             :   /** The name of a secondary index. */
     115             :   public abstract Optional<String> indexName();
     116             : 
     117             :   /** The version of a secondary index. */
     118             :   public abstract Optional<Integer> indexVersion();
     119             : 
     120             :   /** The name of the implementation method. */
     121             :   public abstract Optional<String> memoryPoolName();
     122             : 
     123             :   /** The name of the implementation method. */
     124             :   public abstract Optional<String> methodName();
     125             : 
     126             :   /** One or more resources */
     127             :   public abstract Optional<Boolean> multiple();
     128             : 
     129             :   /** The name of an operation that is performed. */
     130             :   public abstract Optional<String> operationName();
     131             : 
     132             :   /** Partial or full computation */
     133             :   public abstract Optional<Boolean> partial();
     134             : 
     135             :   /** If a value is still current or not */
     136             :   public abstract Optional<Boolean> outdated();
     137             : 
     138             :   /** Path of a metadata file in NoteDb. */
     139             :   public abstract Optional<String> noteDbFilePath();
     140             : 
     141             :   /** Name of a metadata ref in NoteDb. */
     142             :   public abstract Optional<String> noteDbRefName();
     143             : 
     144             :   /** Type of a sequence in NoteDb (ACCOUNTS, CHANGES, GROUPS). */
     145             :   public abstract Optional<String> noteDbSequenceType();
     146             : 
     147             :   /** The ID of a patch set. */
     148             :   public abstract Optional<Integer> patchSetId();
     149             : 
     150             :   /** Plugin metadata that doesn't fit into any other category. */
     151             :   public abstract ImmutableList<PluginMetadata> pluginMetadata();
     152             : 
     153             :   /** The name of a plugin. */
     154             :   public abstract Optional<String> pluginName();
     155             : 
     156             :   /** The name of a Gerrit project (aka Git repository). */
     157             :   public abstract Optional<String> projectName();
     158             : 
     159             :   /** The type of a Git push to Gerrit (CREATE_REPLACE, NORMAL, AUTOCLOSE). */
     160             :   public abstract Optional<String> pushType();
     161             : 
     162             :   /** The type of a Git push to Gerrit (GIT_RECEIVE, GIT_UPLOAD, REST, SSH). */
     163             :   public abstract Optional<String> requestType();
     164             : 
     165             :   /** The number of resources that is processed. */
     166             :   public abstract Optional<Integer> resourceCount();
     167             : 
     168             :   /** The name of a REST view. */
     169             :   public abstract Optional<String> restViewName();
     170             : 
     171             :   public abstract Optional<String> submitRequirementName();
     172             : 
     173             :   /** The SHA1 of Git commit. */
     174             :   public abstract Optional<String> revision();
     175             : 
     176             :   /** The username of an account. */
     177             :   public abstract Optional<String> username();
     178             : 
     179             :   /**
     180             :    * Returns a string representation of this instance that is suitable for logging. This is wrapped
     181             :    * in a {@link LazyArg} because it is expensive to evaluate.
     182             :    *
     183             :    * <p>{@link #toString()} formats the {@link Optional} fields as {@code key=Optional[value]} or
     184             :    * {@code key=Optional.empty}. Since this class has many optional fields from which usually only a
     185             :    * few are populated this leads to long string representations such as
     186             :    *
     187             :    * <pre>
     188             :    * Metadata{accountId=Optional.empty, actionType=Optional.empty, authDomainName=Optional.empty,
     189             :    * branchName=Optional.empty, cacheKey=Optional.empty, cacheName=Optional.empty,
     190             :    * className=Optional.empty, cancellationReason=Optional.empty changeId=Optional[9212550],
     191             :    * changeIdType=Optional.empty, cause=Optional.empty, diffAlgorithm=Optional.empty,
     192             :    * eventType=Optional.empty, exportValue=Optional.empty, filePath=Optional.empty,
     193             :    * garbageCollectorName=Optional.empty, gitOperation=Optional.empty, groupId=Optional.empty,
     194             :    * groupName=Optional.empty, groupUuid=Optional.empty, httpStatus=Optional.empty,
     195             :    * indexName=Optional.empty, indexVersion=Optional[0], methodName=Optional.empty,
     196             :    * multiple=Optional.empty, operationName=Optional.empty, partial=Optional.empty,
     197             :    * noteDbFilePath=Optional.empty, noteDbRefName=Optional.empty,
     198             :    * noteDbSequenceType=Optional.empty, patchSetId=Optional.empty, pluginMetadata=[],
     199             :    * pluginName=Optional.empty, projectName=Optional.empty, pushType=Optional.empty,
     200             :    * requestType=Optional.empty, resourceCount=Optional.empty, restViewName=Optional.empty,
     201             :    * revision=Optional.empty, username=Optional.empty}
     202             :    * </pre>
     203             :    *
     204             :    * <p>That's hard to read in logs. This is why this method
     205             :    *
     206             :    * <ul>
     207             :    *   <li>drops fields which have {@code Optional.empty} as value and
     208             :    *   <li>reformats values that are {@code Optional[value]} to {@code value}.
     209             :    * </ul>
     210             :    *
     211             :    * <p>For the example given above the formatted string would look like this:
     212             :    *
     213             :    * <pre>
     214             :    * Metadata{changeId=9212550, indexVersion=0, pluginMetadata=[]}
     215             :    * </pre>
     216             :    *
     217             :    * @return string representation of this instance that is suitable for logging
     218             :    */
     219             :   LazyArg<String> toStringForLoggingLazy() {
     220             :     // Don't use a lambda because different compilers generate different method names for lambdas,
     221             :     // e.g. "lambda$myFunction$0" vs. just "lambda$0" in Eclipse. We need to identify the method
     222             :     // by name to skip it and avoid infinite recursion.
     223         154 :     return LazyArgs.lazy(this::toStringForLoggingImpl);
     224             :   }
     225             : 
     226             :   private String toStringForLoggingImpl() {
     227             :     // Append class name.
     228          30 :     String className = getClass().getSimpleName();
     229          30 :     if (className.startsWith("AutoValue_")) {
     230          30 :       className = className.substring(10);
     231             :     }
     232          30 :     ToStringHelper stringHelper = MoreObjects.toStringHelper(className);
     233             : 
     234             :     // Append key-value pairs for field which are set.
     235          30 :     Method[] methods = Metadata.class.getDeclaredMethods();
     236          30 :     Arrays.sort(methods, Comparator.comparing(Method::getName));
     237          30 :     for (Method method : methods) {
     238          30 :       if (Modifier.isStatic(method.getModifiers())) {
     239             :         // skip static method
     240          30 :         continue;
     241             :       }
     242             : 
     243          30 :       if (method.getName().equals("toStringForLoggingLazy")
     244          30 :           || method.getName().equals("toStringForLoggingImpl")) {
     245             :         // Don't call myself in infinite recursion.
     246          30 :         continue;
     247             :       }
     248             : 
     249          30 :       if (method.getReturnType().equals(Void.TYPE) || method.getParameterCount() > 0) {
     250             :         // skip method since it's not a getter
     251           0 :         continue;
     252             :       }
     253             : 
     254          30 :       method.setAccessible(true);
     255             : 
     256             :       Object returnValue;
     257             :       try {
     258          30 :         returnValue = method.invoke(this);
     259           0 :       } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
     260             :         // should never happen
     261           0 :         throw new IllegalStateException(e);
     262          30 :       }
     263             : 
     264          30 :       if (returnValue instanceof Optional) {
     265          30 :         Optional<?> fieldValueOptional = (Optional<?>) returnValue;
     266          30 :         if (!fieldValueOptional.isPresent()) {
     267             :           // drop this key-value pair
     268          30 :           continue;
     269             :         }
     270             : 
     271             :         // format as 'key=value' instead of 'key=Optional[value]'
     272          30 :         stringHelper.add(method.getName(), fieldValueOptional.get());
     273          30 :       } else {
     274             :         // not an Optional value, keep as is
     275          30 :         stringHelper.add(method.getName(), returnValue);
     276             :       }
     277             :     }
     278             : 
     279          30 :     return stringHelper.toString();
     280             :   }
     281             : 
     282             :   public static Metadata.Builder builder() {
     283         154 :     return new AutoValue_Metadata.Builder();
     284             :   }
     285             : 
     286             :   public static Metadata empty() {
     287         110 :     return builder().build();
     288             :   }
     289             : 
     290             :   @AutoValue.Builder
     291         154 :   public abstract static class Builder {
     292             :     public abstract Builder accountId(int accountId);
     293             : 
     294             :     public abstract Builder actionType(@Nullable String actionType);
     295             : 
     296             :     public abstract Builder authDomainName(@Nullable String authDomainName);
     297             : 
     298             :     public abstract Builder branchName(@Nullable String branchName);
     299             : 
     300             :     public abstract Builder cacheKey(@Nullable String cacheKey);
     301             : 
     302             :     public abstract Builder cacheName(@Nullable String cacheName);
     303             : 
     304             :     public abstract Builder className(@Nullable String className);
     305             : 
     306             :     public abstract Builder cancellationReason(@Nullable String cancellationReason);
     307             : 
     308             :     public abstract Builder changeId(int changeId);
     309             : 
     310             :     public abstract Builder changeIdType(@Nullable String changeIdType);
     311             : 
     312             :     public abstract Builder cause(@Nullable String cause);
     313             : 
     314             :     public abstract Builder commentSide(int side);
     315             : 
     316             :     public abstract Builder commit(@Nullable String commit);
     317             : 
     318             :     public abstract Builder diffAlgorithm(@Nullable String diffAlgorithm);
     319             : 
     320             :     public abstract Builder eventType(@Nullable String eventType);
     321             : 
     322             :     public abstract Builder exportValue(@Nullable String exportValue);
     323             : 
     324             :     public abstract Builder filePath(@Nullable String filePath);
     325             : 
     326             :     public abstract Builder garbageCollectorName(@Nullable String garbageCollectorName);
     327             : 
     328             :     public abstract Builder gitOperation(@Nullable String gitOperation);
     329             : 
     330             :     public abstract Builder groupId(int groupId);
     331             : 
     332             :     public abstract Builder groupName(@Nullable String groupName);
     333             : 
     334             :     public abstract Builder groupSystem(@Nullable String groupSystem);
     335             : 
     336             :     public abstract Builder groupUuid(@Nullable String groupUuid);
     337             : 
     338             :     public abstract Builder httpStatus(int httpStatus);
     339             : 
     340             :     public abstract Builder indexName(@Nullable String indexName);
     341             : 
     342             :     public abstract Builder indexVersion(int indexVersion);
     343             : 
     344             :     public abstract Builder memoryPoolName(@Nullable String memoryPoolName);
     345             : 
     346             :     public abstract Builder methodName(@Nullable String methodName);
     347             : 
     348             :     public abstract Builder multiple(boolean multiple);
     349             : 
     350             :     public abstract Builder operationName(String operationName);
     351             : 
     352             :     public abstract Builder partial(boolean partial);
     353             : 
     354             :     public abstract Builder outdated(boolean outdated);
     355             : 
     356             :     public abstract Builder noteDbFilePath(@Nullable String noteDbFilePath);
     357             : 
     358             :     public abstract Builder noteDbRefName(@Nullable String noteDbRefName);
     359             : 
     360             :     public abstract Builder noteDbSequenceType(@Nullable String noteDbSequenceType);
     361             : 
     362             :     public abstract Builder patchSetId(int patchSetId);
     363             : 
     364             :     abstract ImmutableList.Builder<PluginMetadata> pluginMetadataBuilder();
     365             : 
     366             :     public Builder addPluginMetadata(PluginMetadata pluginMetadata) {
     367           0 :       pluginMetadataBuilder().add(pluginMetadata);
     368           0 :       return this;
     369             :     }
     370             : 
     371             :     public abstract Builder pluginName(@Nullable String pluginName);
     372             : 
     373             :     public abstract Builder projectName(@Nullable String projectName);
     374             : 
     375             :     public abstract Builder pushType(@Nullable String pushType);
     376             : 
     377             :     public abstract Builder requestType(@Nullable String requestType);
     378             : 
     379             :     public abstract Builder resourceCount(int resourceCount);
     380             : 
     381             :     public abstract Builder restViewName(@Nullable String restViewName);
     382             : 
     383             :     public abstract Builder revision(@Nullable String revision);
     384             : 
     385             :     public abstract Builder submitRequirementName(@Nullable String srName);
     386             : 
     387             :     public abstract Builder username(@Nullable String username);
     388             : 
     389             :     public abstract Metadata build();
     390             :   }
     391             : }

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