// Copyright 2020 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.

/// This file contains interfaces that allow clients to log events that are
/// associated with metrics. These events are collected and later analyzed.
/// Metrics are organized under a Project, which are associated with a Customer.
/// Each of these objects has an integer ID and those IDs are used as parameters
/// in the methods in this file. Metrics can also have one or more dimensions
/// associated with them, which are then passed as a vector of event codes when
/// logging the event.
///
/// Usage: First use MetricEventLoggerFactory to get a MetricEventLogger for your
/// project. Then you log Events as they occur, using the Log*() methods on it.
///
/// The default implementation of this service in Fuchsia is Cobalt. For more
/// details on how to use these interfaces with Cobalt, see README.md.
library fuchsia.metrics;

/// The maximum size of a single Event is 100 KB.
const int64 MAX_BYTES_PER_EVENT = 102400;

/// This is intended as a reasonable maximum number of histogram buckets per
/// event.
const uint32 MAX_HISTOGRAM_BUCKETS = 500;

/// Maximum number of events that may be logged in a single FIDL call.
const uint32 MAX_BATCHED_EVENTS = 500;

/// String events should not be longer than this.
const uint32 MAX_STRING_EVENT_SIZE = 256;

/// Maximum number of event codes that can be associated with a single event.
const uint32 MAX_METRIC_DIMENSIONS = 10;

/// Response codes for MetricEventLogger operations.
enum Status : int32 {
    OK = 0;

    /// For example, the supplied metric id is invalid.
    INVALID_ARGUMENTS = 1;

    /// An attempt was made to log an Event whose serialized size exceeds
    /// MAX_BYTES_PER_EVENT.
    EVENT_TOO_BIG = 2;

    /// The logger's local buffer is temporarily full and cannot handle any more
    /// Events at this time. Try again later. This condition should be rare.
    BUFFER_FULL = 3;

    // The logger has received a ShutDown signal and will not accept any more
    // events.
    SHUT_DOWN = 4;

    /// Catch-all for unexpected errors.
    INTERNAL_ERROR = -1;
};

/// A specification identifying a project to log events for.
table ProjectSpec {
    /// The customer ID. If omitted (i.e. set to 0) then it defaults to the
    /// customer ID for the default "fuchsia" customer.
    1: uint32 customer_id;

    /// The ID of the project.
    2: uint32 project_id;
};

/// A factory that is used to create a MetricEventLogger for a specific project.
[Discoverable]
protocol MetricEventLoggerFactory {
    /// Create a MetricEventLogger for the project specified by `project_spec`.
    CreateMetricEventLogger(ProjectSpec project_spec,
                            request<MetricEventLogger> logger)
        -> (Status status);
};

/// A vector of event codes. When used in one of the Log*() calls below,
/// there must be one event code for each dimension of the metric whose
/// metric_id is supplied, or else the call will return INVALID_ARGUMENTS.
alias event_vector = vector<uint32>:MAX_METRIC_DIMENSIONS;

/// A histogram that assigns a count to each of several integer ranges.
/// The order of the vector is immaterial.
alias integer_histogram = vector<HistogramBucket>:MAX_HISTOGRAM_BUCKETS;

/// A logger for events that are associated with one project's metrics.
protocol MetricEventLogger {
    /// Logs the fact that an event has occurred a number of times.
    ///
    /// `metric_id` ID of the metric being logged.
    ///
    /// `count` The number of times the event has occurred. The value should
    /// be positive as a value of 0 is ignored.
    ///
    /// `event_codes` Ordered list of parameters, one for each of the metric's
    /// dimensions. Occurrence counts with the same event codes are aggregated
    /// based on these parameters.
    LogOccurrence(uint32 metric_id, uint64 count, event_vector event_codes)
        -> (Status status);

    /// Logs an integer measurement.
    ///
    /// `metric_id` ID of the metric being logged.
    ///
    /// `value` The integer measurement.
    ///
    /// `event_codes` Ordered list of parameters, one for each of the metric's
    /// dimensions. Integer values with the same event codes are aggregated
    /// based on these parameters.
    LogInteger(uint32 metric_id, int64 value, event_vector event_codes)
        -> (Status status);

    /// Logs a histogram giving many approximate integer measurements.
    ///
    /// `metric_id` ID of the metric being logged.
    ///
    /// `histogram` The collection of approximate integer measurements.
    ///
    /// `event_codes` Ordered list of parameters, one for each of the metric's
    /// dimensions. Histograms with the same event codes are aggregated together
    /// based on these parameters.
    LogIntegerHistogram(uint32 metric_id, integer_histogram histogram,
                        event_vector event_codes)
        -> (Status status);

    /// Logs a string value that was observed.
    ///
    /// `metric_id` ID of the metric being logged.
    ///
    /// `string_value` The string to log.
    ///
    /// `event_codes` Ordered list of parameters, one for each of the metric's
    /// dimensions. Counts of logged strings are aggregated separately based on
    /// these parameters.
    LogString(uint32 metric_id, string:MAX_STRING_EVENT_SIZE string_value,
              event_vector event_codes)
        -> (Status status);

    /// Bulk logging method, equivalent to making many of the above Log*() calls
    /// at once.
    LogMetricEvents(vector<MetricEvent>:MAX_BATCHED_EVENTS events)
        -> (Status status);

    /// Logs a custom Event.
    ///
    /// `metric_id` ID of the metric being logged.
    ///
    /// `event_values` The values for the custom Event. There must be one value
    /// for each dimension of the metric and the types of the values must
    /// be consistent with the dimensions declared in the metric definition.
    LogCustomEvent(uint32 metric_id, vector<CustomEventValue>:MAX event_values)
        -> (Status status);
};

/// A specification of an event that occurred to be passed to LogMetricEvents().
struct MetricEvent {
    /// ID of the metric being logged.
    uint32 metric_id;

    /// `event_codes` Ordered list of parameters, one for each of the metric's
    /// dimensions.
    event_vector event_codes;

    /// The metric-type-specific data for the event being logged.
    MetricEventPayload payload;
};

/// The variadic part of a MetricEvent.
flexible union MetricEventPayload {
    /// The number of times the event has occurred, see LogOccurrence().
    1: uint64 count;

    /// The integer measured, see LogInteger().
    2: int64 integer_value;

    /// The collection of approximate integer measurements, see
    /// LogIntegerHistogram().
    3: integer_histogram histogram;

    /// The string to log, see LogString().
    4: string:MAX_STRING_EVENT_SIZE string_value;
};

/// A value for a custom event. This is used by the method LogCustomEvent().
struct CustomEventValue {
    /// The name of the metric's dimension this value is for.
    string:MAX dimension_name;

    /// The value for that dimension.
    Value value;
};

/// A custom event value that may be a string, int, double, or index.
union Value {
    1: string:MAX string_value;
    2: int64 int_value;
    3: float64 double_value;
    4: uint32 index_value;
};

/// One bucket of a histogram, used by the method LogIntegerHistogram.
struct HistogramBucket {
    /// The index of the bucket. The metric includes a specification
    /// of a sequence of N+1 integer-range buckets that are indexed from
    /// 0, the underflow bucket, to N, the overflow bucket.
    uint32 index;

    /// The number of values in that bucket.
    uint64 count;
};
