blob: ed04d7f20fb4b2e81d8db77574b25323bda1c33e [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <stdint.h>
#include <fbl/function.h>
#include <fbl/string.h>
namespace cobalt_client {
// Defines basic set of options for instantiating a metric.
struct MetricOptions {
enum class Mode : uint8_t {
// This mode marks a set of options as a placeholder, allowing metric instantiations to
// defer initialization to a later stage.
kLazy,
// Metric is aggregated locally and published via collector interface.
kLocal,
// Metric deltas are aggregated locally, and sent for global aggregation to a remote
// service.
kRemote,
// Combination of kLocal and kRemote.
kRemoteAndLocal,
};
void SetMode(Mode mode) { this->mode = mode; }
// Returns true if the metrics supports remote collection.
// This is values collected by another service, such as Cobalt.
bool IsRemote() const { return mode == Mode::kRemote || mode == Mode::kRemoteAndLocal; }
// Returns true if the metric supports in process collection.
// This is values tied to the process life-time.
bool IsLocal() const { return mode == Mode::kLocal || mode == Mode::kRemoteAndLocal; }
// Returns true if this does not represent a valid configuration, and is in |kLazy| mode.
bool IsLazy() const { return mode == Mode::kLazy; }
// Required for local metrics. If not set, and metric is both Local and Remote,
// this will be generated from the |metric_id|, |event_code|(if not 0) and |component|(if not
// empty).
fbl::String name;
// Provides refined metric collection for remote and local metrics.
// Warning: |component| is not yet supported in the backend, so it will be ignored.
fbl::String component;
// Function that translates |metric_id| to a human readable name.
// If returns |nullptr| or is unset, the stringified version of |uint32_t| will be used.
const char* (*get_metric_name)(uint32_t);
// Function that translates |event_code| to a human readable name.
// If returns |nullptr| or is unset, the stringified version of |uint32_t| will be used.
const char* (*get_event_name)(uint32_t);
// Used by remote metrics to match with the respective unique id for the projects defined
// metrics in the backend.
uint32_t metric_id;
// Provides refined metric collection for |kRemote| and |kLocal| metrics.
// |event_code| 0 is reserved for Unknown events.
// Warning: |event_code| is not yet supported in the backend, so it will be set to 0.
uint32_t event_code;
// Defines whether the metric is local or remote.
// Internal use, should not be set manually.
Mode mode = Mode::kLazy;
};
// Describes an histogram, and provides data for mapping a value to a given bucket.
// Every histogram contains two additional buckets, one at index 0 and bucket_count + 1.
// These buckets are used to store underflow and overflow respectively.
//
// buckets = [-inf, min_value) ...... [max_value, +inf)
//
// Parameters are calculated by the factory methods based on the input parameters,
// so that expectations are met.
//
// If using cobalt to flush your observations to the backend, this options should match
// your metric definitions for correct behavior. Mismatch with the respective metric definition
// will not allow proper collection and aggregation of metrics in the backend.
struct HistogramOptions : public MetricOptions {
enum class Type {
// Each bucket is described in the following form:
// range(i) = [ b * i + c, b * {i +1} + c)
// i = (val - c) / b
kLinear,
// Each bucket is described in the following form:
// range(i) = [ b * a^i + c, b * a^{i+1} + c)
// The cost of this type is O(1), because:
// i = floor(log (val - c) - log b)/log a
kExponential,
};
// Returns HistogramOptions that:
// * Exponential bucket range with base 2 => lower_bound[i] = a*2^i-1 - 1
// * Has underflow bucket from (-inf, 0)
// * The first bucket contains [0, 1)
// * a is an integer greater or equal to 1.
// * if |max| % (2^|bucket_count| - 1):
// - Is not 0, then |max| is contained in the last bucket.
// - Is 0, then |max| is the lower bound of the overflow bucket.
//
// For example:
// - With bucket_count 12 and max 40950, we get scalar 10, base 2,
// and offset -10.
// - With bucket_count 12 and max 40960, we get scalar 11, base 2,
// and offset -11.
static HistogramOptions Exponential(uint32_t bucket_count, int64_t max);
// Returns HistogramOptions that:
// * Exponential bucket range with base 2 => lower_bound[i] = a*2^i-1 - 1
// * Has underflow bucket from (-inf, min)
// * The first bucket contains [min, min+1)
// * a is an integer greater or equal to 1.
// * if |max - min| % (2^|bucket_count| - 1):
// - Is not, then |max| is contained in the last bucket.
// - Is 0, then |max| is the lower bound of the overflow bucket.
static HistogramOptions Exponential(uint32_t bucket_count, int64_t min, int64_t max);
// Returns HistogramOptions that:
// * Has an extra underflow bucket.
// * Has an extra overflow bucket.
// * For every bucket from i = 1 to |bucket_count| has a lower bound defined by:
// scalar * (base^(i-1) - 1) + min
static HistogramOptions CustomizedExponential(uint32_t bucket_count, uint32_t base,
uint32_t scalar, int64_t min);
// Returns HistogramOptions that:
// * Linear bucket range with fixed step size ceil(|max|/|bucket_count|).
// * Has underflow bucket from (-inf, 0)
// * The first bucket contains [0, step_size)
// * |max| is contained in the last bucket if its not a multiple of |bucket_count|.
static HistogramOptions Linear(uint32_t bucket_count, int64_t max);
// Returns HistogramOptions that:
// * Linear bucket range with fixed step size ceil(|max|/|bucket_count|).
// * Has underflow bucket from (-inf, 0)
// * The first bucket contains [0, step_size)
// * |max| is contained in the last bucket if its not a multiple of |bucket_count|.
static HistogramOptions Linear(uint32_t bucket_count, int64_t min, int64_t max);
// Returns HistogramOptions that:
// * Has an extra underflow bucket.
// * Has an extra overflow bucket.
// * For every bucket from i = 1 to |bucket_count| has a lower bound defined by:
// min + step_size * (i-1)
static HistogramOptions CustomizedLinear(uint32_t bucket_count, uint32_t step_size,
int64_t min);
HistogramOptions() = default;
HistogramOptions(const HistogramOptions&);
HistogramOptions& operator=(const HistogramOptions&);
// Sanity check.
bool IsValid() const;
// This parameters should not be set manually.
// Function used for mapping a value to a given bucket.
uint32_t (*map_fn)(double, uint32_t, const HistogramOptions&) = nullptr;
// Function used for mapping a bucket to its lowerbound.
double (*reverse_map_fn)(uint32_t, uint32_t, const HistogramOptions&) = nullptr;
// Base to describe the width of each step, in |kExponentialWidth|.
double base = 1;
// Scalar used by the type. This scales the width of each step.
double scalar = 1;
// This matchest offset', which is calculated depending on the histogram type.
double offset = 0;
// Bounds for the histogram.
double max_value = 0;
// Type of the histogram to be constructed.
Type type;
};
} // namespace cobalt_client