// 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.logging;

import static com.google.common.flogger.LazyArgs.lazy;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.LazyArg;
import java.util.Optional;

/**
 * Utility to compute the caller of a method.
 *
 * <p>In the logs we see for each entry from where it was triggered (class/method/line) but in case
 * the logging is done in a utility method or inside of a module this doesn't tell us from where the
 * action was actually triggered. To get this information we could included the stacktrace into the
 * logs (by calling {@link
 * com.google.common.flogger.LoggingApi#withStackTrace(com.google.common.flogger.StackSize)} but
 * sometimes there are too many uninteresting stacks so that this would blow up the logs too much.
 * In this case CallerFinder can be used to find the first interesting caller from the current
 * stacktrace by specifying the class that interesting callers invoke as target.
 *
 * <p>Example:
 *
 * <p>Index queries are executed by the {@code query(List<String>, List<Predicate<T>>)} method in
 * {@link com.google.gerrit.index.query.QueryProcessor}. At this place the index query is logged but
 * from the log we want to see which code triggered this index query.
 *
 * <p>E.g. the stacktrace could look like this:
 *
 * <pre>{@code
 * GroupQueryProcessor(QueryProcessor<T>).query(List<String>, List<Predicate<T>>) line: 216
 * GroupQueryProcessor(QueryProcessor<T>).query(List<Predicate<T>>) line: 188
 * GroupQueryProcessor(QueryProcessor<T>).query(Predicate<T>) line: 171
 * InternalGroupQuery(InternalQuery<T>).query(Predicate<T>) line: 81
 * InternalGroupQuery.getOnlyGroup(Predicate<InternalGroup>, String) line: 67
 * InternalGroupQuery.byName(NameKey) line: 50
 * GroupCacheImpl$ByNameLoader.load(String) line: 166
 * GroupCacheImpl$ByNameLoader.load(Object) line: 1
 * LocalCache$LoadingValueReference<K,V>.loadFuture(K, CacheLoader<? super K,V>) line: 3527
 * ...
 * }</pre>
 *
 * <p>The first interesting caller is {@code GroupCacheImpl$ByNameLoader.load(String) line: 166}. To
 * find this caller from the stacktrace we could specify {@link
 * com.google.gerrit.server.query.group.InternalGroupQuery} as a target since we know that all
 * internal group queries go through this class:
 *
 * <pre>
 * CallerFinder.builder()
 *   .addTarget(InternalGroupQuery.class)
 *   .build();
 * </pre>
 *
 * <p>Since in some places {@link com.google.gerrit.server.query.group.GroupQueryProcessor} may also
 * be used directly we can add it as a secondary target to catch these callers as well:
 *
 * <pre>
 * CallerFinder.builder()
 *   .addTarget(InternalGroupQuery.class)
 *   .addTarget(GroupQueryProcessor.class)
 *   .build();
 * </pre>
 *
 * <p>However since {@link com.google.gerrit.index.query.QueryProcessor} is also responsible to
 * execute other index queries (for changes, accounts, projects) we would need to add the classes
 * for them as targets too. Since there are common base classes we can simply specify the base
 * classes and request matching of subclasses:
 *
 * <pre>
 * CallerFinder.builder()
 *   .addTarget(InternalQuery.class)
 *   .addTarget(QueryProcessor.class)
 *   .matchSubClasses(true)
 *   .build();
 * </pre>
 *
 * <p>Another special case is if the entry point is always an inner class of a known interface. E.g.
 * {@link com.google.gerrit.server.permissions.PermissionBackend} is the entry point for all
 * permission checks but they are done through inner classes, e.g. {@link
 * com.google.gerrit.server.permissions.PermissionBackend.ForProject}. In this case matching of
 * inner classes must be enabled as well:
 *
 * <pre>
 * CallerFinder.builder()
 *   .addTarget(PermissionBackend.class)
 *   .matchSubClasses(true)
 *   .matchInnerClasses(true)
 *   .build();
 * </pre>
 *
 * <p>Finding the interesting caller requires specifying the entry point class as target. This may
 * easily break when code is refactored and hence should be used only with care. It's recommended to
 * use this only when the corresponding code is relatively stable and logging the caller information
 * brings some significant benefit.
 *
 * <p>Based on {@link com.google.common.flogger.util.CallerFinder}.
 */
@AutoValue
public abstract class CallerFinder {
  public static Builder builder() {
    return new AutoValue_CallerFinder.Builder()
        .matchSubClasses(false)
        .matchInnerClasses(false)
        .skip(0);
  }

