• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "bytrace_parser.h"
17 #include <cmath>
18 #include <sstream>
19 #include <unistd.h>
20 #include "binder_filter.h"
21 #include "cpu_filter.h"
22 #include "hi_sysevent_measure_filter.h"
23 #include "parting_string.h"
24 #include "stat_filter.h"
25 #include "system_event_measure_filter.h"
26 namespace SysTuning {
27 namespace TraceStreamer {
BytraceParser(TraceDataCache * dataCache,const TraceStreamerFilters * filters)28 BytraceParser::BytraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters)
29     : ParserBase(filters),
30       eventParser_(std::make_unique<BytraceEventParser>(dataCache, filters))
31 {
32 #ifdef SUPPORTTHREAD
33     supportThread_ = true;
34     dataSegArray_ = std::make_unique<DataSegment[]>(MAX_SEG_ARRAY_SIZE);
35 #else
36     dataSegArray_ = std::make_unique<DataSegment[]>(1);
37 #endif
38 }
39 
40 BytraceParser::~BytraceParser() = default;
41 
WaitForParserEnd()42 void BytraceParser::WaitForParserEnd()
43 {
44     if (parseThreadStarted_ || filterThreadStarted_) {
45         toExit_ = true;
46         while (!exited_) {
47             usleep(sleepDur_ * sleepDur_);
48         }
49     }
50     eventParser_->FilterAllEvents();
51     eventParser_->Clear();
52     dataSegArray_.reset();
53 }
ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size)54 void BytraceParser::ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size)
55 {
56     if (isParsingOver_) {
57         return;
58     }
59     packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
60     auto packagesBegin = packagesBuffer_.begin();
61     while (1) {
62         auto packagesLine = std::find(packagesBegin, packagesBuffer_.end(), '\n');
63         if (packagesLine == packagesBuffer_.end()) {
64             break;
65         }
66         if (packagesLine == packagesBuffer_.begin()) {
67             packagesLine++;
68             packagesBegin = packagesLine;
69             continue;
70         }
71         // Support parsing windows file format(ff=dos)
72         auto extra = *(packagesLine - 1) == '\r' ? 1 : 0;
73         std::string bufferLine(packagesBegin, packagesLine - extra);
74 
75         if (IsTraceComment(bufferLine)) {
76             traceCommentLines_++;
77             goto NEXT_LINE;
78         }
79         if (bufferLine.empty()) {
80             parsedTraceInvalidLines_++;
81             goto NEXT_LINE;
82         }
83 
84         if (bufferLine.find(script_.c_str()) != std::string::npos) {
85             isParsingOver_ = true;
86             break;
87         }
88         if (isBytrace_) {
89             ParseTraceDataItem(bufferLine);
90         } else {
91             ParseJsonData(bufferLine);
92         }
93 
94     NEXT_LINE:
95         packagesBegin = packagesLine + 1;
96         continue;
97     }
98 
99     if (isParsingOver_) {
100         packagesBuffer_.clear();
101     } else {
102         packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
103     }
104     return;
105 }
JGetData(json & jMessage,JsonData & jData,size_t & maxArraySize,std::vector<size_t> & noArrayIndex,std::vector<size_t> & arrayIndex)106 int32_t BytraceParser::JGetData(json& jMessage,
107                              JsonData& jData,
108                              size_t& maxArraySize,
109                              std::vector<size_t>& noArrayIndex,
110                              std::vector<size_t>& arrayIndex)
111 {
112     for (auto i = jMessage.begin(); i != jMessage.end(); i++) {
113         if (i.key() == "name_") {
114             jData.eventSource = i.value();
115             if (find(eventsAccordingAppNames.begin(), eventsAccordingAppNames.end(), jData.eventSource) ==
116                 eventsAccordingAppNames.end()) {
117                 return -1;
118             }
119             continue;
120         }
121         if (i.key() == "time_") {
122             jData.timestamp = i.value();
123             continue;
124         }
125         if (i.key() == "tag_" && i.value() != "PowerStats") {
126             TS_LOGW("energy data without PowerStats tag_ would be invalid");
127             return -1;
128         }
129         if (i.key() == "APPNAME") {
130             jData.appName.assign(i.value().begin(), i.value().end());
131         }
132         if (i.value().is_array()) {
133             maxArraySize = std::max(maxArraySize, i.value().size());
134             arrayIndex.push_back(jData.key.size());
135         } else {
136             noArrayIndex.push_back(jData.key.size());
137         }
138         jData.key.push_back(i.key());
139         jData.value.push_back(i.value());
140     }
141     return 0;
142 }
143 
NoArrayDataParse(JsonData jData,std::vector<size_t> noArrayIndex,DataIndex eventSourceIndex)144 void BytraceParser::NoArrayDataParse(JsonData jData, std::vector<size_t> noArrayIndex, DataIndex eventSourceIndex)
145 {
146     for (auto itor = noArrayIndex.begin(); itor != noArrayIndex.end(); itor++) {
147         auto value = jData.value[*itor];
148         std::string key = jData.key[*itor];
149         streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex);
150         DataIndex keyIndex = eventParser_->traceDataCache_->GetDataIndex(key);
151         if (value.is_string()) {
152             std::string strValue = value;
153             DataIndex valueIndex = eventParser_->traceDataCache_->GetDataIndex(strValue);
154             streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp,
155                                                                      eventSourceIndex, keyIndex, 1, 0, valueIndex);
156         } else {
157             DataIndex valueIndex = value;
158             streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp,
159                                                                      eventSourceIndex, keyIndex, 0, valueIndex, 0);
160         }
161     }
162 }
ArrayDataParse(JsonData jData,std::vector<size_t> arrayIndex,DataIndex eventSourceIndex,size_t maxArraySize)163 void BytraceParser::ArrayDataParse(JsonData jData,
164                                    std::vector<size_t> arrayIndex,
165                                    DataIndex eventSourceIndex,
166                                    size_t maxArraySize)
167 {
168     for (int j = 0; j < maxArraySize; j++) {
169         for (auto itor = arrayIndex.begin(); itor != arrayIndex.end(); itor++) {
170             auto value = jData.value[*itor][j];
171             std::string key = jData.key[*itor];
172             DataIndex keyIndex = eventParser_->traceDataCache_->GetDataIndex(key);
173             streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex);
174             if (value.is_number()) {
175                 DataIndex valueIndex = value;
176                 streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp,
177                                                                          eventSourceIndex, keyIndex, 0, valueIndex, 0);
178             } else if (value.is_string()) {
179                 std::string strValue = value;
180                 DataIndex valueIndex = eventParser_->traceDataCache_->GetDataIndex(strValue);
181                 streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp,
182                                                                          eventSourceIndex, keyIndex, 1, 0, valueIndex);
183             }
184         }
185     }
186 }
CommonDataParser(JsonData jData,DataIndex eventSourceIndex)187 void BytraceParser::CommonDataParser(JsonData jData, DataIndex eventSourceIndex)
188 {
189     for (int j = 0; j < jData.key.size(); j++) {
190         std::string key = jData.key[j];
191         auto value = jData.value[j];
192         DataIndex keyIndex = eventParser_->traceDataCache_->GetDataIndex(key);
193         streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex);
194         if (value.is_string()) {
195             std::string strValue = value;
196             DataIndex valueIndex = eventParser_->traceDataCache_->GetDataIndex(strValue);
197             streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp,
198                                                                      eventSourceIndex, keyIndex, 1, 0, valueIndex);
199         } else {
200             DataIndex valueIndex = value;
201             streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp,
202                                                                      eventSourceIndex, keyIndex, 0, valueIndex, 0);
203         }
204     }
205 }
ParseJsonData(const std::string & buffer)206 void BytraceParser::ParseJsonData(const std::string& buffer)
207 {
208     std::stringstream ss;
209     json jMessage;
210     ss << buffer;
211     ss >> jMessage;
212     JsonData jData;
213     size_t maxArraySize = 0;
214     std::vector<size_t> noArrayIndex = {};
215     std::vector<size_t> arrayIndex = {};
216     if (JGetData(jMessage, jData, maxArraySize, noArrayIndex, arrayIndex) < 0) {
217         return;
218     }
219     DataIndex eventSourceIndex = eventParser_->traceDataCache_->GetDataIndex(jData.eventSource);
220     if (maxArraySize) {
221         NoArrayDataParse(jData, noArrayIndex, eventSourceIndex);
222         ArrayDataParse(jData, arrayIndex, eventSourceIndex, maxArraySize);
223     } else {
224         CommonDataParser(jData, eventSourceIndex);
225     }
226     return;
227 }
ParseTraceDataItem(const std::string & buffer)228 void BytraceParser::ParseTraceDataItem(const std::string& buffer)
229 {
230     if (!supportThread_) {
231         dataSegArray_[rawDataHead_].seg = std::move(buffer);
232         ParserData(dataSegArray_[rawDataHead_]);
233         return;
234     }
235     int head = rawDataHead_;
236     while (!toExit_) {
237         if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) {
238             TS_LOGD("rawDataHead_:\t%d, parseHead_:\t%d, filterHead_:\t%d status:\t%d\n", rawDataHead_, parseHead_,
239                     filterHead_, dataSegArray_[head].status.load());
240             usleep(sleepDur_);
241             continue;
242         }
243         dataSegArray_[head].seg = std::move(buffer);
244         dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
245         rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE;
246         break;
247     }
248     if (!parseThreadStarted_) {
249         parseThreadStarted_ = true;
250         int tmp = maxThread_;
251         while (tmp--) {
252             parserThreadCount_++;
253             std::thread MatchLineThread(&BytraceParser::ParseThread, this);
254             MatchLineThread.detach();
255             TS_LOGI("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_);
256         }
257     }
258     return;
259 }
GetNextSegment()260 int BytraceParser::GetNextSegment()
261 {
262     int head;
263     dataSegMux_.lock();
264     head = parseHead_;
265     DataSegment& seg = dataSegArray_[head];
266     if (seg.status.load() != TS_PARSE_STATUS_SEPRATED) {
267         if (toExit_) {
268             parserThreadCount_--;
269             TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_);
270             dataSegMux_.unlock();
271             if (!parserThreadCount_ && !filterThreadStarted_) {
272                 exited_ = true;
273             }
274             return ERROR_CODE_EXIT;
275         }
276         if (seg.status.load() == TS_PARSE_STATUS_PARSING) {
277             dataSegMux_.unlock();
278             usleep(sleepDur_);
279             return ERROR_CODE_NODATA;
280         }
281         dataSegMux_.unlock();
282         TS_LOGD("ParseThread watting:\t%d, parseHead_:\t%d, filterHead_:\t%d status:\t%d\n", rawDataHead_, parseHead_,
283                 filterHead_, seg.status.load());
284         usleep(sleepDur_);
285         return ERROR_CODE_NODATA;
286     }
287     parseHead_ = (parseHead_ + 1) % MAX_SEG_ARRAY_SIZE;
288     seg.status = TS_PARSE_STATUS_PARSING;
289     dataSegMux_.unlock();
290     return head;
291 }
292 
GetDataSegAttr(DataSegment & seg,const std::smatch & matcheLine) const293 void BytraceParser::GetDataSegAttr(DataSegment& seg, const std::smatch& matcheLine) const
294 {
295     const uint64_t US_TO_NS = 1000;
296     size_t index = 0;
297     std::string pidStr = matcheLine[++index].str();
298     std::optional<uint32_t> optionalPid = base::StrToUInt32(pidStr);
299     if (!optionalPid.has_value()) {
300         TS_LOGD("Illegal pid: %s", pidStr.c_str());
301         seg.status = TS_PARSE_STATUS_INVALID;
302         return;
303     }
304 
305     std::string tGidStr = matcheLine[++index].str();
306     std::string cpuStr = matcheLine[++index].str();
307     std::optional<uint32_t> optionalCpu = base::StrToUInt32(cpuStr);
308     if (!optionalCpu.has_value()) {
309         TS_LOGD("Illegal cpu %s", cpuStr.c_str());
310         seg.status = TS_PARSE_STATUS_INVALID;
311         return;
312     }
313     std::string timeStr = matcheLine[++index].str();
314     std::optional<double> optionalTime = base::StrToDouble(timeStr);
315     if (!optionalTime.has_value()) {
316         TS_LOGD("Illegal ts %s", timeStr.c_str());
317         seg.status = TS_PARSE_STATUS_INVALID;
318         return;
319     }
320     std::string eventName = matcheLine[++index].str();
321     seg.bufLine.task = StrTrim(matcheLine.prefix());
322     if (seg.bufLine.task == "<...>") {
323         seg.bufLine.task = "";
324     }
325     seg.bufLine.argsStr = StrTrim(matcheLine.suffix());
326     seg.bufLine.pid = optionalPid.value();
327     seg.bufLine.cpu = optionalCpu.value();
328     seg.bufLine.ts = round(static_cast<uint64_t>(optionalTime.value() * 1e6));
329     seg.bufLine.ts *= US_TO_NS;
330     seg.bufLine.tGidStr = tGidStr;
331     seg.bufLine.eventName = eventName;
332     seg.status = TS_PARSE_STATUS_PARSED;
333 }
ParseThread()334 void BytraceParser::ParseThread()
335 {
336     while (1) {
337         int head = GetNextSegment();
338         if (head < 0) {
339             if (head == ERROR_CODE_NODATA) {
340                 continue;
341             }
342             if (!filterThreadStarted_) {
343                 exited_ = true;
344             }
345             return;
346         }
347         DataSegment& seg = dataSegArray_[head];
348         ParserData(seg);
349     }
350 }
351 
ParserData(DataSegment & seg)352 void BytraceParser::ParserData(DataSegment& seg)
353 {
354     std::smatch matcheLine;
355     if (!std::regex_search(seg.seg, matcheLine, bytraceMatcher_)) {
356         TS_LOGD("Not support this event (line: %s)", seg.seg.c_str());
357         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
358         seg.status = TS_PARSE_STATUS_INVALID;
359         parsedTraceInvalidLines_++;
360         return;
361     } else {
362         parsedTraceValidLines_++;
363     }
364     GetDataSegAttr(seg, matcheLine);
365     if (!supportThread_) {
366         FilterData(seg);
367         return;
368     }
369     if (!filterThreadStarted_) {
370         filterThreadStarted_ = true;
371         std::thread ParserThread(&BytraceParser::FilterThread, this);
372         ParserThread.detach();
373     }
374 }
FilterThread()375 void BytraceParser::FilterThread()
376 {
377     while (1) {
378         DataSegment& seg = dataSegArray_[filterHead_];
379         if (!FilterData(seg)) {
380             return;
381         }
382     }
383 }
FilterData(DataSegment & seg)384 bool BytraceParser::FilterData(DataSegment& seg)
385 {
386     if (!supportThread_) {
387         if (seg.status.load() != TS_PARSE_STATUS_INVALID) {
388             eventParser_->ParseDataItem(seg.bufLine);
389             seg.status = TS_PARSE_STATUS_INIT;
390             return true;
391         }
392         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
393         return false;
394     }
395     if (seg.status.load() == TS_PARSE_STATUS_INVALID) {
396         filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE;
397         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
398         seg.status = TS_PARSE_STATUS_INIT;
399         return true;
400     }
401     if (seg.status.load() != TS_PARSE_STATUS_PARSED) {
402         if (toExit_ && !parserThreadCount_) {
403             TS_LOGI("exiting FilterThread Thread\n");
404             exited_ = true;
405             filterThreadStarted_ = false;
406             return false;
407         }
408         usleep(sleepDur_);
409         return true;
410     }
411     eventParser_->ParseDataItem(seg.bufLine);
412     filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE;
413     seg.status = TS_PARSE_STATUS_INIT;
414     return true;
415 }
416 // Remove space at the beginning and end of the string
StrTrim(const std::string & input) const417 std::string BytraceParser::StrTrim(const std::string& input) const
418 {
419     std::string str = input;
420     if (str.empty()) {
421         return str;
422     }
423     str.erase(0, str.find_first_not_of(" "));
424     str.erase(str.find_last_not_of(" ") + 1);
425     return str;
426 }
427 } // namespace TraceStreamer
428 } // namespace SysTuning
429