Untitled
unknown
plain_text
a year ago
3.8 kB
8
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