  /**
   * The target classes for which the caller should be found, in the order in which they should be
   * checked.
   *
   * @return the target classes for which the caller should be found
   */
  public abstract ImmutableList<Class<?>> targets();

  /**
   * Whether inner classes should be matched.
   *
   * @return whether inner classes should be matched
   */
  public abstract boolean matchSubClasses();

  /**
   * Whether sub classes of the target classes should be matched.
   *
   * @return whether sub classes of the target classes should be matched
   */
  public abstract boolean matchInnerClasses();

  /**
   * The minimum number of calls known to have occurred between the first call to the target class
   * and the call of {@link #findCallerLazy()}. If in doubt, specify zero here to avoid accidentally
   * skipping past the caller.
   *
   * @return the number of stack elements to skip when computing the caller
   */
  public abstract int skip();

  /**
   * Packages that should be ignored and not be considered as caller once a target has been found.
   *
   * @return the ignored packages
   */
  public abstract ImmutableList<String> ignoredPackages();

  /**
   * Classes that should be ignored and not be considered as caller once a target has been found.
   *
   * @return the qualified names of the ignored classes
   */
  public abstract ImmutableList<String> ignoredClasses();

  @AutoValue.Builder
  public abstract static class Builder {
    abstract ImmutableList.Builder<Class<?>> targetsBuilder();

    public Builder addTarget(Class<?> target) {
      targetsBuilder().add(target);
      return this;
    }

    public abstract Builder matchSubClasses(boolean matchSubClasses);

    public abstract Builder matchInnerClasses(boolean matchInnerClasses);

    public abstract Builder skip(int skip);

    abstract ImmutableList.Builder<String> ignoredPackagesBuilder();

    public Builder addIgnoredPackage(String ignoredPackage) {
      ignoredPackagesBuilder().add(ignoredPackage);
      return this;
    }

    abstract ImmutableList.Builder<String> ignoredClassesBuilder();

    public Builder addIgnoredClass(Class<?> ignoredClass) {
      ignoredClassesBuilder().add(ignoredClass.getName());
      return this;
    }

    public abstract CallerFinder build();
  }

  public LazyArg<String> findCallerLazy() {
    return lazy(
        () ->
            targets().stream()
                .map(t -> findCallerOf(t, skip() + 1))
                .filter(Optional::isPresent)
                .findFirst()
                .map(Optional::get)
                .orElse("unknown"));
  }

  private Optional<String> findCallerOf(Class<?> target, int skip) {
    // Skip one additional stack frame because we create the Throwable inside this method, not at
    // the point that this method was invoked.
    skip++;

    StackTraceElement[] stack = new Throwable().getStackTrace();

    // Note: To avoid having to reflect the getStackTraceDepth() method as well, we assume that we
    // will find the caller on the stack and simply catch an exception if we fail (which should
    // hardly ever happen).
    boolean foundCaller = false;
    try {
      for (int index = skip; ; index++) {
        StackTraceElement element = stack[index];
        if (isCaller(target, element.getClassName(), matchSubClasses())) {
          foundCaller = true;
        } else if (foundCaller
            && !ignoredPackages().contains(getPackageName(element))
            && !ignoredClasses().contains(element.getClassName())) {
          return Optional.of(element.toString());
        }
      }
    } catch (Exception e) {
      // This should only happen if a) the caller was not found on the stack
      // (IndexOutOfBoundsException) b) a class that is mentioned in the stack was not found
      // (ClassNotFoundException), however we don't want anything to be thrown from here.
      return Optional.empty();
    }
  }

  private static String getPackageName(StackTraceElement element) {
    String className = element.getClassName();
    return className.substring(0, className.lastIndexOf("."));
  }

  private boolean isCaller(Class<?> target, String className, boolean matchSubClasses)
      throws ClassNotFoundException {
    if (matchSubClasses) {
      Class<?> clazz = Class.forName(className);
      while (clazz != null) {
        if (Object.class.getName().equals(clazz.getName())) {
          break;
        }

        if (isCaller(target, clazz.getName(), false)) {
          return true;
        }
        clazz = clazz.getSuperclass();
      }
    }

    if (matchInnerClasses()) {
      int i = className.indexOf('$');
      if (i > 0) {
        className = className.substring(0, i);
      }
    }

    if (target.getName().equals(className)) {
      return true;
    }

    return false;
  }
}
