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