• 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 "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*>(&paramCnt), 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