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 "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 "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).
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,
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
AppendId(const uint64_t id)184 RawDataBuilder& RawDataBuilder::AppendId(const uint64_t id)
185 {
186 header_.id = id;
187 return *this;
188 }
189
AppendId(const std::string & id)190 RawDataBuilder& RawDataBuilder::AppendId(const std::string& id)
191 {
192 uint64_t u64Id = 0;
193 std::stringstream ss(id);
194 ss >> u64Id;
195 AppendId(u64Id);
196 return *this;
197 }
198
AppendTraceId(const uint64_t traceId)199 RawDataBuilder& RawDataBuilder::AppendTraceId(const uint64_t traceId)
200 {
201 header_.isTraceOpened = 1;
202 traceInfo_.traceId = traceId;
203 return *this;
204 }
205
AppendSpanId(const uint32_t spanId)206 RawDataBuilder& RawDataBuilder::AppendSpanId(const uint32_t spanId)
207 {
208 header_.isTraceOpened = 1;
209 traceInfo_.spanId = spanId;
210 return *this;
211 }
212
AppendPSpanId(const uint32_t pSpanId)213 RawDataBuilder& RawDataBuilder::AppendPSpanId(const uint32_t pSpanId)
214 {
215 header_.isTraceOpened = 1;
216 traceInfo_.pSpanId = pSpanId;
217 return *this;
218 }
219
AppendTraceFlag(const uint8_t traceFlag)220 RawDataBuilder& RawDataBuilder::AppendTraceFlag(const uint8_t traceFlag)
221 {
222 header_.isTraceOpened = 1;
223 traceInfo_.traceFlag = traceFlag;
224 return *this;
225 }
226
AppendTraceInfo(const uint64_t traceId,const uint32_t spanId,const uint32_t pSpanId,const uint8_t traceFlag)227 RawDataBuilder& RawDataBuilder::AppendTraceInfo(const uint64_t traceId, const uint32_t spanId,
228 const uint32_t pSpanId, const uint8_t traceFlag)
229 {
230 header_.isTraceOpened = 1; // 1: include trace info, 0: exclude trace info.
231
232 traceInfo_.traceId = traceId;
233 traceInfo_.spanId = spanId;
234 traceInfo_.pSpanId = pSpanId;
235 traceInfo_.traceFlag = traceFlag;
236
237 return *this;
238 }
239
AppendValue(std::shared_ptr<EncodedParam> param)240 RawDataBuilder& RawDataBuilder::AppendValue(std::shared_ptr<EncodedParam> param)
241 {
242 if (param == nullptr || !param->Encode()) {
243 return *this;
244 }
245 auto paramKey = param->GetKey();
246 std::lock_guard<std::mutex> lock(paramsOptMtx_);
247 for (auto iter = allParams_.begin(); iter != allParams_.end(); ++iter) {
248 if ((*iter) == nullptr) {
249 continue;
250 }
251 if ((*iter)->GetKey() == paramKey) {
252 *iter = param;
253 return *this;
254 }
255 }
256 allParams_.emplace_back(param);
257 return *this;
258 }
259
GetValue(const std::string & key)260 std::shared_ptr<EncodedParam> RawDataBuilder::GetValue(const std::string& key)
261 {
262 std::lock_guard<std::mutex> lock(paramsOptMtx_);
263 auto paramCnt = allParams_.size();
264 for (auto iter = allParams_.begin(); iter != allParams_.end(); ++iter) {
265 if (paramCnt != allParams_.size()) {
266 HIVIEW_LOGI("count of all params: [%{public}zu, %{public}zu]", paramCnt, allParams_.size());
267 }
268 if ((*iter) == nullptr) {
269 continue;
270 }
271 if ((*iter)->GetKey() == key) {
272 return *iter;
273 }
274 }
275 return nullptr;
276 }
277
GetDomain()278 std::string RawDataBuilder::GetDomain()
279 {
280 return std::string(header_.domain);
281 }
282
GetName()283 std::string RawDataBuilder::GetName()
284 {
285 return std::string(header_.name);
286 }
287
GetEventType()288 int RawDataBuilder::GetEventType()
289 {
290 return static_cast<int>(header_.type) + 1; // only 2 bits
291 }
292
GetParamCnt()293 size_t RawDataBuilder::GetParamCnt()
294 {
295 return allParams_.size();
296 }
297
GetHeader()298 struct HiSysEventHeader& RawDataBuilder::GetHeader()
299 {
300 return header_;
301 }
302
GetTraceInfo()303 struct TraceInfo& RawDataBuilder::GetTraceInfo()
304 {
305 return traceInfo_;
306 }
307
InitValueParams(std::vector<std::shared_ptr<DecodedParam>> params)308 void RawDataBuilder::InitValueParams(std::vector<std::shared_ptr<DecodedParam>> params)
309 {
310 std::unordered_map<EventRaw::DataCodedType,
311 std::function<void(std::shared_ptr<DecodedParam>)>> paramFuncs = {
312 {EventRaw::DataCodedType::UNSIGNED_VARINT, std::bind(
313 [this] (std::shared_ptr<DecodedParam> param) {
314 if (uint64_t val = 0; param->AsUint64(val)) {
315 this->AppendValue(std::make_shared<UnsignedVarintEncodedParam<uint64_t>>(param->GetKey(),
316 val));
317 }
318 }, std::placeholders::_1)},
319 {EventRaw::DataCodedType::SIGNED_VARINT, std::bind(
320 [this] (std::shared_ptr<DecodedParam> param) {
321 if (int64_t val = 0; param->AsInt64(val)) {
322 this->AppendValue(std::make_shared<SignedVarintEncodedParam<int64_t>>(param->GetKey(),
323 val));
324 }
325 }, std::placeholders::_1)},
326 {EventRaw::DataCodedType::FLOATING, std::bind(
327 [this] (std::shared_ptr<DecodedParam> param) {
328 if (double val = 0.0; param->AsDouble(val)) {
329 this->AppendValue(std::make_shared<FloatingNumberEncodedParam<double>>(param->GetKey(),
330 val));
331 }
332 }, std::placeholders::_1)},
333 {EventRaw::DataCodedType::DSTRING, std::bind(
334 [this] (std::shared_ptr<DecodedParam> param) {
335 if (std::string val; param->AsString(val)) {
336 this->AppendValue(std::make_shared<StringEncodedParam>(param->GetKey(),
337 val));
338 }
339 }, std::placeholders::_1)},
340 };
341 auto iter = paramFuncs.begin();
342 for (auto param : params) {
343 if (param == nullptr) {
344 continue;
345 }
346 iter = paramFuncs.find(param->GetDataCodedType());
347 if (iter == paramFuncs.end()) {
348 continue;
349 }
350 iter->second(param);
351 }
352 InitArrayValueParams(params);
353 }
354
InitArrayValueParams(std::vector<std::shared_ptr<DecodedParam>> params)355 void RawDataBuilder::InitArrayValueParams(std::vector<std::shared_ptr<DecodedParam>> params)
356 {
357 std::unordered_map<EventRaw::DataCodedType,
358 std::function<void(std::shared_ptr<DecodedParam>)>> paramFuncs = {
359 {EventRaw::DataCodedType::UNSIGNED_VARINT_ARRAY, std::bind(
360 [this] (std::shared_ptr<DecodedParam> param) {
361 if (std::vector<uint64_t> vals; param->AsUint64Vec(vals)) {
362 this->AppendValue(std::make_shared<UnsignedVarintEncodedArrayParam<uint64_t>>(param->GetKey(),
363 vals));
364 }
365 }, std::placeholders::_1)},
366 {EventRaw::DataCodedType::SIGNED_VARINT_ARRAY, std::bind(
367 [this] (std::shared_ptr<DecodedParam> param) {
368 if (std::vector<int64_t> vals; param->AsInt64Vec(vals)) {
369 this->AppendValue(std::make_shared<SignedVarintEncodedArrayParam<int64_t>>(param->GetKey(),
370 vals));
371 }
372 }, std::placeholders::_1)},
373 {EventRaw::DataCodedType::FLOATING_ARRAY, std::bind(
374 [this] (std::shared_ptr<DecodedParam> param) {
375 if (std::vector<double> vals; param->AsDoubleVec(vals)) {
376 this->AppendValue(std::make_shared<FloatingNumberEncodedArrayParam<double>>(param->GetKey(),
377 vals));
378 }
379 }, std::placeholders::_1)},
380 {EventRaw::DataCodedType::DSTRING_ARRAY, std::bind(
381 [this] (std::shared_ptr<DecodedParam> param) {
382 if (std::vector<std::string> vals; param->AsStringVec(vals)) {
383 this->AppendValue(std::make_shared<StringEncodedArrayParam>(param->GetKey(),
384 vals));
385 }
386 }, std::placeholders::_1)},
387 };
388 auto iter = paramFuncs.begin();
389 for (auto param : params) {
390 if (param == nullptr) {
391 continue;
392 }
393 iter = paramFuncs.find(param->GetDataCodedType());
394 if (iter == paramFuncs.end()) {
395 continue;
396 }
397 iter->second(param);
398 }
399 }
400 } // namespace EventRaw
401 } // namespace HiviewDFX
402 } // namespace OHOS