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& AppendLog(const uint8_t log); 68 RawDataBuilder& AppendId(const uint64_t id); 69 RawDataBuilder& AppendId(const std::string& id); 70 RawDataBuilder& AppendTraceId(const uint64_t traceId); 71 RawDataBuilder& AppendSpanId(const uint32_t spanId); 72 RawDataBuilder& AppendPSpanId(const uint32_t pSpanId); 73 RawDataBuilder& AppendTraceFlag(const uint8_t traceFlag); 74 RawDataBuilder& AppendTraceInfo(const uint64_t traceId, const uint32_t spanId, 75 const uint32_t pSpanId, const uint8_t traceFlag); 76 77 template<typename T> ParseValueByKey(const std::string & key,T & dest)78 bool ParseValueByKey(const std::string& key, T& dest) 79 { 80 if (IsBaseInfo(key)) { 81 return GetBaseInfoValueByKey(key, dest); 82 } 83 return GetValueByKey(key, dest); 84 } 85 86 template<typename T> AppendValue(const std::string & key,T val)87 RawDataBuilder& AppendValue(const std::string& key, T val) 88 { 89 if (IsBaseInfo(key)) { 90 return AppendBaseInfoValue(key, val); 91 } 92 if constexpr (isString<T>) { 93 return AppendValue(std::make_shared<StringEncodedParam>(key, val)); 94 } 95 if constexpr (isFloatingPointNum<T>) { 96 return AppendValue(std::make_shared<FloatingNumberEncodedParam<double>>(key, static_cast<double>(val))); 97 } 98 if constexpr (std::is_same_v<std::decay_t<T>, bool> || isSignedNum<T>) { 99 return AppendValue(std::make_shared<SignedVarintEncodedParam<int64_t>>(key, static_cast<int64_t>(val))); 100 } 101 if constexpr (isUnsignedNum<T>) { 102 return AppendValue(std::make_shared<UnsignedVarintEncodedParam<uint64_t>>(key, 103 static_cast<uint64_t>(val))); 104 } 105 return AppendArrayValue(key, val); 106 } 107 108 private: 109 template<typename T> UpdateType(const T val)110 RawDataBuilder& UpdateType(const T val) 111 { 112 if constexpr (isUnsignedNum<T>) { 113 return AppendType(static_cast<int>(val)); 114 } 115 return *this; 116 } 117 118 template<typename T> UpdateUid(const T val)119 RawDataBuilder& UpdateUid(const T val) 120 { 121 if constexpr (isUnsignedNum<T>) { 122 return AppendUid(static_cast<uint32_t>(val)); 123 } 124 return *this; 125 } 126 127 template<typename T> UpdateLog(const T val)128 RawDataBuilder& UpdateLog(const T val) 129 { 130 if constexpr (isUnsignedNum<T>) { 131 return AppendLog(static_cast<uint8_t>(val)); 132 } 133 return *this; 134 } 135 136 template<typename T> UpdatePid(const T val)137 RawDataBuilder& UpdatePid(const T val) 138 { 139 if constexpr (isUnsignedNum<T>) { 140 return AppendPid(static_cast<uint32_t>(val)); 141 } 142 return *this; 143 } 144 145 template<typename T> UpdateTid(const T val)146 RawDataBuilder& UpdateTid(const T val) 147 { 148 if constexpr (isUnsignedNum<T>) { 149 return AppendTid(static_cast<uint32_t>(val)); 150 } 151 return *this; 152 } 153 154 template<typename T> UpdateId(const T val)155 RawDataBuilder& UpdateId(const T val) 156 { 157 if constexpr (isString<T>) { 158 return AppendId(val); 159 } 160 if constexpr (isUnsignedNum<T>) { 161 return AppendId(static_cast<uint64_t>(val)); 162 } 163 return *this; 164 } 165 166 template<typename T> TransHexStrToNum(const std::string & hexStr,T & num)167 void TransHexStrToNum(const std::string& hexStr, T& num) 168 { 169 std::stringstream ss; 170 ss << std::hex << hexStr; 171 ss >> num >> std::dec; 172 } 173 174 template<typename T> UpdateTraceId(const T val)175 RawDataBuilder& UpdateTraceId(const T val) 176 { 177 if constexpr (isString<T>) { 178 uint64_t traceId = 0; 179 TransHexStrToNum(val, traceId); 180 return AppendTraceId(traceId); 181 } 182 if constexpr (isUnsignedNum<T>) { 183 return AppendTraceId(static_cast<uint64_t>(val)); 184 } 185 return *this; 186 } 187 188 template<typename T> UpdateSpanId(const T val)189 RawDataBuilder& UpdateSpanId(const T val) 190 { 191 if constexpr (isString<T>) { 192 uint32_t spanId = 0; 193 TransHexStrToNum(val, spanId); 194 return AppendSpanId(spanId); 195 } 196 if constexpr (isUnsignedNum<T>) { 197 return AppendSpanId(static_cast<uint32_t>(val)); 198 } 199 return *this; 200 } 201 202 template<typename T> UpdatePSpanId(const T val)203 RawDataBuilder& UpdatePSpanId(const T val) 204 { 205 if constexpr (isString<T>) { 206 uint32_t pSpanId = 0; 207 TransHexStrToNum(val, pSpanId); 208 return AppendPSpanId(pSpanId); 209 } 210 if constexpr (isUnsignedNum<T>) { 211 return AppendPSpanId(static_cast<uint32_t>(val)); 212 } 213 return *this; 214 } 215 216 template<typename T> UpdateTraceFlag(const T val)217 RawDataBuilder& UpdateTraceFlag(const T val) 218 { 219 if constexpr (isUnsignedNum<T>) { 220 return AppendTraceFlag(static_cast<uint8_t>(val)); 221 } 222 return *this; 223 } 224 225 template<typename T> AppendArrayValue(const std::string & key,T val)226 RawDataBuilder& AppendArrayValue(const std::string& key, T val) 227 { 228 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<std::string>>) { 229 return AppendValue(std::make_shared<StringEncodedArrayParam>(key, val)); 230 } 231 if constexpr (isFloatingPointNumArray<T>) { 232 std::vector<double> dVector; 233 for (auto item : val) { 234 dVector.emplace_back(static_cast<double>(item)); 235 } 236 return AppendValue(std::make_shared<FloatingNumberEncodedArrayParam<double>>(key, dVector)); 237 } 238 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<bool>> || isSignedNumArray<T>) { 239 std::vector<int64_t> i64Vector; 240 for (auto item : val) { 241 i64Vector.emplace_back(static_cast<int64_t>(item)); 242 } 243 return AppendValue(std::make_shared<SignedVarintEncodedArrayParam<int64_t>>(key, i64Vector)); 244 } 245 if constexpr (isUnsignedNumArray<T>) { 246 std::vector<uint64_t> i64Vector; 247 for (auto item : val) { 248 i64Vector.emplace_back(static_cast<uint64_t>(item)); 249 } 250 return AppendValue(std::make_shared<UnsignedVarintEncodedArrayParam<uint64_t>>(key, i64Vector)); 251 } 252 return *this; 253 } 254 255 template<typename T> InitBaseAppendHandlers(std::unordered_map<std::string,std::function<RawDataBuilder & (T)>> & handlers)256 void InitBaseAppendHandlers(std::unordered_map<std::string, std::function<RawDataBuilder&(T)>>& handlers) 257 { 258 handlers.emplace(BASE_INFO_KEY_DOMAIN, [this] (T val) -> decltype(auto) { 259 if constexpr (isString<T>) { 260 return this->AppendDomain(val); 261 } 262 return *this; 263 }); 264 handlers.emplace(BASE_INFO_KEY_NAME, [this] (T val) -> decltype(auto) { 265 if constexpr (isString<T>) { 266 return this->AppendName(val); 267 } 268 return *this; 269 }); 270 handlers.emplace(BASE_INFO_KEY_TYPE, [this] (T val) -> decltype(auto) { 271 return this->UpdateType(val); 272 }); 273 handlers.emplace(BASE_INFO_KEY_TIME_STAMP, [this] (T val) -> decltype(auto) { 274 if constexpr (std::is_same_v<std::decay_t<T>, uint64_t>) { 275 return this->AppendTimeStamp(val); 276 } 277 return *this; 278 }); 279 handlers.emplace(BASE_INFO_KEY_TIME_ZONE, [this] (T val) -> decltype(auto) { 280 if constexpr (isString<T>) { 281 return this->AppendTimeZone(val); 282 } 283 return *this; 284 }); 285 } 286 287 template<typename T> InitIdInfoAppendHandlers(std::unordered_map<std::string,std::function<RawDataBuilder & (T)>> & handlers)288 void InitIdInfoAppendHandlers(std::unordered_map<std::string, std::function<RawDataBuilder&(T)>>& handlers) 289 { 290 handlers.emplace(BASE_INFO_KEY_ID, [this] (T val) -> decltype(auto) { 291 return this->UpdateId(val); 292 }); 293 handlers.emplace(BASE_INFO_KEY_PID, [this] (T val) -> decltype(auto) { 294 return this->UpdatePid(val); 295 }); 296 handlers.emplace(BASE_INFO_KEY_TID, [this] (T val) -> decltype(auto) { 297 return this->UpdateTid(val); 298 }); 299 handlers.emplace(BASE_INFO_KEY_UID, [this] (T val) -> decltype(auto) { 300 return this->UpdateUid(val); 301 }); 302 handlers.emplace(BASE_INFO_KEY_LOG, [this] (T val) -> decltype(auto) { 303 return this->UpdateLog(val); 304 }); 305 handlers.emplace(BASE_INFO_KEY_TRACE_ID, [this] (T val) -> decltype(auto) { 306 return this->UpdateTraceId(val); 307 }); 308 handlers.emplace(BASE_INFO_KEY_SPAN_ID, [this] (T val) -> decltype(auto) { 309 return this->UpdateSpanId(val); 310 }); 311 handlers.emplace(BASE_INFO_KEY_PARENT_SPAN_ID, [this] (T val) -> decltype(auto) { 312 return this->UpdatePSpanId(val); 313 }); 314 handlers.emplace(BASE_INFO_KEY_TRACE_FLAG, [this] (T val) -> decltype(auto) { 315 return this->UpdateTraceFlag(val); 316 }); 317 } 318 319 template<typename T> AppendBaseInfoValue(const std::string & key,T val)320 RawDataBuilder& AppendBaseInfoValue(const std::string& key, T val) 321 { 322 std::unordered_map<std::string, std::function<RawDataBuilder&(T)>> appendHandlers; 323 InitBaseAppendHandlers(appendHandlers); 324 InitIdInfoAppendHandlers(appendHandlers); 325 auto iter = appendHandlers.find(key); 326 return (iter == appendHandlers.end()) ? *this : iter->second(val); 327 } 328 329 template<typename T> GetArrayValueByKey(std::shared_ptr<EncodedParam> encodedParam,T & val)330 bool GetArrayValueByKey(std::shared_ptr<EncodedParam> encodedParam, T& val) 331 { 332 std::unordered_map<DataCodedType, 333 std::function<bool(std::shared_ptr<EncodedParam>, T&)>> getFuncs = { 334 {DataCodedType::UNSIGNED_VARINT_ARRAY, [] (std::shared_ptr<EncodedParam> param, T& val) { 335 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<uint64_t>>) { 336 param->AsUint64Vec(val); 337 return true; 338 } 339 return false; 340 } 341 }, 342 {DataCodedType::SIGNED_VARINT_ARRAY, [] (std::shared_ptr<EncodedParam> param, T& val) { 343 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<int64_t>>) { 344 param->AsInt64Vec(val); 345 return true; 346 } 347 return false; 348 } 349 }, 350 {DataCodedType::FLOATING_ARRAY, [] (std::shared_ptr<EncodedParam> param, T& val) { 351 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<double>>) { 352 param->AsDoubleVec(val); 353 return true; 354 } 355 return false; 356 } 357 }, 358 {DataCodedType::DSTRING_ARRAY, [] (std::shared_ptr<EncodedParam> param, T& val) { 359 if constexpr (std::is_same_v<std::decay_t<T>, std::vector<std::string>>) { 360 param->AsStringVec(val); 361 return true; 362 } 363 return false; 364 } 365 } 366 }; 367 auto iter = getFuncs.find(encodedParam->GetDataCodedType()); 368 return (iter == getFuncs.end()) ? false : iter->second(encodedParam, val); 369 } 370 371 template<typename T> GetValueByKey(const std::string & key,T & val)372 bool GetValueByKey(const std::string& key, T& val) 373 { 374 auto encodedParam = GetValue(key); 375 if (encodedParam == nullptr) { 376 return false; 377 } 378 std::unordered_map<DataCodedType, std::function<bool(std::shared_ptr<EncodedParam>, T&)>> getFuncs = { 379 {DataCodedType::UNSIGNED_VARINT, [] (std::shared_ptr<EncodedParam> param, T& val) { 380 if constexpr (std::is_same_v<std::decay_t<T>, uint64_t>) { 381 param->AsUint64(val); 382 return true; 383 } 384 return false; 385 } 386 }, 387 {DataCodedType::SIGNED_VARINT, [] (std::shared_ptr<EncodedParam> param, T& val) { 388 if constexpr (std::is_same_v<std::decay_t<T>, int64_t>) { 389 param->AsInt64(val); 390 return true; 391 } 392 return false; 393 } 394 }, 395 {DataCodedType::FLOATING, [] (std::shared_ptr<EncodedParam> param, T& val) { 396 if constexpr (std::is_same_v<std::decay_t<T>, double>) { 397 param->AsDouble(val); 398 return true; 399 } 400 return false; 401 } 402 }, 403 {DataCodedType::DSTRING, [] (std::shared_ptr<EncodedParam> param, T& val) { 404 if constexpr (isString<T>) { 405 param->AsString(val); 406 return true; 407 } 408 return false; 409 } 410 } 411 }; 412 auto iter = getFuncs.find(encodedParam->GetDataCodedType()); 413 return (iter == getFuncs.end()) ? GetArrayValueByKey(encodedParam, val) : iter->second(encodedParam, val);\ 414 } 415 416 template<typename T, typename V> ParseAndSetTraceInfo(T & to,V from)417 bool ParseAndSetTraceInfo(T& to, V from) 418 { 419 if constexpr (std::is_same_v<std::decay_t<T>, std::string>) { 420 to = TransNumToHexStr(from); 421 return true; 422 } 423 return ParseValue(to, from); 424 } 425 426 template<typename T> GetBaseInfoValueByKey(const std::string & key,T & val)427 bool GetBaseInfoValueByKey(const std::string& key, T& val) 428 { 429 std::unordered_map<std::string, std::function<bool(T&)>> parseFuncs; 430 parseFuncs.emplace(BASE_INFO_KEY_DOMAIN, [this] (T& val) -> bool { 431 return this->ParseValue(val, std::string(header_.domain)); 432 }); 433 parseFuncs.emplace(BASE_INFO_KEY_NAME, [this] (T& val) -> bool { 434 return this->ParseValue(val, std::string(header_.name)); 435 }); 436 parseFuncs.emplace(BASE_INFO_KEY_TYPE, [this] (T& val) -> bool { 437 int type = static_cast<int>(header_.type) + 1; 438 return this->ParseValue(val, type); 439 }); 440 parseFuncs.emplace(BASE_INFO_KEY_TIME_STAMP, [this] (T& val) -> bool { 441 return this->ParseValue(val, header_.timestamp); 442 }); 443 parseFuncs.emplace(BASE_INFO_KEY_TIME_ZONE, [this] (T& val) -> bool { 444 return this->ParseTimeZoneFromHeader(val); 445 }); 446 parseFuncs.emplace(BASE_INFO_KEY_ID, [this] (T& val) -> bool { 447 return this->ParseValue(val, header_.id); 448 }); 449 parseFuncs.emplace(BASE_INFO_KEY_PID, [this] (T& val) -> bool { 450 return this->ParseValue(val, header_.pid); 451 }); 452 parseFuncs.emplace(BASE_INFO_KEY_TID, [this] (T& val) -> bool { 453 return this->ParseValue(val, header_.tid); 454 }); 455 parseFuncs.emplace(BASE_INFO_KEY_UID, [this] (T& val) -> bool { 456 return this->ParseValue(val, header_.uid); 457 }); 458 parseFuncs.emplace(BASE_INFO_KEY_LOG, [this] (T& val) -> bool { 459 return this->ParseValue(val, header_.log); 460 }); 461 parseFuncs.emplace(BASE_INFO_KEY_TRACE_ID, [this] (T& val) -> bool { 462 return this->ParseAndSetTraceInfo(val, traceInfo_.traceId); 463 }); 464 parseFuncs.emplace(BASE_INFO_KEY_SPAN_ID, [this] (T& val) -> bool { 465 return this->ParseAndSetTraceInfo(val, traceInfo_.spanId); 466 }); 467 parseFuncs.emplace(BASE_INFO_KEY_PARENT_SPAN_ID, [this] (T& val) -> bool { 468 return this->ParseAndSetTraceInfo(val, traceInfo_.pSpanId); 469 }); 470 parseFuncs.emplace(BASE_INFO_KEY_TRACE_FLAG, [this] (T& val) -> bool { 471 return this->PareTraceFlagFromHeader(val); 472 }); 473 auto iter = parseFuncs.find(key); 474 return (iter == parseFuncs.end()) ? false : iter->second(val); 475 } 476 477 template<typename T, typename V> ParseValue(T & to,V from)478 bool ParseValue(T& to, V from) 479 { 480 if constexpr (std::is_same_v<std::decay_t<T>, std::decay_t<V>>) { 481 to = from; 482 return true; 483 } 484 if constexpr ((isSignedNum<T> && isSignedNum<V>) || (isUnsignedNum<T> && isUnsignedNum<V>)) { 485 to = static_cast<std::decay_t<T>>(from); 486 return true; 487 } 488 return false; 489 } 490 491 template<typename T> ParseTimeZoneFromHeader(T & val)492 bool ParseTimeZoneFromHeader(T& val) 493 { 494 if constexpr (isUnsignedNum<T>) { 495 val = static_cast<std::decay_t<T>>(header_.timeZone); 496 return true; 497 } 498 if constexpr (isString<T>) { 499 val = ParseTimeZone(header_.timeZone); 500 return true; 501 } 502 return false; 503 } 504 505 template<typename T> PareTraceFlagFromHeader(T & val)506 bool PareTraceFlagFromHeader(T& val) 507 { 508 if constexpr (isUnsignedNum<T>) { 509 val = static_cast<std::decay_t<T>>(traceInfo_.traceFlag); 510 return true; 511 } 512 return false; 513 } 514 515 bool BuildHeader(std::shared_ptr<RawData> dest); 516 bool BuildCustomizedParams(std::shared_ptr<RawData> dest); 517 void InitValueParams(const std::vector<std::shared_ptr<DecodedParam>>& params); 518 void InitArrayValueParams(const std::vector<std::shared_ptr<DecodedParam>>& params); 519 520 private: 521 struct HiSysEventHeader header_ = { 522 .domain = {0}, 523 .name = {0}, 524 .timestamp = 0, 525 .timeZone = 0, 526 .uid = 0, 527 .pid = 0, 528 .tid = 0, 529 .id = 0, 530 .type = 0, 531 .isTraceOpened = 0, 532 .log = 0, 533 }; 534 struct TraceInfo traceInfo_ { 535 .traceFlag = 0, 536 .traceId = 0, 537 .spanId = 0, 538 .pSpanId = 0, 539 }; 540 std::list<std::shared_ptr<EncodedParam>> allParams_; 541 std::mutex paramsOptMtx_; 542 }; 543 } // namespace EventRaw 544 } // namespace HiviewDFX 545 } // namespace OHOS 546 547 #endif // BASE_EVENT_RAW_ENCODE_INCLUDE_RAW_DATA_BUILDER_H 548