| // Copyright 2026 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_DEVELOPER_FORENSICS_FEEDBACK_DATA_LOG_BUFFER_H_ |
| #define SRC_DEVELOPER_FORENSICS_FEEDBACK_DATA_LOG_BUFFER_H_ |
| |
| #include <lib/fit/function.h> |
| #include <lib/zx/time.h> |
| |
| #include <deque> |
| #include <optional> |
| #include <string> |
| |
| #include "src/developer/forensics/feedback_data/log_source.h" |
| #include "src/developer/forensics/utils/redact/redactor.h" |
| #include "src/developer/forensics/utils/storage_size.h" |
| |
| namespace forensics::feedback { |
| |
| // Stores up to |capacity| bytes of system log messages, dropping the earliest messages when the |
| // stored messages occupy too much space. |
| class LogBuffer : public feedback_data::LogSink { |
| public: |
| LogBuffer(StorageSize capacity, RedactorBase* redactor); |
| |
| virtual ~LogBuffer() = default; |
| |
| // Adds |message| to the buffer and drops messages as required to keep the total size under |
| // |capacity|. Always returns true. |
| // |
| // Messages are assumed to be received mostly in order. |
| bool Add(LogSink::MessageOr message) override; |
| |
| // Records the log stream was interrupted and clears the contents. |
| void NotifyInterruption() override; |
| |
| // It's safe continue to writing to a LogBuffer if the log source has been interrupted. |
| bool SafeAfterInterruption() const override { return true; } |
| |
| // Returns std::nullopt if the buffer is empty. |
| std::optional<zx::time_boot> FirstTimestamp() const; |
| |
| // Returns std::nullopt if the buffer is empty. |
| std::optional<zx::time_boot> LastTimestamp() const; |
| |
| std::string ToString(); |
| |
| // Executes |action| after a message with a time greater than or equal to |timestamp| is received |
| // or NotifyInterruption is called. |
| void ExecuteAfter(zx::time_boot timestamp, ::fit::closure action); |
| |
| private: |
| struct Message { |
| Message(const LogSink::MessageOr& message, zx::time_boot default_timestamp); |
| |
| zx::time_boot timestamp; |
| std::string msg; |
| }; |
| |
| void Sort(); |
| void RunActions(zx::time_boot timestamp); |
| void EnforceCapacity(); |
| |
| // Resets variables keeping track of the last message |
| void ResetLastMessage(); |
| |
| RedactorBase* redactor_; |
| std::deque<Message> messages_; |
| |
| std::string last_msg_{}; |
| int32_t last_severity_{}; |
| std::vector<std::string> last_tags{}; |
| size_t last_msg_repeated_{0u}; |
| |
| bool is_sorted_{true}; |
| |
| std::multimap<zx::time_boot, ::fit::closure, std::greater<>> actions_at_time_; |
| |
| size_t size_{0u}; |
| const size_t capacity_; |
| }; |
| |
| } // namespace forensics::feedback |
| |
| #endif // SRC_DEVELOPER_FORENSICS_FEEDBACK_DATA_LOG_BUFFER_H_ |