• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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