• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(), rawData->GetDataLength());
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>(GetParamCnt());
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, 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 + 1, 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 + 1, 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 
RemoveParam(const std::string & paramName)266 RawDataBuilder& RawDataBuilder::RemoveParam(const std::string& paramName)
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() == paramName) {
274             allParams_.erase(iter);
275             break;
276         }
277     }
278     return *this;
279 }
280 
GetValue(const std::string & key)281 std::shared_ptr<EncodedParam> RawDataBuilder::GetValue(const std::string& key)
282 {
283     std::lock_guard<std::mutex> lock(paramsOptMtx_);
284     for (auto iter = allParams_.begin(); iter != allParams_.end(); ++iter) {
285         if ((*iter) == nullptr) {
286             continue;
287         }
288         if ((*iter)->GetKey() == key) {
289             return *iter;
290         }
291     }
292     return nullptr;
293 }
294 
GetDomain()295 std::string RawDataBuilder::GetDomain()
296 {
297     return std::string(header_.domain);
298 }
299 
GetName()300 std::string RawDataBuilder::GetName()
301 {
302     return std::string(header_.name);
303 }
304 
GetEventType()305 int RawDataBuilder::GetEventType()
306 {
307     return static_cast<int>(header_.type) + 1; // only 2 bits
308 }
309 
GetParamCnt()310 size_t RawDataBuilder::GetParamCnt()
311 {
312     std::lock_guard<std::mutex> lock(paramsOptMtx_);
313     return allParams_.size();
314 }
315 
GetHeader()316 struct HiSysEventHeader& RawDataBuilder::GetHeader()
317 {
318     return header_;
319 }
320 
GetTraceInfo()321 struct TraceInfo& RawDataBuilder::GetTraceInfo()
322 {
323     return traceInfo_;
324 }
325 
InitValueParams(const std::vector<std::shared_ptr<DecodedParam>> & params)326 void RawDataBuilder::InitValueParams(const std::vector<std::shared_ptr<DecodedParam>>& params)
327 {
328     std::unordered_map<EventRaw::DataCodedType,
329         std::function<void(std::shared_ptr<DecodedParam>)>> paramFuncs = {
330         {EventRaw::DataCodedType::UNSIGNED_VARINT, [this] (std::shared_ptr<DecodedParam> param) {
331                 if (uint64_t val = 0; param->AsUint64(val)) {
332                     this->AppendValue(std::make_shared<UnsignedVarintEncodedParam<uint64_t>>(param->GetKey(),
333                         val));
334                 }
335             }
336         },
337         {EventRaw::DataCodedType::SIGNED_VARINT, [this] (std::shared_ptr<DecodedParam> param) {
338                 if (int64_t val = 0; param->AsInt64(val)) {
339                     this->AppendValue(std::make_shared<SignedVarintEncodedParam<int64_t>>(param->GetKey(),
340                         val));
341                 }
342             }
343         },
344         {EventRaw::DataCodedType::FLOATING, [this] (std::shared_ptr<DecodedParam> param) {
345                 if (double val = 0.0; param->AsDouble(val)) {
346                     this->AppendValue(std::make_shared<FloatingNumberEncodedParam<double>>(param->GetKey(),
347                         val));
348                 }
349             }
350         },
351         {EventRaw::DataCodedType::DSTRING, [this] (std::shared_ptr<DecodedParam> param) {
352                 if (std::string val; param->AsString(val)) {
353                     this->AppendValue(std::make_shared<StringEncodedParam>(param->GetKey(),
354                         val));
355                 }
356             }
357         }
358     };
359     auto iter = paramFuncs.begin();
360     for (const auto& param : params) {
361         if (param == nullptr) {
362             continue;
363         }
364         iter = paramFuncs.find(param->GetDataCodedType());
365         if (iter == paramFuncs.end()) {
366             continue;
367         }
368         iter->second(param);
369     }
370     InitArrayValueParams(params);
371 }
372 
InitArrayValueParams(const std::vector<std::shared_ptr<DecodedParam>> & params)373 void RawDataBuilder::InitArrayValueParams(const std::vector<std::shared_ptr<DecodedParam>>& params)
374 {
375     std::unordered_map<EventRaw::DataCodedType,
376         std::function<void(std::shared_ptr<DecodedParam>)>> paramFuncs = {
377         {EventRaw::DataCodedType::UNSIGNED_VARINT_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
378                 if (std::vector<uint64_t> vals; param->AsUint64Vec(vals)) {
379                     this->AppendValue(std::make_shared<UnsignedVarintEncodedArrayParam<uint64_t>>(param->GetKey(),
380                         vals));
381                 }
382             }
383         },
384         {EventRaw::DataCodedType::SIGNED_VARINT_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
385                 if (std::vector<int64_t> vals; param->AsInt64Vec(vals)) {
386                     this->AppendValue(std::make_shared<SignedVarintEncodedArrayParam<int64_t>>(param->GetKey(),
387                         vals));
388                 }
389             }
390         },
391         {EventRaw::DataCodedType::FLOATING_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
392                 if (std::vector<double> vals; param->AsDoubleVec(vals)) {
393                     this->AppendValue(std::make_shared<FloatingNumberEncodedArrayParam<double>>(param->GetKey(),
394                         vals));
395                 }
396             }
397         },
398         {EventRaw::DataCodedType::DSTRING_ARRAY, [this] (std::shared_ptr<DecodedParam> param) {
399                 if (std::vector<std::string> vals; param->AsStringVec(vals)) {
400                     this->AppendValue(std::make_shared<StringEncodedArrayParam>(param->GetKey(),
401                         vals));
402                 }
403             }
404         }
405     };
406     auto iter = paramFuncs.begin();
407     for (const auto& param : params) {
408         if (param == nullptr) {
409             continue;
410         }
411         iter = paramFuncs.find(param->GetDataCodedType());
412         if (iter == paramFuncs.end()) {
413             continue;
414         }
415         iter->second(param);
416     }
417 }
418 } // namespace EventRaw
419 } // namespace HiviewDFX
420 } // namespace OHOS