来自mooon的最简单的日志类CSimpleLogger

/**
 * 单个头文件,可即时独立使用,只要定义了宏NOT_WITH_MOOON,即不依赖于mooon
 * 简单的写日志类,非线程安全,提供按大小滚动功能
 * 不追求功能,也不追求性能,只求简单,若要功能强、性能高,可以使用CLogger
 *
 * 使用方法:
 * 1) 构造一个CSimpleLogger对象
 *    CSimpleLogger logger(".", "test.log", 1024*1024, 10);
 * 2) 调用print方法写日志
 *    logger.print("%s\n", "test");
 */
#ifndef MOOON_SYS_SIMPLE_LOGGER_H
#define MOOON_SYS_SIMPLE_LOGGER_H   

// 只要定义了NOT_WITH_MOOON宏,
// 则本文件和mooon无任何关系,方便集成到自己的代码中
#define NOT_WITH_MOOON
#if !defined(NOT_WITH_MOOON)
#include <sys/config.h>
#endif // NOT_WITH_MOOON   

#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <sstream>
#if !defined(NOT_WITH_MOOON)
SYS_NAMESPACE_BEGIN
#endif // NOT_WITH_MOOON   

/***
  * 万能型类型转换函数
  */
template <typename AnyType>
inline std::string any2string(AnyType any_value)
{
    std::stringstream result_stream;
    result_stream << any_value;   

    return result_stream.str();
}   

/***
  * 取当前时间,和date_util.h有重复,但为保持simple_logger.h的独立性,在所难免
  */
inline void get_current_datetime(char* datetime_buffer, size_t datetime_buffer_size)
{
    struct tm result;
    time_t now = time(NULL);   

    localtime_r(&now, &result);
    snprintf(datetime_buffer, datetime_buffer_size
        ,"%04d-%02d-%02d %02d:%02d:%02d"
        ,result.tm_year+1900, result.tm_mon+1, result.tm_mday
        ,result.tm_hour, result.tm_min, result.tm_sec);
}   

class CSimpleLogger
{
public:
    /***
      * 构造一个CSimpleLogger,并创建或打开日志文件
      * @log_dir 日志存放的目录,不需要以斜杠结尾,目录必须已经存在
      * @filename 日志的文件名,不包含目录部分,
      *           由log_dir和filename共同组成日志文件路径
      * @log_size 每个日志文件的大小,单位为字节数,如果小于1024,则会被强制为1024
      * @log_numer 日志滚动的个数
      * @record_size 单条日志的大小,超过会被截断,单位为字节数,如果小于1024,则会被强制为1024
      */
    CSimpleLogger(const std::string& log_dir
                 ,const std::string& filename
                 ,unsigned int log_size = 1024*1024*100
                 ,unsigned char log_numer = 10
                 ,unsigned short record_size = 8192);
    ~CSimpleLogger();   

    /** 日志文件是否创建或打开成功 */
    bool is_ok() const;   

    /** 输出日志,象printf一样使用,不自动加换行符 */
    void print(const char* format, ...);   

    /** 刷新日志,因为使用FILE是带缓存的 */
    void flush();   

private:
    void reset();    /** 复位状态值 */
    void roll_log(); /** 滚动日志 */

private:
    FILE* _fp;                    /** 当前正在写的日志文件描述符 */
    char* _log_buffer;            /** 存放日志的Buffer */
    int _bytes_writed;            /** 已经写入的字节数 */
    std::string _log_dir;         /** 日志存放目录 */
    std::string _filename;        /** 日志文件名,不包含目录部分 */
    unsigned int _log_size;       /** 单个日志文件的大小 */
    unsigned char _log_numer;     /** 日志滚动的个数 */
    unsigned short _record_size;  /** 单条日志的大小,单位为字节数 */
};   

