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