// Copyright 2017 Istio Authors
//
// 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.

syntax = "proto3";

// $title: Prometheus
// $description: Adapter that exposes Istio metrics for ingestion by a Prometheus harvester.
// $location: https://istio.io/docs/reference/config/policy-and-telemetry/adapters/prometheus.html
// $aliases:
// $  - /docs/reference/config/adapters/prometheus.html

// The `prometheus` adapter collects Istio metrics and makes them available to
// [Prometheus](https://prometheus.io).
//
// This adapter supports the [metric template](https://istio.io/docs/reference/config/policy-and-telemetry/templates/metric/).
package adapter.prometheus.config;

import "gogoproto/gogo.proto";
import "google/protobuf/duration.proto";

option go_package = "config";
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.equal_all) = false;
option (gogoproto.gostring_all) = false;

// Configuration format for the `prometheus` adapter.
message Params {
    // Describes how a metric should be represented in Prometheus.
    message MetricInfo {
        // next unused: 8

        // Optional. The namespace is used as a prefix on the metric names.
        // An example: for a metric named "requests_total" with a namespace of "istio",
        // the full metric name becomes "istio_requests_total".
        // NOTE: The specificed namespace should be a prometheus-safe name. If not, the adapter
        // will attempt to convert the namespace to a prometheus-safe name.
        // NOTE: Changing the value for this will potentially impact downstream integrations
        // and should be used with caution.
        // Default value: "istio".
        string namespace = 7;

        // Recommended. The name is used to register the prometheus metric.
        // It must be unique across all prometheus metrics as prometheus does not allow duplicate names.
        // If name is not specified a sanitized version of instance_name is used.
        string name = 1;

        // Required. The name is the fully qualified name of the Istio metric instance
        // that this MetricInfo processes.
        string instance_name = 2;

        // Optional. A human readable description of this metric.
        string description = 3;

        // Describes what kind of metric this is.
        enum Kind {
            UNSPECIFIED = 0;
            GAUGE = 1;
            COUNTER = 2;
            DISTRIBUTION = 3;
        }
        Kind kind = 4;

        // Describes buckets for DISTRIBUTION kind metrics.
        message BucketsDefinition {
            // Specifies a linear sequence of buckets that all have the same width
            // (except overflow and underflow). Each bucket represents a constant
            // absolute uncertainty on the specific value in the bucket.
            //
            // There are `num_finite_buckets + 2` (= `N`) buckets. The two additional
            // buckets are the underflow and overflow buckets.
            //
            // Bucket `i` has the following boundaries:
            //
            // * Upper bound (`0 <= i < N-1`): `offset + (width * i)`
            // * Lower bound (`1 <= i < N`): `offset + (width * (i - 1))`
            message Linear {
                // Must be greater than 0.
                int32 num_finite_buckets = 1;

                // Must be greater than 0.
                double width = 2;

                // Lower bound of the first bucket.
                double offset = 3;
            }

            // Specifies an exponential sequence of buckets that have a width that is
            // proportional to the value of the lower bound. Each bucket represents a
            // constant relative uncertainty on a specific value in the bucket.
            //
            // There are `num_finite_buckets + 2` (= `N`) buckets. The two additional
            // buckets are the underflow and overflow buckets.
            //
            // Bucket `i` has the following boundaries:
            //
            // * Upper bound (0 <= i < N-1): `scale * (growth_factor ^ i)`
            // * Lower bound (1 <= i < N): `scale * (growth_factor ^ (i - 1))`
            message Exponential {
                // Must be greater than 0.
                int32 num_finite_buckets = 1;

                // Must be greater than 1.
                double growth_factor = 2;

                // Must be greater than 0.
                double scale = 3;
            }

            // Specifies a set of buckets with arbitrary widths.
            //
            // There are `size(bounds) + 1` (= `N`) buckets. Bucket `i` has the following
            // boundaries:
            //
            // * Upper bound (`0 <= i < N-1`): `bounds[i]`
            // * Lower bound (`1 <= i < N`): `bounds[i - 1]`
            //
            // The `bounds` field must contain at least one element. If `bounds` has
            // only one element, then there are no finite buckets, and that single
            // element is the common boundary of the overflow and underflow buckets.
            message Explicit {
                // The values must be monotonically increasing.
                repeated double bounds = 1;
            }

            // Exactly one of these three fields must be set.
            oneof definition {
                // The linear buckets.
                Linear linear_buckets = 1;

                // The exponential buckets.
                Exponential exponential_buckets = 2;

                // The explicit buckets.
                Explicit explicit_buckets = 3;
            }
        }

        // For metrics with a metric kind of DISTRIBUTION, this provides a mechanism
        // for configuring the buckets that will be used to store the aggregated values.
        // This field must be provided for metrics declared to be of type DISTRIBUTION.
        // This field will be ignored for non-distribution metric kinds.
        BucketsDefinition buckets = 5;

        // The names of labels to use: these need to match the dimensions of the Istio metric.
        // TODO: see if we can remove this and rely on only the dimensions in the future.
        repeated string label_names = 6;

    }
    // The set of metrics to represent in Prometheus. If a metric is defined in Istio but doesn't have a corresponding
    // shape here, it will not be populated at runtime.
    repeated MetricInfo metrics = 1;

    // Describes the expiration policy for metrics generated by a prometheus handler.
    //
    // Example: A Metrics Expiration Policy of `{ metrics_expiry_duration: "10m", expiry_check_interval_duration: "1m" }`
    // would configure the handler to delete all metrics that have received no updtaes for 10 minutes. Metrics would be checked
    // every minute to determine whether or not they should be expired.
    message MetricsExpirationPolicy {
        // Required. Describes the desired lifetime of a metric. If the metric is not updated at any point during this duration, it
        // will be removed from the set of metrics exported by the handler.
        google.protobuf.Duration metrics_expiry_duration = 1 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true] ;

        // Optional. Describes the interval in which metrics will be checked to see if they have been stale for longer that the configured
        // `metrics_expiry_duration`. This should be generally be set to a duration much shorter than the configured `metrics_expiry_duration`.
        // This bounds the total amount of additional time (beyond the desired lifetime) that a metric may be exported.
        // If a value is not explicitly provided, this value will default to half of the configured `metrics_expiry_duration`.
        google.protobuf.Duration expiry_check_interval_duration  = 2 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
    }

    // Optional. The rate at which to expire metrics from the adapter. This option controls the amount of metric data
    // that the adapter will maintain over its lifetime.
    //
    // EXPERIMENTAL: This feature should only be used in advanced cases.
    //
    // Example config stanza:
    // ```yaml
    // metricsExpirationPolicy:
    //   metricsExpiryDuration: "5s"
    //   expiryCheckIntervalDuration: "1s"
    // ```
    MetricsExpirationPolicy metrics_expiration_policy = 2;
}
