[metrics] Define Counter and related data structures

Add a definition for Counter, which is a type of metric ART can
collect. Note that this does not yet define any particular counters,
just the infrastructure needed to add them.

Bug: 160734914
Test: m test-art-host-gtest-art_libartbase_tests
Change-Id: Ideabadbf3cca222911da357af56c7ebc2ab637fd
diff --git a/libartbase/base/metrics.h b/libartbase/base/metrics.h
new file mode 100644
index 0000000..735b366
--- /dev/null
+++ b/libartbase/base/metrics.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef ART_LIBARTBASE_BASE_METRICS_H_
+#define ART_LIBARTBASE_BASE_METRICS_H_
+
+#include <stdint.h>
+
+#include <array>
+#include <ostream>
+#include <string_view>
+
+#include "base/time_utils.h"
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wconversion"
+
+// COUNTER(counter_name)
+#define ART_COUNTERS(COUNTER) COUNTER(ClassVerificationTotalTime)
+// TODO: ClassVerificationTime serves as a mock for now. Implementation will come later.
+
+namespace art {
+namespace metrics {
+
+/**
+ * An enumeration of all ART counters and histograms.
+ */
+enum class DatumId {
+#define ART_COUNTER(name) k##name,
+  ART_COUNTERS(ART_COUNTER)
+#undef ART_COUNTER
+};
+
+struct SessionData {
+  const uint64_t session_id;
+  const std::string_view package_name;
+  // TODO: compiler filter / dexopt state
+};
+
+// MetricsBackends are used by a metrics reporter to write metrics to some external location. For
+// example, a backend might write to logcat, or to a file, or to statsd.
+class MetricsBackend {
+ public:
+  virtual ~MetricsBackend() {}
+
+ protected:
+  // Begins an ART metrics session.
+  //
+  // This is called by the metrics reporter when the runtime is starting up. The session_data
+  // includes a session id which is used to correlate any metric reports with the same instance of
+  // the ART runtime. Additionally, session_data includes useful metadata such as the package name
+  // for this process.
+  virtual void BeginSession(const SessionData& session_data) = 0;
+
+  // Marks the end of a metrics session.
+  //
+  // The metrics reporter will call this when metrics reported ends (e.g. when the runtime is
+  // shutting down). No further metrics will be reported for this session. Note that EndSession is
+  // not guaranteed to be called, since clean shutdowns for the runtime are quite rare in practice.
+  virtual void EndSession() = 0;
+
+  // Called by the metrics reporter to give the current value of the counter with id counter_type.
+  //
+  // This will be called multiple times for each counter based on when the metrics reporter chooses
+  // to report metrics. For example, the metrics reporter may call this at shutdown or every N
+  // minutes. Counters are not reset in between invocations, so the value should represent the
+  // total count at the point this method is called.
+  virtual void ReportCounter(DatumId counter_type, uint64_t value) = 0;
+
+  friend class ArtMetrics;
+};
+
+class MetricsCounter {
+ public:
+  explicit constexpr MetricsCounter(uint64_t value = 0) : value_{value} {}
+
+  void AddOne() { value_++; }
+  void Add(uint64_t value) { value_ += value; }
+
+  uint64_t Value() const { return value_; }
+
+ private:
+  uint64_t value_;
+};
+
+/**
+ * This struct contains all of the metrics that ART reports.
+ */
+class ArtMetrics {
+ public:
+  ArtMetrics();
+
+  void ReportAllMetrics(MetricsBackend* backend) const;
+
+#define ART_COUNTER(name) MetricsCounter name;
+  ART_COUNTERS(ART_COUNTER)
+#undef ART_COUNTER
+
+ private:
+  // This field is only included to allow us expand the ART_COUNTERS and ART_HISTOGRAMS macro in
+  // the initializer list in ArtMetrics::ArtMetrics. See metrics.cc for how it's used.
+  //
+  // It's declared as a zero-length array so it has no runtime space impact.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-private-field"
+  int unused_[0];
+#pragma clang diagnostic pop  // -Wunused-private-field
+};
+
+// Returns a human readable name for the given DatumId.
+std::string DatumName(DatumId datum);
+
+}  // namespace metrics
+}  // namespace art
+
+#pragma clang diagnostic pop  // -Wconversion
+
+#endif  // ART_LIBARTBASE_BASE_METRICS_H_