• 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& 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