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