日志体系

31 阅读2分钟

应用日志:printf + valist

// CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(app_logger CXX)

set(CMAKE_CXX_STANDARD 17)

add_executable(app_logger_demo app_logger_demo.cpp)
// app_logger.h
#pragma once
#include <cstdarg>
#include <cstdio>
#include <string>

namespace demo {

enum class Level {
    Debug = 0,
    Info,
    Warn, 
    Error
};

inline const char* level_name(Level level) {
    switch (level) {
    case Level::Debug: 
        return "DEBUG";
    case Level::Info:
        return "INFO";
    case Level::Warn: 
        return "WARN";
    case Level::Error:
        return "ERROR";
    }
    return "UNKNOWN";
}

// plan1: vprintf
inline void logf(Level level, const char* file, int line, const char* fmt, ...) {
    std::printf("[%s] %s:%d - ", level_name(level), file, line);

    va_list args;
    va_start(args, fmt);
    std::vprintf(fmt, args);
    va_end(args);

    std::printf("\n");
}


// plan2: va_list
inline void logf_manual(Level level, const char* file, int line, const char* fmt, ...) {
    std::printf("[%s] %s:%d - ", level_name(level), file, line);

    va_list args;
    va_start(args, fmt);

    const char* str_arg = va_arg(args, const char*); //param1
    int int_arg = va_arg(args, int); //param2

    std::printf(fmt, str_arg, int_arg);

    va_end(args);
    std::printf("\n");
}


// DEFINE
#define APP_LOG_INFO(fmt, ...) demo::logf(demo::Level::Info, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define APP_LOG_MANUAL(fmt, ...) demo::logf_manual(demo::Level::Info, __FILE__, __LINE__, fmt, ##__VA_ARGS__)


} // namespace demo
// app_logger_demo.cpp
#include "app_logger.h"

int main() {
    using namespace demo;

    const char* user = "Alice";
    int score = 23;

    // vprintf
    APP_LOG_INFO("1. User %s has score %d", user, score);

    // va_list
    APP_LOG_MANUAL("2. User %s has score %d", user, score);
    
    return 0;
}

SDK 回调日志

// CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(sdk_logger CXX)

set(CMAKE_CXX_STANDARD 17)

add_library(fake_sdk sdk_log.cpp)
add_executable(sdk_callback_demo sdk_callback_demo.cpp)
target_link_libraries(sdk_callback_demo PRIVATE fake_sdk)
// sdk_log.h
#pragma once
#include <cstddef>

extern "C" {

typedef enum {
    SDK_LOG_DEBUG = 0,
    SDK_LOG_INFO = 1,
    SDK_LOG_WARN = 2,
    SDK_LOG_ERROR = 3,
} sdk_log_level_t;

typedef void (*sdk_log_callback_t) (
    sdk_log_level_t level,
    const char* filename,
    int line,
    const char* message
);

void sdk_register_log_callback(sdk_log_callback_t cb);

void sdk_do_something(int task_id);

} // extern "C"
// sdk_log.cpp
#include "sdk_log.h"
#include <cstdio>
#include <cstdarg>
#include <string>
#include <mutex>

namespace {
    sdk_log_callback_t g_cb = nullptr;
    std::mutex g_mu;

    void sdk_log_fire(sdk_log_level_t lv, const char* file, int line , const char* fmt, ...) {
        if (!g_cb) return ;
        
        char buf[256];
        va_list args;
        va_start(args, fmt);
        vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);

        g_cb(lv, file, line, buf);
    }
}

#define SDK_LOG_INFO_IMPL(fmt, ...) sdk_log_fire(SDK_LOG_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define SDK_LOG_ERROR_IMPL(fmt, ...) sdk_log_fire(SDK_LOG_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)

extern "C" {

void sdk_register_log_callback(sdk_log_callback_t cb) {
    std::lock_guard<std::mutex> lk(g_mu);
    g_cb = cb;
}

void sdk_do_something(int task_id) {
    SDK_LOG_INFO_IMPL("Starting task %d", task_id);
    if (task_id < 0) {
        SDK_LOG_ERROR_IMPL("Invalid task if: %d", task_id);
        return ;
    }
    SDK_LOG_INFO_IMPL("Task %d done", task_id);
}

} // extern "C"
// sdk_callback_demo.cpp
#include "sdk_log.h"
#include <cstdio>

void my_log_callback(sdk_log_level_t level,
                     const char* file,
                     int line,
                     const char* msg) {
    const char* lvname = (level==SDK_LOG_INFO ? "INFO" : 
                          level==SDK_LOG_ERROR ? "ERROR" : "OTHER");
    std::printf("[%s] %s:%d - %s\n", lvname, file, line, msg);
}

int main() {
    sdk_register_log_callback(&my_log_callback);

    sdk_do_something(42);
    sdk_do_something(-1);

    return 0;
}