blob: 3edf052f4d25604f85c3f05657682752c827eed6 [file]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LIB_DIAGNOSTICS_FIDL_LOG_MESSAGE_PARSER_LOG_MESSAGE_H_
#define SRC_LIB_DIAGNOSTICS_FIDL_LOG_MESSAGE_PARSER_LOG_MESSAGE_H_
#include <fuchsia/diagnostics/cpp/fidl.h>
#include <fuchsia/logger/cpp/fidl.h>
#include <lib/fpromise/result.h>
#include <lib/syslog/cpp/log_level.h>
#include <span>
#include <vector>
#include <src/lib/diagnostics/log/message/rust/cpp-log-decoder/log_decoder.h>
namespace diagnostics::fidl_log_message_parser {
// Custom deleter for MessageParser. MessageParser is allocated across the Rust FFI
// boundary via `fuchsia_new_message_parser()` and must be freed using
// `fuchsia_free_message_parser()`. Wrapping it in a std::unique_ptr with this deleter
// ensures safe RAII cleanup and correct move semantics (resetting moved-from pointers).
struct MessageParserDeleter {
void operator()(MessageParser* parser) const;
};
// LogBatchIterator wraps a fuchsia::diagnostics::BatchIterator and maintains the necessary state
// (MessageParser) to decode log messages from it.
// This class is thread-hostile; the same restrictions as InterfacePtr
// (see the comment for InterfacePtr at sdk/lib/fidl/hlcpp/include/lib/fidl/cpp/interface_ptr.h)
// apply to this class. In short, all calls to this class (including the destructor) should
// be made from the thread to which the interface was bound.
class LogBatchIterator {
public:
explicit LogBatchIterator(fuchsia::diagnostics::BatchIteratorPtr iterator,
fuchsia::diagnostics::Format format);
~LogBatchIterator() = default;
// Non-copyable, but movable.
LogBatchIterator(const LogBatchIterator&) = delete;
LogBatchIterator& operator=(const LogBatchIterator&) = delete;
LogBatchIterator(LogBatchIterator&&) = default;
LogBatchIterator& operator=(LogBatchIterator&&) = default;
// Callback type for GetNext. The argument is a result:
// - The outer fpromise::result indicates the success of fetching and
// partially processing the batch. An Err(std::string) here means a
// failure in the overall GetNext operation (e.g., FIDL error, or an error
// processing the entire payload from the BatchIterator).
// - If the outer result is Ok, it contains a vector. Each element in the
// vector is an fpromise::result representing an individual log message:
// - An Ok(fuchsia::logger::LogMessage) means a single log message was
// successfully decoded from the batch.
// - An Err(std::string) means that a specific item in the batch could not
// be converted into a fuchsia::logger::LogMessage. This could be due to
// malformed data for that specific log entry.
using GetNextCallback = fit::callback<void(
fpromise::result<std::vector<fpromise::result<fuchsia::logger::LogMessage, std::string>>,
std::string>)>;
// Calls GetNext on the underlying BatchIterator and converts the results.
//
// This is an asynchronous operation. The method returns immediately, and the
// provided `callback` will be invoked later when a batch of messages is retrieved
// or an error occurs.
//
// Callback details:
// - Threading: The callback is invoked on the thread running the dispatcher
// associated with the underlying FIDL client (`iterator_`), which is typically
// the default dispatcher of the thread where the `LogBatchIterator` was created.
// - Execution: Since `GetNextCallback` is a `fit::callback`, it will be invoked
// at most once.
// - Lifetime/Cancellation: If the `LogBatchIterator` is destroyed or unbound
// (via `Unbind()`) before the callback is run, the pending FIDL callback
// will be discarded and the callback will *never* be called. Therefore,
// any references or captures within the callback must remain valid until either the
// callback is invoked or the `LogBatchIterator` is destroyed/unbound.
void GetNext(GetNextCallback callback);
void Unbind() { iterator_.Unbind(); }
void set_error_handler(fit::function<void(zx_status_t)> handler) {
iterator_.set_error_handler(std::move(handler));
}
private:
fuchsia::diagnostics::BatchIteratorPtr iterator_;
std::unique_ptr<MessageParser, MessageParserDeleter> parser_;
};
// Prints formatted content to the log.
fpromise::result<std::vector<fpromise::result<fuchsia::logger::LogMessage, std::string>>,
std::string>
ConvertFormattedContentToLogMessages(fuchsia::diagnostics::FormattedContent content,
MessageParser* parser = nullptr);
// Get the severity corresponding to the given verbosity. Note that
// verbosity relative to the default severity and can be thought of
// as incrementally "more vebose than" the baseline.
fuchsia_logging::RawLogSeverity GetSeverityFromVerbosity(uint8_t verbosity);
fpromise::result<std::vector<fpromise::result<fuchsia::logger::LogMessage, std::string>>,
std::string>
ConvertFormattedFxtToLogMessages(std::span<const uint8_t> data, bool expect_extended_attribution);
} // namespace diagnostics::fidl_log_message_parser
#endif // SRC_LIB_DIAGNOSTICS_FIDL_LOG_MESSAGE_PARSER_LOG_MESSAGE_H_