Untitled
unknown
plain_text
6 months ago
3.8 kB
7
Indexable
#include <iostream> #include <fstream> #include <string> #include <ctime> #include <map> #include <memory> #include <vector> #include <sstream> #include <iomanip> #include <chrono> #include <filesystem> #include <zlib.h> // For gzip compression, external library needed enum class LogLevel { DEBUG, INFO, WARN, ERROR, FATAL }; std::string getCurrentTimestamp(const std::string& format) { auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); std::ostringstream ss; ss << std::put_time(std::localtime(&in_time_t), format.c_str()); return ss.str(); } class Message { public: std::string content; LogLevel level; std::string ns; std::string timestamp; Message(const std::string& content, LogLevel level, const std::string& ns, const std::string& timestamp) : content(content), level(level), ns(ns), timestamp(timestamp) {} }; class Sink { public: virtual ~Sink() = default; virtual void log(const Message& message) = 0; virtual bool shouldRotate() const { return false; } virtual void rotate() {} }; class FileSink : public Sink { private: std::ofstream logFile; std::string filePath; size_t maxFileSize; size_t currentFileSize; public: FileSink(const std::string& filePath, size_t maxFileSize = 1024 * 1024) : filePath(filePath), maxFileSize(maxFileSize), currentFileSize(0) { openLogFile(); } ~FileSink() { if (logFile.is_open()) { logFile.close(); } } void log(const Message& message) override { if (shouldRotate()) rotate(); std::string logEntry = "[" + message.timestamp + "] " + message.content + "\n"; logFile << logEntry; currentFileSize += logEntry.size(); } bool shouldRotate() const override { return currentFileSize >= maxFileSize; } void rotate() override { logFile.close(); for (int i = 2; i >= 0; --i) { std::string oldFile = filePath + (i == 0 ? "" : ("." + std::to_string(i) + ".gz")); std::string newFile = filePath + "." + std::to_string(i + 1) + ".gz"; if (std::filesystem::exists(oldFile)) { std::filesystem::rename(oldFile, newFile); } } openLogFile(); currentFileSize = 0; } private: void openLogFile() { logFile.open(filePath, std::ios::out | std::ios::app); if (!logFile.is_open()) { throw std::runtime_error("Unable to open log file"); } } }; class LoggerConfig { public: std::string timestampFormat; LogLevel logLevel; std::shared_ptr<Sink> sink; LoggerConfig(const std::string& tsFormat, LogLevel logLevel, std::shared_ptr<Sink> sink) : timestampFormat(tsFormat), logLevel(logLevel), sink(std::move(sink)) {} }; class Logger { private: LoggerConfig config; public: Logger(const LoggerConfig& config) : config(config) {} void log(const std::string& messageContent, LogLevel level, const std::string& ns) { if (level >= config.logLevel) { std::string timestamp = getCurrentTimestamp(config.timestampFormat); Message message(messageContent, level, ns, timestamp); config.sink->log(message); } } }; int main() { try { auto fileSink = std::make_shared<FileSink>("/var/log/app/info.log", 1024 * 10); // 10 KB for testing LoggerConfig config("ddmmyyyyhhmmss", LogLevel::INFO, fileSink); Logger logger(config); logger.log("Starting application", LogLevel::INFO, "App"); logger.log("No user found for the phone number", LogLevel::WARN, "UserModule"); } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; } return 0; }
Editor is loading...
Leave a Comment