1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Code for listening to logger service and dumping the logs. 6 // This implements LogListener interface for logger fidl @ //zircon/system/fidl/fuchsia-logger. 7 8 #ifndef ZIRCON_SYSTEM_ULIB_RUNTESTS_UTILS_INCLUDE_RUNTESTS_UTILS_LOG_EXPORTER_H_ 9 #define ZIRCON_SYSTEM_ULIB_RUNTESTS_UTILS_INCLUDE_RUNTESTS_UTILS_LOG_EXPORTER_H_ 10 11 #include <fbl/string.h> 12 #include <fbl/vector.h> 13 #include <lib/async-loop/cpp/loop.h> 14 #include <lib/async/cpp/wait.h> 15 #include <lib/fidl/cpp/message_buffer.h> 16 #include <lib/zx/channel.h> 17 #include <stdint.h> 18 19 // TODO(FIDL-182): Remove this once fixed. 20 typedef zx_handle_t fuchsia_logger_LogListener; 21 #include <fuchsia/logger/c/fidl.h> 22 23 #include <utility> 24 25 namespace runtests { 26 27 // Error while launching LogExporter. 28 enum ExporterLaunchError { 29 OPEN_FILE, 30 CREATE_CHANNEL, 31 FIDL_ERROR, 32 CONNECT_TO_LOGGER_SERVICE, 33 START_LISTENER, 34 NO_ERROR, 35 }; 36 37 // Listens to channel messages, converts them fidl log object and writes them to 38 // passed file object. 39 // This implements LogListener fidl interface. 40 // Example: 41 // FILE* f = fopen("file", "w"); 42 // zx::channel channel; 43 // //init above channel to link to logger service 44 // ... 45 // LogExporter l(std::move(channel), f); 46 // l->StartThread(); 47 class LogExporter { 48 public: 49 using ErrorHandler = fbl::Function<void(zx_status_t)>; 50 using FileErrorHandler = fbl::Function<void(const char* error)>; 51 52 // Creates object and starts listening for msgs on channel written by Log 53 // interface in logger fidl. 54 // 55 // |channel| channel to read log messages from. 56 // |output_file| file to write logs to. 57 // 58 LogExporter(zx::channel channel, FILE* output_file); 59 ~LogExporter(); 60 61 // Starts LogListener service on a seperate thread. 62 // 63 // Returns result of loop_.StartThread(). 64 zx_status_t StartThread(); 65 66 // Runs LogListener service until message loop is idle. 67 // 68 // Returns result of loop_.RunUntilIdle(). 69 zx_status_t RunUntilIdle(); 70 71 // Sets Error handler which would be called when there is an error 72 // while serving |channel_|. If an error occurs, the channel will close and 73 // the listener thread will stop. set_error_handler(ErrorHandler error_handler)74 void set_error_handler(ErrorHandler error_handler) { 75 error_handler_ = std::move(error_handler); 76 } 77 78 // Sets Error handler which would be called whenever there is an error 79 // writing to file. If an error occurs, the channel will close and the 80 // listener thread will stop. set_file_error_handler(FileErrorHandler error_handler)81 void set_file_error_handler(FileErrorHandler error_handler) { 82 file_error_handler_ = std::move(error_handler); 83 } 84 85 private: 86 // Keeps track of the count of dropped logs for a process. 87 struct DroppedLogs { 88 uint64_t pid; 89 uint32_t dropped_logs; 90 }; 91 92 void OnHandleReady(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status, 93 const zx_packet_signal_t* signal); 94 95 // Decodes channel message and dispatches to correct handler. 96 zx_status_t ReadAndDispatchMessage(fidl::MessageBuffer* buffer); 97 98 // Implementation of LogListener Log method. 99 zx_status_t Log(fidl::Message message); 100 101 // Implementation of LogListener LogMany method. 102 zx_status_t LogMany(fidl::Message message); 103 104 // Helper method to log |message| to file. 105 int LogMessage(fuchsia_logger_LogMessage* message); 106 107 // Helper method to call |error_handler_|. 108 void NotifyError(zx_status_t error); 109 110 // Helper method to call |error_handler_|. 111 void NotifyFileError(const char* error); 112 113 // Helper method to write severity string. 114 int WriteSeverity(int32_t severity); 115 116 async::Loop loop_; 117 zx::channel channel_; 118 async::WaitMethod<LogExporter, &LogExporter::OnHandleReady> wait_; 119 ErrorHandler error_handler_; 120 FileErrorHandler file_error_handler_; 121 122 FILE* output_file_; 123 124 // Vector to keep track of dropped logs per pid 125 fbl::Vector<DroppedLogs> dropped_logs_; 126 }; 127 128 // Launches Log Exporter. 129 // 130 // Starts message loop on a seperate thread. 131 // 132 // |syslog_path| file path where to write logs. 133 // |error| error to set in case of failure. 134 // 135 // Returns nullptr if it is not possible to launch Log Exporter. 136 fbl::unique_ptr<LogExporter> LaunchLogExporter(fbl::StringPiece syslog_path, 137 ExporterLaunchError* error); 138 139 } // namespace runtests 140 141 #endif // ZIRCON_SYSTEM_ULIB_RUNTESTS_UTILS_INCLUDE_RUNTESTS_UTILS_LOG_EXPORTER_H_ 142