// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.plugincontext;

import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.Extension;
import com.google.gerrit.metrics.Counter3;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.DisabledMetricMaker;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer3;
import com.google.gerrit.server.cancellation.RequestCancelledException;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.inject.Inject;
import com.google.inject.Singleton;

/**
 * Context for invoking plugin extensions.
 *
 * <p>Invoking a plugin extension through a PluginContext sets a logging tag with the plugin name is
 * set. This way any errors that are triggered by the plugin extension (even if they happen in
 * Gerrit code which is called by the plugin extension) can be easily attributed to the plugin.
 *
 * <p>If possible plugin extensions should be invoked through:
 *
 * <ul>
 *   <li>{@link PluginItemContext} for extensions from {@link DynamicItem}
 *   <li>{@link PluginSetContext} for extensions from {@link DynamicSet}
 *   <li>{@link PluginMapContext} for extensions from {@link DynamicMap}
 * </ul>
 *
 * <p>A plugin context can be manually opened by invoking the newTrace methods. This should only be
 * needed if an extension throws multiple exceptions that need to be handled:
 *
 * <pre>{@code
 * public interface Foo {
 *   void doFoo() throws Exception1, Exception2, Exception3;
 * }
 *
 * ...
 *
 * for (Extension<Foo> fooExtension : fooDynamicMap) {
 *   try (TraceContext traceContext = PluginContext.newTrace(fooExtension)) {
 *     fooExtension.get().doFoo();
 *   }
 * }
 * }</pre>
 *
 * <p>This class hosts static methods with generic functionality to invoke plugin extensions with a
 * trace context that are commonly used by {@link PluginItemContext}, {@link PluginSetContext} and
 * {@link PluginMapContext}.
 *
 * <p>The run* methods execute an extension but don't deliver a result back to the caller.
 * Exceptions can be caught and logged.
 *
 * <p>The call* methods execute an extension and deliver a result back to the caller.
 */
