1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 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 #ifndef PTREADER_PARSER_H 17 #define PTREADER_PARSER_H 18 19 #include <condition_variable> 20 #include <mutex> 21 #include <regex> 22 #include <thread> 23 24 #ifdef ENABLE_BYTRACE 25 #include "bytrace_event_parser.h" 26 #endif 27 #include "common_types.h" 28 #ifdef ENABLE_HILOG 29 #include "ptreader_hilog_parser.h" 30 #endif 31 #ifdef ENABLE_HISYSEVENT 32 #include "ptreader_hisysevent_parser.h" 33 #endif 34 #include "parser_base.h" 35 #include "string_to_numerical.h" 36 #include "trace_data_cache.h" 37 #include "trace_streamer_filters.h" 38 39 namespace SysTuning { 40 namespace TraceStreamer { 41 constexpr int32_t DETERMINE_CONTINUE = 2; 42 constexpr int32_t DETERMINE_RETURN = 3; 43 class PtreaderParser : public ParserBase { 44 public: 45 PtreaderParser(TraceDataCache *dataCache, 46 const TraceStreamerFilters *filters, 47 TraceFileType fileType = TRACE_FILETYPE_BY_TRACE); 48 ~PtreaderParser(); 49 50 template <typename Iterator> 51 int32_t WhileDetermine(Iterator &determine, Iterator &packagesBegin, bool &isParsingOver_, bool isFinish); 52 int32_t GotoDetermine(std::string &bufferLine, bool &haveSplitSeg); 53 54 void ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, bool isFinish = false) override; ParsedTraceValidLines()55 size_t ParsedTraceValidLines() const 56 { 57 return parsedTraceValidLines_; 58 } ParsedTraceInvalidLines()59 size_t ParsedTraceInvalidLines() const 60 { 61 return parsedTraceInvalidLines_; 62 } TraceCommentLines()63 size_t TraceCommentLines() const 64 { 65 return traceCommentLines_; 66 } 67 #ifdef ENABLE_BYTRACE EnableBytrace(bool enable)68 void EnableBytrace(bool enable) 69 { 70 isBytrace_ = enable; 71 } 72 #endif MinSplitPos()73 int32_t MinSplitPos() 74 { 75 return minSplitPos_; 76 } MaxSplitPos()77 int32_t MaxSplitPos() 78 { 79 return maxSplitPos_; 80 } GetPtreaderSplitData()81 const auto &GetPtreaderSplitData() 82 { 83 return mPtreaderSplitData_; 84 } ClearPtreaderSplitData()85 void ClearPtreaderSplitData() 86 { 87 mPtreaderSplitData_.clear(); 88 curFileOffset_ = 0; 89 curDataSize_ = 0; 90 minSplitPos_ = INVALID_INT32; 91 maxSplitPos_ = INVALID_INT32; 92 isParsingOver_ = false; 93 } 94 95 void WaitForParserEnd(); 96 97 private: 98 bool UpdateSplitPos(); 99 void ParseTraceDataItem(const std::string &buffer) override; 100 #ifdef ENABLE_BYTRACE 101 int32_t GetNextSegment(); 102 void GetDataSegAttr(DataSegment &seg, const std::smatch &matcheLine) const; IsNotSpace(char c)103 inline static bool IsNotSpace(char c) 104 { 105 return !std::isspace(c); 106 } IsTraceComment(const std::string & buffer)107 inline static bool IsTraceComment(const std::string &buffer) 108 { 109 return ((buffer[0] == '#') || buffer.find("TASK-PID") != std::string::npos); 110 } IsHtmlTrace(const std::string & buffer)111 inline static bool IsHtmlTrace(const std::string &buffer) 112 { 113 std::string lower(buffer); 114 transform(buffer.begin(), buffer.end(), lower.begin(), ::tolower); 115 return ((lower.compare(0, std::string("<!doctype html>").length(), "<!doctype html>") == 0) || 116 (lower.compare(0, std::string("<html>").length(), "<html>") == 0)); 117 } IsHtmlTraceBegin(const std::string & buffer)118 inline static bool IsHtmlTraceBegin(const std::string &buffer) 119 { 120 return buffer.find(R"(<script class="trace-data" type="application/text">)") != std::string::npos; 121 } 122 std::string StrTrim(const std::string &input) const; 123 void ParserData(DataSegment &seg); 124 void ParseThread(); 125 bool FilterData(DataSegment &seg); 126 void FilterThread(); 127 #endif 128 129 private: 130 TraceFileType fileType_ = TRACE_FILETYPE_BY_TRACE; 131 TraceDataCache *traceDataCache_; 132 #ifdef ENABLE_BYTRACE 133 std::unique_ptr<BytraceEventParser> bytraceEventParser_; 134 const std::regex bytraceMatcher_ = std::regex(R"(-(\d+)\s+\(?\s*(\d+|-+)?\)?\s?\[(\d+)\]\s*)" 135 R"([a-zA-Z0-9.]{0,5}\s+(\d+\.\d+):\s+(\S+):)"); 136 bool isBytrace_ = true; 137 #endif 138 #ifdef ENABLE_HILOG 139 std::unique_ptr<PtreaderHilogParser> hilogParser_; 140 #endif 141 #ifdef ENABLE_HISYSEVENT 142 std::unique_ptr<PtreaderHiSysEventParser> hiSysEventParser_; 143 #endif 144 bool isParsingOver_ = false; 145 const std::string script_ = R"(</script>)"; 146 size_t parsedTraceValidLines_ = 0; 147 size_t parsedTraceInvalidLines_ = 0; 148 size_t traceCommentLines_ = 0; 149 std::mutex dataSegMux_; 150 int32_t parseHead_ = 0; 151 std::atomic<bool> filterThreadStarted_{false}; 152 bool parseThreadStarted_ = false; 153 const int32_t maxSegArraySize = 5000; 154 const int32_t maxThread_ = 4; // 4 is the best on ubuntu 113MB/s, max 138MB/s, 6 is best on mac m1 21MB/s, 155 int32_t parserThreadCount_ = 0; 156 bool toExit_ = false; 157 bool exited_ = false; 158 std::unique_ptr<DataSegment[]> dataSegArray_; 159 int32_t rawDataHead_ = 0; 160 int32_t filterHead_ = 0; 161 const int32_t sleepDur_ = 100; 162 bool traceBegan_ = false; 163 bool isFirstLine_ = true; 164 bool isHtmlTrace_ = false; 165 bool isHtmlTraceContent_ = false; 166 int64_t seq_ = 1; 167 uint64_t curFileOffset_ = 0; 168 uint32_t curDataSize_ = 0; 169 int32_t minSplitPos_ = INVALID_INT32; 170 int32_t maxSplitPos_ = INVALID_INT32; 171 std::deque<std::pair<int32_t /* offset */, int32_t /* size */>> mPtreaderSplitData_ = {}; 172 }; 173 } // namespace TraceStreamer 174 } // namespace SysTuning 175 #endif // _ptreader_parser_H_ 176