| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef SRC_TRACED_PROBES_ANDROID_LOG_ANDROID_LOG_DATA_SOURCE_H_ |
| #define SRC_TRACED_PROBES_ANDROID_LOG_ANDROID_LOG_DATA_SOURCE_H_ |
| |
| #include <unordered_map> |
| #include <unordered_set> |
| #include <vector> |
| |
| #include "perfetto/ext/base/paged_memory.h" |
| #include "perfetto/ext/base/scoped_file.h" |
| #include "perfetto/ext/base/string_view.h" |
| #include "perfetto/ext/base/unix_socket.h" |
| #include "perfetto/ext/base/weak_ptr.h" |
| #include "perfetto/tracing/core/forward_decls.h" |
| #include "src/traced/probes/probes_data_source.h" |
| |
| namespace perfetto { |
| |
| class TraceWriter; |
| namespace base { |
| class TaskRunner; |
| } |
| |
| namespace protos { |
| namespace pbzero { |
| class AndroidLogPacket; |
| class AndroidLogPacket_LogEvent; |
| } // namespace pbzero |
| } // namespace protos |
| |
| class AndroidLogDataSource : public ProbesDataSource { |
| public: |
| static const ProbesDataSource::Descriptor descriptor; |
| |
| struct Stats { |
| uint64_t num_total = 0; // Total number of log entries received. |
| uint64_t num_failed = 0; // Parser failures. |
| uint64_t num_skipped = 0; // Messages skipped due to filters. |
| }; |
| |
| // One EventFormat == one line of /system/etc/event-log-tags. |
| struct EventFormat { |
| std::string name; |
| std::vector<std::string> fields; |
| }; |
| |
| AndroidLogDataSource(DataSourceConfig, |
| base::TaskRunner*, |
| TracingSessionID, |
| std::unique_ptr<TraceWriter> writer); |
| |
| ~AndroidLogDataSource() override; |
| |
| // ProbesDataSource implementation. |
| void Start() override; |
| void Flush(FlushRequestID, std::function<void()> callback) override; |
| |
| // Reads the contents of /system/etc/event-log-tags. Virtual for testing. |
| virtual std::string ReadEventLogDefinitions(); |
| |
| // Connects to the /dev/socket/logdr socket. Virtual for testing. |
| virtual base::UnixSocketRaw ConnectLogdrSocket(); |
| |
| // Parses the contents of ReadEventLogDefinitions(). |
| void ParseEventLogDefinitions(); |
| |
| const EventFormat* GetEventFormat(int id) const; |
| const Stats& stats() const { return stats_; } |
| base::WeakPtr<AndroidLogDataSource> GetWeakPtr() const; |
| |
| private: |
| void EnableSocketWatchTask(bool); |
| void OnSocketDataAvailable(); |
| void ReadLogSocket(); |
| |
| // Parses one line of /system/etc/event-log-tags. |
| bool ParseEventLogDefinitionLine(char* line, size_t len); |
| |
| // Parses a textual (i.e. tag + message) event, which is the majority of |
| // log events. All buffers but the LID_EVENTS contain text events. |
| // If parsing fails returns false and leaves the |out_evt| field unset. |
| // If parsing succeeds returns true and: |
| // - If the event is skipped due to filters, |out_evt| is left unset. |
| // - If a new event is aded to the packet, |out_evt| is set to that. |
| bool ParseTextEvent(const char* start, |
| const char* end, |
| protos::pbzero::AndroidLogPacket* packet, |
| protos::pbzero::AndroidLogPacket_LogEvent** out_evt); |
| |
| // Parses a binary event from the "events" buffer. |
| // If parsing fails returns false and leaves the |out_evt| field unset. |
| // If parsing succeeds returns true and: |
| // - If the event is skipped due to filters, |out_evt| is left unset. |
| // - If a new event is aded to the packet, |out_evt| is set to that. |
| bool ParseBinaryEvent(const char* start, |
| const char* end, |
| protos::pbzero::AndroidLogPacket* packet, |
| protos::pbzero::AndroidLogPacket_LogEvent** out_evt); |
| |
| base::TaskRunner* const task_runner_; |
| std::unique_ptr<TraceWriter> writer_; |
| base::UnixSocketRaw logdr_sock_; |
| |
| // Config parameters coming from the data source section in the trace config. |
| int min_prio_ = 0; |
| std::string mode_; |
| |
| // For filtering events based on tags. |
| std::unordered_set<base::StringView> filter_tags_; |
| std::vector<char> filter_tags_strbuf_; |
| |
| // Lookup map for binary events (log_id=EVENTS). Translates a numeric id into |
| // a corresponding field descriptor. This is generated by parsing |
| // /system/etc/event-log-tags when starting. |
| std::unordered_map<int, EventFormat> event_formats_; |
| |
| // Buffer used for parsing. It's safer (read: fails sooner) than using the |
| // stack, due to red zones around the boundaries. |
| base::PagedMemory buf_; |
| Stats stats_; |
| bool fd_watch_task_enabled_ = false; |
| |
| base::WeakPtrFactory<AndroidLogDataSource> weak_factory_; // Keep last. |
| }; |
| |
| } // namespace perfetto |
| |
| #endif // SRC_TRACED_PROBES_ANDROID_LOG_ANDROID_LOG_DATA_SOURCE_H_ |