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