1 /*
2 * Copyright (c) 2021-2022 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 #include "sys_event.h"
16
17 #include <chrono>
18 #include <regex>
19 #include <sstream>
20 #include <string>
21 #include <sys/time.h>
22
23 #include "string_util.h"
24 #include "time_util.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28 static const std::vector<ParseItem> PARSE_ORDER = {
29 {"domain_", ":\"", "\"", nullptr, STATE_PARSING_DOMAIN, true},
30 {"name_", ":\"", "\"", nullptr, STATE_PARSING_NAME, true},
31 {"type_", ":", ",", nullptr, STATE_PARSING_TYPE, true},
32 {"time_", ":", ",", nullptr, STATE_PARSING_TIME, true},
33 {"seq_", ":", ",", "}", STATE_PARSING_EVENT_SEQ, true},
34 {"tz_", ":\"", "\"", nullptr, STATE_PARSING_TZONE, true},
35 {"pid_", ":", ",", nullptr, STATE_PARSING_PID, true},
36 {"tid_", ":", ",", nullptr, STATE_PARSING_TID, true},
37 {"uid_", ":", ",", "}", STATE_PARSING_UID, true},
38 {"traceid_", ":\"", "\"", nullptr, STATE_PARSING_TRACE_ID, false},
39 {"spanid_", ":\"", "\"", nullptr, STATE_PARSING_SPAN_ID, false},
40 {"pspanid_", ":\"", "\"", nullptr, STATE_PARSING_PARENT_SPAN_ID, false},
41 {"trace_flag_", ":\"", "\"", nullptr, STATE_PARSING_TRACE_FLAG, false},
42 };
43
44 std::atomic<uint32_t> SysEvent::totalCount_(0);
45 std::atomic<int64_t> SysEvent::totalSize_(0);
46
SysEvent(const std::string & sender,PipelineEventProducer * handler,const std::string & jsonStr)47 SysEvent::SysEvent(const std::string& sender, PipelineEventProducer* handler, const std::string& jsonStr)
48 : PipelineEvent(sender, handler), seq_(0), pid_(0), tid_(0), uid_(0), tz_(0)
49 {
50 messageType_ = Event::MessageType::SYS_EVENT;
51 jsonExtraInfo_ = jsonStr;
52 totalCount_.fetch_add(1);
53 totalSize_.fetch_add(jsonStr.length());
54 }
55
SysEvent(const std::string & sender,PipelineEventProducer * handler,SysEventCreator & sysEventCreator)56 SysEvent::SysEvent(const std::string& sender, PipelineEventProducer* handler, SysEventCreator& sysEventCreator)
57 : SysEvent(sender, handler, sysEventCreator.BuildSysEventJson())
58 {
59 ParseJson();
60 }
61
~SysEvent()62 SysEvent::~SysEvent()
63 {
64 if (totalCount_ > 0) {
65 totalCount_.fetch_sub(1);
66 }
67
68 totalSize_.fetch_sub(jsonExtraInfo_.length());
69 if (totalSize_ < 0) {
70 totalSize_.store(0);
71 }
72 }
73
ParseJson()74 int SysEvent::ParseJson()
75 {
76 if (jsonExtraInfo_.empty()) {
77 return -1;
78 }
79 size_t curPos = 0;
80 for (auto ele = PARSE_ORDER.cbegin(); ele != PARSE_ORDER.cend(); ele++) {
81 size_t keyPos = jsonExtraInfo_.find(ele->keyString, curPos);
82 if (keyPos != std::string::npos) {
83 size_t startPos = jsonExtraInfo_.find(ele->valueStart, keyPos);
84 if (startPos == std::string::npos) {
85 continue;
86 }
87 startPos += strlen(ele->valueStart);
88 size_t endPos = jsonExtraInfo_.find(ele->valueEnd1, startPos);
89 if (endPos == std::string::npos && ele->valueEnd2 != nullptr) {
90 endPos = jsonExtraInfo_.find(ele->valueEnd2, startPos);
91 }
92 if (endPos != std::string::npos) {
93 std::string content = jsonExtraInfo_.substr(startPos, endPos - startPos);
94 InitialMember(ele->status, content);
95 curPos = endPos;
96 }
97 } else {
98 if (!ele->isParseContinue) {
99 break;
100 }
101 }
102 }
103 if (domain_.empty() || eventName_.empty() || what_ == 0 || happenTime_ == 0) {
104 return -1;
105 }
106 return 0;
107 }
108
InitialMember(ParseStatus status,const std::string & content)109 void SysEvent::InitialMember(ParseStatus status, const std::string &content)
110 {
111 switch (status) {
112 case STATE_PARSING_DOMAIN:
113 domain_ = content;
114 break;
115 case STATE_PARSING_NAME:
116 eventName_ = content;
117 break;
118 case STATE_PARSING_TYPE:
119 what_ = static_cast<uint16_t>(std::atoi(content.c_str()));
120 break;
121 case STATE_PARSING_TIME:
122 happenTime_ = static_cast<uint64_t>(std::atoll(content.c_str()));
123 break;
124 case STATE_PARSING_EVENT_SEQ:
125 eventSeq_ = static_cast<int64_t>(std::atoll(content.c_str()));
126 break;
127 case STATE_PARSING_TZONE:
128 tz_ = std::atoi(content.c_str());
129 break;
130 case STATE_PARSING_PID:
131 pid_ = std::atoi(content.c_str());
132 break;
133 case STATE_PARSING_TID:
134 tid_ = std::atoi(content.c_str());
135 break;
136 case STATE_PARSING_UID:
137 uid_ = std::atoi(content.c_str());
138 break;
139 case STATE_PARSING_TRACE_ID:
140 traceId_ = content;
141 break;
142 case STATE_PARSING_SPAN_ID:
143 spanId_ = content;
144 break;
145 case STATE_PARSING_PARENT_SPAN_ID:
146 parentSpanId_ = content;
147 break;
148 case STATE_PARSING_TRACE_FLAG:
149 traceFlag_ = content;
150 break;
151 default:
152 break;
153 }
154 }
155
SetSeq(int64_t seq)156 void SysEvent::SetSeq(int64_t seq)
157 {
158 seq_ = seq;
159 }
160
GetSeq() const161 int64_t SysEvent::GetSeq() const
162 {
163 return seq_;
164 }
165
GetEventSeq() const166 int64_t SysEvent::GetEventSeq() const
167 {
168 return eventSeq_;
169 }
170
GetPid() const171 int32_t SysEvent::GetPid() const
172 {
173 return pid_;
174 }
175
GetTid() const176 int32_t SysEvent::GetTid() const
177 {
178 return tid_;
179 }
180
GetUid() const181 int32_t SysEvent::GetUid() const
182 {
183 return uid_;
184 }
185
GetTz() const186 int16_t SysEvent::GetTz() const
187 {
188 return tz_;
189 }
190
GetEventValue(const std::string & key)191 std::string SysEvent::GetEventValue(const std::string& key)
192 {
193 if (jsonExtraInfo_.empty() || key.empty()) {
194 return "";
195 }
196 std::string targetStr = "\"" + key + "\":\"";
197 size_t startPos = jsonExtraInfo_.find(targetStr);
198 if (startPos == std::string::npos) {
199 return "";
200 }
201 startPos += targetStr.size();
202
203 size_t endPos = startPos;
204 while (endPos < jsonExtraInfo_.size()) {
205 if (jsonExtraInfo_[endPos] == '\"') {
206 std::string value = jsonExtraInfo_.substr(startPos, endPos - startPos);
207 if (!value.empty()) {
208 SetValue(key, value);
209 }
210 return value;
211 }
212 if (jsonExtraInfo_[endPos] == '\\' && endPos < (jsonExtraInfo_.size() - 1)) { // 1: for '"'
213 endPos += 2; // 2: for '\' and '"'
214 continue;
215 }
216 endPos++;
217 }
218 return "";
219 }
220
GetEventIntValue(const std::string & key)221 uint64_t SysEvent::GetEventIntValue(const std::string& key)
222 {
223 if (jsonExtraInfo_.empty() || key.empty()) {
224 return 0;
225 }
226 std::string targetStr = "\"" + key + "\":";
227 size_t startPos = jsonExtraInfo_.find(targetStr);
228 if (startPos == std::string::npos) {
229 return 0;
230 }
231 startPos += targetStr.size();
232
233 size_t endPos = startPos;
234 while (endPos < jsonExtraInfo_.size()) {
235 if (!std::isdigit(jsonExtraInfo_[endPos])) {
236 break;
237 }
238 endPos++;
239 }
240 return std::atoll(jsonExtraInfo_.substr(startPos, endPos - startPos).c_str());
241 }
242
SetEventValue(const std::string & key,int64_t value)243 void SysEvent::SetEventValue(const std::string& key, int64_t value)
244 {
245 std::smatch keyMatch;
246 std::string keyReplace = "\"" + key + "\":" + std::to_string(value);
247 std::regex keyReg("\"" + key + "\":([\\d]*)");
248 if (std::regex_search(jsonExtraInfo_, keyMatch, keyReg)) {
249 jsonExtraInfo_ = std::regex_replace(jsonExtraInfo_, keyReg, keyReplace);
250 return;
251 }
252
253 // new key here
254 std::regex newReg("\\{([.\\s\\S\\r\\n]*)\\}");
255 std::string newReplace = "{$1,\"" + key + "\":" + std::to_string(value) + "}";
256 if (std::regex_search(jsonExtraInfo_, keyMatch, newReg)) {
257 jsonExtraInfo_ = std::regex_replace(jsonExtraInfo_, newReg, newReplace);
258 }
259 else {
260 jsonExtraInfo_ = "{\"" + key + "\":" + std::to_string(value) + "}";
261 }
262 return;
263 }
264
SetEventValue(const std::string & key,const std::string & value,bool append)265 void SysEvent::SetEventValue(const std::string& key, const std::string& value, bool append)
266 {
267 // fixme, $1 in value may cause error
268 std::smatch keyMatch;
269 std::string keyReplace;
270 if (append) {
271 keyReplace = "\"" + key + "\":\"" + value + ",$1\"";
272 }
273 else {
274 keyReplace = "\"" + key + "\":\"" + value + "\"";
275 }
276 std::regex keyReg("\"" + key + "\":\"([.\\s\\S\\r\\n]*?)\"");
277 if (std::regex_search(jsonExtraInfo_, keyMatch, keyReg)) {
278 jsonExtraInfo_ = std::regex_replace(jsonExtraInfo_, keyReg, keyReplace);
279 return;
280 }
281
282 // new key here
283 std::regex newReg("\\{([.\\s\\S\\r\\n]*)\\}");
284 auto kvStr = "\"" + key + "\":\"" + value + "\"";
285 if (std::regex_search(jsonExtraInfo_, keyMatch, newReg)) {
286 auto pos = jsonExtraInfo_.find_last_of("}");
287 if (pos == std::string::npos) {
288 return;
289 }
290 jsonExtraInfo_.insert(pos, "," + kvStr);
291 } else {
292 jsonExtraInfo_ = "{" + kvStr + "}";
293 }
294 return;
295 }
296
SysEventCreator(const std::string & domain,const std::string & eventName,SysEventCreator::EventType type)297 SysEventCreator::SysEventCreator(const std::string &domain, const std::string &eventName,
298 SysEventCreator::EventType type)
299 {
300 jsonStr_ << "{";
301 SetKeyValue("domain_", domain);
302 SetKeyValue("name_", eventName);
303 SetKeyValue("type_", static_cast<int>(type));
304 SetKeyValue("time_", TimeUtil::GetMilliseconds());
305 SetKeyValue("tz_", TimeUtil::GetTimeZone());
306 SetKeyValue("pid_", getpid());
307 SetKeyValue("tid_", gettid());
308 SetKeyValue("uid_", getuid());
309 }
310
BuildSysEventJson()311 std::string SysEventCreator::BuildSysEventJson()
312 {
313 jsonStr_.seekp(-1, std::ios_base::end);
314 jsonStr_ << "}";
315 return jsonStr_.str();
316 }
317
EscapeStringValue(const std::string & value)318 std::string SysEventCreator::EscapeStringValue(const std::string& value)
319 {
320 return StringUtil::EscapeJsonStringValue(value);
321 }
322
EscapeStringValue(const char * value)323 std::string SysEventCreator::EscapeStringValue(const char* value)
324 {
325 return StringUtil::EscapeJsonStringValue(value);
326 }
327
EscapeStringValue(char * value)328 std::string SysEventCreator::EscapeStringValue(char* value)
329 {
330 return StringUtil::EscapeJsonStringValue(value);
331 }
332 } // namespace HiviewDFX
333 } // namespace OHOS
334