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