[经验之谈]程序之中如何通过日志跟踪错误信息

这里写图片描述
##一 摘要

我们在开发一个项目时,尤其在写后台程序时,程序运行过程中发生的各种错误信息都要做监控并及时的错误信息输出,方便我们通过日志来定位到错误出现的地方.及时优化,祛除错误.

那么日志打印语句应该输出哪些信息呢?
##二 日志信息内容
###1. 对于错误、异常情况

应尽量记录尽可能多的“上下文环境”信息.
###2. 函数调用失败信息
如果是函数调用失败,日志中必须包含返回值信息、以及函数调用的相关参数信息。

###3. 错误时场景信息

任何程序在返回错误码前,一定要通过日志记录具体的错误原因,并给出尽量多的场景信息。

##三 日志信息分级

日志信息,也是有分类了,也分轻重缓急,重要,不要之分,这对我们程序出了问题,通过日志来定位问题非常重要.那么等级分哪些呢?

之前写程序时,一般把日志等级分为4个等级:

1.LOG_LEVEL_ERR 错误
2.LOG_LEVEL_WRN 警告
3.LOG_LEVEL_INF 信息
LOG_LEVEL_DBG 调试

typedef enum
{
    LOG_LEVEL_ERR,//错误
    LOG_LEVEL_WRN,//警告
    LOG_LEVEL_INF,//信息
    LOG_LEVEL_DBG//调试
}E_LOG_LEVEL;

####LOG_LEVEL_ERR

该错误发生后程序仍然可以运行,但是极有可能运行在某种非正常的状态下,导致无法完成全部既定的功能。

####LOG_LEVEL_WRN

警告信息,表明程序处理中遇到非法数据或者某种可能的错误,该错误是一过性的、可恢复的,不会影响程序继续运行,程序仍处在正常状态。

####LOG_LEVEL_INF

LOG_LEVEL_INF的主要使用目的报告程序进度和转态信息。一般这种信息都是一过性的,不会大量反复输出。例如:连接商用库成功后,可以打印一条连库成功的信息,便于跟踪程序进展信息。
该级别日志,默认情况下会同时打印到终端和归档到日志文件(下同)。
####LOG_LEVEL_DBG
DEUG的主要使用目的是终端查看和在线调试。
该级别日志,默认情况下会打印到终端输出,但是不会归档到日志文件。因此,一般用于开发者在程序当前启动窗口上,查看日志流水信息。

##具体实现
####Logger.h

#ifndef LOGGER_H
#define LOGGER_H
typedef enum
{
    LOG_LEVEL_ERR,
    LOG_LEVEL_WRN,
    LOG_LEVEL_INF,
    LOG_LEVEL_DBG
}E_LOG_LEVEL;

#define LOG_ERR(X,...) Logger::Instance()->WriteLog(__FILE__, __func__, __LINE__, LOG_LEVEL_ERR, X, ##__VA_ARGS__)
#define LOG_WRN(X,...) Logger::Instance()->WriteLog(__FILE__, __func__, __LINE__, LOG_LEVEL_ERR, X, ##__VA_ARGS__)
#define LOG_INF(X,...) Logger::Instance()->WriteLog(__FILE__, __func__, __LINE__, LOG_LEVEL_INF, X, ##__VA_ARGS__)
#define LOG_DBG(X,...) Logger::Instance()->WriteLog(__FILE__, __func__, __LINE__, LOG_LEVEL_DBG, X, ##__VA_ARGS__)

class Logger
{
public:
    ~Logger();
    static Logger* Instance();
    void WriteLog(const char* fileNamePtr, const char* funcNamePtr,
                  int lineNum, E_LOG_LEVEL level, const char* format, ...);
private:
    Logger();

private:
    static Logger *m_loggerPtr;
    char *m_buffPtr;
    QString m_logFilename;
    QFile m_logFile;
};

#endif // LOGGER_H

####Logger.cpp


#include <iostream>
#include <QString>
#include <QDateTime>
#include <stdio.h>
#include "Logger.h"

#define LOG_BUFF_SIZE 4096

Logger *Logger::m_loggerPtr = NULL;

Logger::Logger()
{
    m_buffPtr = new char[LOG_BUFF_SIZE];
#ifdef Q_OS_WIN32
     m_logFilename = "F:/log.txt";
#else
     m_logFilename = "/DCM/parking/log.txt";
#endif
    m_logFile.setFileName(m_logFilename);
  //  m_logFile.open(QIODevice::Append|QIODevice::WriteOnly);
}

Logger::~Logger()
{
    delete [] m_buffPtr;
}

Logger* Logger::Instance()
{
    if(NULL == m_loggerPtr)
    {
        m_loggerPtr = new Logger();
    }
    return m_loggerPtr;
}

void Logger::WriteLog(const char* fileNamePtr, const char* funcNamePtr,
                      int lineNum, E_LOG_LEVEL level, const char* format, ...)
{
    QString logLevelStr;
    switch(level)
    {
        case LOG_LEVEL_ERR:
            logLevelStr.append("ERR");
            break;
        case LOG_LEVEL_WRN:
            logLevelStr.append("WRN");
            break;
        case LOG_LEVEL_INF:
            logLevelStr.append("INF");
            break;
        case LOG_LEVEL_DBG:
            logLevelStr.append("DBG");
            break;
        default:
            logLevelStr.append("DBG");
    }

    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateTimeStr = dateTime.toString("yyyy/MM/dd hh:mm:ss:zzz");

    /* 组调试信息头 */
    int logLength = sprintf(m_buffPtr, "[%s][%s][%s]: [%s] ",
                            dateTimeStr.toUtf8().data(),fileNamePtr, funcNamePtr,logLevelStr.toUtf8().data());

    va_list valst;
    va_start(valst, format);
    logLength += vsprintf(&m_buffPtr[logLength], format, valst);
    m_buffPtr[logLength] = 0x00;
    printf("%s", m_buffPtr);

    /* log to file */
    va_end(valst);
    m_logFile.open(QIODevice::Append|QIODevice::WriteOnly);
    m_logFile.write(m_buffPtr);
    m_logFile.flush();
    m_logFile.close();

    /* log to terminal, add color */

}

/* END OF FILE */

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图解AI

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值