1
#pragma once
2

            
3
#include <string>
4

            
5
#include "envoy/buffer/buffer.h"
6
#include "envoy/stats/custom_stat_namespaces.h"
7
#include "envoy/stats/histogram.h"
8
#include "envoy/stats/stats.h"
9

            
10
#include "source/server/admin/stats_params.h"
11

            
12
namespace Envoy {
13
namespace Server {
14
/**
15
 * Formatter for metric/labels exported to Prometheus.
16
 *
17
 * See: https://prometheus.io/docs/concepts/data_model
18
 */
19
class PrometheusStatsFormatter {
20
public:
21
  // Responsible for converting groups of metrics into the raw output format (such as prometheus
22
  // text exposition format or prometheus protobuf exposition format).
23
  class OutputFormat {
24
  public:
25
    virtual ~OutputFormat() = default;
26

            
27
    enum class HistogramType {
28
      Summary,
29
      ClassicHistogram,
30
      NativeHistogram,
31
    };
32

            
33
64
    void setHistogramType(HistogramType type) { histogram_type_ = type; }
34

            
35
140
    HistogramType histogramType() const { return histogram_type_; }
36

            
37
    // Return the prometheus output for a group of Counters.
38
    virtual void generateOutput(Buffer::Instance& output,
39
                                const std::vector<const Stats::Counter*>& counters,
40
                                const std::string& prefixed_tag_extracted_name) const PURE;
41

            
42
    // Return the prometheus output for a group of PrimitiveCounters.
43
    virtual void generateOutput(Buffer::Instance& output,
44
                                const std::vector<const Stats::PrimitiveCounterSnapshot*>& counters,
45
                                const std::string& prefixed_tag_extracted_name) const PURE;
46

            
47
    // Return the prometheus output for a group of Gauges.
48
    virtual void generateOutput(Buffer::Instance& output,
49
                                const std::vector<const Stats::Gauge*>& gauges,
50
                                const std::string& prefixed_tag_extracted_name) const PURE;
51

            
52
    // Returns the prometheus output for a group of TextReadouts.
53
    virtual void generateOutput(Buffer::Instance& output,
54
                                const std::vector<const Stats::TextReadout*>& text_readouts,
55
                                const std::string& prefixed_tag_extracted_name) const PURE;
56

            
57
    // Return the prometheus output for a group of PrimitiveGauges.
58
    virtual void generateOutput(Buffer::Instance& output,
59
                                const std::vector<const Stats::PrimitiveGaugeSnapshot*>& gauges,
60
                                const std::string& prefixed_tag_extracted_name) const PURE;
61

            
62
    // Return the prometheus output for a group of Histograms.
63
    virtual void generateOutput(Buffer::Instance& output,
64
                                const std::vector<const Stats::ParentHistogram*>& histograms,
65
                                const std::string& prefixed_tag_extracted_name) const PURE;
66

            
67
  private:
68
    HistogramType histogram_type_;
69
  };
70

            
71
  /**
72
   * Extracts counters and gauges and relevant tags, appending them to
73
   * the response buffer after sanitizing the metric / label names.
74
   * Detects based on request headers whether to emit text or protobuf format.
75
   * @return uint64_t total number of metric types inserted in response.
76
   */
77
  static uint64_t statsAsPrometheus(const std::vector<Stats::CounterSharedPtr>& counters,
78
                                    const std::vector<Stats::GaugeSharedPtr>& gauges,
79
                                    const std::vector<Stats::ParentHistogramSharedPtr>& histograms,
80
                                    const std::vector<Stats::TextReadoutSharedPtr>& text_readouts,
81
                                    const Upstream::ClusterManager& cluster_manager,
82
                                    const Http::RequestHeaderMap& request_headers,
83
                                    Http::ResponseHeaderMap& response_headers,
84
                                    Buffer::Instance& response, const StatsParams& params,
85
                                    const Stats::CustomStatNamespaces& custom_namespaces);
86

            
87
  static uint64_t
88
  statsAsPrometheusText(const std::vector<Stats::CounterSharedPtr>& counters,
89
                        const std::vector<Stats::GaugeSharedPtr>& gauges,
90
                        const std::vector<Stats::ParentHistogramSharedPtr>& histograms,
91
                        const std::vector<Stats::TextReadoutSharedPtr>& text_readouts,
92
                        const Upstream::ClusterManager& cluster_manager, Buffer::Instance& response,
93
                        const StatsParams& params,
94
                        const Stats::CustomStatNamespaces& custom_namespaces);
95

            
96
  static uint64_t
97
  statsAsPrometheusProtobuf(const std::vector<Stats::CounterSharedPtr>& counters,
98
                            const std::vector<Stats::GaugeSharedPtr>& gauges,
99
                            const std::vector<Stats::ParentHistogramSharedPtr>& histograms,
100
                            const std::vector<Stats::TextReadoutSharedPtr>& text_readouts,
101
                            const Upstream::ClusterManager& cluster_manager,
102
                            Http::ResponseHeaderMap& response_headers, Buffer::Instance& response,
103
                            const StatsParams& params,
104
                            const Stats::CustomStatNamespaces& custom_namespaces);
105

            
106
  static uint64_t
107
  generateWithOutputFormat(const std::vector<Stats::CounterSharedPtr>& counters,
108
                           const std::vector<Stats::GaugeSharedPtr>& gauges,
109
                           const std::vector<Stats::ParentHistogramSharedPtr>& histograms,
110
                           const std::vector<Stats::TextReadoutSharedPtr>& text_readouts,
111
                           const Upstream::ClusterManager& cluster_manager,
112
                           Buffer::Instance& response, const StatsParams& params,
113
                           const Stats::CustomStatNamespaces& custom_namespaces,
114
                           OutputFormat& output_format);
115

            
116
  /**
117
   * Format the given tags, returning a string as a comma-separated list
118
   * of <tag_name>="<tag_value>" pairs.
119
   */
120
  static std::string formattedTags(const std::vector<Stats::Tag>& tags);
121

            
122
  /**
123
   * Validate the given params, returning an error on invalid arguments
124
   */
125
  static absl::Status validateParams(const StatsParams& params,
126
                                     const Http::RequestHeaderMap& headers);
127

            
128
  /**
129
   * Format the given metric name, and prefixed with "envoy_" if it does not have a custom
130
   * stat namespace. If it has a custom stat namespace AND the name without the custom namespace
131
   * has a valid prometheus namespace, the trimmed name is returned.
132
   * Otherwise, return nullopt.
133
   */
134
  static absl::optional<std::string>
135
  metricName(const std::string& extracted_name,
136
             const Stats::CustomStatNamespaces& custom_namespace_factory);
137
};
138

            
139
} // namespace Server
140
} // namespace Envoy