inline CSimpleLogger::CSimpleLogger(
                     const std::string& log_dir
                    ,const std::string& filename
                    ,unsigned int log_size
                    ,unsigned char log_numer
                    ,unsigned short record_size)
 :_fp(NULL)
 ,_log_buffer(NULL)
 ,_bytes_writed(0)
 ,_log_dir(log_dir)
 ,_filename(filename)
 ,_log_size(log_size)
 ,_log_numer(log_numer)
 ,_record_size(record_size)
{
    std::string log_path = log_dir + std::string("/") + filename;
    _fp = fopen(log_path.c_str(), "a");   

    if (_fp != NULL)
    {
        if (-1 == fseek(_fp, 0, SEEK_END))
        {
            // 失败,将不会写日志
            fclose(_fp);
            _fp = NULL;
        }
        else
        {
            // 取得已有大小
            _bytes_writed = ftell(_fp);   

            // 不能太小气了
            if (_log_size < 1024)
            {
                _log_size = 1024;
            }   

            // 同样不能太小气
            if (_record_size < 1024)
            {
                _record_size = 1024;
            }   

            _log_buffer = new char[_record_size];
        }
    }
}   

inline CSimpleLogger::~CSimpleLogger()
{
    if (_fp != NULL)
        fclose(_fp);   

    delete []_log_buffer;
}   

inline bool CSimpleLogger::is_ok() const
{
    return _fp != NULL;
}   

inline void CSimpleLogger::print(const char* format, ...)
{
    if (_fp != NULL)
    {
        va_list ap;
        va_start(ap, format);   

        char datetime_buffer[sizeof("2012-12-21 00:00:00")]; // 刚好世界末日
        get_current_datetime(datetime_buffer, sizeof(datetime_buffer));   

        vsnprintf(_log_buffer, _record_size, format, ap);
        int bytes_writed = fprintf(_fp, "[%s]%s", datetime_buffer, _log_buffer);
        if (bytes_writed > 0)
            _bytes_writed += bytes_writed;   

        if (_bytes_writed > static_cast<int>(_log_size))
        {
            roll_log();
        }   

        va_end(ap);
    }
}   

inline void CSimpleLogger::roll_log()
{
    std::string new_path; // 滚动后的文件路径,包含目录和文件名
    std::string old_path; // 滚动前的文件路径,包含目录和文件名   

    reset(); // 轮回,一切重新开始   

    // 历史滚动
    for (int i=_log_numer-1; i>0; --i)
    {
        new_path = _log_dir + std::string("/") + _filename + std::string(".") + any2string(i);
        old_path = _log_dir + std::string("/") + _filename + std::string(".") + any2string(i-1);   

        if (0 == access(old_path.c_str(), F_OK))
        {
            rename(old_path.c_str(), new_path.c_str());
        }
    }   

    if (_log_numer > 0)
    {
        // 当前滚动
        new_path = _log_dir + std::string("/") + _filename + std::string(".1");
        old_path = _log_dir + std::string("/") + _filename;
        if (0 == access(old_path.c_str(), F_OK))
        {
            rename(old_path.c_str(), new_path.c_str());
        }
    }   

    // 重新创建
    _fp = fopen(old_path.c_str(), "w+");
}   

inline void CSimpleLogger::reset()
{
    _bytes_writed = 0;   

    if (_fp != NULL)
    {
        fclose(_fp);
        _fp = NULL;
    }
}   

inline void CSimpleLogger::flush()
{
    if (_fp != NULL)
        fflush(_fp);
}   

/***
  * 测试代码
#include "simple_logger.h"
int main()
{
    CSimpleLogger logger(".", "test.log", 10240);
    for (int i=0; i<100000; ++i)
        logger.print("%d ==> abcdefghijklmnopqrestuvwxyz.\n", i);   

    return 0;
}
*/

#if !defined(NOT_WITH_MOOON)
SYS_NAMESPACE_END
#endif // NOT_WITH_MOOON
#endif // MOOON_SYS_SIMPLE_LOGGER_H

本文出自 “飞月” 博客,请务必保留此出处http://mooon.blog.51cto.com/1246491/941081

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索string
, include
, path类
, 滚动
, std
, 滚动日志
, c_str
, 日志滚动
define性能
logger打印日志、logger日志级别、logger记录日志、java打印日志logger、logger日志,以便于您获取更多的相关知识。

时间: 2024-11-02 12:40:13

来自mooon的最简单的日志类CSimpleLogger的相关文章

