logger added
This commit is contained in:
parent
4819674833
commit
c0228b0c12
3
.gitignore
vendored
3
.gitignore
vendored
@ -14,3 +14,6 @@ install_strip_local_manifest.txt
|
|||||||
|
|
||||||
.venv/
|
.venv/
|
||||||
my_own_redis
|
my_own_redis
|
||||||
|
|
||||||
|
|
||||||
|
*.log
|
||||||
@ -12,6 +12,7 @@ set(SOURCES
|
|||||||
src/config.cpp
|
src/config.cpp
|
||||||
src/server.cpp
|
src/server.cpp
|
||||||
src/net_util.cpp
|
src/net_util.cpp
|
||||||
|
src/logger.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(my_own_redis ${SOURCES})
|
add_executable(my_own_redis ${SOURCES})
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
port 6379
|
port 6379
|
||||||
address 127.0.0.1
|
address 127.0.0.1
|
||||||
|
log_level INFO
|
||||||
|
log_file not_redis.log
|
||||||
|
|||||||
@ -18,6 +18,8 @@ void Config::load_from_file(const std::string& filename) {
|
|||||||
std::cout << "Using default parameters: 127.0.0.1:6379\n";
|
std::cout << "Using default parameters: 127.0.0.1:6379\n";
|
||||||
address = "127.0.0.1";
|
address = "127.0.0.1";
|
||||||
port = 6379;
|
port = 6379;
|
||||||
|
log_level = "INFO";
|
||||||
|
log_file = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,12 +29,19 @@ void Config::load_from_file(const std::string& filename) {
|
|||||||
file >> address;
|
file >> address;
|
||||||
} else if (key == "port") {
|
} else if (key == "port") {
|
||||||
file >> port;
|
file >> port;
|
||||||
|
} else if (key == "log_level") {
|
||||||
|
file >> log_level;
|
||||||
|
} else if (key == "log_file") {
|
||||||
|
file >> log_file;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Unknown key: " << key << "\n";
|
std::cerr << "Unknown key: " << key << "\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set defaults if not provided
|
||||||
|
if (log_level.empty()) log_level = "INFO";
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +53,14 @@ int Config::get_port() const {
|
|||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Config::get_log_level() const {
|
||||||
|
return log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Config::get_log_file() const {
|
||||||
|
return log_file;
|
||||||
|
}
|
||||||
|
|
||||||
void Config::check_required_keys() const {
|
void Config::check_required_keys() const {
|
||||||
if (address.empty()) {
|
if (address.empty()) {
|
||||||
std::cerr << "Address is not set\n";
|
std::cerr << "Address is not set\n";
|
||||||
|
|||||||
@ -11,12 +11,16 @@ public:
|
|||||||
// Геттеры
|
// Геттеры
|
||||||
std::string get_address() const;
|
std::string get_address() const;
|
||||||
int get_port() const;
|
int get_port() const;
|
||||||
|
std::string get_log_level() const;
|
||||||
|
std::string get_log_file() const;
|
||||||
|
|
||||||
void check_required_keys() const;
|
void check_required_keys() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string address;
|
std::string address;
|
||||||
int port;
|
int port;
|
||||||
|
std::string log_level;
|
||||||
|
std::string log_file;
|
||||||
|
|
||||||
void load_from_file(const std::string& filename);
|
void load_from_file(const std::string& filename);
|
||||||
};
|
};
|
||||||
|
|||||||
77
src/logger.cpp
Normal file
77
src/logger.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "logger.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
LogLevel Logger::current_level = LogLevel::INFO;
|
||||||
|
std::ofstream Logger::log_file;
|
||||||
|
std::mutex Logger::log_mutex;
|
||||||
|
bool Logger::to_file = false;
|
||||||
|
|
||||||
|
void Logger::init(const std::string& level, const std::string& file_path) {
|
||||||
|
std::lock_guard<std::mutex> lock(log_mutex);
|
||||||
|
current_level = string_to_level(level);
|
||||||
|
|
||||||
|
if (!file_path.empty()) {
|
||||||
|
log_file.open(file_path, std::ios::app);
|
||||||
|
if (log_file.is_open()) {
|
||||||
|
to_file = true;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to open log file: " << file_path << ". Logging to console only.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::log(LogLevel level, const std::string& msg) {
|
||||||
|
if (level < current_level) return;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(log_mutex);
|
||||||
|
std::string timestamp = get_timestamp();
|
||||||
|
std::string level_str = level_to_string(level);
|
||||||
|
|
||||||
|
std::ostream& out = (level == LogLevel::ERROR) ? std::cerr : std::cout;
|
||||||
|
|
||||||
|
std::string full_msg = "[" + timestamp + "] [" + level_str + "] " + msg + "\n";
|
||||||
|
|
||||||
|
out << full_msg;
|
||||||
|
if (to_file) {
|
||||||
|
log_file << full_msg;
|
||||||
|
log_file.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::log_info(const std::string& msg) { log(LogLevel::INFO, msg); }
|
||||||
|
void Logger::log_error(const std::string& msg) { log(LogLevel::ERROR, msg); }
|
||||||
|
void Logger::log_warning(const std::string& msg) { log(LogLevel::WARNING, msg); }
|
||||||
|
void Logger::log_debug(const std::string& msg) { log(LogLevel::DEBUG, msg); }
|
||||||
|
|
||||||
|
LogLevel Logger::string_to_level(const std::string& level) {
|
||||||
|
std::string upper_level = level;
|
||||||
|
std::transform(upper_level.begin(), upper_level.end(), upper_level.begin(), ::toupper);
|
||||||
|
|
||||||
|
if (upper_level == "DEBUG") return LogLevel::DEBUG;
|
||||||
|
if (upper_level == "INFO") return LogLevel::INFO;
|
||||||
|
if (upper_level == "WARNING") return LogLevel::WARNING;
|
||||||
|
if (upper_level == "ERROR") return LogLevel::ERROR;
|
||||||
|
|
||||||
|
return LogLevel::INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Logger::level_to_string(LogLevel level) {
|
||||||
|
switch (level) {
|
||||||
|
case LogLevel::DEBUG: return "DEBUG";
|
||||||
|
case LogLevel::INFO: return "INFO";
|
||||||
|
case LogLevel::WARNING: return "WARNING";
|
||||||
|
case LogLevel::ERROR: return "ERROR";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Logger::get_timestamp() {
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto in_time_t = std::chrono::system_clock::to_time_t(now);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %H:%M:%S");
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
36
src/logger.hpp
Normal file
36
src/logger.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
enum class LogLevel {
|
||||||
|
DEBUG,
|
||||||
|
INFO,
|
||||||
|
WARNING,
|
||||||
|
ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
public:
|
||||||
|
static void init(const std::string& level, const std::string& file_path = "");
|
||||||
|
|
||||||
|
static void log(LogLevel level, const std::string& msg);
|
||||||
|
static void log_info(const std::string& msg);
|
||||||
|
static void log_error(const std::string& msg);
|
||||||
|
static void log_warning(const std::string& msg);
|
||||||
|
static void log_debug(const std::string& msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logger() = default;
|
||||||
|
|
||||||
|
static LogLevel string_to_level(const std::string& level);
|
||||||
|
static std::string level_to_string(LogLevel level);
|
||||||
|
static std::string get_timestamp();
|
||||||
|
|
||||||
|
static LogLevel current_level;
|
||||||
|
static std::ofstream log_file;
|
||||||
|
static std::mutex log_mutex;
|
||||||
|
static bool to_file;
|
||||||
|
};
|
||||||
@ -3,6 +3,7 @@
|
|||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "server.hpp"
|
#include "server.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::signal(SIGINT, stop_program);
|
std::signal(SIGINT, stop_program);
|
||||||
@ -11,10 +12,14 @@ int main() {
|
|||||||
Config config("config.ini");
|
Config config("config.ini");
|
||||||
config.check_required_keys();
|
config.check_required_keys();
|
||||||
|
|
||||||
|
Logger::init(config.get_log_level(), config.get_log_file());
|
||||||
|
Logger::log_info("Logger initialized");
|
||||||
|
|
||||||
Server server(config);
|
Server server(config);
|
||||||
|
print_logo();
|
||||||
server.run();
|
server.run();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "Fatal error: " << e.what() << "\n";
|
Logger::log_error("Fatal error: " + std::string(e.what()));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "net_util.hpp"
|
#include "net_util.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
|
||||||
Server::Server(const Config& config)
|
Server::Server(const Config& config)
|
||||||
@ -51,36 +52,39 @@ void Server::setup() {
|
|||||||
throw std::runtime_error("Error listening for connections");
|
throw std::runtime_error("Error listening for connections");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Server started on " << address << ":" << port << "\n";
|
Logger::log_info("Server started on " + address + ":" + std::to_string(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Server::handle_connection(int connectionfd) {
|
int32_t Server::handle_connection(int connectionfd) {
|
||||||
std::cout << "Waiting for data from " << connectionfd << "\n";
|
Logger::log_debug("Waiting for data from fd=" + std::to_string(connectionfd));
|
||||||
|
|
||||||
uint32_t len_net = 0;
|
uint32_t len_net = 0;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (read_full(connectionfd, &len_net, sizeof(len_net)) != 0) {
|
if (read_full(connectionfd, &len_net, sizeof(len_net)) != 0) {
|
||||||
print_error(errno == 0 ? "EOF from client" : "Error reading length");
|
if (errno == 0) {
|
||||||
|
Logger::log_info("Client disconnected (EOF) from fd=" + std::to_string(connectionfd));
|
||||||
|
} else {
|
||||||
|
Logger::log_error("Error reading length from fd=" + std::to_string(connectionfd) + ": " + std::strerror(errno));
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t len = ntohl(len_net);
|
uint32_t len = ntohl(len_net);
|
||||||
|
|
||||||
if (len > k_max_message_size) {
|
if (len > k_max_message_size) {
|
||||||
print_error("Message length is too long");
|
Logger::log_error("Message length is too long: " + std::to_string(len) + " (max: " + std::to_string(k_max_message_size) + ")");
|
||||||
std::cerr << len << " > " << k_max_message_size << "\n";
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string message(len, '\0');
|
std::string message(len, '\0');
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
if (read_full(connectionfd, message.data(), len) != 0) {
|
if (read_full(connectionfd, message.data(), len) != 0) {
|
||||||
print_error("Error reading payload");
|
Logger::log_error("Error reading payload from fd=" + std::to_string(connectionfd));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Client says: " << message << "\n";
|
Logger::log_info("Client (fd=" + std::to_string(connectionfd) + ") says: " + message);
|
||||||
|
|
||||||
const std::string reply = "world";
|
const std::string reply = "world";
|
||||||
uint32_t reply_len_net = htonl(static_cast<uint32_t>(reply.size()));
|
uint32_t reply_len_net = htonl(static_cast<uint32_t>(reply.size()));
|
||||||
@ -99,16 +103,19 @@ void Server::run() {
|
|||||||
socklen_t addrlen = sizeof(client_addr);
|
socklen_t addrlen = sizeof(client_addr);
|
||||||
int connectionfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
|
int connectionfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
|
||||||
if (connectionfd < 0) {
|
if (connectionfd < 0) {
|
||||||
|
Logger::log_error("accept() error: " + std::string(std::strerror(errno)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::cout << "Accepted connection from " << connectionfd << "\n";
|
|
||||||
|
Logger::log_info("Accepted connection from " + std::string(inet_ntoa(client_addr.sin_addr)) + ":" + std::to_string(ntohs(client_addr.sin_port)) + " (fd=" + std::to_string(connectionfd) + ")");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int32_t err = handle_connection(connectionfd);
|
int32_t err = handle_connection(connectionfd);
|
||||||
if (err) {
|
if (err) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "Closing connection from " << connectionfd << "\n";
|
Logger::log_info("Closing connection from " + std::to_string(connectionfd));
|
||||||
close(connectionfd);
|
close(connectionfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,28 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
void stop_program(int signum) {
|
void stop_program(int signum) {
|
||||||
std::cout << "\nInterrupt signal (" << signum << ") received.\n";
|
Logger::log_info("Interrupt signal (" + std::to_string(signum) + ") received. Shutting down...");
|
||||||
std::cout << "Exiting program...\n";
|
exit(signum);
|
||||||
exit(signum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_error(const std::string& msg) {
|
void print_error(const std::string& msg) {
|
||||||
std::cerr << msg << ": " << std::strerror(errno) << "\n";
|
Logger::log_error(msg + ": " + std::strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print_logo() {
|
||||||
|
std::cout << R"(
|
||||||
|
╔════════════════════════════════════════════════════════════╗
|
||||||
|
║ _ _____ ______ _____ _____ _____ ║
|
||||||
|
║ | | | __ \| ____| __ \_ _|/ ____|║
|
||||||
|
║ _ __ ___ | |_ __ _ | |__) | |__ | | | || | | (___ ║
|
||||||
|
║| '_ \ / _ \| __| / _` | | _ /| __| | | | || | \___ \ ║
|
||||||
|
║| | | | (_) | |_ | (_| | | | \ \| |____| |__| || |_ ____) |║
|
||||||
|
║|_| |_|\___/ \__| \__,_| |_| \_\______|_____/_____|_____/ ║
|
||||||
|
╚════════════════════════════════════════════════════════════╝
|
||||||
|
)" << std::endl;
|
||||||
|
}
|
||||||
@ -5,4 +5,4 @@
|
|||||||
|
|
||||||
void stop_program(int signum);
|
void stop_program(int signum);
|
||||||
void print_error(const std::string& msg);
|
void print_error(const std::string& msg);
|
||||||
|
void print_logo();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user