免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3315 | 回复: 5
打印 上一主题 下一主题

linux下是否有日志库,请大家介绍一下,谢谢 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-06 13:44 |只看该作者 |倒序浏览
5可用积分
我想写程序时,打印自己的日志,大家给点建议,谢谢

自己实现了一个,没怎么测试,需要的拿去用吧。后果自负。

头文件

#ifndef __MYLOG_H_
#define __MYLOG_H_
#include <pthread.h>
#include <stdint.h>
/*
* Name: MyLog - The Mutil-Thread Logger
* Features:
* (1) Mutil-Thread
* (2) 支持日志文件大小限制, 最大 1G
* (3) 支持4个日志级别:
*     -0- DEBUG, 调试模式
*     -1- ROUTN, 正常模式
*     -2- ALARM, 警告,本次会话可能无法正常服务
*     -3- FATAL, 致命问题,程序已经无法运行
* (4) 支持日志切分,切分支持时,只需要把日志文件重命名即可
*/
class MyLog
{
        private:
                static const uint32_t LogNameMaxLen = 128;
                static const uint32_t LogFileMaxSize = 1024*1024*1024;
                static const uint32_t TimeBuffMaxLen = 32;
                static const uint32_t LogContentMaxLen = 2048;
                static const char* const strLogName;
                static const char* LevelTag[];
                uint32_t m_level; // 日志级别
                uint32_t m_file_size; // 日志大小
                char m_path[LogNameMaxLen]; // 日志路径
                int m_log_fd; // 当前日志的文件描述符
                pthread_mutex_t m_lock; // 写文件锁
                char m_timebuff[TimeBuffMaxLen];
                const char* GetTimeNow();
                void LogFileSizeCheck();
                void LogFileCheckOpen(); // 如果不存在就创建
                void Mkdirs(const char* dir); // 递归的创建文件夹
                void WriteNByte(int fd, const char* buff, uint32_t size);
                MyLog();
        public:
                enum { DEBUG = 0, ROUTN, ALARM, FATAL, };
                MyLog(const uint32_t level, const uint32_t size, const char* logname);
                ~MyLog();
                void WriteLog(const uint32_t mylevel, const char* file,
                                const uint32_t line, const char* func, const char *format, ...);
};

#endif

代码文件

#include <stdarg.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "MyLog.h"

const char* const MyLog::strLogName = "./log/"PROJNAME".log";
const char* MyLog::LevelTag[] = { "DEBUG", "ROUTN", "ALARM", "FATAL", };

MyLog :: MyLog(const uint32_t level, const uint32_t size, const char* logname)
{
        pthread_mutex_init(&m_lock, NULL);
        m_level = (level > (uint32_t)FATAL) ? (uint32_t)ROUTN : level;
        m_file_size = size > LogFileMaxSize ? LogFileMaxSize : size;
        const char* mylogname = (logname[0] != 0 ) ? logname : strLogName;
        snprintf(m_path, sizeof(m_path), "%s", mylogname);
        m_log_fd = -1;
        LogFileCheckOpen();
        fprintf(stderr, "MyLog Level[%u] OL[%u] Path[%s] Size[%u] fd[%d]\n",
                        m_level, level, m_path, m_file_size, m_log_fd);
}

void MyLog :: WriteNByte(const int fd, const char* buff, const uint32_t size)
{
        int32_t  left   = size;
        uint32_t offset = size;
        while (left > 0)
        {
                int len = write(fd, buff+offset-left, left);
                if (len == -1 || len == 0)
                {
                        return;
                }
                left -= len;
        }
}
void MyLog :: WriteLog(const uint32_t mylevel, const char* file,
                const uint32_t line, const char* func, const char *format, ...)
{
        pthread_mutex_lock(&m_lock);
        LogFileCheckOpen();
        va_list args;
        va_start(args, format);
        char buff[LogContentMaxLen];
        uint32_t pos = 0;
        if (mylevel < m_level) {
                pthread_mutex_unlock(&m_lock);
                return;
        }
        uint32_t  level = (mylevel > (uint32_t)FATAL) ? (uint32_t)FATAL : mylevel;
        pos =  snprintf(&buff[pos], LogContentMaxLen-pos, "%s ", LevelTag[level]);
        pos += snprintf(&buff[pos], LogContentMaxLen-pos, "%s ", GetTimeNow());
        pos += snprintf(&buff[pos], LogContentMaxLen-pos, "%lu ", pthread_self());
        pos += snprintf(&buff[pos], LogContentMaxLen-pos, "file[%s:%u] ", file, line);
        pos += snprintf(&buff[pos], LogContentMaxLen-pos, "func[%s] ", func);
        vsnprintf(&buff[pos], LogContentMaxLen-pos-2, format, args);
        va_end(args);
        pos = strlen(buff);
        buff[pos] = '\n';
        buff[pos+1] = '\0';
        WriteNByte(m_log_fd, buff, pos+1);
        pthread_mutex_unlock(&m_lock);
}

