AnyCollect  1.1.2
Matcher.cc
Go to the documentation of this file.
1 //
2 // Matcher.cc
3 //
4 // Created on October 25th 2018
5 //
6 // Copyright 2018 CFM (www.cfm.fr)
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 //
20 
21 #include <cmath>
22 
23 #include <tinyexpr/tinyexpr.h>
24 
25 #include "Matcher.h"
26 
27 
28 namespace AnyCollect {
29  Matcher::Matcher() noexcept { }
30 
31  Matcher::Matcher(const Config::expression::metric& config) noexcept :
32  name_(config.name),
33  value_(config.value),
34  unit_(config.unit),
35  tags_(config.tags),
36  computeRate_(config.computeRate),
37  convertToUnitsPerSecond_(config.convertToUnitsPerSecond)
38  { }
39 
40 
41  const std::vector<std::string>& Matcher::name() const noexcept {
42  return this->name_;
43  }
44 
45  const std::string& Matcher::value() const noexcept {
46  return this->value_;
47  }
48 
49  const std::string& Matcher::unit() const noexcept {
50  return this->unit_;
51  }
52 
53  const std::map<std::string, std::string>& Matcher::tags() const noexcept {
54  return this->tags_;
55  }
56 
57  bool Matcher::computeRate() const noexcept {
58  return this->computeRate_;
59  }
60 
61  bool Matcher::convertToUnitsPerSecond() const noexcept {
62  return this->convertToUnitsPerSecond_;
63  }
64 
65 
66  void Matcher::setName(const std::vector<std::string>& name) noexcept {
67  this->name_ = name;
68  }
69 
70  void Matcher::setValue(const std::string& value) noexcept {
71  this->value_ = value;
72  }
73 
74  void Matcher::setUnit(const std::string& unit) noexcept {
75  this->unit_ = unit;
76  }
77 
78  void Matcher::setTags(const std::map<std::string, std::string>& tags) noexcept {
79  this->tags_ = tags;
80  }
81 
82  void Matcher::setComputeRate(bool computeRate) noexcept {
83  this->computeRate_ = computeRate;
84  }
85 
86  void Matcher::setConvertToUnitsPerSecond(bool convertToUnitsPerSecond) noexcept {
87  this->convertToUnitsPerSecond_ = convertToUnitsPerSecond;
88  }
89 
90 
91  inline uint64_t parseUint(const char*& buffer) noexcept {
92  uint64_t result = 0;
93  while (!std::isdigit(*buffer))
94  buffer++;
95  while (std::isdigit(*buffer)) {
96  result = (result << 1) + (result << 3) + *buffer - '0';
97  buffer++;
98  }
99  return result;
100  }
101 
102  inline void replaceMatches(std::string& str, const std::cmatch& match, const std::vector<std::string>& pathParts) {
103  const char* buffer = str.data();
104  bool escaped = false;
105  while (*buffer != '\0') {
106  if (escaped) {
107  if (*buffer == Matcher::matchSubstitutionPrefix || *buffer == Matcher::matchEscapeChar) {
108  size_t pos = buffer - str.data() - 1;
109  str.erase(pos, 1);
110  buffer = str.data() + pos;
111  }
112  escaped = false;
113  buffer++;
114  }
115  else if (*buffer == Matcher::matchEscapeChar) {
116  escaped = true;
117  buffer++;
118  }
119  else if (*buffer == Matcher::matchSubstitutionPrefix) {
120  size_t pos = buffer - str.data();
121  buffer++;
122  bool replace = false;
123  std::string_view replacementString;
124  // Match $123
125  if (isdigit(*buffer)) {
126  replace = true;
127  size_t i = parseUint(buffer);
128  if (i < match.size() && match[i].matched)
129  replacementString = std::string_view{match[i].first, static_cast<size_t>(std::distance(match[i].first, match[i].second))};
130  }
131  // Match $path_123
132  else if (pos + Matcher::matchSubstitutionPathPrefix.size() + 1 < str.size() && strncmp(buffer, Matcher::matchSubstitutionPathPrefix.data(), Matcher::matchSubstitutionPathPrefix.size()) == 0 && isdigit(*(buffer + Matcher::matchSubstitutionPathPrefix.size()))) {
133  replace = true;
134  buffer += Matcher::matchSubstitutionPathPrefix.size();
135  size_t i = parseUint(buffer);
136  if (i < pathParts.size())
137  replacementString = std::string_view{pathParts[i].data()};
138  }
139 
140  if (replace) {
141  str.replace(pos, buffer - str.data() - pos, replacementString);
142  buffer = str.data() + pos + replacementString.size();
143  }
144  }
145  else {
146  buffer++;
147  }
148  }
149  }
150 
151 
152  std::optional<std::vector<std::string>> Matcher::getName(const std::cmatch& match, const std::vector<std::string>& pathParts) const noexcept {
153  std::vector<std::string> name = this->name_;
154  for (auto& part : name) {
155  replaceMatches(part, match, pathParts);
156  if (part.empty())
157  return std::optional<std::vector<std::string>>{};
158  }
159  return std::make_optional(std::move(name));
160  }
161 
162  std::optional<double> Matcher::getValue(const std::cmatch& match, const std::vector<std::string>& pathParts) const noexcept {
163  std::string expression = this->value_;
164  replaceMatches(expression, match, pathParts);
165  int error = 0;
166  double value = te_interp(expression.c_str(), &error);
167  if (!error)
168  return std::make_optional(value);
169  return std::optional<double>{};
170  }
171 
172  std::optional<std::string> Matcher::getUnit(const std::cmatch& match, const std::vector<std::string>& pathParts) const noexcept {
173  std::string unit = this->unit_;
174  replaceMatches(unit, match, pathParts);
175  return std::make_optional(std::move(unit));
176  }
177 
178  std::optional<std::map<std::string, std::string>> Matcher::getTags(const std::cmatch& match, const std::vector<std::string>& pathParts) const noexcept {
179  std::map<std::string, std::string> tags;
180  for (auto& [key, value] : this->tags_) {
181  auto keyCopy = key;
182  auto valueCopy = value;
183  replaceMatches(keyCopy, match, pathParts);
184  replaceMatches(valueCopy, match, pathParts);
185  if (keyCopy.empty() || valueCopy.empty())
186  return std::optional<std::map<std::string, std::string>>{};
187  else
188  tags.insert_or_assign(std::move(keyCopy), std::move(valueCopy));
189  }
190  return std::make_optional(std::move(tags));
191  }
192 
193  std::optional<Metric> Matcher::getMetric(const std::cmatch& match, const std::vector<std::string>& pathParts) const noexcept {
194  auto name = this->getName(match, pathParts);
195  if (!name.has_value())
196  return std::optional<Metric>{};
197  auto unit = this->getUnit(match, pathParts);
198  if (!unit.has_value())
199  return std::optional<Metric>{};
200  auto tags = this->getTags(match, pathParts);
201  if (!tags.has_value())
202  return std::optional<Metric>{};
203  return std::make_optional<Metric>(std::move(name.value()), std::move(tags.value()), std::move(unit.value()));
204  }
205 }
void setConvertToUnitsPerSecond(bool convertToUnitsPerSecond) noexcept
Sets whether the metric should be converted to units per second.
Definition: Matcher.cc:86
void setTags(const std::map< std::string, std::string > &tags) noexcept
Sets the pattern for the tags of the metric.
Definition: Matcher.cc:78
const std::string & unit() const noexcept
Returns the pattern for the unit of the metric.
Definition: Matcher.cc:49
std::map< std::string, std::string > tags_
Pattern for the tags of the metric.
Definition: Matcher.h:50
std::string value_
Pattern for the value of the metric.
Definition: Matcher.h:48
std::string unit_
Pattern for the unit of the metric.
Definition: Matcher.h:49
std::optional< std::string > getUnit(const std::cmatch &match, const std::vector< std::string > &pathParts) const noexcept
Use an expression match to compute the metric&#39;s unit.
Definition: Matcher.cc:172
const std::vector< std::string > & name() const noexcept
Returns the pattern for the name of the metric.
Definition: Matcher.cc:41
bool computeRate_
Whether the metric is a rate.
Definition: Matcher.h:51
Matcher() noexcept
Construct a new Matcher object.
Definition: Matcher.cc:29
std::optional< std::vector< std::string > > getName(const std::cmatch &match, const std::vector< std::string > &pathParts) const noexcept
Use an expression match to compute the metric&#39;s name.
Definition: Matcher.cc:152
bool convertToUnitsPerSecond_
Whether the metric should be converted to units per second.
Definition: Matcher.h:52
uint64_t parseUint(const char *&buffer) noexcept
Definition: Matcher.cc:91
void setComputeRate(bool computeRate) noexcept
Sets whether the metric is a rate.
Definition: Matcher.cc:82
std::optional< std::map< std::string, std::string > > getTags(const std::cmatch &match, const std::vector< std::string > &pathParts) const noexcept
Use an expression match to compute the metric&#39;s tags.
Definition: Matcher.cc:178
const std::string & value() const noexcept
Returns the pattern for the value of the metric.
Definition: Matcher.cc:45
bool computeRate() const noexcept
Returns whether the metric is a rate.
Definition: Matcher.cc:57
std::optional< double > getValue(const std::cmatch &match, const std::vector< std::string > &pathParts) const noexcept
Use an expression match to compute the metric&#39;s value.
Definition: Matcher.cc:162
static constexpr char matchEscapeChar
Escape character.
Definition: Matcher.h:42
std::vector< std::string > name_
Pattern for the name of the metric.
Definition: Matcher.h:47
static constexpr char matchSubstitutionPrefix
Variables prefix character.
Definition: Matcher.h:43
void setUnit(const std::string &unit) noexcept
Sets the pattern for the unit of the metric.
Definition: Matcher.cc:74
const std::map< std::string, std::string > & tags() const noexcept
Returns the pattern for the tags of the metric.
Definition: Matcher.cc:53
static constexpr std::string_view matchSubstitutionPathPrefix
Path part prefix variable string.
Definition: Matcher.h:44
void setValue(const std::string &value) noexcept
Sets the pattern for the value of the metric.
Definition: Matcher.cc:70
std::optional< Metric > getMetric(const std::cmatch &match, const std::vector< std::string > &pathParts) const noexcept
Use an expression match to compute the metric.
Definition: Matcher.cc:193
bool convertToUnitsPerSecond() const noexcept
Returns whether the metric should be converted to units per second.
Definition: Matcher.cc:61
void setName(const std::vector< std::string > &name) noexcept
Sets the pattern for the name of the metric.
Definition: Matcher.cc:66
void replaceMatches(std::string &str, const std::cmatch &match, const std::vector< std::string > &pathParts)
Definition: Matcher.cc:102