1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_ANDROID_BUGREPORT_ANDROID_LOG_READER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_ANDROID_BUGREPORT_ANDROID_LOG_READER_H_ 19 20 #include <chrono> 21 #include <cstdint> 22 #include <optional> 23 24 #include "perfetto/base/status.h" 25 #include "perfetto/ext/base/string_view.h" 26 #include "src/trace_processor/importers/android_bugreport/android_log_event.h" 27 #include "src/trace_processor/importers/android_bugreport/chunked_line_reader.h" 28 29 namespace perfetto ::trace_processor { 30 31 class TraceProcessorContext; 32 33 // Parses log lines coming from persistent logcat (FS/data/misc/logd), interns 34 // string in the TP string pools and populates a vector of AndroidLogEvent 35 // structs. Does NOT insert log events into any table (for testing isolation), 36 // the caller is in charge to do that. 37 // It supports the following formats (auto-detected): 38 // 1) 12-31 23:59:00.123456 <pid> <tid> I tag: message 39 // This is typically found in persistent logcat (FS/data/misc/logd/) 40 // 2) 06-24 15:57:11.346 <uid> <pid> <tid> D Tag: Message 41 // This is typically found in the recent logcat dump in bugreport-xxx.txt 42 class AndroidLogReader : public ChunkedLineReader { 43 public: 44 // Log cat will not write year into the trace so the caller needs to figure it 45 // out. If not provided the reader will make a best guess. 46 explicit AndroidLogReader(TraceProcessorContext* context); 47 AndroidLogReader(TraceProcessorContext* context, int32_t year); 48 49 ~AndroidLogReader() override; 50 51 base::Status ParseLine(base::StringView line) override; 52 void EndOfStream(base::StringView leftovers) override; 53 54 // Called for each event parsed from the stream. 55 // `event_ts_ns` is the ts of the event as read from the log. 56 // Default implementation just calls `SendToSorter`. 57 virtual base::Status ProcessEvent(std::chrono::nanoseconds event_ts, 58 AndroidLogEvent event); 59 60 protected: 61 // Sends the given event to the sorting stage. 62 // `event_ts` is the ts of the event as read from the log and will be 63 // converted to a trace_ts (with necessary clock conversions applied) 64 base::Status SendToSorter(std::chrono::nanoseconds event_ts, 65 AndroidLogEvent event); 66 67 private: 68 TraceProcessorContext* const context_; 69 std::optional<AndroidLogEvent::Format> format_; 70 int32_t year_; 71 std::chrono::nanoseconds timezone_offset_; 72 }; 73 74 // Helper struct to deduplicate events. 75 // When reading bug reports log data will be present in a dumpstate file and in 76 // the log cat files. 77 struct TimestampedAndroidLogEvent { 78 // Log timestamp. We use ms resolution because dumpstate files only write at 79 // this resolution. 80 std::chrono::milliseconds ts; 81 AndroidLogEvent event; 82 // Flag to track whether a given event was already matched by the 83 // deduplication logic. When set to true we will no longer consider this event 84 // as a candidate for deduplication. 85 bool matched; 86 87 // Only sort by time to find duplicates at the same ts. 88 bool operator<(const TimestampedAndroidLogEvent& other) const { 89 return ts < other.ts; 90 } 91 }; 92 93 // Same as AndroidLogReader (sends events to sorter), but also stores them in a 94 // vector that can later be feed to a `DedupingAndroidLogReader` instance. 95 class BufferingAndroidLogReader : public AndroidLogReader { 96 public: BufferingAndroidLogReader(TraceProcessorContext * context,int32_t year)97 BufferingAndroidLogReader(TraceProcessorContext* context, int32_t year) 98 : AndroidLogReader(context, year) {} 99 ~BufferingAndroidLogReader() override; 100 101 base::Status ProcessEvent(std::chrono::nanoseconds event_ts, 102 AndroidLogEvent event) override; 103 ConsumeBufferedEvents()104 std::vector<TimestampedAndroidLogEvent> ConsumeBufferedEvents() && { 105 return std::move(events_); 106 } 107 108 private: 109 std::vector<TimestampedAndroidLogEvent> events_; 110 }; 111 112 // Similar to `AndroidLogReader` but this class will not forward duplicate 113 // events. These are events already present in a given vector of events. 114 class DedupingAndroidLogReader : public AndroidLogReader { 115 public: 116 // Creates a reader that will not forward events already present in the given 117 // vector. Note that entries in the vector will only be matched once. That is 118 // when a match is found in the vector the event is not send to the sorter, 119 // but the event is removed from the vector (seen flag is set to true) so that 120 // subsequent event will not match that entry. 121 DedupingAndroidLogReader(TraceProcessorContext* context, 122 int32_t year, 123 std::vector<TimestampedAndroidLogEvent> events); 124 ~DedupingAndroidLogReader() override; 125 126 base::Status ProcessEvent(std::chrono::nanoseconds event_ts, 127 AndroidLogEvent event) override; 128 129 private: 130 std::vector<TimestampedAndroidLogEvent> events_; 131 }; 132 133 } // namespace perfetto::trace_processor 134 135 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_ANDROID_BUGREPORT_ANDROID_LOG_READER_H_ 136