自己动手写一个C++日志库

自己动手写一个C++日志库

logger.h

//
// Created by Fkkt on 2023/9/8.
//

#pragma once

#include <string>
#include <iostream>
#include <fstream>
#include <chrono>
#include <sstream>

namespace fkkt {

    class logger {
    public:

        enum log_level {
            D, // Debug
            I, // Info
            W, // Warning
            E  // Error
        };

        /**
         * Construct logger
         *
         * @param log_file_name log file name
         * @param default_console_log_level log level, see log_level
         * @param mode mode, default is append
         */
        explicit logger(const std::string &log_file_name = "app",
                        log_level default_console_log_level = D,
                        const std::ios_base::openmode &mode = std::ios_base::app);

        ~logger();

        /**
         * Set level of console, which will be print
         *
         * @param level log level, see log_level
         */
        void set_console_log_level(log_level level);

        template<typename... Args>
        void d(Args... args) {
            std::ostringstream oss;
            append(oss, args...);
            write(D, oss.str());
        }

        template<typename... Args>
        void i(Args... args) {
            std::ostringstream oss;
            append(oss, args...);
            write(I, oss.str());
        }

        template<typename... Args>
        void w(Args... args) {
            std::ostringstream oss;
            append(oss, args...);
            write(W, oss.str());
        }

        template<typename... Args>
        void e(Args... args) {
            std::ostringstream oss;
            append(oss, args...);
            write(E, oss.str());
        }

    private:
        std::ofstream log_file;
        log_level console_log_level;

        static std::string get_log_level(log_level level);

        static std::string get_current_time_stamp();

        void write(log_level level, const std::string &message);

        void append(std::ostringstream &oss) {}

        template<typename T, typename... Args>
        void append(std::ostringstream &oss, const T &first, Args... args) {
            oss << first;
            append(oss, args...);
        }

    };
}

logger.cpp

//
// Created by Fkkt on 2023/9/8.
//
#include "logger.h"
#include <iostream>
#include <ctime>
#include <iomanip>
#include <fstream>
#include <mutex>

namespace fkkt {
    logger::logger(const std::string &log_file_name,
                   log_level default_console_log_level,
                   const std::ios_base::openmode &mode) : console_log_level(default_console_log_level) {
        log_file.open(log_file_name, mode);
        if (!log_file.is_open()) {
            throw std::runtime_error("Failed to open log file: " + log_file_name);
        }
        std::ios::sync_with_stdio(false);
        set_console_log_level(W);
    }

    logger::~logger() {
        if (log_file.is_open()) {
            log_file.close();
        }
        std::ios::sync_with_stdio(true);
    }

    void logger::set_console_log_level(log_level level) {
        console_log_level = level;
    }

    std::string logger::get_log_level(log_level level) {
        switch (level) {
            case D:
                return "DEBUG";
            case I:
                return "INFO";
            case W:
                return "WARNING";
            case E:
                return "ERROR";
            default:
                return "UNKNOWN";
        }
    }

    std::string logger::get_current_time_stamp() {
        auto currentTime = std::chrono::system_clock::now();
        auto currentTimeT = std::chrono::system_clock::to_time_t(currentTime);
        auto timeInfo = *std::localtime(&currentTimeT);
        std::stringstream ss;
        ss << std::put_time(&timeInfo, "%Y-%m-%d %H:%M:%S");
        return ss.str();
    }

    void logger::write(log_level level, const std::string &message) {
        std::lock_guard<std::mutex> lock(std::mutex);
        std::string logMessage = get_current_time_stamp() + " [" + get_log_level(level) + "] " + message + "\n";
        if (level >= console_log_level) {
            std::cout << logMessage;
        }
        if (log_file.is_open()) {
            log_file << logMessage;
        }
    }

}

使用方法

#include "logger.h"

int main() {

    auto log = make_unique<fkkt::logger>("app.log", fkkt::logger::log_level::D, ios::in);
    log->set_console_log_level(fkkt::logger::D);
    log->d("Hello ", 10924);

    return 0;
}
posted @ 2023-09-09 09:36  fkkt-55  阅读(43)  评论(0编辑  收藏  举报