1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef BASE_EVENT_RAW_ENCODE_INCLUDE_RAW_DATA_BUILDER_H 17 #define BASE_EVENT_RAW_ENCODE_INCLUDE_RAW_DATA_BUILDER_H 18 19 #include <cstddef> 20 #include <cstdint> 21 #include <list> 22 #include <memory> 23 #include <mutex> 24 #include <sstream> 25 #include <string> 26 #include <vector> 27 #include <unordered_map> 28 #include <functional> 29 30 #include "decoded/decoded_param.h" 31 #include "encoded/encoded_param.h" 32 #include "base/raw_data_base_def.h" 33 #include "base/raw_data.h" 34 35 namespace OHOS { 36 namespace HiviewDFX { 37 namespace EventRaw { 38 class RawDataBuilder { 39 public: RawDataBuilder()40 RawDataBuilder() {}; 41 RawDataBuilder(std::shared_ptr<EventRaw::RawData> rawData); 42 RawDataBuilder(const std::string& domain, const std::string& name, const int eventType); 43 ~RawDataBuilder() = default; 44 45 public: 46 std::shared_ptr<RawData> Build(); 47 std::shared_ptr<EncodedParam> GetValue(const std::string& key); 48 struct HiSysEventHeader& GetHeader(); 49 struct TraceInfo& GetTraceInfo(); 50 std::string GetDomain(); 51 std::string GetName(); 52 int GetEventType(); 53 size_t GetParamCnt(); 54 bool IsBaseInfo(const std::string& key); 55 56 public: 57 RawDataBuilder& AppendValue(std::shared_ptr<EncodedParam> param); 58 RawDataBuilder& AppendDomain(const std::string& domain); 59 RawDataBuilder& AppendName(const std::string& name); 60 RawDataBuilder& AppendType(const int eventType); 61 RawDataBuilder& AppendTimeStamp(const uint64_t timeStamp); 62 RawDataBuilder& AppendTimeZone(const std::string& timeZone); 63 RawDataBuilder& AppendTimeZone(const uint8_t timeZone); 64 RawDataBuilder& AppendUid(const uint32_t uid); 65 RawDataBuilder& AppendPid(const uint32_t pid); 66 RawDataBuilder& AppendTid(const uint32_t tid); 67 RawDataBuilder& AppendId(const uint64_t id); 68 RawDataBuilder& AppendId(const std::string& id); 69 RawDataBuilder& AppendTraceId(const uint64_t traceId); 70 RawDataBuilder& AppendSpanId(const uint32_t spanId); 71 RawDataBuilder& AppendPSpanId(const uint32_t pSpanId); 72 RawDataBuilder& AppendTraceFlag(const uint8_t traceFlag); 73 RawDataBuilder& AppendTraceInfo(const uint64_t traceId, const uint32_t spanId, 74 const uint32_t pSpanId, const uint8_t traceFlag); 75 76 template<typename T> ParseValueByKey(const std::string & key,T & dest)77 bool ParseValueByKey(const std::string& key, T& dest) 78 { 79 if (IsBaseInfo(key)) { 80 return GetBaseInfoValueByKey(key, dest); 81 } 82 return GetValueByKey(key, dest); 83 } 84 85 template<typename T> AppendValue(const std::string & key,T val)86 RawDataBuilder& AppendValue(const std::string& key, T val) 87 { 88 if (IsBaseInfo(key)) { 89 return AppendBaseInfoValue(key, val); 90 } 91 if constexpr (isString<T>) { 92 return AppendValue(std::make_shared<StringEncodedParam>(key, val)); 93 } 94 if constexpr (isFloatingPointNum<T>) { 95 return AppendValue(std::make_shared<FloatingNumberEncodedParam<double>>(key, static_cast<double>(val))); 96 } 97 if constexpr (std::is_same_v<std::decay_t<T>, bool> || isSignedNum<T>) { 98 return AppendValue(std::make_shared<SignedVarintEncodedParam<int64_t>>(key, static_cast<int64_t>(val))); 99 } 100 if constexpr (isUnsignedNum<T>) { 101 return AppendValue(std::make_shared<UnsignedVarintEncodedParam<uint64_t>>(key, 102 static_cast<uint64_t>(val))); 103 } 104 return AppendArrayValue(key, val); 105 } 106 107 private: 108 template<typename T> UpdateType(const T val)109 RawDataBuilder& UpdateType(const T val) 110 { 111 if constexpr (isUnsignedNum<T>) { 112 return AppendType(static_cast<int>(val)); 113 } 114 return *this; 115 } 116 117 template<typename T> UpdateUid(const T val)118 RawDataBuilder& UpdateUid(const T val) 119 { 120 if constexpr (isUnsignedNum<T>) { 121 return AppendUid(static_cast<uint32_t>(val)); 122 } 123 return *this; 124 } 125 126 template<typename T> UpdatePid(const T val)127 RawDataBuilder& UpdatePid(const T val) 128 { 129 if constexpr (isUnsignedNum<T>) { 130 return AppendPid(static_cast<uint32_t>(val)); 131 } 132 return *this; 133 } 134 135 template<typename T> UpdateTid(const T val)136 RawDataBuilder& UpdateTid(const T val) 137 { 138 if constexpr (isUnsignedNum<T>) { 139 return AppendTid(static_cast<uint32_t>(val)); 140 } 141 return *this; 142 } 143 144 template<typename T> UpdateId(const T val)145 RawDataBuilder& UpdateId(const T val) 146 { 147 if constexpr (isString<T>) { 148 return AppendId(val); 149 } 150 if constexpr (isUnsignedNum<T>) { 151 return AppendId(static_cast<uint64_t>(val)); 152 } 153 return *this; 154 } 155 156 template<typename T> TransHexStrToNum(const std::string & hexStr,T & num)157 void TransHexStrToNum(const std::string& hexStr, T& num) 158 { 159 std::stringstream ss; 160 ss << std::hex << hexStr; 161 ss >> num >> std::dec; 162 } 163 164 template<typename T> UpdateTraceId(const T val)165 RawDataBuilder& UpdateTraceId(const T val) 166 { 167 if constexpr (isString<T>) { 168 uint64_t traceId = 0; 169 TransHexStrToNum(val, traceId); 170 return AppendTraceId(traceId); 171 } 172 if constexpr (isUnsignedNum<T>) { 173 return AppendTraceId(static_cast<uint64_t>(val)); 174 } 175 return *this; 176 } 177 178 template<typename T> UpdateSpanId(const T val)179 RawDataBuilder& UpdateSpanId(const T val) 180 { 181 if constexpr (isString<T>) { 182 uint32_t spanId = 0; 183 TransHexStrToNum(val, spanId); 184 return AppendSpanId(spanId); 185 } 186 if constexpr (isUnsignedNum<T>) { 187 return AppendSpanId(static_cast<uint32_t>(val)); 188 } 189 return *this; 190 } 191 192 template<typename T> UpdatePSpanId(const T val)193 RawDataBuilder& UpdatePSpanId(const T val) 194 { 195 if constexpr (isString<T>) { 196 uint32_t pSpanId = 0; 197 TransHexStrToNum(val, pSpanId); 198 return AppendPSpanId(pSpanId); 199 } 200 if constexpr (isUnsignedNum<T>) { 201 return AppendPSpanId(static_cast<uint32_t>(val)); 202 } 203 return *this; 204 } 205 206 template<typename T> UpdateTraceFlag(const T val)207 RawDataBuilder& UpdateTraceFlag(const T val) 208 { 209 if constexpr (isUnsignedNum<T>) { 210 return AppendTraceFlag(static_cast<uint8_t>(val)); 211 } 212 return *this; 213 } 214 215 template<typename T> AppendArrayValue(const std::string & key,T val)216 RawDataBuilder& AppendArrayValue(const std::string& key, T val) 217 { 218 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<std::string>>) { 219 return AppendValue(std::make_shared<StringEncodedArrayParam>(key, val)); 220 } 221 if constexpr (isFloatingPointNumArray<T>) { 222 std::vector<double> dVector; 223 for (auto item : val) { 224 dVector.emplace_back(static_cast<double>(item)); 225 } 226 return AppendValue(std::make_shared<FloatingNumberEncodedArrayParam<double>>(key, dVector)); 227 } 228 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<bool>> || isSignedNumArray<T>) { 229 std::vector<int64_t> i64Vector; 230 for (auto item : val) { 231 i64Vector.emplace_back(static_cast<int64_t>(item)); 232 } 233 return AppendValue(std::make_shared<SignedVarintEncodedArrayParam<int64_t>>(key, i64Vector)); 234 } 235 if constexpr (isUnsignedNumArray<T>) { 236 std::vector<uint64_t> i64Vector; 237 for (auto item : val) { 238 i64Vector.emplace_back(static_cast<uint64_t>(item)); 239 } 240 return AppendValue(std::make_shared<UnsignedVarintEncodedArrayParam<uint64_t>>(key, i64Vector)); 241 } 242 return *this; 243 } 244 245 template<typename T> AppendBaseInfoValue(const std::string & key,T val)246 RawDataBuilder& AppendBaseInfoValue(const std::string& key, T val) 247 { 248 std::unordered_map<std::string, std::function<RawDataBuilder&(T)>> appendFuncs = { 249 {BASE_INFO_KEY_DOMAIN, std::bind([this] (T val) -> decltype(auto) { 250 if constexpr (isString<T>) { 251 return this->AppendDomain(val); 252 } 253 return *this; 254 }, std::placeholders::_1)}, 255 {BASE_INFO_KEY_NAME, std::bind([this] (T val) -> decltype(auto) { 256 if constexpr (isString<T>) { 257 return this->AppendName(val); 258 } 259 return *this; 260 }, std::placeholders::_1)}, 261 {BASE_INFO_KEY_TYPE, std::bind(&RawDataBuilder::UpdateType<T>, this, std::placeholders::_1)}, 262 {BASE_INFO_KEY_TIME_STAMP, std::bind([this] (T val) -> decltype(auto) { 263 if constexpr (std::is_same_v<std::decay_t<T>, uint64_t>) { 264 return this->AppendTimeStamp(val); 265 } 266 return *this; 267 }, std::placeholders::_1)}, 268 {BASE_INFO_KEY_TIME_ZONE, std::bind([this] (T val) -> decltype(auto) { 269 if constexpr (isString<T>) { 270 return this->AppendTimeZone(val); 271 } 272 return *this; 273 }, std::placeholders::_1)}, 274 {BASE_INFO_KEY_ID, std::bind(&RawDataBuilder::UpdateId<T>, this, std::placeholders::_1)}, 275 {BASE_INFO_KEY_PID, std::bind(&RawDataBuilder::UpdatePid<T>, this, std::placeholders::_1)}, 276 {BASE_INFO_KEY_TID, std::bind(&RawDataBuilder::UpdateTid<T>, this, std::placeholders::_1)}, 277 {BASE_INFO_KEY_UID, std::bind(&RawDataBuilder::UpdateUid<T>, this, std::placeholders::_1)}, 278 {BASE_INFO_KEY_TRACE_ID, std::bind(&RawDataBuilder::UpdateTraceId<T>, this, std::placeholders::_1)}, 279 {BASE_INFO_KEY_SPAN_ID, std::bind(&RawDataBuilder::UpdateSpanId<T>, this, std::placeholders::_1)}, 280 {BASE_INFO_KEY_PARENT_SPAN_ID, std::bind(&RawDataBuilder::UpdatePSpanId<T>, this, std::placeholders::_1)}, 281 {BASE_INFO_KEY_TRACE_FLAG, std::bind(&RawDataBuilder::UpdateTraceFlag<T>, this, std::placeholders::_1)}, 282 }; 283 auto iter = appendFuncs.find(key); 284 return (iter == appendFuncs.end()) ? *this : iter->second(val); 285 } 286 287 template<typename T> GetArrayValueByKey(std::shared_ptr<EncodedParam> encodedParam,T & val)288 bool GetArrayValueByKey(std::shared_ptr<EncodedParam> encodedParam, T& val) 289 { 290 std::unordered_map<DataCodedType, 291 std::function<bool(std::shared_ptr<EncodedParam>, T&)>> getFuncs = { 292 {DataCodedType::UNSIGNED_VARINT_ARRAY, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 293 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<uint64_t>>) { 294 param->AsUint64Vec(val); 295 return true; 296 } 297 return false; 298 }, std::placeholders::_1, std::placeholders::_2)}, 299 {DataCodedType::SIGNED_VARINT_ARRAY, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 300 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<int64_t>>) { 301 param->AsInt64Vec(val); 302 return true; 303 } 304 return false; 305 }, std::placeholders::_1, std::placeholders::_2)}, 306 {DataCodedType::FLOATING_ARRAY, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 307 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<double>>) { 308 param->AsDoubleVec(val); 309 return true; 310 } 311 return false; 312 }, std::placeholders::_1, std::placeholders::_2)}, 313 {DataCodedType::DSTRING_ARRAY, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 314 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<std::string>>) { 315 param->AsStringVec(val); 316 return true; 317 } 318 return false; 319 }, std::placeholders::_1, std::placeholders::_2)}, 320 }; 321 auto iter = getFuncs.find(encodedParam->GetDataCodedType()); 322 return (iter == getFuncs.end()) ? false : iter->second(encodedParam, val); 323 } 324 325 template<typename T> GetValueByKey(const std::string & key,T & val)326 bool GetValueByKey(const std::string& key, T& val) 327 { 328 auto encodedParam = GetValue(key); 329 if (encodedParam == nullptr) { 330 return false; 331 } 332 std::unordered_map<DataCodedType, std::function<bool(std::shared_ptr<EncodedParam>, T&)>> getFuncs = { 333 {DataCodedType::UNSIGNED_VARINT, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 334 if constexpr (std::is_same_v<std::decay_t<T>, uint64_t>) { 335 param->AsUint64(val); 336 return true; 337 } 338 return false; 339 }, std::placeholders::_1, std::placeholders::_2)}, 340 {DataCodedType::SIGNED_VARINT, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 341 if constexpr (std::is_same_v<std::decay_t<T>, int64_t>) { 342 param->AsInt64(val); 343 return true; 344 } 345 return false; 346 }, std::placeholders::_1, std::placeholders::_2)}, 347 {DataCodedType::FLOATING, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 348 if constexpr (std::is_same_v<std::decay_t<T>, double>) { 349 param->AsDouble(val); 350 return true; 351 } 352 return false; 353 }, std::placeholders::_1, std::placeholders::_2)}, 354 {DataCodedType::DSTRING, std::bind([] (std::shared_ptr<EncodedParam> param, T& val) { 355 if constexpr (isString<T>) { 356 param->AsString(val); 357 return true; 358 } 359 return false; 360 }, std::placeholders::_1, std::placeholders::_2)}, 361 }; 362 auto iter = getFuncs.find(encodedParam->GetDataCodedType()); 363 return (iter == getFuncs.end()) ? GetArrayValueByKey(encodedParam, val) : iter->second(encodedParam, val);\ 364 } 365 366 template<typename T, typename V> ParseAndSetTraceInfo(T & to,V from)367 bool ParseAndSetTraceInfo(T& to, V from) 368 { 369 if constexpr (std::is_same_v<std::decay_t<T>, std::string>) { 370 to = TransNumToHexStr(from); 371 return true; 372 } 373 return ParseValue(to, from); 374 } 375 376 template<typename T> GetBaseInfoValueByKey(const std::string & key,T & val)377 bool GetBaseInfoValueByKey(const std::string& key, T& val) 378 { 379 std::unordered_map<std::string, std::function<bool(T&)>> parseFuncs = { 380 {BASE_INFO_KEY_DOMAIN, std::bind([this] (T& val) -> bool { 381 return this->ParseValue(val, std::string(header_.domain)); 382 }, std::placeholders::_1)}, 383 {BASE_INFO_KEY_NAME, std::bind([this] (T& val) -> bool { 384 return this->ParseValue(val, std::string(header_.name)); 385 }, std::placeholders::_1)}, 386 {BASE_INFO_KEY_TYPE, std::bind([this] (T& val) -> bool { 387 int type = static_cast<int>(header_.type) + 1; 388 return this->ParseValue(val, type); 389 }, std::placeholders::_1)}, 390 {BASE_INFO_KEY_TIME_STAMP, std::bind([this] (T& val) -> bool { 391 return this->ParseValue(val, header_.timestamp); 392 }, std::placeholders::_1)}, 393 {BASE_INFO_KEY_TIME_ZONE, std::bind(&RawDataBuilder::ParseTimeZoneFromHeader<T>, this, 394 std::placeholders::_1)}, 395 {BASE_INFO_KEY_ID, std::bind([this] (T& val) -> bool { 396 return this->ParseValue(val, header_.id); 397 }, std::placeholders::_1)}, 398 {BASE_INFO_KEY_PID, std::bind([this] (T& val) -> bool { 399 return this->ParseValue(val, header_.pid); 400 }, std::placeholders::_1)}, 401 {BASE_INFO_KEY_TID, std::bind([this] (T& val) -> bool { 402 return this->ParseValue(val, header_.tid); 403 }, std::placeholders::_1)}, 404 {BASE_INFO_KEY_UID, std::bind([this] (T& val) -> bool { 405 return this->ParseValue(val, header_.uid); 406 }, std::placeholders::_1)}, 407 {BASE_INFO_KEY_TRACE_ID, std::bind([this] (T& val) -> bool { 408 return this->ParseAndSetTraceInfo(val, traceInfo_.traceId); 409 }, std::placeholders::_1)}, 410 {BASE_INFO_KEY_SPAN_ID, std::bind([this] (T& val) -> bool { 411 return this->ParseAndSetTraceInfo(val, traceInfo_.spanId); 412 }, std::placeholders::_1)}, 413 {BASE_INFO_KEY_PARENT_SPAN_ID, std::bind([this] (T& val) -> bool { 414 return this->ParseAndSetTraceInfo(val, traceInfo_.pSpanId); 415 }, std::placeholders::_1)}, 416 {BASE_INFO_KEY_TRACE_FLAG, std::bind(&RawDataBuilder::PareTraceFlagFromHeader<T>, this, 417 std::placeholders::_1)}, 418 }; 419 auto iter = parseFuncs.find(key); 420 return (iter == parseFuncs.end()) ? false : iter->second(val); 421 } 422 423 template<typename T, typename V> ParseValue(T & to,V from)424 bool ParseValue(T& to, V from) 425 { 426 if constexpr (std::is_same_v<std::decay_t<T>, std::decay_t<V>>) { 427 to = from; 428 return true; 429 } 430 if constexpr ((isSignedNum<T> && isSignedNum<V>) || (isUnsignedNum<T> && isUnsignedNum<V>)) { 431 to = static_cast<std::decay_t<T>>(from); 432 return true; 433 } 434 return false; 435 } 436 437 template<typename T> ParseTimeZoneFromHeader(T & val)438 bool ParseTimeZoneFromHeader(T& val) 439 { 440 if constexpr (isUnsignedNum<T>) { 441 val = static_cast<std::decay_t<T>>(header_.timeZone); 442 return true; 443 } 444 if constexpr (isString<T>) { 445 val = ParseTimeZone(header_.timeZone); 446 return true; 447 } 448 return false; 449 } 450 451 template<typename T> PareTraceFlagFromHeader(T & val)452 bool PareTraceFlagFromHeader(T& val) 453 { 454 if constexpr (isUnsignedNum<T>) { 455 val = static_cast<std::decay_t<T>>(traceInfo_.traceFlag); 456 return true; 457 } 458 return false; 459 } 460 461 bool BuildHeader(std::shared_ptr<RawData> dest); 462 bool BuildCustomizedParams(std::shared_ptr<RawData> dest); 463 void InitValueParams(std::vector<std::shared_ptr<DecodedParam>> params); 464 void InitArrayValueParams(std::vector<std::shared_ptr<DecodedParam>> params); 465 466 private: 467 struct HiSysEventHeader header_ = { 468 .domain = {0}, 469 .name = {0}, 470 .timestamp = 0, 471 .timeZone = 0, 472 .uid = 0, 473 .pid = 0, 474 .tid = 0, 475 .id = 0, 476 .type = 0, 477 .isTraceOpened = 0, 478 }; 479 struct TraceInfo traceInfo_ { 480 .traceFlag = 0, 481 .traceId = 0, 482 .spanId = 0, 483 .pSpanId = 0, 484 }; 485 std::list<std::shared_ptr<EncodedParam>> allParams_; 486 std::mutex paramsOptMtx_; 487 }; 488 } // namespace EventRaw 489 } // namespace HiviewDFX 490 } // namespace OHOS 491 492 #endif // BASE_EVENT_RAW_ENCODE_INCLUDE_RAW_DATA_BUILDER_H 493