public class PluginContext<T> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @FunctionalInterface
  public interface ExtensionImplConsumer<T> {
    void run(T t) throws Exception;
  }

  @FunctionalInterface
  public interface ExtensionImplFunction<T, R> {
    R call(T input);
  }

  @FunctionalInterface
  public interface CheckedExtensionImplFunction<T, R, X extends Exception> {
    R call(T input) throws X;
  }

  @FunctionalInterface
  public interface ExtensionConsumer<T extends Extension<?>> {
    void run(T extension) throws Exception;
  }

  @FunctionalInterface
  public interface ExtensionFunction<T extends Extension<?>, R> {
    R call(T extension);
  }

  @FunctionalInterface
  public interface CheckedExtensionFunction<T extends Extension<?>, R, X extends Exception> {
    R call(T extension) throws X;
  }

  @Singleton
  public static class PluginMetrics {
    public static final PluginMetrics DISABLED_INSTANCE =
        new PluginMetrics(new DisabledMetricMaker());

    final Timer3<String, String, String> latency;
    final Counter3<String, String, String> errorCount;

    @Inject
    PluginMetrics(MetricMaker metricMaker) {
      Field<String> pluginNameField =
          Field.ofString("plugin_name", Metadata.Builder::pluginName)
              .description("The name of the plugin.")
              .build();
      Field<String> classNameField =
          Field.ofString("class_name", Metadata.Builder::className)
              .description("The class of the plugin that was invoked.")
              .build();
      Field<String> exportValueField =
          Field.ofString("export_value", Metadata.Builder::exportValue)
              .description("The export name under which the invoked class is registered.")
              .build();

      this.latency =
          metricMaker.newTimer(
              "plugin/latency",
              new Description("Latency for plugin invocation")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS),
              pluginNameField,
              classNameField,
              exportValueField);
      this.errorCount =
          metricMaker.newCounter(
              "plugin/error_count",
              new Description("Number of plugin errors").setCumulative().setUnit("errors"),
              pluginNameField,
              classNameField,
              exportValueField);
    }

    Timer3.Context<String, String, String> startLatency(Extension<?> extension) {
      return latency.start(
          extension.getPluginName(),
          extension.get().getClass().getName(),
          Strings.nullToEmpty(extension.getExportName()));
    }

    void incrementErrorCount(Extension<?> extension) {
      errorCount.increment(
          extension.getPluginName(),
          extension.get().getClass().getName(),
          Strings.nullToEmpty(extension.getExportName()));
    }
  }

  /**
   * Opens a new trace context for invoking a plugin extension.
   *
   * @param dynamicItem dynamic item that holds the extension implementation that is being invoked
   *     from within the trace context
   * @return the created trace context
   */
  public static <T> TraceContext newTrace(DynamicItem<T> dynamicItem) {
    Extension<T> extension = dynamicItem.getEntry();
    if (extension == null) {
      return TraceContext.open();
    }
    return newTrace(extension);
  }

  /**
   * Opens a new trace context for invoking a plugin extension.
   *
   * @param extension extension that is being invoked from within the trace context
   * @return the created trace context
   */
  public static <T> TraceContext newTrace(Extension<T> extension) {
    return TraceContext.open().addPluginTag(requireNonNull(extension).getPluginName());
  }

  /**
   * Runs a plugin extension. All exceptions from the plugin extension are caught and logged (except
   * {@link RequestCancelledException}.
   *
   * <p>The consumer gets the extension implementation provided that should be invoked.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param extensionImplConsumer the consumer that invokes the extension
   */
  static <T> void runLogExceptions(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      ExtensionImplConsumer<T> extensionImplConsumer) {
    T extensionImpl = extension.get();
    if (extensionImpl == null) {
      return;
    }
    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      extensionImplConsumer.run(extensionImpl);
    } catch (Exception e) {
      Throwables.throwIfInstanceOf(e, RequestCancelledException.class);
      pluginMetrics.incrementErrorCount(extension);
      logger.atWarning().withCause(e).log(
          "Failure in %s of plugin %s", extensionImpl.getClass(), extension.getPluginName());
    }
  }

  /**
   * Runs a plugin extension. All exceptions from the plugin extension are caught and logged (except
   * {@link RequestCancelledException}.
   *
   * <p>The consumer get the {@link Extension} provided that should be invoked. The extension
   * provides access to the plugin name and the export name.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param extensionConsumer the consumer that invokes the extension
   */
  static <T> void runLogExceptions(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      ExtensionConsumer<Extension<T>> extensionConsumer) {
    T extensionImpl = extension.get();
    if (extensionImpl == null) {
      return;
    }

    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      extensionConsumer.run(extension);
    } catch (Exception e) {
      Throwables.throwIfInstanceOf(e, RequestCancelledException.class);
      pluginMetrics.incrementErrorCount(extension);
      logger.atWarning().withCause(e).log(
          "Failure in %s of plugin %s", extensionImpl.getClass(), extension.getPluginName());
    }
  }

  /**
   * Runs a plugin extension. All exceptions from the plugin extension except exceptions of the
   * specified type are caught and logged. Exceptions of the specified type are thrown and must be
   * handled by the caller.
   *
   * <p>The consumer gets the extension implementation provided that should be invoked.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param extensionImplConsumer the consumer that invokes the extension
   * @param exceptionClass type of the exceptions that should be thrown
   * @throws X expected exception from the plugin extension
   */
  static <T, X extends Exception> void runLogExceptions(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      ExtensionImplConsumer<T> extensionImplConsumer,
      Class<X> exceptionClass)
      throws X {
    T extensionImpl = extension.get();
    if (extensionImpl == null) {
      return;
    }

    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      extensionImplConsumer.run(extensionImpl);
    } catch (Exception e) {
      Throwables.throwIfInstanceOf(e, exceptionClass);
      Throwables.throwIfUnchecked(e);
      pluginMetrics.incrementErrorCount(extension);
      logger.atWarning().withCause(e).log(
          "Failure in %s of plugin %s", extensionImpl.getClass(), extension.getPluginName());
    }
  }

  /**
   * Runs a plugin extension. All exceptions from the plugin extension except exceptions of the
   * specified type are caught and logged. Exceptions of the specified type are thrown and must be
   * handled by the caller.
   *
   * <p>The consumer get the {@link Extension} provided that should be invoked. The extension
   * provides access to the plugin name and the export name.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param extensionConsumer the consumer that invokes the extension
   * @param exceptionClass type of the exceptions that should be thrown
   * @throws X expected exception from the plugin extension
   */
  static <T, X extends Exception> void runLogExceptions(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      ExtensionConsumer<Extension<T>> extensionConsumer,
      Class<X> exceptionClass)
      throws X {
    T extensionImpl = extension.get();
    if (extensionImpl == null) {
      return;
    }

    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      extensionConsumer.run(extension);
    } catch (Exception e) {
      Throwables.throwIfInstanceOf(e, exceptionClass);
      Throwables.throwIfUnchecked(e);
      pluginMetrics.incrementErrorCount(extension);
      logger.atWarning().withCause(e).log(
          "Failure in %s of plugin %s", extensionImpl.getClass(), extension.getPluginName());
    }
  }

  /**
   * Calls a plugin extension and returns the result from the plugin extension call.
   *
   * <p>The function gets the extension implementation provided that should be invoked.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param extensionImplFunction function that invokes the extension
   * @return the result from the plugin extension
   */
  static <T, R> R call(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      ExtensionImplFunction<T, R> extensionImplFunction) {
    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      return extensionImplFunction.call(extension.get());
    }
  }

  /**
   * Calls a plugin extension and returns the result from the plugin extension call. Exceptions of
   * the specified type are thrown and must be handled by the caller.
   *
   * <p>The function gets the extension implementation provided that should be invoked.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param checkedExtensionImplFunction function that invokes the extension
   * @param exceptionClass type of the exceptions that should be thrown
   * @return the result from the plugin extension
   * @throws X expected exception from the plugin extension
   */
  static <T, R, X extends Exception> R call(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      CheckedExtensionImplFunction<T, R, X> checkedExtensionImplFunction,
      Class<X> exceptionClass)
      throws X {
    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      try {
        return checkedExtensionImplFunction.call(extension.get());
      } catch (Exception e) {
        // The only exception that can be thrown is X, but we cannot catch X since it is a generic
        // type.
        Throwables.throwIfInstanceOf(e, exceptionClass);
        Throwables.throwIfUnchecked(e);
        throw new IllegalStateException("unexpected exception: " + e.getMessage(), e);
      }
    }
  }

  /**
   * Calls a plugin extension and returns the result from the plugin extension call.
   *
   * <p>The function get the {@link Extension} provided that should be invoked. The extension
   * provides access to the plugin name and the export name.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param extensionFunction function that invokes the extension
   * @return the result from the plugin extension
   */
  static <T, R> R call(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      ExtensionFunction<Extension<T>, R> extensionFunction) {
    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      return extensionFunction.call(extension);
    }
  }

  /**
   * Calls a plugin extension and returns the result from the plugin extension call. Exceptions of
   * the specified type are thrown and must be handled by the caller.
   *
   * <p>The function get the {@link Extension} provided that should be invoked. The extension
   * provides access to the plugin name and the export name.
   *
   * @param pluginMetrics the plugin metrics
   * @param extension extension that is being invoked
   * @param checkedExtensionFunction function that invokes the extension
   * @param exceptionClass type of the exceptions that should be thrown
   * @return the result from the plugin extension
   * @throws X expected exception from the plugin extension
   */
  static <T, R, X extends Exception> R call(
      PluginMetrics pluginMetrics,
      Extension<T> extension,
      CheckedExtensionFunction<Extension<T>, R, X> checkedExtensionFunction,
      Class<X> exceptionClass)
      throws X {
    try (TraceContext traceContext = newTrace(extension);
        Timer3.Context<String, String, String> ctx = pluginMetrics.startLatency(extension)) {
      try {
        return checkedExtensionFunction.call(extension);
      } catch (Exception e) {
        // The only exception that can be thrown is X, but we cannot catch X since it is a generic
        // type.
        Throwables.throwIfInstanceOf(e, exceptionClass);
        Throwables.throwIfUnchecked(e);
        throw new IllegalStateException("unexpected exception: " + e.getMessage(), e);
      }
    }
  }
}
