blob: e4af7a9eea44bc8489ef51eb60a59ac5949ca3f8 [file]
// 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_