Skip to content

基本用法示例

本文档提供了 AuroraCore 的实际集成示例,展示如何在真实项目中使用 Logger 和 FileWatcher API。

示例 1:简单应用程序日志记录

这个示例展示了如何在应用程序中集成基本的日志记录功能。

C++ 代码

cpp
// simple_app.cpp
#include "logger_api.hpp"
#include <iostream>
#include <vector>
#include <stdexcept>

class SimpleApplication {
private:
    std::unique_ptr<InternalLogger> logger_;
    
public:
    SimpleApplication() {
        // 配置日志记录器
        LoggerConfig config;
        config.log_path = "/data/local/tmp/simple_app.log";
        config.max_file_size = 5 * 1024 * 1024;  // 5MB
        config.max_file_count = 3;
        config.min_level = LogLevel::INFO;
        config.buffer_size = 32 * 1024;  // 32KB
        
        logger_ = std::make_unique<InternalLogger>(config);
        logger_->info("SimpleApplication 已初始化");
    }
    
    void run() {
        logger_->info("应用程序开始运行");
        
        try {
            // 模拟应用程序逻辑
            process_data();
            perform_calculations();
            save_results();
            
            logger_->info("应用程序成功完成所有任务");
        } catch (const std::exception& e) {
            logger_->errorf("应用程序执行失败:%s", e.what());
            throw;
        }
    }
    
    ~SimpleApplication() {
        logger_->info("SimpleApplication 正在关闭");
        logger_->flush();
    }
    
private:
    void process_data() {
        logger_->info("开始处理数据");
        
        std::vector<int> data = {1, 2, 3, 4, 5};
        logger_->infof("处理 %zu 个数据项", data.size());
        
        for (size_t i = 0; i < data.size(); ++i) {
            logger_->debugf("处理项目 %zu: 值 = %d", i, data[i]);
            
            if (data[i] < 0) {
                logger_->warnf("检测到负值:%d", data[i]);
            }
        }
        
        logger_->info("数据处理完成");
    }
    
    void perform_calculations() {
        logger_->info("开始执行计算");
        
        // 模拟一些计算
        int result = 42;
        logger_->infof("计算结果:%d", result);
        
        if (result > 100) {
            logger_->warn("计算结果异常高");
        }
        
        logger_->info("计算完成");
    }
    
    void save_results() {
        logger_->info("开始保存结果");
        
        // 模拟保存操作
        bool success = true;  // 模拟保存成功
        
        if (success) {
            logger_->info("结果保存成功");
        } else {
            logger_->error("结果保存失败");
            throw std::runtime_error("保存操作失败");
        }
    }
};

int main() {
    try {
        SimpleApplication app;
        app.run();
        
        std::cout << "应用程序执行成功" << std::endl;
        return 0;
    } catch (const std::exception& e) {
        std::cerr << "应用程序错误:" << e.what() << std::endl;
        return -1;
    }
}

CMakeLists.txt

