• 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 #include "decoded/decoded_event.h"
17 
18 #include <functional>
19 #include <securec.h>
20 #include <sstream>
21 #include <unordered_map>
22 
23 #include "base/raw_data_base_def.h"
24 #include "hilog/log.h"
25 #include "decoded/raw_data_decoder.h"
26 
27 namespace OHOS {
28 namespace HiviewDFX {
29 namespace EventRaw {
30 namespace {
31 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD002D10, "HiView-DecodedEvent" };
32 constexpr size_t MAX_BLOCK_SIZE = 384 * 1024; // 384K
33 
TransUInt64ToFixedLengthStr(uint64_t src)34 std::string TransUInt64ToFixedLengthStr(uint64_t src)
35 {
36     const size_t maxIdLen = 20;
37     std::string uint64Str = std::to_string(src);
38     if (uint64Str.size() >= maxIdLen) {
39         return uint64Str;
40     }
41     std::string dest(maxIdLen, '0');
42     dest.replace(maxIdLen - uint64Str.size(), uint64Str.size(), uint64Str);
43     return dest;
44 }
45 
46 template<typename T>
TransNumToHexStr(T num)47 std::string TransNumToHexStr(T num)
48 {
49     std::stringstream ss;
50     ss << std::hex << num;
51     return ss.str();
52 }
53 }
54 
DecodedEvent(uint8_t * src)55 DecodedEvent::DecodedEvent(uint8_t* src)
56 {
57     if (src == nullptr) {
58         return;
59     }
60     size_t blockSize = static_cast<size_t>(*(reinterpret_cast<int32_t*>(src)));
61     if (blockSize < GetValidDataMinimumByteCount() || blockSize > MAX_BLOCK_SIZE) {
62         HiLog::Error(LABEL, "size of raw data is %{public}zu, which is invalid.", blockSize);
63         return;
64     }
65     rawData_ = new(std::nothrow) uint8_t[blockSize];
66     if (rawData_ == nullptr) {
67         return;
68     }
69     auto ret = memcpy_s(rawData_, blockSize, src, blockSize);
70     if (ret != EOK) {
71         HiLog::Error(LABEL, "Decode memory copy failed, ret is %{public}d.", ret);
72         delete[] rawData_;
73         return;
74     }
75     Parse();
76 }
77 
~DecodedEvent()78 DecodedEvent::~DecodedEvent()
79 {
80     if (rawData_ != nullptr) {
81         delete[] rawData_;
82         rawData_ = nullptr;
83     }
84 }
85 
AppendBaseInfo(std::stringstream & ss)86 void DecodedEvent::AppendBaseInfo(std::stringstream& ss)
87 {
88     char* domain = new(std::nothrow) char[MAX_DOMAIN_LENGTH + 1];
89     if (domain == nullptr) {
90         return;
91     }
92     if (memcpy_s(domain, MAX_DOMAIN_LENGTH, header_.domain, MAX_DOMAIN_LENGTH) != EOK) {
93         delete[] domain;
94         return;
95     }
96     domain[MAX_DOMAIN_LENGTH] = '\0';
97     auto eventDomain = std::string(domain);
98     AppendValue(ss, BASE_INFO_KEY_DOMAIN, eventDomain);
99     delete[] domain;
100     char* name = new(std::nothrow) char[MAX_EVENT_NAME_LENGTH + 1];
101     if (name == nullptr) {
102         return;
103     }
104     if (memcpy_s(name, MAX_EVENT_NAME_LENGTH, header_.name, MAX_EVENT_NAME_LENGTH) != EOK) {
105         delete[] name;
106         return;
107     }
108     name[MAX_EVENT_NAME_LENGTH] = '\0';
109     auto eventName = std::string(name);
110     AppendValue(ss, BASE_INFO_KEY_NAME, eventName);
111     delete[] name;
112     AppendValue(ss, BASE_INFO_KEY_TYPE, (static_cast<int>(header_.type) + 1)); // header_.type is only 2 bits which has
113                                                                           // been subtracted 1 before wrote.
114     AppendValue(ss, BASE_INFO_KEY_TIME_STAMP, header_.timestamp);
115     auto timeZone = ParseTimeZone(static_cast<size_t>(header_.timeZone));
116     AppendValue(ss, BASE_INFO_KEY_TIME_ZONE, timeZone);
117     AppendValue(ss, BASE_INFO_KEY_PID, header_.pid);
118     AppendValue(ss, BASE_INFO_KEY_TID, header_.tid);
119     AppendValue(ss, BASE_INFO_KEY_UID, header_.uid);
120     AppendValue(ss, BASE_INFO_KEY_ID, TransUInt64ToFixedLengthStr(header_.id));
121     if (header_.isTraceOpened == 1) {
122         AppendValue(ss, BASE_INFO_KEY_TRACE_FLAG, static_cast<int>(traceInfo_.traceFlag));
123         AppendValue(ss, BASE_INFO_KEY_TRACE_ID, TransNumToHexStr(traceInfo_.traceId));
124         AppendValue(ss, BASE_INFO_KEY_SPAN_ID, TransNumToHexStr(traceInfo_.spanId));
125         AppendValue(ss, BASE_INFO_KEY_PARENT_SPAN_ID, TransNumToHexStr(traceInfo_.pSpanId));
126     }
127 }
128 
AppendCustomizedArrayParam(std::stringstream & ss,std::shared_ptr<DecodedParam> param)129 void DecodedEvent::AppendCustomizedArrayParam(std::stringstream& ss, std::shared_ptr<DecodedParam> param)
130 {
131     std::unordered_map<DataCodedType, std::function<void(std::shared_ptr<DecodedParam>)>> allFuncs = {
132         {DataCodedType::UNSIGNED_VARINT_ARRAY, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
133                 std::vector<uint64_t> u64Vec;
134                 if (param->AsUint64Vec(u64Vec)) {
135                     this->AppendValue(ss, param->GetKey(), u64Vec);
136                 }
137             }, std::placeholders::_1)},
138         {DataCodedType::SIGNED_VARINT_ARRAY, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
139                 std::vector<int64_t> i64Vec;
140                 if (param->AsInt64Vec(i64Vec)) {
141                     this->AppendValue(ss, param->GetKey(), i64Vec);
142                 }
143             }, std::placeholders::_1)},
144         {DataCodedType::FLOATING_ARRAY, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
145                 std::vector<double> dVec;
146                 if (param->AsDoubleVec(dVec)) {
147                     this->AppendValue(ss, param->GetKey(), dVec);
148                 }
149             }, std::placeholders::_1)},
150         {DataCodedType::DSTRING_ARRAY, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
151                 std::vector<std::string> strVec;
152                 if (param->AsStringVec(strVec)) {
153                     this->AppendValue(ss, param->GetKey(), strVec);
154                 }
155             }, std::placeholders::_1)},
156     };
157     auto iter = allFuncs.find(param->GetDataCodedType());
158     if (iter == allFuncs.end()) {
159         return;
160     }
161     iter->second(param);
162 }
163 
AppendCustomizedParam(std::stringstream & ss,std::shared_ptr<DecodedParam> param)164 void DecodedEvent::AppendCustomizedParam(std::stringstream& ss, std::shared_ptr<DecodedParam> param)
165 {
166     std::unordered_map<DataCodedType, std::function<void(std::shared_ptr<DecodedParam>)>> allFuncs = {
167         {DataCodedType::UNSIGNED_VARINT, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
168                 uint64_t uint64DecodedVal;
169                 if (param->AsUint64(uint64DecodedVal)) {
170                     this->AppendValue(ss, param->GetKey(), uint64DecodedVal);
171                 }
172             }, std::placeholders::_1)},
173         {DataCodedType::SIGNED_VARINT, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
174                 int64_t int64DecodedVal;
175                 if (param->AsInt64(int64DecodedVal)) {
176                     this->AppendValue(ss, param->GetKey(), int64DecodedVal);
177                 }
178             }, std::placeholders::_1)},
179         {DataCodedType::FLOATING, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
180                 double dDecodedVal;
181                 if (param->AsDouble(dDecodedVal)) {
182                     this->AppendValue(ss, param->GetKey(), dDecodedVal);
183                 }
184             }, std::placeholders::_1)},
185         {DataCodedType::DSTRING, std::bind([this, &ss](std::shared_ptr<DecodedParam> param) {
186                 std::string strDecodedVal;
187                 if (param->AsString(strDecodedVal)) {
188                     this->AppendValue(ss, param->GetKey(), strDecodedVal);
189                 }
190             }, std::placeholders::_1)},
191     };
192     auto iter = allFuncs.find(param->GetDataCodedType());
193     if (iter == allFuncs.end()) {
194         return;
195     }
196     iter->second(param);
197 }
198 
AppendCustomizedParams(std::stringstream & ss)199 void DecodedEvent::AppendCustomizedParams(std::stringstream& ss)
200 {
201     for (auto param: allParams_) {
202         if (param == nullptr) {
203             continue;
204         }
205         std::vector<DataCodedType> noArrayEncodedTypes = {
206             DataCodedType::UNSIGNED_VARINT,
207             DataCodedType::SIGNED_VARINT,
208             DataCodedType::FLOATING,
209             DataCodedType::DSTRING,
210         };
211         if (find(noArrayEncodedTypes.begin(), noArrayEncodedTypes.end(), param->GetDataCodedType()) !=
212             noArrayEncodedTypes.end()) {
213             AppendCustomizedParam(ss, param);
214             continue;
215         }
216         AppendCustomizedArrayParam(ss, param);
217     }
218 }
219 
AsJsonStr()220 std::string DecodedEvent::AsJsonStr()
221 {
222     std::stringstream jsonStream;
223     jsonStream << "{";
224     AppendBaseInfo(jsonStream);
225     AppendCustomizedParams(jsonStream);
226     if (jsonStream.tellp() != 0) {
227         jsonStream.seekp(-1, std::ios_base::end);
228     }
229     jsonStream << "}";
230     HiLog::Debug(LABEL, "Decoded event: %{public}s.", jsonStream.str().c_str());
231     return jsonStream.str();
232 }
233 
GetRawData()234 std::shared_ptr<RawData> DecodedEvent::GetRawData()
235 {
236     return std::make_shared<RawData>(rawData_, pos_);
237 }
238 
IsValid()239 bool DecodedEvent::IsValid()
240 {
241     return isValid_;
242 }
243 
GetHeader()244 const struct HiSysEventHeader& DecodedEvent::GetHeader()
245 {
246     return header_;
247 }
248 
GetTraceInfo()249 const struct TraceInfo& DecodedEvent::GetTraceInfo()
250 {
251     return traceInfo_;
252 }
253 
GetAllCustomizedValues()254 const std::vector<std::shared_ptr<DecodedParam>>& DecodedEvent::GetAllCustomizedValues()
255 {
256     return allParams_;
257 }
258 
Parse()259 void DecodedEvent::Parse()
260 {
261     isValid_ = true;
262     if (rawData_ == nullptr) {
263         isValid_ = false;
264         return;
265     }
266     pos_ = 0; // reset to 0
267     // decode block size
268     size_t blockSize = static_cast<size_t>(*(reinterpret_cast<int32_t*>(rawData_)));
269     pos_ += sizeof(int32_t);
270     ParseHeader(blockSize);
271     ParseCustomizedParams(blockSize);
272 }
273 
ParseHeader(const size_t maxLen)274 void DecodedEvent::ParseHeader(const size_t maxLen)
275 {
276     // decode event header
277     if ((pos_ + sizeof(struct HiSysEventHeader)) > maxLen) {
278         isValid_ = false;
279         return;
280     }
281     header_ = *(reinterpret_cast<struct HiSysEventHeader*>(rawData_ + pos_));
282     pos_ += sizeof(struct HiSysEventHeader);
283     // decode trace info
284     if (header_.isTraceOpened == 1) { // 1: include trace info, 0: exclude trace info
285         if (((pos_ + sizeof(struct TraceInfo)) > maxLen)) {
286             isValid_ = false;
287             return;
288         }
289         traceInfo_ = *(reinterpret_cast<struct TraceInfo*>(rawData_ + pos_));
290         pos_ += sizeof(struct TraceInfo);
291     }
292 }
293 
ParseCustomizedParams(const size_t maxLen)294 void DecodedEvent::ParseCustomizedParams(const size_t maxLen)
295 {
296     if ((pos_ + sizeof(int32_t)) > maxLen) {
297         isValid_ = false;
298         return;
299     }
300     auto paramCnt = static_cast<size_t>(*(reinterpret_cast<int32_t*>(rawData_ + pos_)));
301     HiLog::Debug(LABEL, "paramCnt is : %{public}zu.", paramCnt);
302     pos_ += sizeof(int32_t);
303     while (paramCnt > 0) {
304         auto decodedParam = ParseCustomizedParam(maxLen);
305         if (decodedParam == nullptr || !(decodedParam->DecodeValue())) {
306             HiLog::Error(LABEL, "Value of customized parameter is decoded failed.");
307             isValid_ = false;
308             return;
309         }
310         pos_ = decodedParam->GetPosition();
311         allParams_.emplace_back(decodedParam);
312         --paramCnt;
313     }
314 }
315 
CreateFloatingNumTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)316 std::shared_ptr<DecodedParam> DecodedEvent::CreateFloatingNumTypeDecodedParam(const size_t maxLen,
317     const std::string& key, bool isArray)
318 {
319     if (isArray) {
320         return std::make_shared<FloatingNumberDecodedArrayParam>(rawData_, maxLen, pos_, key);
321     }
322     return std::make_shared<FloatingNumberDecodedParam>(rawData_, maxLen, pos_, key);
323 }
324 
CreateSignedVarintTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)325 std::shared_ptr<DecodedParam> DecodedEvent::CreateSignedVarintTypeDecodedParam(const size_t maxLen,
326     const std::string& key, bool isArray)
327 {
328     if (isArray) {
329         return std::make_shared<SignedVarintDecodedArrayParam>(rawData_, maxLen, pos_, key);
330     }
331     return std::make_shared<SignedVarintDecodedParam>(rawData_, maxLen, pos_, key);
332 }
333 
CreateStringTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)334 std::shared_ptr<DecodedParam> DecodedEvent::CreateStringTypeDecodedParam(const size_t maxLen,
335     const std::string& key, bool isArray)
336 {
337     if (isArray) {
338         return std::make_shared<StringDecodedArrayParam>(rawData_, maxLen, pos_, key);
339     }
340     return std::make_shared<StringDecodedParam>(rawData_, maxLen, pos_, key);
341 }
342 
CreateUnsignedVarintTypeDecodedParam(const size_t maxLen,const std::string & key,bool isArray)343 std::shared_ptr<DecodedParam> DecodedEvent::CreateUnsignedVarintTypeDecodedParam(const size_t maxLen,
344     const std::string& key, bool isArray)
345 {
346     if (isArray) {
347         return std::make_shared<UnsignedVarintDecodedArrayParam>(rawData_, maxLen, pos_, key);
348     }
349     return std::make_shared<UnsignedVarintDecodedParam>(rawData_, maxLen, pos_, key);
350 }
351 
ParseCustomizedParam(const size_t maxLen)352 std::shared_ptr<DecodedParam> DecodedEvent::ParseCustomizedParam(const size_t maxLen)
353 {
354     std::string key;
355     if (!RawDataDecoder::StringValueDecoded(rawData_, maxLen, pos_, key)) {
356         isValid_ = false;
357         return nullptr;
358     }
359     struct ParamValueType valueType {
360         .isArray = 0,
361         .valueType = static_cast<uint8_t>(ValueType::UNKNOWN),
362         .valueByteCnt = 0,
363     };
364     if (!RawDataDecoder::ValueTypeDecoded(rawData_, maxLen, pos_, valueType)) {
365         isValid_ = false;
366         return nullptr;
367     }
368     std::shared_ptr<DecodedParam> ret = nullptr;
369     switch (ValueType(valueType.valueType)) {
370         case ValueType::STRING: {
371             ret = CreateStringTypeDecodedParam(maxLen, key, valueType.isArray == 1);
372             break;
373         }
374         case ValueType::FLOAT:
375         case ValueType::DOUBLE: {
376             ret = CreateFloatingNumTypeDecodedParam(maxLen, key, valueType.isArray == 1);
377             break;
378         }
379         case ValueType::UINT8:
380         case ValueType::UINT16:
381         case ValueType::UINT32:
382         case ValueType::UINT64: {
383             ret = CreateUnsignedVarintTypeDecodedParam(maxLen, key, valueType.isArray == 1);
384             break;
385         }
386         case ValueType::BOOL:
387         case ValueType::INT8:
388         case ValueType::INT16:
389         case ValueType::INT32:
390         case ValueType::INT64: {
391             ret = CreateSignedVarintTypeDecodedParam(maxLen, key, valueType.isArray == 1);
392             break;
393         }
394         default:
395             break;
396     }
397     return ret;
398 }
399 } // namespace EventRaw
400 } // namespace HiviewDFX
401 } // namespace OHOS