3 #include <kafka/Project.h>
6 #include <rapidjson/document.h>
7 #include <rapidjson/stringbuffer.h>
8 #include <rapidjson/writer.h>
33 static const constexpr
char* WILDCARD =
"*";
35 using KeysType = std::vector<std::string>;
40 template<
typename ValueType>
41 using ResultsType = std::vector<std::pair<KeysType, ValueType>>;
55 static std::string toString(
const KafkaMetrics::KeysType& keys);
57 template<
typename ValueType>
61 template<
typename ValueType>
62 ResultsType<ValueType> get(
const KeysType& keys)
const;
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);
71 template<
typename ValueType>
72 static ValueType getValue(rapidjson::Value::ConstMemberIterator iter);
74 #if COMPILER_SUPPORTS_CPP_17
75 std::string _decodeBuf;
77 std::vector<char> _decodeBuf;
79 rapidjson::Document _jsonDoc;
84 #if COMPILER_SUPPORTS_CPP_17
85 : _decodeBuf(std::move(jsonMetrics))
87 : _decodeBuf(jsonMetrics.cbegin(), jsonMetrics.cend() + 1)
90 if (_jsonDoc.ParseInsitu(_decodeBuf.data()).HasParseError())
92 throw std::runtime_error(
"Failed to parse string with JSON format!");
98 KafkaMetrics::getValue<std::int64_t>(rapidjson::Value::ConstMemberIterator iter)
100 return iter->value.GetInt();
105 KafkaMetrics::getValue<std::string>(rapidjson::Value::ConstMemberIterator iter)
107 return iter->value.GetString();
110 template<
typename ValueType>
111 inline KafkaMetrics::ResultsType<ValueType>
112 KafkaMetrics::get(
const KeysType& keys)
const
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!");
118 ResultsType<ValueType> results;
120 const rapidjson::Value::ConstMemberIterator iter = _jsonDoc.FindMember(keys.front().c_str());
121 if (iter == _jsonDoc.MemberEnd())
return results;
123 if (keys.size() == 1)
125 if (std::is_same<ValueType, std::string>::value ? iter->value.IsString() : iter->value.IsInt())
127 results.emplace_back(KeysType{}, getValue<ValueType>(iter));
133 KeysType keysForWildcards;
135 getResults(results, keysForWildcards, iter, keys.cbegin() + 1, keys.cend());
139 template<
typename ValueType>
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)
147 if (!iter->value.IsObject())
return;
149 const auto& key = *(keysToParse++);
150 const bool isTheEnd = (keysToParse == keysEnd);
154 for (rapidjson::Value::ConstMemberIterator subIter = iter->value.MemberBegin(); subIter != iter->value.MemberEnd(); ++subIter)
156 KeysType newKeysForWildcards = keysForWildcards;
157 newKeysForWildcards.emplace_back(subIter->name.GetString());
159 getResults(results, newKeysForWildcards, subIter, keysToParse, keysEnd);
164 const rapidjson::Value::ConstMemberIterator subIter = iter->value.FindMember(key.c_str());
165 if (subIter == iter->value.MemberEnd())
return;
169 getResults(results, keysForWildcards, subIter, keysToParse, keysEnd);
171 else if (std::is_same<ValueType, std::string>::value ? subIter->value.IsString() : subIter->value.IsInt())
173 results.emplace_back(keysForWildcards, getValue<ValueType>(subIter));
179 KafkaMetrics::toString(
const KafkaMetrics::KeysType& keys)
183 std::for_each(keys.cbegin(), keys.cend(),
184 [&ret](
const auto& key){ ret.append((ret.empty() ? std::string() : std::string(
", ")) +
"\"" + key +
"\""); });
189 template<
typename ValueType>
191 KafkaMetrics::toString(
const KafkaMetrics::ResultsType<ValueType>& results)
193 std::ostringstream oss;
194 bool isTheFirstOne =
true;
196 std::for_each(results.cbegin(), results.cend(),
197 [&oss, &isTheFirstOne](
const auto& result) {
198 const auto keysString = toString(result.first);
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 ?
"\"" :
"");
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