Add latency metrics for relevant operations Signed-off-by: Edwin Kempin <ekempin@google.com> Change-Id: I0545d8012820834382d4b0cca8c18c93a0b4053e
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/BUILD b/java/com/google/gerrit/plugins/codeowners/backend/BUILD index 5aefae5..83671a0 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/BUILD +++ b/java/com/google/gerrit/plugins/codeowners/backend/BUILD
@@ -7,6 +7,7 @@ visibility = ["//visibility:public"], deps = PLUGIN_DEPS_NEVERLINK + [ "//plugins/code-owners/java/com/google/gerrit/plugins/codeowners/common", + "//plugins/code-owners/java/com/google/gerrit/plugins/codeowners/metrics", "//plugins/code-owners/java/com/google/gerrit/plugins/codeowners/util", "//plugins/code-owners/proto:owners_metadata_java_proto", ],
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/ChangedFiles.java b/java/com/google/gerrit/plugins/codeowners/backend/ChangedFiles.java index 78956a2..1e76b05 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/ChangedFiles.java +++ b/java/com/google/gerrit/plugins/codeowners/backend/ChangedFiles.java
@@ -23,9 +23,11 @@ import com.google.gerrit.entities.Patch; import com.google.gerrit.entities.Project; import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace; +import com.google.gerrit.metrics.Timer0; import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration; import com.google.gerrit.plugins.codeowners.common.ChangedFile; import com.google.gerrit.plugins.codeowners.common.MergeCommitStrategy; +import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics; import com.google.gerrit.server.change.RevisionResource; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.patch.PatchListCache; @@ -60,15 +62,18 @@ private final GitRepositoryManager repoManager; private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration; private final PatchListCache patchListCache; + private final CodeOwnerMetrics codeOwnerMetrics; @Inject public ChangedFiles( GitRepositoryManager repoManager, CodeOwnersPluginConfiguration codeOwnersPluginConfiguration, - PatchListCache patchListCache) { + PatchListCache patchListCache, + CodeOwnerMetrics codeOwnerMetrics) { this.repoManager = repoManager; this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration; this.patchListCache = patchListCache; + this.codeOwnerMetrics = codeOwnerMetrics; } /** @@ -139,12 +144,14 @@ logger.atFine().log( "computing changed files for revision %s in project %s", revCommit.name(), project); - if (revCommit.getParentCount() > 1 - && MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION.equals(mergeCommitStrategy)) { - return computeByComparingAgainstAutoMerge(project, revCommit); - } + try (Timer0.Context ctx = codeOwnerMetrics.computeChangedFiles.start()) { + if (revCommit.getParentCount() > 1 + && MergeCommitStrategy.FILES_WITH_CONFLICT_RESOLUTION.equals(mergeCommitStrategy)) { + return computeByComparingAgainstAutoMerge(project, revCommit); + } - return computeByComparingAgainstFirstParent(repoConfig, revWalk, revCommit); + return computeByComparingAgainstFirstParent(repoConfig, revWalk, revCommit); + } } /**
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerApprovalCheck.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerApprovalCheck.java index 49eddd7..937a118 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerApprovalCheck.java +++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerApprovalCheck.java
@@ -33,15 +33,14 @@ import com.google.gerrit.entities.Project; import com.google.gerrit.exceptions.StorageException; import com.google.gerrit.extensions.restapi.ResourceConflictException; +import com.google.gerrit.metrics.Timer0; import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration; import com.google.gerrit.plugins.codeowners.backend.config.RequiredApproval; import com.google.gerrit.plugins.codeowners.common.ChangedFile; import com.google.gerrit.plugins.codeowners.common.CodeOwnerStatus; +import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics; import com.google.gerrit.server.ApprovalsUtil; import com.google.gerrit.server.git.GitRepositoryManager; -import com.google.gerrit.server.logging.Metadata; -import com.google.gerrit.server.logging.TraceContext; -import com.google.gerrit.server.logging.TraceContext.TraceTimer; import com.google.gerrit.server.notedb.ChangeNotes; import com.google.gerrit.server.notedb.ReviewerStateInternal; import com.google.gerrit.server.patch.PatchListNotAvailableException; @@ -91,6 +90,7 @@ private final CodeOwnerConfigHierarchy codeOwnerConfigHierarchy; private final Provider<CodeOwnerResolver> codeOwnerResolver; private final ApprovalsUtil approvalsUtil; + private final CodeOwnerMetrics codeOwnerMetrics; @Inject CodeOwnerApprovalCheck( @@ -101,7 +101,8 @@ CodeOwnerConfigScanner.Factory codeOwnerConfigScannerFactory, CodeOwnerConfigHierarchy codeOwnerConfigHierarchy, Provider<CodeOwnerResolver> codeOwnerResolver, - ApprovalsUtil approvalsUtil) { + ApprovalsUtil approvalsUtil, + CodeOwnerMetrics codeOwnerMetrics) { this.permissionBackend = permissionBackend; this.repoManager = repoManager; this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration; @@ -110,6 +111,7 @@ this.codeOwnerConfigHierarchy = codeOwnerConfigHierarchy; this.codeOwnerResolver = codeOwnerResolver; this.approvalsUtil = approvalsUtil; + this.codeOwnerMetrics = codeOwnerMetrics; } /** @@ -200,13 +202,11 @@ public Stream<FileCodeOwnerStatus> getFileStatuses(ChangeNotes changeNotes) throws ResourceConflictException, IOException, PatchListNotAvailableException { requireNonNull(changeNotes, "changeNotes"); - try (TraceTimer traceTimer = - TraceContext.newTimer( - "Compute file statuses", - Metadata.builder() - .projectName(changeNotes.getProjectName().get()) - .changeId(changeNotes.getChangeId().get()) - .build())) { + try (Timer0.Context ctx = codeOwnerMetrics.computeFileStatuses.start()) { + logger.atFine().log( + "compute file statuses (project = %s, change = %d)", + changeNotes.getProjectName(), changeNotes.getChangeId().get()); + boolean enableImplicitApprovalFromUploader = codeOwnersPluginConfiguration.areImplicitApprovalsEnabled(changeNotes.getProjectName()); Account.Id patchSetUploader = changeNotes.getCurrentPatchSet().uploader(); @@ -287,14 +287,14 @@ requireNonNull(changeNotes, "changeNotes"); requireNonNull(patchSet, "patchSet"); requireNonNull(accountId, "accountId"); - try (TraceTimer traceTimer = - TraceContext.newTimer( - "Compute file statuses for account", - Metadata.builder() - .projectName(changeNotes.getProjectName().get()) - .changeId(changeNotes.getChangeId().get()) - .patchSetId(patchSet.id().get()) - .build())) { + try (Timer0.Context ctx = codeOwnerMetrics.computeFileStatusesForAccount.start()) { + logger.atFine().log( + "compute file statuses for account %d (project = %s, change = %d, patch set = %d)", + accountId.get(), + changeNotes.getProjectName(), + changeNotes.getChangeId().get(), + patchSet.id().get()); + RequiredApproval requiredApproval = codeOwnersPluginConfiguration.getRequiredApproval(changeNotes.getProjectName()); logger.atFine().log("requiredApproval = %s", requiredApproval);
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java index 2fb7607..31dda71 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java +++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
@@ -25,7 +25,9 @@ import com.google.gerrit.entities.Account; import com.google.gerrit.entities.Project; import com.google.gerrit.exceptions.StorageException; +import com.google.gerrit.metrics.Timer0; import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration; +import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.account.AccountCache; @@ -33,9 +35,6 @@ import com.google.gerrit.server.account.AccountState; import com.google.gerrit.server.account.externalids.ExternalId; import com.google.gerrit.server.account.externalids.ExternalIds; -import com.google.gerrit.server.logging.Metadata; -import com.google.gerrit.server.logging.TraceContext; -import com.google.gerrit.server.logging.TraceContext.TraceTimer; import com.google.gerrit.server.permissions.GlobalPermission; import com.google.gerrit.server.permissions.PermissionBackend; import com.google.gerrit.server.permissions.PermissionBackendException; @@ -62,6 +61,7 @@ private final AccountCache accountCache; private final AccountControl.Factory accountControlFactory; private final PathCodeOwners.Factory pathCodeOwnersFactory; + private final CodeOwnerMetrics codeOwnerMetrics; // Enforce visibility by default. private boolean enforceVisibility = true; @@ -79,7 +79,8 @@ ExternalIds externalIds, AccountCache accountCache, AccountControl.Factory accountControlFactory, - PathCodeOwners.Factory pathCodeOwnersFactory) { + PathCodeOwners.Factory pathCodeOwnersFactory, + CodeOwnerMetrics codeOwnerMetrics) { this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration; this.permissionBackend = permissionBackend; this.currentUser = currentUser; @@ -87,6 +88,7 @@ this.accountCache = accountCache; this.accountControlFactory = accountControlFactory; this.pathCodeOwnersFactory = pathCodeOwnersFactory; + this.codeOwnerMetrics = codeOwnerMetrics; } /** @@ -147,15 +149,10 @@ requireNonNull(absolutePath, "absolutePath"); checkState(absolutePath.isAbsolute(), "path %s must be absolute", absolutePath); - try (TraceTimer traceTimer = - TraceContext.newTimer( - "Resolve path code owners", - Metadata.builder() - .projectName(codeOwnerConfig.key().project().get()) - .branchName(codeOwnerConfig.key().ref()) - .filePath(codeOwnerConfig.key().fileName().orElse("<default>")) - .build())) { - logger.atFine().log("resolving path code owners for path %s", absolutePath); + try (Timer0.Context ctx = codeOwnerMetrics.resolvePathCodeOwners.start()) { + logger.atFine().log( + "resolve path code owners (code owner config = %s, path = %s)", + codeOwnerConfig.key(), absolutePath); PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwnersFactory.create(codeOwnerConfig, absolutePath).resolveCodeOwnerConfig(); return resolve(
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerSubmitRule.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerSubmitRule.java index 6cf8ef3..4c23676 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerSubmitRule.java +++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerSubmitRule.java
@@ -23,10 +23,9 @@ import com.google.gerrit.extensions.annotations.Exports; import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.metrics.Timer0; import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration; -import com.google.gerrit.server.logging.Metadata; -import com.google.gerrit.server.logging.TraceContext; -import com.google.gerrit.server.logging.TraceContext.TraceTimer; +import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics; import com.google.gerrit.server.notedb.ChangeNotes; import com.google.gerrit.server.patch.PatchListNotAvailableException; import com.google.gerrit.server.query.change.ChangeData; @@ -56,13 +55,16 @@ private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration; private final CodeOwnerApprovalCheck codeOwnerApprovalCheck; + private final CodeOwnerMetrics codeOwnerMetrics; @Inject CodeOwnerSubmitRule( CodeOwnersPluginConfiguration codeOwnersPluginConfiguration, - CodeOwnerApprovalCheck codeOwnerApprovalCheck) { + CodeOwnerApprovalCheck codeOwnerApprovalCheck, + CodeOwnerMetrics codeOwnerMetrics) { this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration; this.codeOwnerApprovalCheck = codeOwnerApprovalCheck; + this.codeOwnerMetrics = codeOwnerMetrics; } @Override @@ -70,13 +72,11 @@ try { requireNonNull(changeData, "changeData"); - try (TraceTimer traceTimer = - TraceContext.newTimer( - "Run code owner submit rule", - Metadata.builder() - .projectName(changeData.project().get()) - .changeId(changeData.getId().get()) - .build())) { + try (Timer0.Context ctx = codeOwnerMetrics.runCodeOwnerSubmitRule.start()) { + logger.atFine().log( + "run code owner submit rule (project = %s, change = %d)", + changeData.project().get(), changeData.getId().get()); + if (codeOwnersPluginConfiguration.isDisabled(changeData.change().getDest())) { logger.atFine().log( "code owners functionality is disabled for branch %s", changeData.change().getDest());
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/PathCodeOwners.java b/java/com/google/gerrit/plugins/codeowners/backend/PathCodeOwners.java index f787dc8..4f67254 100644 --- a/java/com/google/gerrit/plugins/codeowners/backend/PathCodeOwners.java +++ b/java/com/google/gerrit/plugins/codeowners/backend/PathCodeOwners.java
@@ -24,10 +24,9 @@ import com.google.common.flogger.FluentLogger; import com.google.gerrit.entities.BranchNameKey; import com.google.gerrit.entities.Project; +import com.google.gerrit.metrics.Timer0; import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration; -import com.google.gerrit.server.logging.Metadata; -import com.google.gerrit.server.logging.TraceContext; -import com.google.gerrit.server.logging.TraceContext.TraceTimer; +import com.google.gerrit.plugins.codeowners.metrics.CodeOwnerMetrics; import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectState; import com.google.inject.Inject; @@ -54,15 +53,18 @@ @Singleton public static class Factory { + private final CodeOwnerMetrics codeOwnerMetrics; private final ProjectCache projectCache; private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration; private final CodeOwners codeOwners; @Inject Factory( + CodeOwnerMetrics codeOwnerMetrics, ProjectCache projectCache, CodeOwnersPluginConfiguration codeOwnersPluginConfiguration, CodeOwners codeOwners) { + this.codeOwnerMetrics = codeOwnerMetrics; this.projectCache = projectCache; this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration; this.codeOwners = codeOwners; @@ -71,6 +73,7 @@ public PathCodeOwners create(CodeOwnerConfig codeOwnerConfig, Path absolutePath) { requireNonNull(codeOwnerConfig, "codeOwnerConfig"); return new PathCodeOwners( + codeOwnerMetrics, projectCache, codeOwners, codeOwnerConfig, @@ -85,6 +88,7 @@ .map( codeOwnerConfig -> new PathCodeOwners( + codeOwnerMetrics, projectCache, codeOwners, codeOwnerConfig, @@ -118,6 +122,7 @@ } } + private final CodeOwnerMetrics codeOwnerMetrics; private final ProjectCache projectCache; private final CodeOwners codeOwners; private final CodeOwnerConfig codeOwnerConfig; @@ -127,11 +132,13 @@ private PathCodeOwnersResult pathCodeOwnersResult; private PathCodeOwners( + CodeOwnerMetrics codeOwnerMetrics, ProjectCache projectCache, CodeOwners codeOwners, CodeOwnerConfig codeOwnerConfig, Path path, PathExpressionMatcher pathExpressionMatcher) { + this.codeOwnerMetrics = requireNonNull(codeOwnerMetrics, "codeOwnerMetrics"); this.projectCache = requireNonNull(projectCache, "projectCache"); this.codeOwners = requireNonNull(codeOwners, "codeOwners"); this.codeOwnerConfig = requireNonNull(codeOwnerConfig, "codeOwnerConfig"); @@ -187,13 +194,7 @@ return this.pathCodeOwnersResult; } - try (TraceTimer traceTimer = - TraceContext.newTimer( - "Resolve code owner config", - Metadata.builder() - .projectName(codeOwnerConfig.key().project().get()) - .filePath(path.toString()) - .build())) { + try (Timer0.Context ctx = codeOwnerMetrics.resolveCodeOwnerConfig.start()) { logger.atFine().log( "resolve code owners for %s from code owner config %s", path, codeOwnerConfig.key()); @@ -249,14 +250,9 @@ CodeOwnerConfig importingCodeOwnerConfig, CodeOwnerConfig.Builder resolvedCodeOwnerConfigBuilder) { ImmutableList.Builder<UnresolvedImport> unresolvedImports = ImmutableList.builder(); - try (TraceTimer traceTimer = - TraceContext.newTimer( - "Resolve code owner config imports", - Metadata.builder() - .projectName(codeOwnerConfig.key().project().get()) - .branchName(codeOwnerConfig.key().ref()) - .filePath(codeOwnerConfig.key().filePath("<default>").toString()) - .build())) { + try (Timer0.Context ctx = codeOwnerMetrics.resolveCodeOwnerConfigImports.start()) { + logger.atFine().log("resolve imports of codeOwnerConfig %s", importingCodeOwnerConfig.key()); + // To detect cyclic dependencies we keep track of all seen code owner configs. Set<CodeOwnerConfig.Key> seenCodeOwnerConfigs = new HashSet<>(); seenCodeOwnerConfigs.add(codeOwnerConfig.key()); @@ -278,17 +274,10 @@ CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig = createKeyForImportedCodeOwnerConfig( importingCodeOwnerConfig.key(), codeOwnerConfigReference); - try (TraceTimer traceTimer2 = - TraceContext.newTimer( - "Resolve code owner config import", - Metadata.builder() - .projectName(keyOfImportedCodeOwnerConfig.project().get()) - .branchName(keyOfImportedCodeOwnerConfig.ref()) - .filePath( - keyOfImportedCodeOwnerConfig - .filePath(codeOwnerConfigReference.fileName()) - .toString()) - .build())) { + try (Timer0.Context ctx2 = codeOwnerMetrics.resolveCodeOwnerConfigImport.start()) { + logger.atFine().log( + "resolve import of code owner config %s", keyOfImportedCodeOwnerConfig); + Optional<ProjectState> projectState = projectCache.get(keyOfImportedCodeOwnerConfig.project()); if (!projectState.isPresent()) {
diff --git a/java/com/google/gerrit/plugins/codeowners/metrics/BUILD b/java/com/google/gerrit/plugins/codeowners/metrics/BUILD new file mode 100644 index 0000000..1f1ad14 --- /dev/null +++ b/java/com/google/gerrit/plugins/codeowners/metrics/BUILD
@@ -0,0 +1,9 @@ +load("@rules_java//java:defs.bzl", "java_library") +load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS_NEVERLINK") + +java_library( + name = "metrics", + srcs = glob(["*.java"]), + visibility = ["//visibility:public"], + deps = PLUGIN_DEPS_NEVERLINK, +)
diff --git a/java/com/google/gerrit/plugins/codeowners/metrics/CodeOwnerMetrics.java b/java/com/google/gerrit/plugins/codeowners/metrics/CodeOwnerMetrics.java new file mode 100644 index 0000000..e1ce3bf --- /dev/null +++ b/java/com/google/gerrit/plugins/codeowners/metrics/CodeOwnerMetrics.java
@@ -0,0 +1,74 @@ +// Copyright (C) 2021 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.plugins.codeowners.metrics; + +import com.google.gerrit.metrics.Description; +import com.google.gerrit.metrics.Description.Units; +import com.google.gerrit.metrics.MetricMaker; +import com.google.gerrit.metrics.Timer0; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** Metrics of the code-owners plugin. */ +@Singleton +public class CodeOwnerMetrics { + public final Timer0 computeChangedFiles; + public final Timer0 computeFileStatuses; + public final Timer0 computeFileStatusesForAccount; + public final Timer0 resolveCodeOwnerConfig; + public final Timer0 resolveCodeOwnerConfigImport; + public final Timer0 resolveCodeOwnerConfigImports; + public final Timer0 resolvePathCodeOwners; + public final Timer0 runCodeOwnerSubmitRule; + + private final MetricMaker metricMaker; + + @Inject + CodeOwnerMetrics(MetricMaker metricMaker) { + this.metricMaker = metricMaker; + + this.computeChangedFiles = + createLatencyTimer("compute_changed_files", "Latency for computing changed files"); + this.computeFileStatuses = + createLatencyTimer("compute_file_statuses", "Latency for computing file statuses"); + this.computeFileStatusesForAccount = + createLatencyTimer( + "compute_file_statuses_for_account", + "Latency for computing file statuses for an account"); + this.resolveCodeOwnerConfig = + createLatencyTimer( + "resolve_code_owner_config", "Latency for resolving a code owner config file"); + this.resolveCodeOwnerConfigImport = + createLatencyTimer( + "resolve_code_owner_config_import", + "Latency for resolving an import of a code owner config file"); + this.resolveCodeOwnerConfigImports = + createLatencyTimer( + "resolve_code_owner_config_imports", + "Latency for resolving all imports of a code owner config file"); + this.resolvePathCodeOwners = + createLatencyTimer( + "resolve_path_code_owners", "Latency for resolving the code owners of a path"); + this.runCodeOwnerSubmitRule = + createLatencyTimer( + "run_code_owner_submit_rule", "Latency for running the code owner submit rule"); + } + + private Timer0 createLatencyTimer(String name, String description) { + return metricMaker.newTimer( + "code_owners/" + name, + new Description(description).setCumulative().setUnit(Units.MILLISECONDS)); + } +}
diff --git a/resources/Documentation/metrics.md b/resources/Documentation/metrics.md new file mode 100644 index 0000000..2e63c23 --- /dev/null +++ b/resources/Documentation/metrics.md
@@ -0,0 +1,27 @@ +# Metrics + +The @PLUGIN@ plugin exports several metrics which can give insights into the +usage and performance of the code owners functionality. + +## <a id="latencyMetrics"> Latency Metrics + +* `compute_changed_files`: + Latency for computing changed files. +* `compute_file_statuses`: + Latency for computing file statuses. +* `compute_file_statuses_for_account`: + Latency for computing file statuses for an account. +* `resolve_code_owner_config`: + Latency for resolving a code owner config file. +* `resolve_code_owner_config_import`: + Latency for resolving an import of a code owner config file. +* `resolve_code_owner_config_imports`: + Latency for resolving all imports of a code owner config file. +* `run_code_owner_submit_rule`: + Latency for running the code owner submit rule. + +--- + +Back to [@PLUGIN@ documentation index](index.html) + +Part of [Gerrit Code Review](../../../Documentation/index.html)