• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Helper struct to deduplicate events.
34 // When reading bug reports log data will be present in a dumpstate file and in
35 // the log cat files.
36 struct TimestampedAndroidLogEvent {
37   // Log timestamp. We use ms resolution because dumpstate files only write at
38   // this resolution.
39   std::chrono::milliseconds ts;
40   AndroidLogEvent event;
41   // Flag to track whether a given event was already matched by the
42   // deduplication logic. When set to true we will no longer consider this event
43   // as a candidate for deduplication.
44   bool matched;
45 
46   // Only sort by time to find duplicates at the same ts.
47   bool operator<(const TimestampedAndroidLogEvent& other) const {
48     return ts < other.ts;
49   }
50 };
51 
52 // Parses log lines coming from persistent logcat (FS/data/misc/logd), interns
53 // string in the TP string pools and populates a vector of AndroidLogEvent
54 // structs. Does NOT insert log events into any table (for testing isolation),
55 // the caller is in charge to do that.
56 // It supports the following formats (auto-detected):
57 // 1) 12-31 23:59:00.123456 <pid> <tid> I tag: message
58 //    This is typically found in persistent logcat (FS/data/misc/logd/)
59 // 2) 06-24 15:57:11.346 <uid> <pid> <tid> D Tag: Message
60 //    This is typically found in the recent logcat dump in bugreport-xxx.txt
61 class AndroidLogReader : public ChunkedLineReader {
62  public:
63   // Log cat will not write year into the trace so the caller needs to figure it
64   // out. If not provided the reader will make a best guess.
65   explicit AndroidLogReader(TraceProcessorContext* context);
66   AndroidLogReader(TraceProcessorContext* context,
67                    int32_t year,
68                    bool wait_for_tz = false);
69 
70   ~AndroidLogReader() override;
71 
72   base::Status ParseLine(base::StringView line) override;
73   void EndOfStream(base::StringView leftovers) override;
74 
75   // Called for each event parsed from the stream.
76   // `event_ts_ns` is the ts of the event as read from the log.
77   // Default implementation just calls `SendToSorter`.
78   virtual base::Status ProcessEvent(std::chrono::nanoseconds event_ts,
79                                     AndroidLogEvent event);
80 
81  protected:
82   // Sends the given event to the sorting stage.
83   // `event_ts` is the ts of the event as read from the log and will be
84   // converted to a trace_ts (with necessary clock conversions applied)
85   base::Status SendToSorter(std::chrono::nanoseconds event_ts,
86                             AndroidLogEvent event);
87 
88   // Send any events to the sorter that have not already had their timestamp
89   // adjusted based on the timezone. This is meant to be called once the TZ
90   // offset becomes known, or we reach the end of the input without any TZ info.
91   base::Status FlushNonTzAdjustedEvents();
92 
93  private:
94   TraceProcessorContext* const context_;
95   std::optional<AndroidLogEvent::Format> format_;
96   int32_t year_;
97   bool wait_for_tz_;
98   std::vector<TimestampedAndroidLogEvent> non_tz_adjusted_events_;
99 };
100 
101 // Same as AndroidLogReader (sends events to sorter), but also stores them in a
102 // vector that can later be feed to a `DedupingAndroidLogReader` instance.
103 class BufferingAndroidLogReader : public AndroidLogReader {
104  public:
105   BufferingAndroidLogReader(TraceProcessorContext* context,
106                             int32_t year,
107                             bool wait_for_tz = false)
AndroidLogReader(context,year,wait_for_tz)108       : AndroidLogReader(context, year, wait_for_tz) {}
109   ~BufferingAndroidLogReader() override;
110 
111   base::Status ProcessEvent(std::chrono::nanoseconds event_ts,
112                             AndroidLogEvent event) override;
113 
ConsumeBufferedEvents()114   std::vector<TimestampedAndroidLogEvent> ConsumeBufferedEvents() && {
115     return std::move(events_);
116   }
117 
118  private:
119   std::vector<TimestampedAndroidLogEvent> events_;
120 };
121 
122 // Similar to `AndroidLogReader` but this class will not forward duplicate
123 // events. These are events already present in a given vector of events.
124 class DedupingAndroidLogReader : public AndroidLogReader {
125  public:
126   // Creates a reader that will not forward events already present in the given
127   // vector. Note that entries in the vector will only be matched once. That is
128   // when a match is found in the vector the event is not send to the sorter,
129   // but the event is removed from the vector (seen flag is set to true) so that
130   // subsequent event will not match that entry.
131   DedupingAndroidLogReader(TraceProcessorContext* context,
132                            int32_t year,
133                            bool wait_for_tz,
134                            std::vector<TimestampedAndroidLogEvent> events);
DedupingAndroidLogReader(TraceProcessorContext * context,int32_t year,std::vector<TimestampedAndroidLogEvent> events)135   DedupingAndroidLogReader(TraceProcessorContext* context,
136                            int32_t year,
137                            std::vector<TimestampedAndroidLogEvent> events)
138       : DedupingAndroidLogReader(context, year, false, events) {}
139   ~DedupingAndroidLogReader() override;
140 
141   base::Status ProcessEvent(std::chrono::nanoseconds event_ts,
142                             AndroidLogEvent event) override;
143 
144  private:
145   std::vector<TimestampedAndroidLogEvent> events_;
146 };
147 
148 }  // namespace perfetto::trace_processor
149 
150 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_ANDROID_BUGREPORT_ANDROID_LOG_READER_H_
151