一个简单php日志类

日志类如下,news目录为当前php文档根目录下子目录. <?phpif( ! defined('BASEPATH') ) {    define ('BASEPATH', $_SERVER['DOCUMENT_ROOT'].'/news/');}require_once BASEPATH.'config/config.inc.php';require_once BASEPATH.'config/constants.php';define ("LOG_PATH", $config

C# 日志类

本文代码来自:http://www.oschina.net/code/snippet_1181744_27513 作者:ebola 该类的作用:简单日志类,队列实现.可按天 周 月 年 大小分割文件. 代码如下: using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System

改进后的日志类CLogger

在原有的基础上增加了module_name,表示模块名,当一个系统由多模块组成时,输出的日志将更加清晰,使用方法,以MOOON-agent中的为例: /** 不要修改下面的常量值,而应当通过对应的方法去修改 * 这些常量值主要是方便多模块共享,故放在这个公有头文件当中 */enum{ LOG_LINE_SIZE_MIN = 256, /** 日志行最小长度 */ LOG_LINE_SIZE_MAX = 32768, /** 日志行最大长度(32K) ,最大不能超过64K,因为使用2字节无符号整数

介绍一个简单的JavaScript类框架

  这篇文章主要介绍了一个简单的JavaScript类框架,有助于初学者理解JS类的创建与继承,需要的朋友可以参考下 在写work-in-progress JavaScript book一书时,对于javascript继承体系,我花费了相当的时间,并在该过程中研究了各种不同的模拟经典类继承的方案.这些技术方案中,我最为推崇的是base2与Prototype的实现. 从这些方案中,应该能提炼出一个具有其思想内涵的框架,该框架须具有简单.可重用.易于理解并无依赖等特点,其中简单性与可用性是重点.以下

ASP日志类和判断是否包涵JS脚本类

ASP日志类  代码如下 复制代码 Function WriteLogReg(Error_lerong)     On Error Resume Next     LogFileTmp = "Error.log"     Set tmpFsoR = Server.CreateObject("scripting.filesystemobject")     Set tmpLogR = tmpFsoR.OpentextFile(Server.MapPath(LogFil

C# 简易异步日志类 [ C# | Log | TextWriterTraceListener ]

前言 即使是小型项目,也需要日志的功能,这里就不讨论Log4Net之类的框架,提供一个异步的.控制台输出+日志文件输出的简易日志帮助类.   正文 一.帮助类文件Logger.cs //=========================================//// 作 者:农民伯伯// 邮 箱:over140@gmail.com// 博 客:http://over140.cnblogs.com/// 时 间:2009-7-16// 描 述:日志类,注意需要在日志记录的目录给用户写入权

Linux下一个简单的日志系统的设计及其C代码实现

1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息,包括:变量名称及其值.消息结构定义.函数返回值及其执行情况.脚本执行及调用情况等.通过阅读日志文件,我们能够较快地跟踪程序流程,并发现程序问题.因此,熟练掌握日志系统的编写方法并快速地阅读日志文件,是对一个软件开发工程师的基本要求. 本文详细地介绍了Linux下一个简单的日志系统的设计方法,并给出了其C代码实现.本文为相关开发项目Linux下软

php 简单简洁分页类

php 简单简洁分页类 <?php /**  *-------------------------翻页类----------------------*  */ class PageClass {  private $myde_count;       //总记录数  var $myde_size;        //每页记录数  private $myde_page;        //当前页  private $myde_page_count;  //总页数  private $page_ur

PHP简单数据库操作类实例【支持增删改查及链式操作】_php技巧

本文实例讲述了PHP简单数据库操作类.分享给大家供大家参考,具体如下: 在进行项目开发时,数据库是必不可少的东西了.但是很多时候却又对数据库SQL语句的繁杂而感到头疼.提供一个我自己使用的数据库操作类(模型Model),供大家使用.支持增.删.改.查,支持链式操作,代码不到100行,非常小巧方便,很适合小项目的快速部署使用. /** * * @Authot: summer * * @E-mail: wenghang1228@me.com * * @Data: 2015-02-06 * * @Pr