#ifndef __CLASS_LOG_UTILS_H #define __CLASS_LOG_UTILS_H #include #include #include #include #include #include #include #include #include namespace prometheus { class Counter; } /** * @brief Manages a string buffer and a flush timestamp for logging. * * Used to accumulate log data in memory before writing to a file. */ class LogBuffer { private: std::string buffer; uint64_t last_flush_time; public: LogBuffer(); /** * @brief Stream insertion operator for appending strings to the buffer. * @param value The string to append to the buffer. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& operator<<(const std::string& value); /** * @brief Stream insertion operator for appending C-strings to the buffer. * @param value The C-string to append to the buffer. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& operator<<(const char* value); /** * @brief Stream insertion operator for appending characters to the buffer. * @param value The character to append to the buffer. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& operator<<(char value); /** * @brief Appends a string to the buffer. * @param str The string to append to the buffer. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& append(const std::string& str); /** * @brief Appends a C-string to the buffer. * @param str The C-string to append to the buffer. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& append(const char* str); /** * @brief Appends a character sequence to the buffer. * @param str Pointer to the character sequence. * @param len Length of the character sequence. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& append(const char* str, size_t len); /** * @brief Writes a string to the buffer (alias for append). * @param str The string to write to the buffer. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& write(const std::string& str); /** * @brief Writes a character sequence to the buffer. * @param str Pointer to the character sequence. * @param len Length of the character sequence. * @return Reference to this LogBuffer for method chaining. */ LogBuffer& write(const char* str, size_t len); /** * @brief Resets the buffer for next use. * * Clears the buffer content and updates the last flush time. * * @param flush_time The timestamp at which the buffer was flushed. */ void reset(uint64_t flush_time); /** * @brief Sets the last flush time explicitly. * * @param flush_time The timestamp to set. */ void set_last_flush_time(uint64_t flush_time); /** * @brief Returns the last flush time. */ uint64_t get_last_flush_time() const; /** * @brief Returns true if the buffer is empty. */ bool empty() const; /** * @brief Returns the size of the buffer. */ size_t size() const; /** * @brief Returns a pointer to the buffer data. */ const char* data() const; /** * @brief Flushes the buffer to an output file stream. * * Writes the entire contents of the buffer to the provided file stream. * The caller is responsible for resetting the buffer after flushing. * * @param logfile The output file stream to write to. */ void flush_to_file(std::fstream* logfile); }; /** * @brief Class to hold per-thread logging context for both event and audit logging. * * This class encapsulates all per-thread state needed for logging operations: * - events: Buffer and timestamp state for event logging * - audit: Buffer and timestamp state for audit logging * - rng: Thread-local Mersenne Twister random number generator for log sampling * - dist: Uniform real distribution [0.0, 1.0) for sampling * * Each thread gets its own instance to avoid race conditions and lock contention. */ class LogBufferThreadContext { private: std::mt19937 rng; ///< Mersenne Twister random number generator (per-thread) std::uniform_real_distribution dist; ///< Uniform distribution [0.0, 1.0) public: std::mutex buffer_lock; ///< Protects cross-thread flush operations on thread-local buffers. LogBuffer events; ///< Event log buffer and timestamp LogBuffer audit; ///< Audit log buffer and timestamp /** * @brief Constructor that initializes the thread logging context with random seed. * * Seeds the RNG using a combination of hardware entropy, high-resolution time, * and thread ID for maximum uniqueness and unpredictability. */ LogBufferThreadContext(); /** * @brief Determines if an event should be logged based on the rate limit. * * Calculates whether a random sample falls within the acceptance threshold * determined by the rate limit. * * @param rate_limit The sampling rate limit. 1 means log all, N means log approx 1/N. * @return true if the event should be logged, false otherwise. */ bool should_log(int rate_limit); }; /** * @brief Retrieves or creates the LogBufferThreadContext for the current thread. * * This helper function checks if a context for the current thread exists in the provided map. * If found, it returns the existing context. Otherwise, it creates a new one, initializes * it with the current time, and adds it to the map. * * @param log_thread_contexts The map of thread contexts. * @param log_thread_contexts_lock The mutex protecting access to the map. * @param current_time The current time to initialize last_flush_time (e.g. monotonic_time()). * @return LogBufferThreadContext* Pointer to the thread's logging context. */ LogBufferThreadContext* GetLogBufferThreadContext(std::unordered_map>& log_thread_contexts, std::mutex& log_thread_contexts_lock, uint64_t current_time); /** * @brief Helper function to flush buffer to file stream and rotate file if required. * * @param buffer The LogBuffer to flush * @param logfile Pointer to the logfile stream * @param current_log_size Reference to current log size counter * @param max_log_file_size Maximum log file size before rotation * @param lock_fn Function to acquire write lock * @param unlock_fn Function to release write lock * @param rotate_fn Function to rotate the log file * @param reset_time Timestamp to use when resetting the buffer after flush * @return true if buffer was flushed, false otherwise */ bool flush_and_rotate( LogBuffer& buffer, std::fstream*& logfile, unsigned int& current_log_size, unsigned int max_log_file_size, std::function lock_fn, std::function unlock_fn, std::function rotate_fn, uint64_t reset_time = 0); /** * @brief Returns the protocol-scoped query logger counter. * @param protocol Protocol label (e.g. "mysql" or "pgsql"). * @return Counter pointer or nullptr if Prometheus registry isn't available. */ prometheus::Counter* get_logger_queries_logged_counter(const std::string& protocol); #endif /* __CLASS_LOG_UTILS_H */