• Windows/Linux通用c语言日志log库(零依赖)


    #ifndef __CLOG_H__
    #define __CLOG_H__
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
    ///////////////////////////////////////////////////////////////////////////
    // Disable all warning: _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    #include <io.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <stdarg.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    #include <direct.h>
    #define __off_t        _off_t
    #define F_OK       0
    #define O_APPEND   _O_APPEND
    #define O_CREAT        _O_CREAT
    #define O_WRONLY   _O_WRONLY
    #define O_CLOEXEC  _O_NOINHERIT
    #define DEFFILEMODE 0666
    //#define DEFFILEMODE _S_IREAD | _S_IWRITE
    #define strcasecmp stricmp
    #define sys_get_tid() ::GetCurrentThreadId()
    #define PATH_SEPARATOR         "/"
    #define PATH_SEPARATOR_CHAR        '/'
    #define make_dir(x)                mkdir(x)
    #define LOG_STDOUT_FILENO      fileno(stdout)
    // For windows implementation of "gettimeofday"
    #if defined(_WIN32) || defined(WIN32)
    #include <time.h>
    #include <WinSock2.h> //I've ommited this line.
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
    #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
    #else
    #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
    #endif
    struct timezone
    {
        int  tz_minuteswest; /* minutes W of Greenwich */
        int  tz_dsttime;     /* type of dst correction */
    };
    __inline static
    int gettimeofday(struct timeval* tv, struct timezone* tz)
    {
        FILETIME f = { 0 };
        static char _tz = 0x00;
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
        unsigned long long u = 0Ui64;
    #else
        unsigned long long u = 0ULL;
    #endif
        if (tv)
        {
    #ifdef _WIN32_WCE 
            SYSTEMTIME s = { 0 };
            ::GetSystemTime(&s);
            ::SystemTimeToFileTime(&s, &f);
    #else 
            ::GetSystemTimeAsFileTime(&f);
    #endif 
            u |= f.dwHighDateTime;
            u <<= 32;
            u |= f.dwLowDateTime;
            //convert into microseconds
            u /= 10;
            //converting file time to unix epoch
            u -= DELTA_EPOCH_IN_MICROSECS;
            tv->tv_sec = (long)(u / 1000000UL);
            tv->tv_usec = (long)(u % 1000000UL);
        }
        if (tz)
        {
            if (_tz == 0x00)
            {
                _tzset();
                _tz = 0x01;
            }
            tz->tz_minuteswest = _timezone / 60;
            tz->tz_dsttime = _daylight;
        }
        return 0;
    }
    #endif
    /*static CRITICAL_SECTION log_locker = { 0 };
    #define log_init_lock() InitializeCriticalSection(&log_locker)
    #define log_lock()     EnterCriticalSection(&log_locker)
    #define log_unlock()   LeaveCriticalSection(&log_locker)
    #define log_exit_lock() DeleteCriticalSection(&log_locker)*/
    #else
    ///////////////////////////////////////////////////////////////////////////
    #include <stdarg.h>
    #include <unistd.h>
    #include <malloc.h>
    #include <string.h>
    #include <errno.h>
    #include <time.h>
    #include <pthread.h>
    #include <sys/fcntl.h>
    #include <sys/stat.h>
    #include <sys/time.h>
    #include <sys/syscall.h>
    #define sys_get_tid() syscall(SYS_gettid)
    #define PATH_SEPARATOR         "/"
    #define PATH_SEPARATOR_CHAR        '/'
    #define make_dir(x)                mkdir(x, DEFFILEMODE)
    #define LOG_STDOUT_FILENO      STDOUT_FILENO
    /*static pthread_mutex_t log_locker;
    #define log_init_lock() pthread_mutex_init(&log_locker,0)
    #define log_lock()     pthread_mutex_lock(&log_locker)
    #define log_unlock()   pthread_mutex_unlock(&log_locker)
    #define log_exit_lock() pthread_mutex_destroy(&log_locker)*/
    #endif
    #define MAX_LOG_PATH           4096
    #define DATA_SIZE              102400
    #define DAY_SECONDS                86400
    #define DEFAULT_LOG_ROTATETIME DAY_SECONDS
    #define DEFAULT_LOG_LIMIT_SIZE 10*1024*1024
    #define DEFAULT_LOG_FMT            ""
    #define DEFAULT_LOG_EXT            ".log"
    #define DEFAULT_LOG_PATH       "." PATH_SEPARATOR
    #define DEFAULT_LOG_CONS       0xFF
    #define NEED_LOG_CONS(X)       (X!=0x00)
    #define LOG_FILE_FORMAT            "%Y-%m-%d %H:%M:%S"
    #define LOG_LR                 '\r'
    #define LOG_CF                 '\n'
    #pragma pack (1)
    struct log_arg {
        int fd;
        long num;
        long idx;
        time_t ftime;
        char fname[64];
        char lname[MAX_LOG_PATH];
        long size;
        char* data;
    };
    struct log_set {
        long args;
        int level;
        char ext[8];
        char fmt[64];
        __off_t limit;
        long rotatetime;
        unsigned char cons;
        char path[MAX_LOG_PATH];
        struct log_arg* argl;
    };
    #pragma pack ()
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
    #define __CLOG_GLOBAL_MACROS_DEFINE__ static CRITICAL_SECTION log_locker = { 0 };static struct log_set* p_log_set = 0;
    #define __CLOG_GLOBAL_MACROS_EXTERN__ extern CRITICAL_SECTION log_locker;extern struct log_set* p_log_set;
    #define log_init_lock()        InitializeCriticalSection(&log_locker)
    #define log_lock()         EnterCriticalSection(&log_locker)
    #define log_unlock()       LeaveCriticalSection(&log_locker)
    #define log_exit_lock()        DeleteCriticalSection(&log_locker)
    #else
    #define __CLOG_GLOBAL_MACROS_DEFINE__  static pthread_mutex_t log_locker;static struct log_set* p_log_set = 0;
    #define __CLOG_GLOBAL_MACROS_EXTERN__ extern pthread_mutex_t log_locker;extern struct log_set* p_log_set;
    #define log_init_lock()        pthread_mutex_init(&log_locker,0)
    #define log_lock()         pthread_mutex_lock(&log_locker)
    #define log_unlock()       pthread_mutex_unlock(&log_locker)
    #define log_exit_lock()        pthread_mutex_destroy(&log_locker)
    #endif
    __CLOG_GLOBAL_MACROS_DEFINE__
    __CLOG_GLOBAL_MACROS_EXTERN__
    enum log_level_type
    {
        LOG_NONE = 0,
        LOG_FATAL,
        LOG_ERROR,
        LOG_WARN,
        LOG_INFO,
        LOG_DEBUG,
        LOG_TRACE,
        LOG_VERBOSE,
        LOG_MAX,
    };
    #define IS_VALID_LOG_LEVEL_TYPE(X) (X > LOG_NONE && X < LOG_MAX)
    static const char* p_log_level_name[LOG_MAX] = {
        "NONE",
        "FATAL",
        "ERROR",
        "WARN",
        "INFO",
        "DEBUG",
        "TRACE",
        "VERBOSE"
    };
    #define NONE_COLOR "\033[00m"
    static const char* p_log_level_color[LOG_MAX] = {
        "\033[30m",
        "\033[31m",
        "\033[32m",
        "\033[33m",
        "\033[34m",
        "\033[35m",
        "\033[36m",
        "\033[37m"
    };
    __inline static
    time_t get_log_rotatetime()
    {
        return p_log_set->rotatetime;
    }
    __inline static
    const char* get_log_path()
    {
        return p_log_set->path;
    }
    __inline static
    const char* get_log_ext()
    {
        return p_log_set->ext;
    }
    __inline static
    const char* get_log_fmt()
    {
        return p_log_set->fmt;
    }
    __inline static
    __off_t get_log_limit()
    {
        return p_log_set->limit;
    }
    __inline static
    int get_log_top_level()
    {
        return p_log_set->level;
    }
    __inline static
    unsigned char get_log_cons()
    {
        return p_log_set->cons;
    }
    __inline static
    const char* get_log_level_name(int level)
    {
        return p_log_level_name[level];
    }
    __inline static
    const char* get_log_level_color(int level)
    {
        return p_log_level_color[level];
    }
    __inline static
    const char* get_log_level_color_end()
    {
        return NONE_COLOR;
    }
    __inline static
    struct log_arg* get_log_arg(const char* fname)
    {
        for (long i = 0; i < p_log_set->args; i++)
        {
            if (strcasecmp(p_log_set->argl[i].fname, fname) == 0)
            {
                return &p_log_set->argl[i];
            }
        }
        return (0);
    }
    __inline static
    int exit_log()
    {
        if (p_log_set)
        {
            if (p_log_set->argl)
            {
                for (long i = 0; i < p_log_set->args; i++)
                {
                    if (p_log_set->argl[i].fd != (-1))
                    {
                        close(p_log_set->argl[i].fd);
                        p_log_set->argl[i].fd = (-1);
                    }
                    if (p_log_set->argl[i].data != 0)
                    {
                        free(p_log_set->argl[i].data);
                        p_log_set->argl[i].data = 0;
                    }
                }
                free(p_log_set->argl);
                p_log_set->argl = (0);
            }
            free(p_log_set);
            p_log_set = (0);
        }
        log_exit_lock();
        return 0;
    }
    __inline static
    struct log_set* init_log(const char* path, const char* fmt, const char* ext, unsigned char cons,
        long rotatetime, int level, long limit, const struct log_arg* pargl, unsigned long args)
    {
        char* p = 0;
        int nCount = 0;
        time_t log_secs = 0;
        struct tm* tm_log = 0;
        struct timeval tv = { 0 };
        struct timezone tz = { 0 };
        char lname[MAX_LOG_PATH] = { 0 };
        char tpath[MAX_LOG_PATH] = { 0 };
        char lpath[MAX_LOG_PATH] = { 0 };
        size_t path_len = strlen(path);
        size_t tpath_size = sizeof(tpath) / sizeof(*tpath);
        log_init_lock();
        if (p_log_set == 0)
        {
            p_log_set = (struct log_set*)malloc(sizeof(struct log_set));
            if (p_log_set == 0)
            {
                exit_log();
                return (0);
            }
        }
        for (size_t i = 0; i < path_len && i < tpath_size; i++)
        {
            if (path[i] == '\\')
            {
                tpath[i] = '/';
            }
            else
            {
                tpath[i] = path[i];
            }
        }
        if (tpath[strlen(tpath) - 1] != '/')
        {
            tpath[strlen(tpath)] = '/';
        }
        p = (char*)tpath;
        while (((p = strchr((char*)tpath + (p - tpath), PATH_SEPARATOR_CHAR)) != 0))
        {
            snprintf(lpath, sizeof(lpath) / sizeof(*lpath), "%.*s\0", (int)((++p) - tpath), tpath);
            make_dir(lpath);
        }
        snprintf(p_log_set->path, sizeof(p_log_set->path) / sizeof(*(p_log_set->path)), "%s\0", (tpath != 0) ? (tpath) : DEFAULT_LOG_PATH);
        if ((p_log_set->path[strlen(p_log_set->path) - 1] != PATH_SEPARATOR_CHAR))
        {
            p_log_set->path[strlen(p_log_set->path)] = PATH_SEPARATOR_CHAR;
        }
        snprintf(p_log_set->fmt, sizeof(p_log_set->fmt) / sizeof(*(p_log_set->fmt)), "%s\0", (fmt != 0) ? (fmt) : "");
        snprintf(p_log_set->ext, sizeof(p_log_set->ext) / sizeof(*(p_log_set->ext)), "%s\0", (tpath != 0) ? (ext) : DEFAULT_LOG_EXT);
        p_log_set->level = IS_VALID_LOG_LEVEL_TYPE(level) ? level : LOG_VERBOSE;
        p_log_set->limit = limit > 0 ? limit : DEFAULT_LOG_LIMIT_SIZE;
        p_log_set->cons = cons;
        p_log_set->args = args;
        p_log_set->rotatetime = rotatetime > 0 ? rotatetime : DAY_SECONDS;
        p_log_set->argl = (struct log_arg*)malloc(p_log_set->args * sizeof(struct log_arg));
        if (p_log_set->argl == 0)
        {
            exit_log();
            return (0);
        }
        memset(p_log_set->argl, 0, p_log_set->args * sizeof(struct log_arg));
        gettimeofday(&tv, &tz);
        log_secs = tv.tv_sec;
        log_secs -= log_secs % p_log_set->rotatetime;
        for (long i = 0; i < p_log_set->args; i++)
        {
            nCount = 0;
            memcpy(&p_log_set->argl[i], &pargl[i], sizeof(struct log_arg));
            p_log_set->argl[i].data = (char*)malloc(p_log_set->argl[i].size);
            if (p_log_set->argl[i].data == 0)
            {
                exit_log();
                return (0);
            }
            nCount += snprintf(lname + nCount, sizeof(lname) / sizeof(*lname), "%s%s\0", p_log_set->path, p_log_set->argl[i].fname);
            if (*p_log_set->fmt)
            {
                tm_log = localtime(&log_secs);
                nCount += (int)(strftime(lname + nCount, sizeof(lname) / sizeof(*lname), p_log_set->fmt, tm_log));
            }
            p_log_set->argl[i].ftime = log_secs;
            nCount += snprintf(lname + nCount, sizeof(lname) / sizeof(*lname), "%s\0", p_log_set->ext);
            snprintf(p_log_set->argl[i].lname, sizeof(p_log_set->argl[i].lname) / sizeof(*p_log_set->argl[i].lname), "%s\0", lname);
            for (long n = 0; n < p_log_set->argl[i].num; n++)
            {
                snprintf(lname, sizeof(lname) / sizeof(*lname), "%s.%d\0", p_log_set->argl[i].lname, n);
                if (access(lname, F_OK) != 0)
                {
                    p_log_set->argl[i].idx = (n + 1);
                    p_log_set->argl[i].idx %= (p_log_set->argl[i].num + 1);
                    p_log_set->argl[i].idx = (p_log_set->argl[i].idx <= 0) ? 1 : p_log_set->argl[i].idx;
                    break;
                }
            }
            p_log_set->argl[i].fd = open(p_log_set->argl[i].lname, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, DEFFILEMODE);
            if (p_log_set->argl[i].fd == (-1))
            {
                printf("%d,%s\n", errno, strerror(errno));
                exit_log();
                return (0);
            }
        }
        return (p_log_set);
    }
    __inline static
    int check_log(struct log_arg* pla, time_t now_secs)
    {
        int nCount = 0;
        time_t fsecs = 0;
        struct stat st = { 0 };
        __off_t limit = get_log_limit();
        const char* ext = get_log_ext();
        const char* fmt = get_log_fmt();
        char lname[MAX_LOG_PATH] = { 0 };
        const char* path = get_log_path();
        fsecs = now_secs - now_secs % get_log_rotatetime();
        if (pla->ftime != fsecs)
        {
            pla->ftime = fsecs;
            nCount += snprintf(lname + nCount, sizeof(lname) / sizeof(*lname), "%s%s\0", path, pla->fname);
            if (*fmt)
            {
                nCount += (int)(strftime(lname + nCount, sizeof(lname) / sizeof(*lname), fmt, localtime(&fsecs)));
                nCount += snprintf(lname + nCount, sizeof(lname) / sizeof(*lname), "%s\0", ext);
                close(pla->fd);
                snprintf(pla->lname, sizeof(pla->lname) / sizeof(*pla->lname), "%s\0", lname);
                int fd = open(pla->lname, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, DEFFILEMODE);
                if (fd == (-1))
                {
                    pla->fd = (-1);
                    printf("open log file %s failed. msg: (errno=%d)%s\n", pla->fname, errno, strerror(errno));
                    return (-1);
                }
                dup2(fd, pla->fd);
                if (fd != pla->fd)
                {
                    close(fd);
                }
            }
            else
            {
                if (pla->num > 0)
                {
                    pla->idx %= (pla->num + 1);
                    pla->idx = (pla->idx <= 0) ? 1 : pla->idx;
                }
                snprintf(lname, sizeof(lname) / sizeof(*lname), "%s.%d\0", pla->lname, pla->idx++);
                close(pla->fd);
                unlink(lname);
                if (rename(pla->lname, lname) != 0)
                {
                    pla->fd = (-1);
                    printf("rename logfile %s -> %s failed msg: (errno=%d)%s\n", pla->lname, lname, errno, strerror(errno));
                    return (-1);
                }
                int fd = open(pla->lname, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, DEFFILEMODE);
                if (fd == (-1))
                {
                    pla->fd = (-1);
                    printf("open log file %s failed. msg: (errno=%d)%s\n", pla->fname, errno, strerror(errno));
                    return (-1);
                }
                dup2(fd, pla->fd);
                if (fd != pla->fd)
                {
                    close(fd);
                }
            }
        }
        else
        {
            if (fstat(pla->fd, &st) == (-1))
            {
                switch (errno)
                {
                case ENOENT:
                {
                    nCount += snprintf(lname + nCount, sizeof(lname) / sizeof(*lname), "%s%s\0", path, pla->fname);
                    if (*fmt)
                    {
                        nCount += (int)(strftime(lname + nCount, sizeof(lname) / sizeof(*lname), fmt, localtime(&now_secs)));
                    }
                    nCount += snprintf(lname + nCount, sizeof(lname) / sizeof(*lname), "%s\0", ext);
                    snprintf(pla->lname, sizeof(pla->lname) / sizeof(*pla->lname), "%s\0", lname);
                    pla->fd = open(pla->lname, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, DEFFILEMODE);
                    if (pla->fd == (-1))
                    {
                        printf("open log file %s failed. msg: (errno=%d)%s\n", pla->fname, errno, strerror(errno));
                        return (-1);
                    }
                }
                break;
                default:
                {
                    printf("stat log file %s failed. msg: (errno=%d)%s\n", pla->fname, errno, strerror(errno));
                    return (-1);
                }
                break;
                }
            }
            else
            {
                if (st.st_size + pla->size >= limit)
                {
                    if (pla->num > 0)
                    {
                        pla->idx %= (pla->num + 1);
                        pla->idx = (pla->idx <= 0) ? 1 : pla->idx;
                    }
                    snprintf(lname, sizeof(lname) / sizeof(*lname), "%s.%d\0", pla->lname, pla->idx++);
                    close(pla->fd);
                    unlink(lname);
                    if (rename(pla->lname, lname) != 0)
                    {
                        pla->fd = (-1);
                        printf("rename logfile %s -> %s failed msg: (errno=%d)%s\n", pla->lname, lname, errno, strerror(errno));
                        return (-1);
                    }
                    int fd = open(pla->lname, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, DEFFILEMODE);
                    if (fd == (-1))
                    {
                        pla->fd = (-1);
                        printf("open log file %s failed. msg: (errno=%d)%s\n", pla->fname, errno, strerror(errno));
                        return (-1);
                    }
                    dup2(fd, pla->fd);
                    if (fd != pla->fd)
                    {
                        close(fd);
                    }
                }
            }
        }
        return (0);
    }
    __inline static
    int log(const char* fname, int level, const char* fmt, ...)
    {
        va_list arg;
        int data_len = 0;
        long tt_now_usecs = 0;
        struct stat st = { 0 };
        struct tm* tm_now = 0;
        time_t tt_now_secs = 0;
        struct log_arg* pla = 0;
        struct timeval tv = { 0 };
        struct timezone tz = { 0 };
        char date_time[128] = { 0 };
        // 若level大于指定的level,则不打印日志信息
        if (level > get_log_top_level())
        {
            return (-1);
        }
        if ((pla = get_log_arg(fname)) == 0)
        {
            return (-1);
        }
        log_lock();
        memset(pla->data, 0, pla->size);
        gettimeofday(&tv, &tz);
        tt_now_secs = tv.tv_sec;
        tt_now_usecs = tv.tv_usec;
        tm_now = localtime(&tt_now_secs);
        strftime(date_time, sizeof(date_time) / sizeof(*date_time), LOG_FILE_FORMAT, tm_now);
        data_len += snprintf(pla->data + data_len, pla->size, "%s[%s.%ld][%ld][%C]\0",
            get_log_level_color(level), date_time, tt_now_usecs, sys_get_tid(), *get_log_level_name(level));
        va_start(arg, fmt);
        data_len += vsnprintf(pla->data + data_len, pla->size, fmt, arg);
        va_end(arg);
        if (LOG_CF == pla->data[data_len - 1])
        {
            data_len--;
            if (LOG_LR == pla->data[data_len - 1])
            {
                data_len--;
            }
        }
        data_len += snprintf(pla->data + data_len, pla->size, "%s\n\0", get_log_level_color_end());
        check_log(pla, tt_now_secs);
        write(pla->fd, pla->data, data_len);
        if (NEED_LOG_CONS(get_log_cons()))
        {
            //printf("%.*s", data_len, data);
            write(LOG_STDOUT_FILENO, pla->data, data_len);
        }
        log_unlock();
        return (0);
    }
    //#define LOG(NAME,LEVEL,FMT...)       log(#NAME,LEVEL,##FMT)
    #define LOG(NAME,LEVEL,FMT,...)    log(#NAME,LEVEL,FMT,##__VA_ARGS__)
    /////////////////////////////////////////////////////////////////////////////////////////////////
    __inline static
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
    DWORD
    #else
    void*
    #endif
    log_task(void* p) {
        for (size_t i = 0; i < 1000; i++)
        {
            log("main", LOG_INFO, "%s(%d)\n", "I am test!!!!!!", i);
            LOG(main, LOG_WARN, "%s(%d)\n", "I am test!!!!!!", i);
            LOG(main, LOG_TRACE, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_ERROR, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_FATAL, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_WARN, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_TRACE, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_DEBUG, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_INFO, "%s(%d)\n", "I am test!!!!!!", i);
            LOG(main1, LOG_WARN, "%s(%d)\n", "I am test!!!!!!", i);
            LOG(main1, LOG_TRACE, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_ERROR, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_FATAL, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_WARN, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_TRACE, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_DEBUG, "%s(%d)\n", "I am test!!!!!!", i);
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
            //_sleep(1000);
        }
        return (0);
    #else
            usleep(1000000);
    }
        pthread_exit(0);
        return (void*)(0);
    #endif
    }
    __inline static
    int log_test_init()
    {
        const struct log_arg largl[] = {
            {-1,30,0,0,"main","", DATA_SIZE, 0},
            //{-1,30,0,0,"main1","", DATA_SIZE, 0},
        };
        long n_rotatetime = 10;//DEFAULT_LOG_ROTATETIME
        const char* log_fmt = "%Y%m%d%H%M%S";// DEFAULT_LOG_FMT;
        init_log(DEFAULT_LOG_PATH, log_fmt, DEFAULT_LOG_EXT, DEFAULT_LOG_CONS,
            n_rotatetime, LOG_VERBOSE, DEFAULT_LOG_LIMIT_SIZE, largl, sizeof(largl) / sizeof(*largl));
        return 0;
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // >>>>>> copy the content to main.c/main.cpp and build <<<<<<
    //
    // #include <stdio.h>
    // #include "clog.h"
    // 
    // int main(int argc, char ** argv)
    // {
    //     printf("hello from clog_test!\n");
    // 
    //     log_test_main();
    // 
    //     return 0;
    // }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    __inline static
    int log_test_main()
    {
        const struct log_arg largl[] = {
            {-1,30,0,0,"main","", DATA_SIZE, 0},
            {-1,30,0,0,"main1","", DATA_SIZE, 0},
        };
        long n_rotatetime = 10;//DEFAULT_LOG_ROTATETIME
        const char* log_fmt = "%Y%m%d%H%M%S";// DEFAULT_LOG_FMT;
        init_log(DEFAULT_LOG_PATH, log_fmt, DEFAULT_LOG_EXT, DEFAULT_LOG_CONS,
            n_rotatetime, LOG_VERBOSE, DEFAULT_LOG_LIMIT_SIZE, largl, sizeof(largl) / sizeof(*largl));
        for (size_t i = 0; i < 100; i++)
        {
            LOG(main, LOG_INFO, "%s(%d)\n", "I am test!!!!!!", i);
            LOG(main1, LOG_INFO, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_ERROR, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_FATAL, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_WARN, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_TRACE, "%s(%d)\n", "I am test!!!!!!", i);
            log("main", LOG_DEBUG, "%s(%d)\n", "I am test!!!!!!", i);
            log("main1", LOG_INFO, "%s(%d)\n", "I am test!!!!!!", i);
        }
        int ret = 0;
    #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
        DWORD t[4] = { 0 };
        HANDLE h[4] = { 0 };
        for (int i = 0; i < sizeof(t) / sizeof(*t); i++)
        {
            h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)log_task, 0, 0, &t[i]);
        }
        getchar();
        WaitForMultipleObjects(sizeof(t) / sizeof(*t), h, TRUE, INFINITE);
    #else
        pthread_t t[4] = { 0 };
        for (int i = 0; i < sizeof(t) / sizeof(*t); i++)
        {
            ret = pthread_create(&t[i], 0, log_task, 0);
        }
        getchar();
        for (int i = 0; i < sizeof(t) / sizeof(*t); i++)
        {
            pthread_join(t[i], 0);
        }
    #endif
        exit_log();
        return 0;
    }
    #endif // __CLOG_H__
    
  • 相关阅读:
    【MySQL】MySQL如何高效地归档数据
    【MySQL】MySQL导出用户权限信息
    【SQLServer】并行执行计划中的分支和线程
    【MySQL】加速MySQL中大表的删除
    SaToken一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!
    Windows版Redis7.04
    使用 Redis 源码编译发布 Windows 版 Redis For Windows 发行包
    【转】实战!工作中常用到哪些设计模式
    logback日志实践相关
    vue通过代理devServer 解决跨域问题 与 配置代理后打包部署报错404的解决方法
  • 原文地址:https://www.cnblogs.com/xiaohai123/p/16326030.html
Copyright © 2020-2023  润新知