1 /*
2 * Copyright (c) 2023-2024 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 "encoded/raw_data_builder.h"
17
18 #include <cinttypes>
19 #include <securec.h>
20 #include <sstream>
21 #include <vector>
22
23 #include "decoded/decoded_event.h"
24 #include "hiview_logger.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28 namespace EventRaw {
29 DEFINE_LOG_TAG("HiView-RawDataBuilder");
RawDataBuilder(std::shared_ptr<EventRaw::RawData> rawData)30 RawDataBuilder::RawDataBuilder(std::shared_ptr<EventRaw::RawData> rawData)
31 {
32 if (rawData == nullptr) {
33 return;
34 }
35 EventRaw::DecodedEvent event(rawData->GetData());
36 auto header = event.GetHeader();
37 auto traceInfo = event.GetTraceInfo();
38 AppendDomain(header.domain).AppendName(header.name).AppendType(static_cast<int>(header.type) + 1).
39 AppendTimeStamp(header.timestamp).AppendTimeZone(header.timeZone).AppendLog(header.log).
40 AppendUid(header.uid).AppendPid(header.pid).AppendTid(header.tid).AppendId(header.id);
41 if (header.isTraceOpened == 1) {
42 AppendTraceInfo(traceInfo.traceId, traceInfo.spanId, traceInfo.pSpanId, traceInfo.traceFlag);
43 }
44 InitValueParams(event.GetAllCustomizedValues());
45 }
46
RawDataBuilder(const std::string & domain,const std::string & name,const int eventType)47 RawDataBuilder::RawDataBuilder(const std::string& domain, const std::string& name, const int eventType)
48 {
49 (void)AppendDomain(domain);
50 (void)AppendName(name);
51 (void)AppendType(eventType);
52 }
53
BuildHeader(std::shared_ptr<RawData> dest)54 bool RawDataBuilder::BuildHeader(std::shared_ptr<RawData> dest)
55 {
56 if (!dest->Append(reinterpret_cast<uint8_t*>(&header_), sizeof(struct HiSysEventHeader))) {
57 HIVIEW_LOGE("Event header copy failed.");
58 return false;
59 }
60 // append trace info
61 if (header_.isTraceOpened == 1 &&
62 !dest->Append(reinterpret_cast<uint8_t*>(&traceInfo_), sizeof(struct TraceInfo))) {
63 HIVIEW_LOGE("Trace info copy failed.");
64 return false;
65 }
66 return true;
67 }
68
BuildCustomizedParams(std::shared_ptr<RawData> dest)69 bool RawDataBuilder::BuildCustomizedParams(std::shared_ptr<RawData> dest)
70 {
71 std::lock_guard<std::mutex> lock(paramsOptMtx_);
72 return !any_of(allParams_.begin(), allParams_.end(), [&dest] (auto& param) {
73 auto rawData = param->GetRawData();
74 return !dest->Append(rawData.GetData(), rawData.GetDataLength());
75 });
76 }
77
Build()78 std::shared_ptr<RawData> RawDataBuilder::Build()
79 {
80 // placehold block size
81 int32_t blockSize = 0;
82 auto rawData = std::make_shared<RawData>();
83 if (!rawData->Append(reinterpret_cast<uint8_t*>(&blockSize), sizeof(int32_t))) {
84 HIVIEW_LOGE("Block size copy failed.");
85 return nullptr;
86 }
87 if (!BuildHeader(rawData)) {
88 HIVIEW_LOGE("Header of sysevent build failed.");
89 return nullptr;
90 }
91 // append parameter count
92 int32_t paramCnt = static_cast<int32_t>(allParams_.size());
93 if (!rawData->Append(reinterpret_cast<uint8_t*>(¶mCnt), sizeof(int32_t))) {
94 HIVIEW_LOGE("Parameter count copy failed.");
95 return rawData;
96 }
97 if (!BuildCustomizedParams(rawData)) {
98 HIVIEW_LOGE("Customized paramters of sysevent build failed.");
99 return rawData;
100 }
101 // update block size
102 blockSize = static_cast<int32_t>(rawData->GetDataLength());
103 if (!rawData->Update(reinterpret_cast<uint8_t*>(&blockSize), sizeof(int32_t), 0)) {
104 HIVIEW_LOGE("Failed to update block size.");
105 }
106 return rawData;
107 }
108
IsBaseInfo(const std::string & key)109 bool RawDataBuilder::IsBaseInfo(const std::string& key)
110 {
111 std::vector<const std::string> allBaseInfoKeys = {
112 BASE_INFO_KEY_DOMAIN, BASE_INFO_KEY_NAME, BASE_INFO_KEY_TYPE, BASE_INFO_KEY_TIME_STAMP, BASE_INFO_KEY_LOG,
113 BASE_INFO_KEY_TIME_ZONE, BASE_INFO_KEY_ID, BASE_INFO_KEY_PID, BASE_INFO_KEY_TID, BASE_INFO_KEY_UID,
114 BASE_INFO_KEY_TRACE_ID, BASE_INFO_KEY_SPAN_ID, BASE_INFO_KEY_PARENT_SPAN_ID, BASE_INFO_KEY_TRACE_FLAG
115 };
116 return find(allBaseInfoKeys.begin(), allBaseInfoKeys.end(), key) != allBaseInfoKeys.end();
117 }
118
AppendDomain(const std::string & domain)119 RawDataBuilder& RawDataBuilder::AppendDomain(const std::string& domain)
120 {
121 auto ret = memcpy_s(header_.domain, MAX_DOMAIN_LENGTH, domain.c_str(), domain.length());
122 if (ret != EOK) {
123 HIVIEW_LOGE("Failed to copy event domain, ret is %{public}d.", ret);
124 }
125 auto resetPos = std::min(domain.length(), static_cast<size_t>(MAX_DOMAIN_LENGTH));
126 header_.domain[resetPos] = '\0';
127 return *this;
128 }
129
AppendName(const std::string & name)130 RawDataBuilder& RawDataBuilder::AppendName(const std::string& name)
131 {
132 auto ret = memcpy_s(header_.name, MAX_EVENT_NAME_LENGTH, name.c_str(), name.length());
133 if (ret != EOK) {
134 HIVIEW_LOGE("Failed to copy event name, ret is %{public}d.", ret);
135 }
136 auto resetPos = std::min(name.length(), static_cast<size_t>(MAX_EVENT_NAME_LENGTH));
137 header_.name[resetPos] = '\0';
138 return *this;
139 }
140
AppendType(const int eventType)141 RawDataBuilder& RawDataBuilder::AppendType(const int eventType)
142 {
143 header_.type = static_cast<uint8_t>(eventType - 1); // header_.type is only 2 bits which must be
144 // subtracted 1 in order to avoid data overrflow.
145 return *this;
146 }
147
AppendTimeStamp(const uint64_t timestamp)148 RawDataBuilder& RawDataBuilder::AppendTimeStamp(const uint64_t timestamp)
149 {
150 header_.timestamp = timestamp;
151 return *this;
152 }
153
AppendTimeZone(const std::string & timeZone)154 RawDataBuilder& RawDataBuilder::AppendTimeZone(const std::string& timeZone)
155 {
156 header_.timeZone = static_cast<uint8_t>(ParseTimeZone(timeZone));
157 return *this;
158 }
159
AppendTimeZone(const uint8_t timeZone)160 RawDataBuilder& RawDataBuilder::AppendTimeZone(const uint8_t timeZone)
161 {
162 header_.timeZone = timeZone;
163 return *this;
164 }
165
AppendUid(const uint32_t uid)166 RawDataBuilder& RawDataBuilder::AppendUid(const uint32_t uid)
167 {
168 header_.uid = uid;
169 return *this;
170 }
171
AppendPid(const uint32_t pid)172 RawDataBuilder& RawDataBuilder::AppendPid(const uint32_t pid)
173 {
174 header_.pid = pid;
175 return *this;
176 }
177
AppendTid(const uint32_t tid)178 RawDataBuilder& RawDataBuilder::AppendTid(const uint32_t tid)
179 {
180 header_.tid = tid;
181 return *this;
182 }
183
AppendLog(const uint8_t log)184 RawDataBuilder& RawDataBuilder::AppendLog(const uint8_t log)
185 {
186 header_.log = log;
187 return *this;
188 }
189
AppendId(const uint64_t id)190 RawDataBuilder& RawDataBuilder::AppendId(const uint64_t id)
191 {
192 header_.id = id;
193 return *this;
194 }
195
AppendId(const std::string & id)196 RawDataBuilder& RawDataBuilder::AppendId(const std::string& id)
197 {
198 uint64_t u64Id = 0;
199 std::stringstream ss(id);
200 ss >> u64Id;
201 AppendId(u64Id);
202 return *this;
203 }
204
AppendTraceId(const uint64_t traceId)205 RawDataBuilder& RawDataBuilder::AppendTraceId(const uint64_t traceId)
206 {
207 header_.isTraceOpened = 1;
208 traceInfo_.traceId = traceId;
209 return *this;
210 }
211
AppendSpanId(const uint32_t spanId)212 RawDataBuilder& RawDataBuilder::AppendSpanId(const uint32_t spanId)
213 {
214 header_.isTraceOpened = 1;
215 traceInfo_.spanId = spanId;
216 return *this;
217 }
218
AppendPSpanId(const uint32_t pSpanId)219 RawDataBuilder& RawDataBuilder::AppendPSpanId(const uint32_t pSpanId)
220 {
221 header_.isTraceOpened = 1;
222 traceInfo_.pSpanId = pSpanId;
223 return *this;
224 }
225
AppendTraceFlag(const uint8_t traceFlag)226 RawDataBuilder& RawDataBuilder::AppendTraceFlag(const uint8_t traceFlag)
227 {
228 header_.isTraceOpened = 1;
229 traceInfo_.traceFlag = traceFlag;
230 return *this;
231 }
232
AppendTraceInfo(const uint64_t traceId,const uint32_t spanId,const uint32_t pSpanId,const uint8_t traceFlag)233 RawDataBuilder& RawDataBuilder::AppendTraceInfo(const uint64_t traceId, const uint32_t spanId,
234 const uint32_t pSpanId, const uint8_t traceFlag)
235 {
236 header_.isTraceOpened = 1; // 1: include trace info, 0: exclude trace info.
237
238 traceInfo_.traceId = traceId;
239 traceInfo_.spanId = spanId;
240 traceInfo_.pSpanId = pSpanId;
241 traceInfo_.traceFlag = traceFlag;
242
243 return *this;
244 }
245
AppendValue(std::shared_ptr<EncodedParam> param)246 RawDataBuilder& RawDataBuilder::AppendValue(std::shared_ptr<EncodedParam> param)
247 {
248 if (param == nullptr || !param->Encode()) {
249 return *this;
250 }
251 auto paramKey = param->GetKey();
252 std::lock_guard<std::mutex> lock(paramsOptMtx_);
253 for (auto iter = allParams_.begin(); iter != allParams_.end(); ++iter) {
254 if ((*iter) == nullptr) {
255 continue;
256 }
257 if ((*iter)->GetKey() == paramKey) {
258 *iter = param;
259 return *this;
260 }
261 }
262 allParams_.emplace_back(param);
263 return *this;
264 }
265
GetValue(const std::string & key)266 std::shared_ptr<EncodedParam> RawDataBuilder::GetValue(const std::string& key)
267 {
268 std::lock_guard<std::mutex> lock(paramsOptMtx_);
269 for (auto iter = allParams_.begin(); iter != allParams_.end(); ++iter) {
270 if ((*iter) == nullptr) {
271 continue;
272 }
273 if ((*iter)->GetKey() == key) {
274 return *iter;
275 }
276 }
277 return nullptr;
278 }
279
GetDomain()280 std::string RawDataBuilder::GetDomain()
281 {
282 return std::string(header_.domain);
283 }
284
GetName()285 std::string RawDataBuilder::GetName()
286 {
287 return std::string(header_.name);
288 }
289
GetEventType()290 int RawDataBuilder::GetEventType()
291 {
292 return static_cast<int>(header_.type) + 1; // only 2 bits
293 }
294
GetParamCnt()295 size_t RawDataBuilder::GetParamCnt()
296 {
297 return allParams_.size();
298 }
299
GetHeader()300 struct HiSysEventHeader& RawDataBuilder::GetHeader()
301 {
302 return header_;
303 }
304
GetTraceInfo()305 struct TraceInfo& RawDataBuilder::GetTraceInfo()
306 {
307 return traceInfo_;
308 }
309
InitValueParams(const std::vector<std::shared_ptr<DecodedParam>> & params)310 void RawDataBuilder::InitValueParams(const std::vector<std::shared_ptr<DecodedParam>>& params)
311 {
312 std::unordered_map<EventRaw::DataCodedType,
313 std::function<void(std::shared_ptr<DecodedParam>)>> paramFuncs = {
314 {EventRaw::DataCodedType::UNSIGNED_VARINT, [this] (std::shared_ptr<DecodedParam> param) {
315 if (uint64_t val = 0; param->AsUint64(val)) {
316 this->AppendValue(std::make_shared<UnsignedVarintEncodedParam<uint64_t>>(param->GetKey(),
317 val));
318 }
319 }
320 },
321 {EventRaw::DataCodedType::SIGNED_VARINT, [this] (std::shared_ptr<DecodedParam> param) {
322 if (int64_t val = 0; param->AsInt64(val)) {
323 this->AppendValue(std::make_shared<SignedVarintEncodedParam<int64_t>>(param->GetKey(),
324 val));
325 }
326 }
327 },
328 {EventRaw::DataCodedType::FLOATING, [this] (std::shared_ptr<DecodedParam> param) {
329 if (double val = 0.0; param->AsDouble(val)) {
330 this->AppendValue(std::make_shared<FloatingNumberEncodedParam<double>>(param->GetKey(),
331 val));
332 }
333 }
334 },
335 {EventRaw::DataCodedType::DSTRING, [this] (std::shared_ptr<DecodedParam> param) {
336 if (std::string val; param->AsString(val)) {
337 this->AppendValue(std::make_shared<StringEncodedParam>(param->GetKey(),
338 val));
339 }
340 }
341 }
342 };
343 auto iter = paramFuncs.begin();
344 for (const auto& param : params) {
345 if (param == nullptr) {
346 continue;
347 }
348 iter = paramFuncs.find(param->GetDataCodedType());
349 if (iter == paramFuncs.end()) {
350 continue;
351 }
352 iter->second(param);
353 }
354 InitArrayValueParams(params);
355 }
356
InitArrayValueParams(const std::vector<std::shared_ptr<DecodedParam>> & params)357 void RawDataBuilder::InitArrayValueParams(const std::vector<std::shared_ptr<DecodedParam>>& params)
358 {
359 std::unordered_map<EventRaw::DataCodedType,
360 std::function<void(std::shared_ptr<DecodedParam>)>> paramFuncs = {
361 {EventRaw::DataCodedType::UNSIGNED_VARINT_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
362 if (std::vector<uint64_t> vals; param->AsUint64Vec(vals)) {
363 this->AppendValue(std::make_shared<UnsignedVarintEncodedArrayParam<uint64_t>>(param->GetKey(),
364 vals));
365 }
366 }
367 },
368 {EventRaw::DataCodedType::SIGNED_VARINT_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
369 if (std::vector<int64_t> vals; param->AsInt64Vec(vals)) {
370 this->AppendValue(std::make_shared<SignedVarintEncodedArrayParam<int64_t>>(param->GetKey(),
371 vals));
372 }
373 }
374 },
375 {EventRaw::DataCodedType::FLOATING_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
376 if (std::vector<double> vals; param->AsDoubleVec(vals)) {
377 this->AppendValue(std::make_shared<FloatingNumberEncodedArrayParam<double>>(param->GetKey(),
378 vals));
379 }
380 }
381 },
382 {EventRaw::DataCodedType::DSTRING_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
383 if (std::vector<std::string> vals; param->AsStringVec(vals)) {
384 this->AppendValue(std::make_shared<StringEncodedArrayParam>(param->GetKey(),
385 vals));
386 }
387 }
388 }
389 };
390 auto iter = paramFuncs.begin();
391 for (const auto& param : params) {
392 if (param == nullptr) {
393 continue;
394 }
395 iter = paramFuncs.find(param->GetDataCodedType());
396 if (iter == paramFuncs.end()) {
397 continue;
398 }
399 iter->second(param);
400 }
401 }
402 } // namespace EventRaw
403 } // namespace HiviewDFX
404 } // namespace OHOS