Modern C++ Kafka API
KafkaMetrics.h
1 #pragma once
2 
3 #include <kafka/Project.h>
4 
5 // https://github.com/Tencent/rapidjson/releases/tag/v1.1.0
6 #include <rapidjson/document.h>
7 #include <rapidjson/stringbuffer.h>
8 #include <rapidjson/writer.h>
9 
10 #include <algorithm>
11 #include <cstdint>
12 #include <iostream>
13 #include <sstream>
14 #include <stdexcept>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 
20 namespace KAFKA_API {
21 
26 {
27 public:
31  explicit KafkaMetrics(std::string jsonMetrics);
32 
33  static const constexpr char* WILDCARD = "*";
34 
35  using KeysType = std::vector<std::string>;
36 
40  template<typename ValueType>
41  using ResultsType = std::vector<std::pair<KeysType, ValueType>>;
42 
47  ResultsType<std::int64_t> getInt(const KeysType& keys) const { return get<std::int64_t>(keys); }
48 
53  ResultsType<std::string> getString(const KeysType& keys) const { return get<std::string>(keys); }
54 
55  static std::string toString(const KafkaMetrics::KeysType& keys);
56 
57  template<typename ValueType>
58  static std::string toString(const KafkaMetrics::ResultsType<ValueType>& results);
59 
60 private:
61  template<typename ValueType>
62  ResultsType<ValueType> get(const KeysType& keys) const;
63 
64  template<typename ValueType>
65  static void getResults(ResultsType<ValueType>& results,
66  KeysType& keysForWildcards,
67  rapidjson::Value::ConstMemberIterator iter,
68  KeysType::const_iterator keysToParse,
69  KeysType::const_iterator keysEnd);
70 
71  template<typename ValueType>
72  static ValueType getValue(rapidjson::Value::ConstMemberIterator iter);
73 
74 #if COMPILER_SUPPORTS_CPP_17
75  std::string _decodeBuf;
76 #else
77  std::vector<char> _decodeBuf;
78 #endif
79  rapidjson::Document _jsonDoc;
80 };
81 
82 inline
83 KafkaMetrics::KafkaMetrics(std::string jsonMetrics)
84 #if COMPILER_SUPPORTS_CPP_17
85  : _decodeBuf(std::move(jsonMetrics))
86 #else
87  : _decodeBuf(jsonMetrics.cbegin(), jsonMetrics.cend() + 1)
88 #endif
89 {
90  if (_jsonDoc.ParseInsitu(_decodeBuf.data()).HasParseError())
91  {
92  throw std::runtime_error("Failed to parse string with JSON format!");
93  }
94 }
95 
96 template<>
97 inline std::int64_t
98 KafkaMetrics::getValue<std::int64_t>(rapidjson::Value::ConstMemberIterator iter)
99 {
100  return iter->value.GetInt();
101 }
102 
103 template<>
104 inline std::string
105 KafkaMetrics::getValue<std::string>(rapidjson::Value::ConstMemberIterator iter)
106 {
107  return iter->value.GetString();
108 }
109 
110 template<typename ValueType>
111 inline KafkaMetrics::ResultsType<ValueType>
112 KafkaMetrics::get(const KeysType& keys) const
113 {
114  if (keys.empty()) throw std::invalid_argument("Input keys cannot be empty!");
115  if (keys.front() == WILDCARD) throw std::invalid_argument("The first key cannot be wildcard!");
116  if (keys.back() == WILDCARD) throw std::invalid_argument("The last key cannot be wildcard!");
117 
118  ResultsType<ValueType> results;
119 
120  const rapidjson::Value::ConstMemberIterator iter = _jsonDoc.FindMember(keys.front().c_str());
121  if (iter == _jsonDoc.MemberEnd()) return results;
122 
123  if (keys.size() == 1)
124  {
125  if (std::is_same<ValueType, std::string>::value ? iter->value.IsString() : iter->value.IsInt())
126  {
127  results.emplace_back(KeysType{}, getValue<ValueType>(iter));
128  }
129 
130  return results;
131  }
132 
133  KeysType keysForWildcards;
134 
135  getResults(results, keysForWildcards, iter, keys.cbegin() + 1, keys.cend());
136  return results;
137 }
138 
139 template<typename ValueType>
140 inline void
141 KafkaMetrics::getResults(KafkaMetrics::ResultsType<ValueType>& results,
142  KeysType& keysForWildcards,
143  rapidjson::Value::ConstMemberIterator iter,
144  KeysType::const_iterator keysToParse,
145  KeysType::const_iterator keysEnd)
146 {
147  if (!iter->value.IsObject()) return;
148 
149  const auto& key = *(keysToParse++);
150  const bool isTheEnd = (keysToParse == keysEnd);
151 
152  if (key == WILDCARD)
153  {
154  for (rapidjson::Value::ConstMemberIterator subIter = iter->value.MemberBegin(); subIter != iter->value.MemberEnd(); ++subIter)
155  {
156  KeysType newKeysForWildcards = keysForWildcards;
157  newKeysForWildcards.emplace_back(subIter->name.GetString());
158 
159  getResults(results, newKeysForWildcards, subIter, keysToParse, keysEnd);
160  }
161  }
162  else
163  {
164  const rapidjson::Value::ConstMemberIterator subIter = iter->value.FindMember(key.c_str());
165  if (subIter == iter->value.MemberEnd()) return;
166 
167  if (!isTheEnd)
168  {
169  getResults(results, keysForWildcards, subIter, keysToParse, keysEnd);
170  }
171  else if (std::is_same<ValueType, std::string>::value ? subIter->value.IsString() : subIter->value.IsInt())
172  {
173  results.emplace_back(keysForWildcards, getValue<ValueType>(subIter));
174  }
175  }
176 }
177 
178 inline std::string
179 KafkaMetrics::toString(const KafkaMetrics::KeysType& keys)
180 {
181  std::string ret;
182 
183  std::for_each(keys.cbegin(), keys.cend(),
184  [&ret](const auto& key){ ret.append((ret.empty() ? std::string() : std::string(", ")) + "\"" + key + "\""); });
185 
186  return ret;
187 }
188 
189 template<typename ValueType>
190 inline std::string
191 KafkaMetrics::toString(const KafkaMetrics::ResultsType<ValueType>& results)
192 {
193  std::ostringstream oss;
194  bool isTheFirstOne = true;
195 
196  std::for_each(results.cbegin(), results.cend(),
197  [&oss, &isTheFirstOne](const auto& result) {
198  const auto keysString = toString(result.first);
199 
200  oss << (isTheFirstOne ? (isTheFirstOne = false, "") : ", ")
201  << (keysString.empty() ? "" : (std::string("[") + keysString + "]:"));
202  oss << (std::is_same<ValueType, std::string>::value ? "\"" : "") << result.second << (std::is_same<ValueType, std::string>::value ? "\"" : "");
203  });
204 
205  return oss.str();
206 }
207 
208 } // end of KAFKA_API
209 
Helps to parse the metrics string with JSON format.
Definition: KafkaMetrics.h:26
ResultsType< std::string > getString(const KeysType &keys) const
Get string value(s) for the specified metrics.
Definition: KafkaMetrics.h:53
ResultsType< std::int64_t > getInt(const KeysType &keys) const
Get integer value(s) for the specified metrics.
Definition: KafkaMetrics.h:47
KafkaMetrics(std::string jsonMetrics)
Initilize with the metrics string.
Definition: KafkaMetrics.h:83
std::vector< std::pair< KeysType, ValueType > > ResultsType
The matched keys (for wildcards) and the value.
Definition: KafkaMetrics.h:41
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy