Have a dedicated class for metadata that is provided to TraceTimer and PerformanceLogger

Currently all metadata are key-value pairs, where both keys and values
are strings. This leads to an API that is difficult to use:

* change I776138eaa had to fix callers which forgot to specify metadata
  keys
* change I758660f8b had to make metadata keys consistent
* there are many similar methods with different numbers of key-value
  pairs for metadata

This change introduces a dedicated Metadata class that is used in the
API instead of key-value pairs that are strings. The Metadata class
contains dedicated fields for all known metadata types. Using the
Metadata.Builder it's now easy to provide metadata consistenly in all
places (there are dedicated methods to set pieces of metadata, so that
there is no longer a need to provide string keys for them).

For plugins that want to provide metadata for which Gerrit core doesn't
provide a suitable metadata field, Metadata contains a pluginMetadata
field in which arbitrary key-value pairs can be stored. That should only
be used for plugins. If Gerrit core needs additional metadata fields the
Metadata class should be extended.

The fields in Metadata only use basic Java types because the logging
package, that contains the Metadata class, should not have any
dependency on the large Gerrit packages that define the Gerrit types
(e.g. Project.NameKey).

For PerformanceLoggers it is important to know about the semantics of
the provided metadata, as some of the metadata may be considered
sensitive and must not end up in a performance log. Having the Metadata
class allows PerformanceLogger implementations to decide which metadata
they want to log and which metadata they want to omit.

A speciality is the recording of performance log entries from metric
timers. Whenever a metric timer is used we automatically report the
measured time as a performance log record. As metadata we provide the
value of the metric fields which are used for bucketing. As metadata
keys we used the field names. To properly populate the metadata in the
new Metadata type now, the definition of the metric fields must do the
mapping of the field value to a field in the Metadata class. For this a
MetadataMapper must be provided when the field is created.

Change-Id: Idedf6368365cd7b54a78c86457d26933746477e8
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin
2019-06-26 13:57:38 +02:00
parent c90dc3af6d
commit 103c5d14fe
50 changed files with 594 additions and 788 deletions

View File

@@ -0,0 +1,208 @@
// Copyright (C) 2019 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 com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import java.util.Optional;
/** Metadata that is provided to {@link PerformanceLogger}s as context for performance records. */
@AutoValue
public abstract class Metadata {
// The numeric ID of an account.
public abstract Optional<Integer> accountId();
// The type of an action (ACCOUNT_UPDATE, CHANGE_UPDATE, GROUP_UPDATE, INDEX_QUERY,
// PLUGIN_UPDATE).
public abstract Optional<String> actionType();
// An authentication domain name.
public abstract Optional<String> authDomainName();
// The name of a branch.
public abstract Optional<String> branchName();
// Key of an entity in a cache.
public abstract Optional<String> cacheKey();
// The name of a cache.
public abstract Optional<String> cacheName();
// The name of the implementation class.
public abstract Optional<String> className();
// The numeric ID of a change.
public abstract Optional<Integer> changeId();
// The type of change ID which the user used to identify a change (e.g. numeric ID, triplet etc.).
public abstract Optional<String> changeIdType();
// The type of an event.
public abstract Optional<String> eventType();
// The value of the @Export annotation which was used to register a plugin extension.
public abstract Optional<String> exportValue();
// Garbage collector name.
public abstract Optional<String> garbageCollectorName();
// Git operation (CLONE, FETCH).
public abstract Optional<String> gitOperation();
// The numeric ID of an internal group.
public abstract Optional<Integer> groupId();
// The name of a group.
public abstract Optional<String> groupName();
// The UUID of a group.
public abstract Optional<String> groupUuid();
// HTTP status response code.
public abstract Optional<Integer> httpStatus();
// The name of a secondary index.
public abstract Optional<String> indexName();
// The version of a secondary index.
public abstract Optional<Integer> indexVersion();
// The name of the implementation method.
public abstract Optional<String> methodName();
// Boolean: one or more
public abstract Optional<Boolean> multiple();
// Name of a metadata file in NoteDb.
public abstract Optional<String> noteDbFileName();
// Name of a metadata ref in NoteDb.
public abstract Optional<String> noteDbRefName();
// Type of a sequence in NoteDb (ACCOUNTS, CHANGES, GROUPS).
public abstract Optional<String> noteDbSequenceType();
// Name of a "table" in NoteDb (if set, always CHANGES).
public abstract Optional<String> noteDbTable();
// Plugin metadata that doesn't fit into any other category.
public abstract ImmutableList<PluginMetadata> pluginMetadata();
// The name of a plugin.
public abstract Optional<String> pluginName();
// The name of a Gerrit project (aka Git repository).
public abstract Optional<String> projectName();
// The type of a Git push to Gerrit (CREATE_REPLACE, NORMAL, AUTOCLOSE).
public abstract Optional<String> pushType();
// The number of resources that is processed.
public abstract Optional<Integer> resourceCount();
// The name of a REST view.
public abstract Optional<String> restViewName();
// The SHA1 of Git commit.
public abstract Optional<String> revision();
// The username of an account.
public abstract Optional<String> username();
public static Metadata.Builder builder() {
return new AutoValue_Metadata.Builder();
}
public static Metadata empty() {
return builder().build();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder accountId(int accountId);
public abstract Builder actionType(@Nullable String actionType);
public abstract Builder authDomainName(@Nullable String authDomainName);
public abstract Builder branchName(@Nullable String branchName);
public abstract Builder cacheKey(@Nullable String cacheKey);
public abstract Builder cacheName(@Nullable String cacheName);
public abstract Builder className(@Nullable String className);
public abstract Builder changeId(int changeId);
public abstract Builder changeIdType(@Nullable String changeIdType);
public abstract Builder eventType(@Nullable String eventType);
public abstract Builder exportValue(@Nullable String exportValue);
public abstract Builder garbageCollectorName(@Nullable String garbageCollectorName);
public abstract Builder gitOperation(@Nullable String gitOperation);
public abstract Builder groupId(int groupId);
public abstract Builder groupName(@Nullable String groupName);
public abstract Builder groupUuid(@Nullable String groupUuid);
public abstract Builder httpStatus(int httpStatus);
public abstract Builder indexName(@Nullable String indexName);
public abstract Builder indexVersion(int indexVersion);
public abstract Builder methodName(@Nullable String methodName);
public abstract Builder multiple(boolean multiple);
public abstract Builder noteDbFileName(@Nullable String noteDbFileName);
public abstract Builder noteDbRefName(@Nullable String noteDbRefName);
public abstract Builder noteDbSequenceType(@Nullable String noteDbSequenceType);
public abstract Builder noteDbTable(@Nullable String noteDbTable);
abstract ImmutableList.Builder<PluginMetadata> pluginMetadataBuilder();
public Builder addPluginMetadata(PluginMetadata pluginMetadata) {
pluginMetadataBuilder().add(pluginMetadata);
return this;
}
public abstract Builder pluginName(@Nullable String pluginName);
public abstract Builder projectName(@Nullable String projectName);
public abstract Builder pushType(@Nullable String pushType);
public abstract Builder resourceCount(int resourceCount);
public abstract Builder restViewName(@Nullable String restViewName);
public abstract Builder revision(@Nullable String revision);
public abstract Builder username(@Nullable String username);
public abstract Metadata build();
}
}