AbstractGetCodeOwnersForPath: Include filtered out code owners into debug logs
Filtered out code owners are relevant for debugging (e.g. to understand
why a certain user was not suggested). Hence the debug logs should tell
if a code owner was filtered out.
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I315e0ec2a1f67662eb77249052a2bb0cfbd381e1
diff --git a/java/com/google/gerrit/plugins/codeowners/restapi/AbstractGetCodeOwnersForPath.java b/java/com/google/gerrit/plugins/codeowners/restapi/AbstractGetCodeOwnersForPath.java
index 0fc90f9..56aa627 100644
--- a/java/com/google/gerrit/plugins/codeowners/restapi/AbstractGetCodeOwnersForPath.java
+++ b/java/com/google/gerrit/plugins/codeowners/restapi/AbstractGetCodeOwnersForPath.java
@@ -212,7 +212,7 @@
Set<CodeOwner> codeOwners = new HashSet<>();
ListMultimap<CodeOwner, CodeOwnerAnnotation> annotations = LinkedListMultimap.create();
AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
- List<String> debugLogs = new ArrayList<>();
+ ImmutableList.Builder<String> debugLogsBuilder = ImmutableList.builder();
codeOwnerConfigHierarchy.visit(
rsrc.getBranch(),
rsrc.getRevision(),
@@ -221,7 +221,7 @@
CodeOwnerResolverResult pathCodeOwners =
codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, rsrc.getPath());
- debugLogs.addAll(pathCodeOwners.messages());
+ debugLogsBuilder.addAll(pathCodeOwners.messages());
codeOwners.addAll(pathCodeOwners.codeOwners());
annotations.putAll(pathCodeOwners.annotations());
@@ -268,8 +268,8 @@
if (!ownedByAllUsers.get()) {
CodeOwnerResolverResult globalCodeOwners = getGlobalCodeOwners(rsrc.getBranch().project());
- debugLogs.add("resolve global code owners");
- debugLogs.addAll(globalCodeOwners.messages());
+ debugLogsBuilder.add("resolve global code owners");
+ debugLogsBuilder.addAll(globalCodeOwners.messages());
globalCodeOwners
.codeOwners()
@@ -295,7 +295,10 @@
ImmutableSet<CodeOwner> filteredCodeOwners =
filterCodeOwners(
- rsrc, ImmutableMultimap.copyOf(annotations), ImmutableSet.copyOf(codeOwners));
+ rsrc,
+ ImmutableMultimap.copyOf(annotations),
+ ImmutableSet.copyOf(codeOwners),
+ debugLogsBuilder);
CodeOwnerScorings codeOwnerScorings =
createScorings(
rsrc,
@@ -322,8 +325,9 @@
codeOwnersInfo.codeOwners =
codeOwnerJsonFactory.create(getFillOptions()).format(sortedAndLimitedCodeOwners);
codeOwnersInfo.ownedByAllUsers = ownedByAllUsers.get() ? true : null;
- codeOwnersInfo.debugLogs = debug ? debugLogs : null;
+ ImmutableList<String> debugLogs = debugLogsBuilder.build();
+ codeOwnersInfo.debugLogs = debug ? debugLogs : null;
logger.atFine().log("debug logs: %s", debugLogs);
return Response.ok(codeOwnersInfo);
@@ -375,8 +379,9 @@
private ImmutableSet<CodeOwner> filterCodeOwners(
R rsrc,
ImmutableMultimap<CodeOwner, CodeOwnerAnnotation> annotations,
- ImmutableSet<CodeOwner> codeOwners) {
- return filterCodeOwners(rsrc, annotations, getVisibleCodeOwners(rsrc, codeOwners))
+ ImmutableSet<CodeOwner> codeOwners,
+ ImmutableList.Builder<String> debugLogs) {
+ return filterCodeOwners(rsrc, annotations, getVisibleCodeOwners(rsrc, codeOwners), debugLogs)
.collect(toImmutableSet());
}
@@ -386,12 +391,14 @@
* @param rsrc resource on which the request is being performed
* @param annotations annotations that were set on the code owners
* @param codeOwners stream of code owners that should be filtered
+ * @param debugLogs builder to collect debug logs that may be returned to the caller
* @return the filtered stream of code owners
*/
protected Stream<CodeOwner> filterCodeOwners(
R rsrc,
ImmutableMultimap<CodeOwner, CodeOwnerAnnotation> annotations,
- Stream<CodeOwner> codeOwners) {
+ Stream<CodeOwner> codeOwners,
+ ImmutableList.Builder<String> debugLogs) {
return codeOwners;
}
diff --git a/java/com/google/gerrit/plugins/codeowners/restapi/GetCodeOwnersForPathInChange.java b/java/com/google/gerrit/plugins/codeowners/restapi/GetCodeOwnersForPathInChange.java
index 5e7235b..8b7281c 100644
--- a/java/com/google/gerrit/plugins/codeowners/restapi/GetCodeOwnersForPathInChange.java
+++ b/java/com/google/gerrit/plugins/codeowners/restapi/GetCodeOwnersForPathInChange.java
@@ -18,9 +18,9 @@
import static com.google.gerrit.plugins.codeowners.backend.CodeOwnerScore.NO_REVIEWER_SCORING_VALUE;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.common.AccountVisibility;
import com.google.gerrit.extensions.restapi.Response;
@@ -56,7 +56,6 @@
*/
public class GetCodeOwnersForPathInChange
extends AbstractGetCodeOwnersForPath<CodeOwnersInChangeCollection.PathResource> {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@VisibleForTesting
public static final CodeOwnerAnnotation NEVER_SUGGEST_ANNOTATION =
@@ -132,50 +131,54 @@
protected Stream<CodeOwner> filterCodeOwners(
CodeOwnersInChangeCollection.PathResource rsrc,
ImmutableMultimap<CodeOwner, CodeOwnerAnnotation> annotations,
- Stream<CodeOwner> codeOwners) {
+ Stream<CodeOwner> codeOwners,
+ ImmutableList.Builder<String> debugLogs) {
return codeOwners
- .filter(filterOutChangeOwner(rsrc))
- .filter(filterOutCodeOwnersThatAreAnnotatedWithNeverSuggest(annotations))
- .filter(filterOutServiceUsers());
+ .filter(filterOutChangeOwner(rsrc, debugLogs))
+ .filter(filterOutCodeOwnersThatAreAnnotatedWithNeverSuggest(annotations, debugLogs))
+ .filter(filterOutServiceUsers(debugLogs));
}
private Predicate<CodeOwner> filterOutChangeOwner(
- CodeOwnersInChangeCollection.PathResource rsrc) {
+ CodeOwnersInChangeCollection.PathResource rsrc, ImmutableList.Builder<String> debugLogs) {
return codeOwner -> {
if (!codeOwner.accountId().equals(rsrc.getRevisionResource().getChange().getOwner())) {
// Returning true from the Predicate here means that the code owner should be kept.
return true;
}
- logger.atFine().log(
- "Filtering out %s because this code owner is the change owner", codeOwner);
+ debugLogs.add(
+ String.format("filtering out %s because this code owner is the change owner", codeOwner));
// Returning false from the Predicate here means that the code owner should be filtered out.
return false;
};
}
private Predicate<CodeOwner> filterOutCodeOwnersThatAreAnnotatedWithNeverSuggest(
- ImmutableMultimap<CodeOwner, CodeOwnerAnnotation> annotations) {
+ ImmutableMultimap<CodeOwner, CodeOwnerAnnotation> annotations,
+ ImmutableList.Builder<String> debugLogs) {
return codeOwner -> {
boolean neverSuggest = annotations.containsEntry(codeOwner, NEVER_SUGGEST_ANNOTATION);
if (!neverSuggest) {
// Returning true from the Predicate here means that the code owner should be kept.
return true;
}
- logger.atFine().log(
- "Filtering out %s because this code owner is annotated with %s",
- codeOwner, NEVER_SUGGEST_ANNOTATION);
+ debugLogs.add(
+ String.format(
+ "filtering out %s because this code owner is annotated with %s",
+ codeOwner, NEVER_SUGGEST_ANNOTATION.key()));
// Returning false from the Predicate here means that the code owner should be filtered out.
return false;
};
}
- private Predicate<CodeOwner> filterOutServiceUsers() {
+ private Predicate<CodeOwner> filterOutServiceUsers(ImmutableList.Builder<String> debugLogs) {
return codeOwner -> {
if (!isServiceUser(codeOwner)) {
// Returning true from the Predicate here means that the code owner should be kept.
return true;
}
- logger.atFine().log("Filtering out %s because this code owner is a service user", codeOwner);
+ debugLogs.add(
+ String.format("filtering out %s because this code owner is a service user", codeOwner));
// Returning false from the Predicate here means that the code owner should be filtered out.
return false;
};
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnersForPathInChangeIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnersForPathInChangeIT.java
index 2294d61..9869a54 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnersForPathInChangeIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/GetCodeOwnersForPathInChangeIT.java
@@ -36,6 +36,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.codeowners.api.CodeOwners;
import com.google.gerrit.plugins.codeowners.api.CodeOwnersInfo;
+import com.google.gerrit.plugins.codeowners.backend.CodeOwner;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerResolver;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet;
import com.google.gerrit.plugins.codeowners.restapi.GetCodeOwnersForPathInChange;
@@ -636,4 +637,53 @@
.inOrder();
assertThat(codeOwnersInfo).hasOwnedByAllUsersThat().isTrue();
}
+
+ @Test
+ public void filteredOutCodeOwnersAreMentionedInDebugLogs() throws Exception {
+ skipTestIfAnnotationsNotSupportedByCodeOwnersBackend();
+
+ // Create a service user.
+ TestAccount serviceUser =
+ accountCreator.create("serviceUser", "service.user@example.com", "Service User", null);
+ groupOperations
+ .group(groupCache.get(AccountGroup.nameKey("Service Users")).get().getGroupUUID())
+ .forUpdate()
+ .addMember(serviceUser.id())
+ .update();
+
+ codeOwnerConfigOperations
+ .newCodeOwnerConfig()
+ .project(project)
+ .branch("master")
+ .folderPath("/")
+ .addCodeOwnerSet(
+ CodeOwnerSet.builder()
+ .addCodeOwnerEmail(changeOwner.email())
+ .addCodeOwnerEmail(serviceUser.email())
+ .addCodeOwnerEmail(admin.email())
+ .addAnnotation(admin.email(), GetCodeOwnersForPathInChange.NEVER_SUGGEST_ANNOTATION)
+ .addCodeOwnerEmail(user.email())
+ .build())
+ .create();
+
+ String path = "/foo/bar/baz.md";
+ CodeOwnersInfo codeOwnersInfo =
+ queryCodeOwners(getCodeOwnersApi().query().withDebug(/* debug= */ true), path);
+ assertThat(codeOwnersInfo)
+ .hasCodeOwnersThat()
+ .comparingElementsUsing(hasAccountId())
+ .containsExactly(user.id());
+ assertThat(codeOwnersInfo)
+ .hasDebugLogsThatContainAllOf(
+ String.format(
+ "filtering out %s because this code owner is the change owner",
+ CodeOwner.create(changeOwner.id())),
+ String.format(
+ "filtering out %s because this code owner is a service user",
+ CodeOwner.create(serviceUser.id())),
+ String.format(
+ "filtering out %s because this code owner is annotated with %s",
+ CodeOwner.create(admin.id()),
+ GetCodeOwnersForPathInChange.NEVER_SUGGEST_ANNOTATION.key()));
+ }
}