LCOV - code coverage report
Current view: top level - server - ExceptionHook.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 3 8 37.5 %
Date: 2022-11-19 15:00:39 Functions: 2 7 28.6 %

          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;
      16             : 
      17             : import static java.util.Objects.requireNonNull;
      18             : 
      19             : import com.google.auto.value.AutoValue;
      20             : import com.google.common.collect.ImmutableList;
      21             : import com.google.gerrit.common.Nullable;
      22             : import com.google.gerrit.extensions.annotations.ExtensionPoint;
      23             : import java.util.Optional;
      24             : 
      25             : /**
      26             :  * Allows implementors to control how certain exceptions should be handled.
      27             :  *
      28             :  * <p>This interface is intended to be implemented for cluster setups with multiple primary nodes to
      29             :  * control the behavior for handling exceptions that are thrown by a lower layer that handles the
      30             :  * consensus and synchronization between different server nodes. E.g. if an operation fails because
      31             :  * consensus for a Git update could not be achieved (e.g. due to slow responding server nodes) this
      32             :  * interface can be used to retry the request instead of failing it immediately.
      33             :  */
      34             : @ExtensionPoint
      35             : public interface ExceptionHook {
      36             :   /**
      37             :    * Whether an operation should be retried if it failed with the given throwable.
      38             :    *
      39             :    * <p>Only affects operations that are executed with {@link
      40             :    * com.google.gerrit.server.update.RetryHelper}.
      41             :    *
      42             :    * <p>Should return {@code true} only for exceptions that are caused by temporary issues where a
      43             :    * retry of the operation has a chance to succeed.
      44             :    *
      45             :    * <p>If {@code false} is returned the operation is still retried once to capture a trace, unless
      46             :    * {@link #skipRetryWithTrace(String, String, Throwable)} skips the auto-retry.
      47             :    *
      48             :    * <p>If multiple exception hooks are registered, the operation is retried if any of them returns
      49             :    * {@code true} from this method.
      50             :    *
      51             :    * @param throwable throwable that was thrown while executing the operation
      52             :    * @param actionType the type of the action for which the exception occurred
      53             :    * @param actionName the name of the action for which the exception occurred
      54             :    * @return whether the operation should be retried
      55             :    */
      56             :   default boolean shouldRetry(String actionType, String actionName, Throwable throwable) {
      57           0 :     return false;
      58             :   }
      59             : 
      60             :   /**
      61             :    * Whether auto-retrying of an operation with tracing should be skipped for the given throwable.
      62             :    *
      63             :    * <p>Only affects operations that are executed with {@link
      64             :    * com.google.gerrit.server.update.RetryHelper}.
      65             :    *
      66             :    * <p>This method is only called for exceptions for which the operation should not be retried
      67             :    * ({@link #shouldRetry(String, String, Throwable)} returned {@code false}).
      68             :    *
      69             :    * <p>By default this method returns {@code false}, so that by default traces for unexpected
      70             :    * exceptions are captured, which allows to investigate them.
      71             :    *
      72             :    * <p>Implementors may use this method to skip retry with tracing for exceptions that occur due to
      73             :    * known causes that are permanent and where a trace is not needed for the investigation. For
      74             :    * example, if an operation fails because persisted data is corrupt, it makes no sense to retry
      75             :    * the operation with a trace, because the trace will not help with fixing the corrupt data.
      76             :    *
      77             :    * <p>This method is only invoked if retry with tracing is enabled on the server ({@code
      78             :    * retry.retryWithTraceOnFailure} in {@code gerrit.config} is set to {@code true}).
      79             :    *
      80             :    * <p>If multiple exception hooks are registered, retrying with tracing is skipped if any of them
      81             :    * returns {@code true} from this method.
      82             :    *
      83             :    * @param throwable throwable that was thrown while executing the operation
      84             :    * @param actionType the type of the action for which the exception occurred
      85             :    * @param actionName the name of the action for which the exception occurred
      86             :    * @return whether auto-retrying of an operation with tracing should be skipped for the given
      87             :    *     throwable
      88             :    */
      89             :   default boolean skipRetryWithTrace(String actionType, String actionName, Throwable throwable) {
      90           0 :     return false;
      91             :   }
      92             : 
      93             :   /**
      94             :    * Formats the cause of an exception for use in metrics.
      95             :    *
      96             :    * <p>This method allows implementors to group exceptions that have the same cause into one metric
      97             :    * bucket.
      98             :    *
      99             :    * <p>If multiple exception hooks return a value from this method, the value from the exception
     100             :    * hook that is registered first is used.
     101             :    *
     102             :    * @param throwable the exception cause
     103             :    * @return formatted cause or {@link Optional#empty()} if no formatting was done
     104             :    */
     105             :   default Optional<String> formatCause(Throwable throwable) {
     106           0 :     return Optional.empty();
     107             :   }
     108             : 
     109             :   /**
     110             :    * Returns messages that should be returned to the user.
     111             :    *
     112             :    * <p>These messages are included into the HTTP response that is sent to the user.
     113             :    *
     114             :    * <p>If multiple exception hooks return a value from this method, all the values are included
     115             :    * into the HTTP response (in the order in which the exception hooks are registered).
     116             :    *
     117             :    * @param throwable throwable that was thrown while executing an operation
     118             :    * @param traceId ID of the trace if this request was traced, otherwise {@code null}
     119             :    * @return error messages that should be returned to the user, {@link Optional#empty()} if no
     120             :    *     message should be returned to the user
     121             :    */
     122             :   default ImmutableList<String> getUserMessages(Throwable throwable, @Nullable String traceId) {
     123           0 :     return ImmutableList.of();
     124             :   }
     125             : 
     126             :   /**
     127             :    * Returns the HTTP status that should be returned to the user.
     128             :    *
     129             :    * <p>Implementors may use this method to change the status for certain exceptions (e.g. using
     130             :    * this method it would be possible to return {@code 503 Lock failure} for {@link
     131             :    * com.google.gerrit.git.LockFailureException}s instead of {@code 500 Internal server error}).
     132             :    *
     133             :    * <p>If no value is returned ({@link Optional#empty()}) it means that this exception hook doesn't
     134             :    * want to change the default response code for the given exception which is {@code 500 Internal
     135             :    * Server Error}, but is fine if other exception hook implementation do so.
     136             :    *
     137             :    * <p>If multiple exception hooks return a value from this method, the value from exception hook
     138             :    * that is registered first is used.
     139             :    *
     140             :    * <p>{@link #getUserMessages(Throwable, String)} allows to define which additional messages
     141             :    * should be included into the body of the HTTP response.
     142             :    *
     143             :    * @param throwable throwable that was thrown while executing an operation
     144             :    * @return HTTP status that should be returned to the user, {@link Optional#empty()} if the
     145             :    *     exception should result in {@code 500 Internal Server Error}
     146             :    */
     147             :   default Optional<Status> getStatus(Throwable throwable) {
     148           0 :     return Optional.empty();
     149             :   }
     150             : 
     151             :   @AutoValue
     152           1 :   public abstract class Status {
     153             :     public abstract int statusCode();
     154             : 
     155             :     public abstract String statusMessage();
     156             : 
     157             :     public static Status create(int statusCode, String statusMessage) {
     158           1 :       return new AutoValue_ExceptionHook_Status(
     159           1 :           statusCode, requireNonNull(statusMessage, "statusMessage"));
     160             :     }
     161             :   }
     162             : }

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