• 波奇学Linux:日志


    日志信息

    日志:日志时间+日志等级+日志内容+文件的名称和代号

    日志等级示范:Info:常规消息

                              Warning:报警信息

                               Error:必要严重了,可能要立即处理

                               Fatal:致命的

                                Debug:调试

    日志时间获取

    1. time_t t= time(nullptr);// 获取时间戳
    2. struct tm* ctime=localtime(&t);// 将时间戳转换为年月日
    3. //tm是个结构体,里面保存时间戳转换的年月日
    4. //打印时间
    5. printf("[%s][%d-%d-%d %d:%d:%d]",levelToString(level).c_str(),\
    6. ctime->tm_year+1900,ctime->tm_mon+1,ctime->tm_mday,\
    7. ctime->tm_hour,ctime->tm_min,ctime->tm_sec)

     

    注意点:

    tm->year是从1900年开始算所以要加上1900,月份从0开始算tm_mon+1

    levetToString是将int转换成string类型

     日志等级处理

    defin 信息的值,再转变成%s方便打印

    1. #define Info 0
    2. #define Debug 1
    3. #define Warning 2
    4. #define Error 3
    5. #define Fatal 4
    6. #define Size 1024
    7. std::string levelToString(int level)
    8. {
    9. switch(level)
    10. {
    11. case Info:return "Info";
    12. case Debug: return "Debug";
    13. case Warning: return "Debug";
    14. case Error: return "Debug";
    15. case Fatal: return "Debug";
    16. default: return "None";
    17. }
    18. }

     处理可变参数

    1. //n 表示前两个参数,当参数数量大于n时,只算从左到右的两个,参数从右往左压栈
    2. int sum(int n,...)
    3. {
    4. va_list s;//char* 类型指针帮助我们找到可变类型参数
    5. va_start(s,n); //让 s指向n的地址 s=&n+1
    6. //va_start是宏
    7. // 可变参数至少有一个具体的实参、
    8. int sum=0;
    9. while(n)
    10. {
    11. sum+=va_arg(s,int);//s指向的可变参数类型,int表示参数类型 ,每次返回一个值
    12. n--;
    13. }
    14. va_end(s);//使得s为nullptr
    15. return sum;
    16. }

     视解图

     s=&n+1// 可变参数需要一个实参来确定位置,参数压栈是从左往右的

     消息函数代码实现

    1. // level表示等级,format表示格式,...表示日志等级
    2. void logmessage(int level,char* format, ...)
    3. {
    4. char leftbuffer[Size];
    5. time_t t= time(nullptr);// 获取时间戳
    6. struct tm* ctime=localtime(&t);// 将时间戳转换为年月日
    7. //snpritf,后面的参数和printf类似,按某种格式输出参数,前面是输出位置,输入到数组leftbuffer中
    8. snprintf(leftbuffer,sizeof(leftbuffer),"[%s][%d-%d-%d %d:%d:%d]",levelToString(level).c_str(),\
    9. ctime->tm_year+1900,ctime->tm_mon+1,ctime->tm_mday,\
    10. ctime->tm_hour,ctime->tm_min,ctime->tm_sec);
    11. va_list s;// va_list就是封装的char*
    12. va_start(s,format);//s=&format+1
    13. char rightbuffer[Size];
    14. //vsnprinft,用来处理可变参数,后面的参数和printf类似,按某种格式输出参数,前面是输出位置,输入到数组righttbuffer中
    15. vsnprintf(rightbuffer,sizeof(rightbuffer),format,s);//传入一个s指向第一个可变参数的指针
    16. // 默认部分+自定义部分
    17. char logtxt[Size*2];
    18. //拼接字符串
    19. snprintf(logtxt,sizeof(logtxt),"%s %s\n",leftbuffer,rightbuffer);
    20. printf("%s",logtxt);
    21. }

     运用示例:代替perror

    日志输入到文件

    1. class Log
    2. {
    3. public:
    4. Log()
    5. {
    6. printMethod=Screen;
    7. path="./log/";
    8. }
    9. void Enable(int method)
    10. {
    11. printMethod=method;
    12. }
    13. std::string levelToString(int level)
    14. {
    15. ......
    16. }
    17. void logmessage(int level,char* format, ...)
    18. {
    19. ......
    20. printLog(level,logtxt);
    21. }
    22. void printLog(int level,const std::string& logtxt)
    23. {
    24. switch(printMethod)
    25. {
    26. case Screen:
    27. std::cout<
    28. break;
    29. case Onefile:
    30. printOneFile(LogFile,logtxt);
    31. break;
    32. case Classfile:
    33. printClassFile(level,logtxt);
    34. break;
    35. default:
    36. break;
    37. }
    38. }
    39. void printOneFile(const std::string& logname,const std::string& logtxt)
    40. {
    41. std::string _logname=path+logname;
    42. //打开创建文件
    43. int fd=open(_logname.c_str(), O_WRONLY|O_CREAT|O_APPEND,0666);
    44. if(fd<0) return ;
    45. write(fd,logtxt.c_str(),logtxt.size());
    46. close(fd);
    47. }
    48. void printClassFile(int level,const std::string &logtxt)
    49. {
    50. //将Warning/Fatal等分开
    51. std::string filename = LogFile;
    52. filename+=".";
    53. filename+=levelToString(level); //"log.txt.Debug/Warning/Fatal"
    54. printOneFile(filename,logtxt);
    55. }
    56. ~Log()
    57. {}
    58. private:
    59. int printMethod; //确定输出位置
    60. std::string path; //输出地址
    61. };

  • 相关阅读:
    HTML区块、布局
    数学建模算法与应用 插值与拟合
    通过数(判断一个数是否在集合M中)
    git push出现git@github.com: Permission denied (publickey) 解决办法
    Python 组合序号
    Android自定义控件(二) Android下聚光灯实现
    React之React成功运行Hello React页面
    Vue插值语法、指令语法、单向绑定、双向绑定(详细解释)
    智能感应门改造工程
    启动-异常学习笔记-代码导读
  • 原文地址:https://blog.csdn.net/Bagayalu1234567/article/details/136362143