void MyLog :: LogFileCheckOpen()
{
        char  tmppath[LogNameMaxLen];
        char  curpath[LogNameMaxLen];
        if (NULL == getcwd(curpath, sizeof(curpath))) {
                fprintf(stderr, "Get Current Dir Fail.\n");
                return;
        }
        char* p = NULL;
        // 不存在就创建日志文件, 兼顾初始化和运行时的状态
        // 第一步,创建文件夹
        if (0 != access(m_path,F_OK)) {
                snprintf(tmppath, sizeof(tmppath), "%s", m_path);
                p = strrchr(tmppath, '/');
                if (p) {
                        *p = '\0';
                        Mkdirs(tmppath);
                }
                if (m_log_fd >= 0){
                        close(m_log_fd);
                        m_log_fd = -1;
                }
        }
        chdir(curpath);
        // 第二步,创建文件
        if (m_log_fd < 0) {
                m_log_fd = open(m_path, O_WRONLY|O_CREAT|O_APPEND, S_IRWXU|S_IRWXG|S_IRWXO);
                if (m_log_fd < 0) {
                        fprintf(stderr, "FILE[%s:%u] create logfile[%s] fail. msg[%m]\n",
                                        __FILE__, __LINE__, m_path);
                        while(0 != raise(SIGKILL)){}
                }
        }
}

void MyLog :: LogFileSizeCheck()
{
        struct stat st;
        fstat(m_log_fd, &st);
        if (st.st_size + LogContentMaxLen > m_file_size)
        {
                ftruncate(m_log_fd, 0);
        }
}

const char* MyLog :: GetTimeNow()
{
        time_t now;
        struct tm mytm;

        m_timebuff[0] = 0;
        time(&now);
        localtime_r(&now, &mytm);
        mytm.tm_year += 1900;
        sprintf(m_timebuff, "%02d-%02d %02d:%02d:%02d",
                        mytm.tm_mon+1, mytm.tm_mday, mytm.tm_hour, mytm.tm_min, mytm.tm_sec);

        return  m_timebuff;
}

void MyLog :: Mkdirs(const char* dir)
{
        char tmp[1024];
        char *p = NULL;
        if (strlen(dir) == 0 || dir == NULL) {
                return;
        }
        memset(tmp, '\0', sizeof(tmp));
        strncpy(tmp, dir, strlen(dir));
        if (tmp[0] == '/') {
                p = strchr(tmp + 1, '/');
        } else {
                p = strchr(tmp, '/');
        }

        if (p) {
                *p = '\0';
                mkdir(tmp, 0777);
                chdir(tmp);
        } else {
                mkdir(tmp, 0777);
                chdir(tmp);
                return;
        }
        Mkdirs(p + 1);
}

[ 本帖最后由 科技牛 于 2009-11-8 15:59 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-11-06 14:38 |只看该作者
cd /var/log/

里面好多日志

论坛徽章:
0
3 [报告]
发表于 2009-11-06 14:44 |只看该作者
/etc/syslog.conf 可以修改你想要的东西

论坛徽章:
0
4 [报告]
发表于 2009-11-07 00:26 |只看该作者

回复 #1 科技牛 的帖子

呵呵。表示关注。我也在写一个日志程序

论坛徽章:
0
5 [报告]
发表于 2009-11-07 10:23 |只看该作者
man syslog

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
6 [报告]
发表于 2009-11-08 12:24 |只看该作者
如果仅是业务日志,还是不用syslog了。一般记本地流水日志,打时间戳,控制文件大小和日志备份,100行左右代码就可封装完毕。如果一定要用现成的高级日志功能,那就google log4cpp
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP