diff options
Diffstat (limited to 'java/com/google/gerrit/metrics/Description.java')
-rw-r--r-- | java/com/google/gerrit/metrics/Description.java | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/java/com/google/gerrit/metrics/Description.java b/java/com/google/gerrit/metrics/Description.java new file mode 100644 index 0000000000..10568bcd6d --- /dev/null +++ b/java/com/google/gerrit/metrics/Description.java @@ -0,0 +1,199 @@ +// Copyright (C) 2015 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.metrics; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** Describes a metric created by {@link MetricMaker}. */ +public class Description { + public static final String DESCRIPTION = "DESCRIPTION"; + public static final String UNIT = "UNIT"; + public static final String CUMULATIVE = "CUMULATIVE"; + public static final String RATE = "RATE"; + public static final String GAUGE = "GAUGE"; + public static final String CONSTANT = "CONSTANT"; + public static final String FIELD_ORDERING = "FIELD_ORDERING"; + public static final String TRUE_VALUE = "1"; + + public static class Units { + public static final String SECONDS = "seconds"; + public static final String MILLISECONDS = "milliseconds"; + public static final String MICROSECONDS = "microseconds"; + public static final String NANOSECONDS = "nanoseconds"; + + public static final String BYTES = "bytes"; + + private Units() {} + } + + public enum FieldOrdering { + /** Default ordering places fields at end of the parent metric name. */ + AT_END, + + /** + * Splits the metric name by inserting field values before the last '/' in the metric name. For + * example {@code "plugins/replication/push_latency"} with a {@code Field.ofString("remote")} + * will create submetrics named {@code "plugins/replication/some-server/push_latency"}. + */ + PREFIX_FIELDS_BASENAME; + } + + private final Map<String, String> annotations; + + /** + * Describe a metric. + * + * @param helpText a short one-sentence string explaining the values captured by the metric. This + * may be made available to administrators as documentation in the reporting tools. + */ + public Description(String helpText) { + annotations = Maps.newLinkedHashMapWithExpectedSize(4); + annotations.put(DESCRIPTION, helpText); + } + + /** + * Set unit used to describe the value. + * + * @param unitName name of the unit, e.g. "requests", "seconds", etc. + * @return this + */ + public Description setUnit(String unitName) { + annotations.put(UNIT, unitName); + return this; + } + + /** + * Mark the value as constant for the life of this process. Typically used for software versions, + * command line arguments, etc. that cannot change without a process restart. + * + * @return this + */ + public Description setConstant() { + annotations.put(CONSTANT, TRUE_VALUE); + return this; + } + + /** + * Indicates the metric may be usefully interpreted as a count over short periods of time, such as + * request arrival rate. May only be applied to a {@link Counter0}. + * + * @return this + */ + public Description setRate() { + annotations.put(RATE, TRUE_VALUE); + return this; + } + + /** + * Instantaneously sampled value that may increase or decrease at a later time. Memory allocated + * or open network connections are examples of gauges. + * + * @return this + */ + public Description setGauge() { + annotations.put(GAUGE, TRUE_VALUE); + return this; + } + + /** + * Indicates the metric accumulates over the lifespan of the process. A {@link Counter0} like + * total requests handled accumulates over the process and should be {@code setCumulative()}. + * + * @return this + */ + public Description setCumulative() { + annotations.put(CUMULATIVE, TRUE_VALUE); + return this; + } + + /** + * Configure how fields are ordered into submetric names. + * + * @param ordering field ordering + * @return this + */ + public Description setFieldOrdering(FieldOrdering ordering) { + annotations.put(FIELD_ORDERING, ordering.name()); + return this; + } + + /** @return true if the metric value never changes after startup. */ + public boolean isConstant() { + return TRUE_VALUE.equals(annotations.get(CONSTANT)); + } + + /** @return true if the metric may be interpreted as a rate over time. */ + public boolean isRate() { + return TRUE_VALUE.equals(annotations.get(RATE)); + } + + /** @return true if the metric is an instantaneous sample. */ + public boolean isGauge() { + return TRUE_VALUE.equals(annotations.get(GAUGE)); + } + + /** @return true if the metric accumulates over the lifespan of the process. */ + public boolean isCumulative() { + return TRUE_VALUE.equals(annotations.get(CUMULATIVE)); + } + + /** @return the suggested field ordering. */ + public FieldOrdering getFieldOrdering() { + String o = annotations.get(FIELD_ORDERING); + return o != null ? FieldOrdering.valueOf(o) : FieldOrdering.AT_END; + } + + /** + * Decode the unit as a unit of time. + * + * @return valid time unit. + * @throws IllegalArgumentException if the unit is not a valid unit of time. + */ + public TimeUnit getTimeUnit() { + return getTimeUnit(annotations.get(UNIT)); + } + + private static final ImmutableMap<String, TimeUnit> TIME_UNITS = + ImmutableMap.of( + Units.NANOSECONDS, TimeUnit.NANOSECONDS, + Units.MICROSECONDS, TimeUnit.MICROSECONDS, + Units.MILLISECONDS, TimeUnit.MILLISECONDS, + Units.SECONDS, TimeUnit.SECONDS); + + public static TimeUnit getTimeUnit(String unit) { + if (Strings.isNullOrEmpty(unit)) { + throw new IllegalArgumentException("no unit configured"); + } + TimeUnit u = TIME_UNITS.get(unit); + if (u == null) { + throw new IllegalArgumentException(String.format("unit %s not TimeUnit", unit)); + } + return u; + } + + /** @return immutable copy of all annotations (configurable properties). */ + public ImmutableMap<String, String> getAnnotations() { + return ImmutableMap.copyOf(annotations); + } + + @Override + public String toString() { + return annotations.toString(); + } +} |