240717班级,工业化控制系统,煤矿相关行业,昆仑系统
fufu
2024-10-30 d8318ea48f3b7594726283b766db63b70493368a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#ifndef LOG_H
#define LOG_H
 
#include <stdio.h>
#include <iostream>
#include <string>
#include <stdarg.h>
#include <pthread.h>
#include "block_queue.h"
 
using namespace std;
 
class Log
{
public:
    // C++11以后,使用局部变量懒汉不用加锁
    static Log *get_instance()
    {
        static Log instance;
        return &instance;
    }
 
    static void *flush_log_thread(void *args)
    {
        Log::get_instance()->async_write_log();
    }
 
    // 可选择的参数有日志文件、日志缓冲区大小、最大行数以及最长日志条队列
    bool init(const char *file_name, int close_log, int log_buf_size = 8192, int split_lines = 5000000, int max_queue_size = 0);
 
    void write_log(int level, const char *format, ...);
    void flush(void);
 
private:
    Log();
    virtual ~Log();
    
    void *async_write_log()
    {
        string single_log;
        // 从阻塞队列中取出一个日志string,写入文件
        while (m_log_queue->pop(single_log))
        {
            m_mutex.lock();
            if (check_log_size()) // 检查文件大小
            {
                rotate_logs(); // 轮换日志
            }
            fputs(single_log.c_str(), m_fp);
            m_mutex.unlock();
        }
    }
 
    // 检查日志文件大小
    bool check_log_size()
    {
        if (m_fp)
        {
            fseek(m_fp, 0, SEEK_END);
            long file_size = ftell(m_fp);
            return file_size >= max_size; // 返回文件是否超出限制
        }
        return false;
    }
 
    // 轮换日志文件
    void rotate_logs()
    {
        fclose(m_fp); // 关闭当前日志文件
        char new_log[256] = {0};
        snprintf(new_log, sizeof(new_log), "%s/%s.%lld", dir_name, log_name, m_count / m_split_lines);
        m_fp = fopen(new_log, "a"); // 打开新的日志文件
        m_count = 0; // 重置日志计数
    }
 
private:
    char dir_name[128]; // 路径名
    char log_name[128]; // log文件名
    int m_split_lines;  // 日志最大行数
    int m_log_buf_size; // 日志缓冲区大小
    long long m_count;  // 日志行数记录
    int m_today;        // 因为按天分类,记录当前时间是那一天
    FILE *m_fp;         // 打开log的文件指针
    char *m_buf;
    block_queue<string> *m_log_queue; // 阻塞队列
    bool m_is_async;                  // 是否同步标志位
    locker m_mutex;
    int m_close_log; // 关闭日志
    long max_size = 10 * 1024 * 1024; // 10MB
};
 
#define LOG_DEBUG(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(0, format, ##__VA_ARGS__); Log::get_instance()->flush();}
#define LOG_INFO(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(1, format, ##__VA_ARGS__); Log::get_instance()->flush();}
#define LOG_WARN(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(2, format, ##__VA_ARGS__); Log::get_instance()->flush();}
#define LOG_ERROR(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(3, format, ##__VA_ARGS__); Log::get_instance()->flush();}
 
#endif