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