cmake
cmake_minimum_required(VERSION 3.10)
project(SimpleApp)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 添加 AuroraCore 路径
set(AuroraCore_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../AuroraCore")
include_directories(${AuroraCore_ROOT}/loggerAPI)
include_directories(${AuroraCore_ROOT}/filewatcherAPI)

# 添加可执行文件
add_executable(simple_app simple_app.cpp)

# 链接 AuroraCore 库
target_link_libraries(simple_app 
    ${AuroraCore_ROOT}/build/logger/liblogger.a
    ${AuroraCore_ROOT}/build/loggerAPI/libloggerAPI.a
    pthread
)

# 设置输出目录
set_target_properties(simple_app PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

构建和运行

bash
# 创建构建目录
mkdir build && cd build

# 配置项目
cmake ..

# 编译
make

# 运行
./bin/simple_app

预期输出

日志文件 /data/local/tmp/simple_app.log 将包含:

[2024-01-15 14:30:25.123] [INFO] SimpleApplication 已初始化
[2024-01-15 14:30:25.124] [INFO] 应用程序开始运行
[2024-01-15 14:30:25.125] [INFO] 开始处理数据
[2024-01-15 14:30:25.126] [INFO] 处理 5 个数据项
[2024-01-15 14:30:25.127] [INFO] 数据处理完成
[2024-01-15 14:30:25.128] [INFO] 开始执行计算
[2024-01-15 14:30:25.129] [INFO] 计算结果:42
[2024-01-15 14:30:25.130] [INFO] 计算完成
[2024-01-15 14:30:25.131] [INFO] 开始保存结果
[2024-01-15 14:30:25.132] [INFO] 结果保存成功
[2024-01-15 14:30:25.133] [INFO] 应用程序成功完成所有任务
[2024-01-15 14:30:25.134] [INFO] SimpleApplication 正在关闭

示例 2:配置文件监控器

这个示例展示了如何使用 FileWatcher API 监控配置文件的变化并自动重新加载。

C++ 代码

cpp
// config_monitor.cpp
#include "logger_api.hpp"
#include "filewatcher_api.hpp"
#include <iostream>
#include <fstream>
#include <map>
#include <thread>
#include <chrono>
#include <atomic>

class ConfigurationManager {
private:
    std::unique_ptr<InternalLogger> logger_;
    std::unique_ptr<FileWatcher> watcher_;
    std::string config_path_;
    std::map<std::string, std::string> config_data_;
    std::atomic<bool> running_{false};
    
public:
    ConfigurationManager(const std::string& config_path) 
        : config_path_(config_path) {
        
        // 初始化日志记录器
        LoggerConfig log_config;
        log_config.log_path = "/data/local/tmp/config_monitor.log";
        log_config.max_file_size = 10 * 1024 * 1024;  // 10MB
        log_config.max_file_count = 5;
        log_config.min_level = LogLevel::INFO;
        
        logger_ = std::make_unique<InternalLogger>(log_config);
        logger_->info("ConfigurationManager 已初始化");
        
        // 初始化文件监控器
        watcher_ = std::make_unique<FileWatcher>();
        
        // 加载初始配置
        load_configuration();
    }
    
    bool start_monitoring() {
        logger_->infof("开始监控配置文件:%s", config_path_.c_str());
        
        // 添加文件监控
        bool watch_added = watcher_->add_watch(
            config_path_,
            EventType::MODIFY,
            [this](const FileEvent& event) {
                this->handle_config_change(event);
            }
        );
        
        if (!watch_added) {
            logger_->errorf("无法添加配置文件监控:%s", config_path_.c_str());
            return false;
        }
        
        // 启动监控
        if (watcher_->start()) {
            running_ = true;
            logger_->info("配置文件监控已启动");
            return true;
        } else {
            logger_->error("启动配置文件监控失败");
            return false;
        }
    }
    
    void stop_monitoring() {
        if (running_) {
            logger_->info("停止配置文件监控");
            watcher_->stop();
            running_ = false;
            logger_->info("配置文件监控已停止");
        }
    }
    
    std::string get_config_value(const std::string& key) const {
        auto it = config_data_.find(key);
        return (it != config_data_.end()) ? it->second : "";
    }
    
    void print_configuration() const {
        std::cout << "当前配置:" << std::endl;
        for (const auto& pair : config_data_) {
            std::cout << "  " << pair.first << " = " << pair.second << std::endl;
        }
    }
    
    bool is_running() const {
        return running_;
    }
    
    ~ConfigurationManager() {
        stop_monitoring();
        logger_->info("ConfigurationManager 已销毁");
    }
    
private:
    void load_configuration() {
        logger_->infof("加载配置文件:%s", config_path_.c_str());
        
        std::ifstream file(config_path_);
        if (!file.is_open()) {
            logger_->errorf("无法打开配置文件:%s", config_path_.c_str());
            return;
        }
        
        config_data_.clear();
        std::string line;
        int line_number = 0;
        
        while (std::getline(file, line)) {
            line_number++;
            
            // 跳过空行和注释
            if (line.empty() || line[0] == '#') {
                continue;
            }
            
            // 解析键值对
            size_t pos = line.find('=');
            if (pos != std::string::npos) {
                std::string key = line.substr(0, pos);
                std::string value = line.substr(pos + 1);
                
                // 去除空格
                key.erase(0, key.find_first_not_of(" \t"));
                key.erase(key.find_last_not_of(" \t") + 1);
                value.erase(0, value.find_first_not_of(" \t"));
                value.erase(value.find_last_not_of(" \t") + 1);
                
                config_data_[key] = value;
                logger_->debugf("配置项:%s = %s", key.c_str(), value.c_str());
            } else {
                logger_->warnf("配置文件第 %d 行格式错误:%s", line_number, line.c_str());
            }
        }
        
        logger_->infof("配置加载完成,共 %zu 个配置项", config_data_.size());
    }
    
    void handle_config_change(const FileEvent& event) {
        logger_->infof("检测到配置文件变化:%s", event.path.c_str());
        
        // 等待一小段时间,确保文件写入完成
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        
        // 重新加载配置
        load_configuration();
        
        logger_->info("配置文件已重新加载");
        
        // 通知应用程序配置已更改
        on_configuration_changed();
    }
    
    void on_configuration_changed() {
        logger_->info("配置已更改,通知应用程序");
        
        // 在这里可以添加配置更改的处理逻辑
        // 例如:重新初始化组件、更新运行参数等
        
        std::cout << "配置已更新!" << std::endl;
        print_configuration();
    }
};

class Application {
private:
    std::unique_ptr<ConfigurationManager> config_manager_;
    std::atomic<bool> should_run_{true};
    
public:
    Application(const std::string& config_path) {
        config_manager_ = std::make_unique<ConfigurationManager>(config_path);
    }
    
    void run() {
        std::cout << "启动应用程序..." << std::endl;
        
        // 启动配置监控
        if (!config_manager_->start_monitoring()) {
            std::cerr << "启动配置监控失败" << std::endl;
            return;
        }
        
        // 显示初始配置
        std::cout << "初始配置:" << std::endl;
        config_manager_->print_configuration();
        
        // 主循环
        std::cout << "应用程序正在运行...(按 Ctrl+C 退出)" << std::endl;
        
        while (should_run_) {
            // 模拟应用程序工作
            std::this_thread::sleep_for(std::chrono::seconds(1));
            
            // 使用配置值
            std::string app_name = config_manager_->get_config_value("app_name");
            std::string log_level = config_manager_->get_config_value("log_level");
            
            if (!app_name.empty()) {
                // 使用配置进行工作
            }
        }
        
        config_manager_->stop_monitoring();
        std::cout << "应用程序已退出" << std::endl;
    }
    
    void stop() {
        should_run_ = false;
    }
};

int main() {
    // 创建示例配置文件
    std::string config_path = "/data/local/tmp/app_config.conf";
    
    std::ofstream config_file(config_path);
    config_file << "# 应用程序配置文件\n";
    config_file << "app_name = MyApplication\n";
    config_file << "log_level = INFO\n";
    config_file << "max_connections = 100\n";
    config_file << "timeout = 30\n";
    config_file.close();
    
    try {
        Application app(config_path);
        
        // 设置信号处理(简化版本)
        std::thread app_thread([&app]() {
            app.run();
        });
        
        // 等待用户输入或信号
        std::cout << "按 Enter 键退出..." << std::endl;
        std::cin.get();
        
        app.stop();
        app_thread.join();
        
    } catch (const std::exception& e) {
        std::cerr << "应用程序错误:" << e.what() << std::endl;
        return -1;
    }
    
    return 0;
}

测试配置更改

在应用程序运行时,可以修改配置文件来测试自动重新加载:

bash
# 修改配置文件
echo "app_name = UpdatedApplication" > /data/local/tmp/app_config.conf
echo "log_level = DEBUG" >> /data/local/tmp/app_config.conf
echo "max_connections = 200" >> /data/local/tmp/app_config.conf
echo "timeout = 60" >> /data/local/tmp/app_config.conf

示例 3:系统服务(组合使用)

这个示例展示了如何将 Logger 和 FileWatcher API 组合使用,创建一个完整的系统监控服务。

C++ 代码

cpp
// system_monitor.cpp
#include "logger_api.hpp"
#include "filewatcher_api.hpp"
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <vector>
#include <map>
#include <signal.h>

class SystemMonitorService {
private:
    std::unique_ptr<InternalLogger> logger_;
    std::unique_ptr<FileWatcher> watcher_;
    std::atomic<bool> running_{false};
    std::thread monitor_thread_;
    
    // 监控统计
    std::map<std::string, int> event_counts_;
    std::chrono::steady_clock::time_point start_time_;
    
public:
    SystemMonitorService() {
        // 配置日志记录器
        LoggerConfig config;
        config.log_path = "/data/local/tmp/system_monitor.log";
        config.max_file_size = 50 * 1024 * 1024;  // 50MB
        config.max_file_count = 10;
        config.min_level = LogLevel::INFO;
        config.buffer_size = 128 * 1024;  // 128KB
        config.flush_interval_ms = 2000;  // 2秒
        
        logger_ = std::make_unique<InternalLogger>(config);
        logger_->info("SystemMonitorService 已初始化");
        
        // 初始化文件监控器
        watcher_ = std::make_unique<FileWatcher>();
        
        // 初始化统计
        start_time_ = std::chrono::steady_clock::now();
    }
    
    bool start() {
        logger_->info("启动系统监控服务");
        
        // 添加多个监控路径
        if (!setup_monitoring_paths()) {
            logger_->error("设置监控路径失败");
            return false;
        }
        
        // 启动文件监控
        if (!watcher_->start()) {
            logger_->error("启动文件监控失败");
            return false;
        }
        
        // 启动监控线程
        running_ = true;
        monitor_thread_ = std::thread(&SystemMonitorService::monitor_loop, this);
        
        logger_->info("系统监控服务已启动");
        return true;
    }
    
    void stop() {
        if (running_) {
            logger_->info("停止系统监控服务");
            
            running_ = false;
            
            if (monitor_thread_.joinable()) {
                monitor_thread_.join();
            }
            
            watcher_->stop();
            
            // 输出统计信息
            print_statistics();
            
            logger_->info("系统监控服务已停止");
        }
    }
    
    bool is_running() const {
        return running_;
    }
    
    ~SystemMonitorService() {
        stop();
        logger_->info("SystemMonitorService 已销毁");
    }
    
private:
    bool setup_monitoring_paths() {
        logger_->info("设置监控路径");
        
        // 监控路径配置
        std::vector<std::pair<std::string, uint32_t>> paths = {
            {"/data/config", make_event_mask(EventType::MODIFY, EventType::CREATE, EventType::DELETE)},
            {"/data/critical", make_event_mask(EventType::DELETE, EventType::MOVED_FROM)},
            {"/data/logs", make_event_mask(EventType::CREATE, EventType::MODIFY)},
            {"/data/temp", make_event_mask(EventType::CREATE, EventType::DELETE)}
        };
        
        for (const auto& path_config : paths) {
            const std::string& path = path_config.first;
            uint32_t mask = path_config.second;
            
            logger_->infof("添加监控路径:%s", path.c_str());
            
            bool success = watcher_->add_watch(path, mask,
                [this, path](const FileEvent& event) {
                    this->handle_file_event(event, path);
                });
            
            if (success) {
                logger_->infof("成功添加监控:%s", path.c_str());
            } else {
                logger_->warnf("添加监控失败:%s(路径可能不存在)", path.c_str());
            }
        }
        
        return true;
    }
    
    void handle_file_event(const FileEvent& event, const std::string& base_path) {
        std::string event_type_str = event_type_to_string(event.type);
        
        // 更新统计
        event_counts_[event_type_str]++;
        
        // 记录事件
        logger_->infof("文件事件 [%s]: %s (%s)", 
                      base_path.c_str(), event_type_str.c_str(), event.path.c_str());
        
        // 根据事件类型进行特殊处理
        switch (event.type) {
            case EventType::DELETE:
                handle_file_deletion(event, base_path);
                break;
                
            case EventType::CREATE:
                handle_file_creation(event, base_path);
                break;
                
            case EventType::MODIFY:
                handle_file_modification(event, base_path);
                break;
                
            default:
                break;
        }
    }
    
    void handle_file_deletion(const FileEvent& event, const std::string& base_path) {
        if (base_path == "/data/critical") {
            logger_->errorf("关键文件被删除:%s", event.path.c_str());
            
            // 发送警报(这里只是记录)
            logger_->fatal("检测到关键文件删除,需要立即关注!");
        } else {
            logger_->infof("文件删除:%s", event.path.c_str());
        }
    }
    
    void handle_file_creation(const FileEvent& event, const std::string& base_path) {
        logger_->infof("新文件创建:%s", event.path.c_str());
        
        if (base_path == "/data/logs") {
            logger_->infof("新日志文件:%s", event.path.c_str());
        }
    }
    
    void handle_file_modification(const FileEvent& event, const std::string& base_path) {
        if (base_path == "/data/config") {
            logger_->infof("配置文件已修改:%s", event.path.c_str());
            
            // 可以在这里触发配置重新加载
            logger_->info("建议重新加载相关配置");
        } else {
            logger_->debugf("文件修改:%s", event.path.c_str());
        }
    }
    
    void monitor_loop() {
        logger_->info("监控循环已启动");
        
        while (running_) {
            // 每分钟输出一次状态
            std::this_thread::sleep_for(std::chrono::minutes(1));
            
            if (running_) {
                log_status();
            }
        }
        
        logger_->info("监控循环已退出");
    }
    
    void log_status() {
        auto now = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::minutes>(now - start_time_);
        
        logger_->infof("系统监控状态 - 运行时间:%ld 分钟", duration.count());
        
        // 记录事件统计
        if (!event_counts_.empty()) {
            logger_->info("事件统计:");
            for (const auto& pair : event_counts_) {
                logger_->infof("  %s: %d 次", pair.first.c_str(), pair.second);
            }
        } else {
            logger_->info("暂无文件事件");
        }
    }
    
    void print_statistics() {
        auto now = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::minutes>(now - start_time_);
        
        logger_->infof("=== 监控服务统计 ===");
        logger_->infof("总运行时间:%ld 分钟", duration.count());
        
        int total_events = 0;
        for (const auto& pair : event_counts_) {
            total_events += pair.second;
            logger_->infof("%s 事件:%d 次", pair.first.c_str(), pair.second);
        }
        
        logger_->infof("总事件数:%d", total_events);
        
        if (duration.count() > 0) {
            double events_per_minute = static_cast<double>(total_events) / duration.count();
            logger_->infof("平均事件频率:%.2f 事件/分钟", events_per_minute);
        }
        
        logger_->info("=== 统计结束 ===");
    }
};

// 全局服务实例
std::unique_ptr<SystemMonitorService> g_service;

// 信号处理函数
void signal_handler(int signal) {
    std::cout << "\n收到信号 " << signal << ",正在关闭服务..." << std::endl;
    
    if (g_service) {
        g_service->stop();
    }
    
    exit(0);
}

int main() {
    std::cout << "启动系统监控服务..." << std::endl;
    
    // 设置信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    try {
        // 创建并启动服务
        g_service = std::make_unique<SystemMonitorService>();
        
        if (!g_service->start()) {
            std::cerr << "启动系统监控服务失败" << std::endl;
            return -1;
        }
        
        std::cout << "系统监控服务已启动" << std::endl;
        std::cout << "监控以下目录:" << std::endl;
        std::cout << "  - /data/config (配置文件)" << std::endl;
        std::cout << "  - /data/critical (关键文件)" << std::endl;
        std::cout << "  - /data/logs (日志文件)" << std::endl;
        std::cout << "  - /data/temp (临时文件)" << std::endl;
        std::cout << "按 Ctrl+C 停止服务" << std::endl;
        
        // 保持服务运行
        while (g_service->is_running()) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        
    } catch (const std::exception& e) {
        std::cerr << "服务错误:" << e.what() << std::endl;
        return -1;
    }
    
    std::cout << "系统监控服务已退出" << std::endl;
    return 0;
}

服务部署脚本

bash
#!/bin/bash
# deploy_monitor.sh

SERVICE_NAME="system_monitor"
BINARY_PATH="./bin/system_monitor"
PID_FILE="/data/local/tmp/${SERVICE_NAME}.pid"
LOG_FILE="/data/local/tmp/${SERVICE_NAME}_service.log"

start_service() {
    echo "启动 $SERVICE_NAME 服务..."
    
    # 检查是否已经运行
    if [ -f "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if kill -0 "$PID" 2>/dev/null; then
            echo "服务已在运行 (PID: $PID)"
            return 1
        else
            echo "删除过期的 PID 文件"
            rm -f "$PID_FILE"
        fi
    fi
    
    # 创建必要的目录
    mkdir -p /data/config
    mkdir -p /data/critical
    mkdir -p /data/logs
    mkdir -p /data/temp
    
    # 启动服务
    nohup "$BINARY_PATH" > "$LOG_FILE" 2>&1 &
    PID=$!
    
    # 保存 PID
    echo $PID > "$PID_FILE"
    
    echo "服务已启动 (PID: $PID)"
    echo "日志文件:$LOG_FILE"
}

stop_service() {
    echo "停止 $SERVICE_NAME 服务..."
    
    if [ -f "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if kill -0 "$PID" 2>/dev/null; then
            kill -TERM "$PID"
            
            # 等待服务停止
            for i in {1..10}; do
                if ! kill -0 "$PID" 2>/dev/null; then
                    break
                fi
                sleep 1
            done
            
            # 强制终止
            if kill -0 "$PID" 2>/dev/null; then
                echo "强制终止服务"
                kill -KILL "$PID"
            fi
            
            echo "服务已停止"
        else
            echo "服务未运行"
        fi
        
        rm -f "$PID_FILE"
    else
        echo "PID 文件不存在,服务可能未运行"
    fi
}

status_service() {
    if [ -f "$PID_FILE" ]; then
        PID=$(cat "$PID_FILE")
        if kill -0 "$PID" 2>/dev/null; then
            echo "服务正在运行 (PID: $PID)"
            return 0
        else
            echo "服务未运行(PID 文件存在但进程不存在)"
            return 1
        fi
    else
        echo "服务未运行"
        return 1
    fi
}

case "$1" in
    start)
        start_service
        ;;
    stop)
        stop_service
        ;;
    restart)
        stop_service
        sleep 2
        start_service
        ;;
    status)
        status_service
        ;;
    *)
        echo "用法: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

构建和部署

bash
# 构建项目
mkdir build && cd build
cmake ..
make

# 部署服务
cp ../deploy_monitor.sh .
chmod +x deploy_monitor.sh

# 启动服务
./deploy_monitor.sh start

# 检查状态
./deploy_monitor.sh status

# 查看日志
tail -f /data/local/tmp/system_monitor.log

关键要点

1. 错误处理

所有示例都包含适当的错误处理:

  • 检查初始化结果
  • 处理文件操作异常
  • 优雅的资源清理

2. 资源管理

  • 使用 RAII 原则
  • 智能指针管理内存
  • 析构函数中清理资源

3. 线程安全

  • 使用原子变量控制线程状态
  • 适当的同步机制
  • 安全的线程退出

4. 配置管理

  • 集中化配置
  • 运行时配置更新
  • 配置验证

5. 日志记录最佳实践

  • 结构化日志消息
  • 适当的日志级别
  • 性能考虑

这些示例展示了如何在实际项目中有效地使用 AuroraCore 的功能,提供了从简单应用到复杂系统服务的完整解决方案。

Released under the MIT License.