1
#include "source/server/admin/stats_params.h"
2

            
3
namespace Envoy {
4
namespace Server {
5

            
6
133
Http::Code StatsParams::parse(absl::string_view url, Buffer::Instance& response) {
7
133
  query_ = Http::Utility::QueryParamsMulti::parseAndDecodeQueryString(url);
8
133
  used_only_ = query_.getFirstValue("usedonly").has_value();
9
133
  pretty_ = query_.getFirstValue("pretty").has_value();
10
133
  prometheus_text_readouts_ = query_.getFirstValue("text_readouts").has_value();
11

            
12
133
  auto filter_val = query_.getFirstValue("filter");
13
133
  if (filter_val.has_value() && !filter_val.value().empty()) {
14
30
    filter_string_ = filter_val.value();
15
30
    re2::RE2::Options options;
16
30
    options.set_log_errors(false);
17
30
    re2_filter_ = std::make_shared<re2::RE2>(filter_string_, options);
18
30
    if (!re2_filter_->ok()) {
19
3
      response.add(absl::StrCat("Invalid re2 regex: ", re2_filter_->error()));
20
3
      return Http::Code::BadRequest;
21
3
    }
22
30
  }
23

            
24
130
  absl::Status status = Utility::histogramBucketsParam(query_, histogram_buckets_mode_);
25
130
  if (!status.ok()) {
26
1
    response.add(status.message());
27
1
    return Http::Code::BadRequest;
28
1
  }
29

            
30
129
  auto max_buckets_val = query_.getFirstValue("native_histogram_max_buckets");
31
129
  if (max_buckets_val.has_value() && !max_buckets_val.value().empty()) {
32
    uint32_t max_buckets;
33
    if (!absl::SimpleAtoi(max_buckets_val.value(), &max_buckets) || max_buckets < 1) {
34
      response.add("invalid native_histogram_max_buckets value: must be a positive integer");
35
      return Http::Code::BadRequest;
36
    }
37
    native_histogram_max_buckets_ = max_buckets;
38
  }
39

            
40
129
  auto parse_type = [](absl::string_view str, StatsType& type) {
41
7
    if (str == StatLabels::Gauges) {
42
1
      type = StatsType::Gauges;
43
6
    } else if (str == StatLabels::Counters) {
44
2
      type = StatsType::Counters;
45
5
    } else if (str == StatLabels::Histograms) {
46
1
      type = StatsType::Histograms;
47
3
    } else if (str == StatLabels::TextReadouts) {
48
1
      type = StatsType::TextReadouts;
49
2
    } else if (str == StatLabels::All) {
50
1
      type = StatsType::All;
51
1
    } else {
52
1
      return false;
53
1
    }
54
6
    return true;
55
7
  };
56

            
57
129
  auto type_val = query_.getFirstValue("type");
58
129
  if (type_val.has_value() && !type_val.value().empty() && !parse_type(type_val.value(), type_)) {
59
1
    response.add("invalid &type= param");
60
1
    return Http::Code::BadRequest;
61
1
  }
62

            
63
128
  const absl::optional<std::string> hidden_value = query_.getFirstValue("hidden");
64
128
  if (hidden_value.has_value() && !hidden_value.value().empty()) {
65
8
    if (hidden_value.value() == "include") {
66
2
      hidden_ = HiddenFlag::Include;
67
6
    } else if (hidden_value.value() == "only") {
68
2
      hidden_ = HiddenFlag::ShowOnly;
69
4
    } else if (hidden_value.value() == "exclude") {
70
2
      hidden_ = HiddenFlag::Exclude;
71
2
    } else {
72
2
      response.add("usage: /stats?hidden=(include|only|exclude)\n\n");
73
2
      return Http::Code::BadRequest;
74
2
    }
75
8
  }
76

            
77
126
  const absl::optional<std::string> format_value = Utility::formatParam(query_);
78
126
  if (format_value.has_value() && !format_value.value().empty()) {
79
63
    if (format_value.value() == "prometheus") {
80
14
      format_ = StatsFormat::Prometheus;
81
49
    } else if (format_value.value() == "json") {
82
38
      format_ = StatsFormat::Json;
83
41
    } else if (format_value.value() == "text") {
84
1
      format_ = StatsFormat::Text;
85
10
    } else if (format_value.value() == "html") {
86
4
#ifdef ENVOY_ADMIN_HTML
87
4
      format_ = StatsFormat::Html;
88
#else
89
      response.add("HTML output was disabled by building with --define=admin_html=disabled");
90
      return Http::Code::BadRequest;
91
#endif
92
8
    } else if (format_value.value() == "active-html") {
93
1
#ifdef ENVOY_ADMIN_HTML
94
1
      format_ = StatsFormat::ActiveHtml;
95
#else
96
      response.add("Active HTML output was disabled by building with --define=admin_html=disabled");
97
      return Http::Code::BadRequest;
98
#endif
99
5
    } else {
100
5
      response.add("usage: /stats?format=(html|active-html|json|prometheus|text)\n\n");
101
5
      return Http::Code::BadRequest;
102
5
    }
103
63
  }
104

            
105
121
  return Http::Code::OK;
106
126
}
107

            
108
5
absl::string_view StatsParams::typeToString(StatsType type) {
109
5
  absl::string_view ret;
110
5
  switch (type) {
111
1
  case StatsType::TextReadouts:
112
1
    ret = StatLabels::TextReadouts;
113
1
    break;
114
1
  case StatsType::Counters:
115
1
    ret = StatLabels::Counters;
116
1
    break;
117
1
  case StatsType::Gauges:
118
1
    ret = StatLabels::Gauges;
119
1
    break;
120
1
  case StatsType::Histograms:
121
1
    ret = StatLabels::Histograms;
122
1
    break;
123
1
  case StatsType::All:
124
1
    ret = StatLabels::All;
125
1
    break;
126
5
  }
127
5
  return ret;
128
5
}
129

            
130
} // namespace Server
131
} // namespace Envoy