• 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 #include "print_event_parser.h"
16 #include "stat_filter.h"
17 #include "string_to_numerical.h"
18 namespace SysTuning {
19 namespace TraceStreamer {
PrintEventParser(TraceDataCache * dataCache,const TraceStreamerFilters * filter)20 PrintEventParser::PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter)
21     : EventParserBase(dataCache, filter),
22       pointLength_(1),
23       maxPointLength_(2)
24 {
25 }
26 
ParsePrintEvent(const std::string & comm,uint64_t ts,uint32_t pid,std::string_view event)27 bool PrintEventParser::ParsePrintEvent(const std::string& comm, uint64_t ts, uint32_t pid, std::string_view event)
28 {
29     streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED);
30     TracePoint point;
31     if (GetTracePoint(event, point) != SUCCESS) {
32         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
33         return false;
34     }
35     if (point.tgid_) {
36         streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_);
37     }
38     uint32_t index = 0;
39     switch (point.phase_) {
40         case 'B': {
41             index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX,
42                                                              traceDataCache_->GetDataIndex(point.name_));
43             if (index != INVALID_UINT32) {
44                 // add distributed data
45                 traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(
46                     index, point.chainId_, point.spanId_, point.parentSpanId_, point.flag_, point.args_);
47             } else {
48                 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST);
49             }
50             break;
51         }
52         case 'E': {
53             streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_);
54             break;
55         }
56         case 'S': {
57             auto cookie = static_cast<uint64_t>(point.value_);
58             streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie,
59                 traceDataCache_->GetDataIndex(point.name_));
60             break;
61         }
62         case 'F': {
63             auto cookie = static_cast<uint64_t>(point.value_);
64             streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie,
65                 traceDataCache_->GetDataIndex(point.name_));
66             break;
67         }
68         case 'C': {
69             DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_);
70             uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_);
71             if (internalPid != INVALID_ID) {
72                 streamFilters_->processMeasureFilter_->AppendNewMeasureData(internalPid, nameIndex, ts, point.value_);
73             } else {
74                 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
75             }
76             break;
77         }
78         default:
79             TS_LOGD("point missing!");
80             return false;
81     }
82     return true;
83 }
84 
CheckTracePoint(std::string_view pointStr) const85 ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const
86 {
87     if (pointStr.size() == 0) {
88         TS_LOGD("get trace point data size is 0!");
89         return ERROR;
90     }
91 
92     std::string clockSyncSts = "trace_event_clock_sync";
93     if (pointStr.compare(0, clockSyncSts.length(), clockSyncSts.c_str()) == 0) {
94         TS_LOGD("skip trace point :%s!", clockSyncSts.c_str());
95         return ERROR;
96     }
97 
98     if (pointStr.find_first_of('B') != 0 && pointStr.find_first_of('E') != 0 && pointStr.find_first_of('C') != 0 &&
99         pointStr.find_first_of('S') != 0 && pointStr.find_first_of('F') != 0) {
100         TS_LOGD("trace point not supported : [%c] !", pointStr[0]);
101         return ERROR;
102     }
103 
104     if (pointStr.find_first_of('E') != 0 && pointStr.size() == 1) {
105         TS_LOGD("point string size error!");
106         return ERROR;
107     }
108 
109     if (pointStr.size() >= maxPointLength_) {
110         if ((pointStr[1] != '|') && (pointStr[1] != '\n')) {
111             TS_LOGD("not support data formart!");
112             return ERROR;
113         }
114     }
115 
116     return SUCCESS;
117 }
118 
GetPointNameForBegin(std::string_view pointStr,size_t tGidlength) const119 std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const
120 {
121     size_t index = maxPointLength_ + tGidlength + pointLength_;
122 
123     size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0);
124     std::string_view name = std::string_view(pointStr.data() + index, length);
125     return name;
126 }
127 
HandlerB(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const128 ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const
129 {
130     outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength);
131     if (outPoint.name_.empty()) {
132         TS_LOGD("point name is empty!");
133         return ERROR;
134     }
135     // Use $# to differentiate distributed data
136     if (outPoint.name_.find("$#") == std::string::npos) {
137         return SUCCESS;
138     }
139     // Resolve distributed calls
140     // the normal data mybe like:
141     // system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#"
142     //    "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \
143     //        system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n
144     const std::regex distributeMatcher =
145         std::regex(R"((?:^\[([a-z0-9]+),(\d+),(\d+)\]:?([CS]?)\$#)?(.*)\$#(.*)$)");
146     std::smatch matcheLine;
147     bool matched = std::regex_match(outPoint.name_, matcheLine, distributeMatcher);
148     if (matched) {
149         size_t index = 0;
150         outPoint.chainId_ = matcheLine[++index].str();
151         outPoint.spanId_ = matcheLine[++index].str();
152         outPoint.parentSpanId_ = matcheLine[++index].str();
153         outPoint.flag_ = matcheLine[++index].str();
154         outPoint.name_ = matcheLine[++index].str();
155         outPoint.args_ = matcheLine[++index].str();
156     }
157     return SUCCESS;
158 }
159 
HandlerE(void)160 ParseResult PrintEventParser::HandlerE(void)
161 {
162     return SUCCESS;
163 }
164 
GetNameLength(std::string_view pointStr,size_t nameIndex)165 size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex)
166 {
167     size_t namelength = 0;
168     for (size_t i = nameIndex; i < pointStr.size(); i++) {
169         if (pointStr[i] == ' ') {
170             namelength = i - nameIndex;
171         }
172         if (pointStr[i] == '|') {
173             namelength = i - nameIndex;
174             break;
175         }
176     }
177     return namelength;
178 }
179 
GetValueLength(std::string_view pointStr,size_t valueIndex) const180 size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const
181 {
182     size_t valuePipe = pointStr.find('|', valueIndex);
183     size_t valueLen = pointStr.size() - valueIndex;
184     if (valuePipe != std::string_view::npos) {
185         valueLen = valuePipe - valueIndex;
186     }
187 
188     if (valueLen == 0) {
189         return 0;
190     }
191 
192     if (pointStr[valueIndex + valueLen - pointLength_] == '\n') {
193         valueLen--;
194     }
195 
196     return valueLen;
197 }
198 
HandlerCSF(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const199 ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const
200 {
201     // point name
202     size_t nameIndex = maxPointLength_ + tGidlength + pointLength_;
203     size_t namelength = GetNameLength(pointStr, nameIndex);
204     if (namelength == 0) {
205         TS_LOGD("point name length is error!");
206         return ERROR;
207     }
208     outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength);
209 
210     // point value
211     size_t valueIndex = nameIndex + namelength + pointLength_;
212     size_t valueLen = GetValueLength(pointStr, valueIndex);
213     if (valueLen == 0) {
214         TS_LOGD("point value length is error!");
215         return ERROR;
216     }
217 
218     std::string valueStr(pointStr.data() + valueIndex, valueLen);
219     if (!base::StrToUInt64(valueStr).has_value()) {
220         TS_LOGD("point value is error!");
221         return ERROR;
222     }
223     outPoint.value_ = base::StrToUInt64(valueStr).value();
224 
225     size_t valuePipe = pointStr.find('|', valueIndex);
226     if (valuePipe != std::string_view::npos) {
227         size_t groupLen = pointStr.size() - valuePipe - pointLength_;
228         if (groupLen == 0) {
229             return ERROR;
230         }
231 
232         if (pointStr[pointStr.size() - pointLength_] == '\n') {
233             groupLen--;
234         }
235 
236         outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen);
237     }
238 
239     return SUCCESS;
240 }
241 
GetTracePoint(std::string_view pointStr,TracePoint & outPoint) const242 ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint& outPoint) const
243 {
244     if (CheckTracePoint(pointStr) != SUCCESS) {
245         return ERROR;
246     }
247 
248     size_t tGidlength = 0;
249     // we may get wrong format data like tracing_mark_write: E
250     // while the format data must be E|call-tid
251     // please use a regular-format to get all the data
252     outPoint.phase_ = pointStr.front();
253     outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength);
254 
255     ParseResult ret = ERROR;
256     switch (outPoint.phase_) {
257         case 'B': {
258             ret = HandlerB(pointStr, outPoint, tGidlength);
259             break;
260         }
261         case 'E': {
262             ret = HandlerE();
263             break;
264         }
265         case 'S':
266         case 'F':
267         case 'C': {
268             ret = HandlerCSF(pointStr, outPoint, tGidlength);
269             break;
270         }
271         default:
272             return ERROR;
273     }
274     return ret;
275 }
276 
GetThreadGroupId(std::string_view pointStr,size_t & length) const277 uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t& length) const
278 {
279     for (size_t i = maxPointLength_; i < pointStr.size(); i++) {
280         if (pointStr[i] == '|' || pointStr[i] == '\n') {
281             break;
282         }
283 
284         if (pointStr[i] < '0' || pointStr[i] > '9') {
285             return ERROR;
286         }
287 
288         length++;
289     }
290 
291     std::string str(pointStr.data() + maxPointLength_, length);
292     return base::StrToUInt32(str).value_or(0);
293 }
294 } // namespace TraceStreamer
295 } // namespace SysTuning
296