当前位置: 首页 > news >正文

自定义日志打印功能--C++

一、介绍

日志是计算机程序中用于记录运行时事件和状态的重要工具。通过记录关键信息和错误情况,日志可以帮助程序开发人员和维护人员追踪程序的执行过程,排查问题和改进性能。 在软件开发中,日志通常记录如下类型的信息:

  1. 事件信息:记录程序执行过程中的重要事件,如启动和关闭,特定操作完成等。
  2. 错误信息:记录发生的错误和异常情况,包括错误类型、位置和可能的原因。
  3. 警告信息:记录潜在问题或需要注意的情况,但不是严重到导致程序崩溃的程度。
  4. 调试信息:记录用于调试程序的详细信息,方便追踪程序状态和流程。 日志的记录一般包括时间戳、事件类型、事件描述等信息。这些记录可以写入文件、数据库或发送至远程服务器,以供后续分析和监控。

通过分析日志,开发人员可以了解程序的运行情况,发现潜在问题并优化程序性能。因此,良好的日志记录和管理对于确保软件运行稳定、故障排除和改进具有重要意义。

二、日志级别

#define DEBUG 0
#define NORMAL 1
#define WARNING 2
#define ERROR 3
#define FATAL 4const char* gLevelMap[]={"DEBUG","NORMAL","WARNING","ERROR","FATAL"
};

日志级别是一种对日志信息进行分类和标记的方法,用于帮助程序员和系统管理员更好地理解和处理日志信息。日志级别包括DEBUG(调试)、NORMAL(正常)、WARNING(警告)、ERROR(错误)和FATAL(严重错误)五种级别。通过宏定义将这五种级别编号化,可以在程序中方便地使用对应的编号来表示不同的日志级别。同时,通过使用一个数组 gLevelMap[],可以将编号与日志级别名对应起来,从而方便地在程序中根据编号找到对应的级别名,并进行相应的处理。这种分类和标记的方法有助于开发人员根据日志级别进行精细化的调试、监控和错误处理。

三、日志函数logMessage

// 日志打印 文件名
#define LOGFILE "./LOG.log"void logMessage(int level, const char* format, ...)
{char timebuffer[1024];// 日志时间time_t timestamp = time(nullptr);tm* ltm = localtime(&timestamp);int year = ltm->tm_year+1900;int month = ltm->tm_mon+1;int day = ltm->tm_mday;int hour = ltm->tm_hour;int min = ltm->tm_min;int second = ltm->tm_sec;snprintf(timebuffer, sizeof timebuffer, "[%s][%04d-%02d-%02d %02d:%02d:%02d]",gLevelMap[level], year, month, day, hour, min, second);// 日志内容char logBuffer[1024];va_list args;  // 初始化参数信息va_start(args, format);  // 初始化参数列表vsnprintf(logBuffer, sizeof logBuffer, format, args);  //日志内容存入logBuffe中va_end(args);// 显示器打印日志信息printf("%s %s\n", timebuffer, logBuffer);// //往文件打印// FILE *fp = fopen(LOGFILE, "a");// fprintf(fp, "%s %s\n", timebuffer, logBuffer);// fclose(fp);
}   

logMessage(int level, const char* format, ...)该日志函数level代表日志等级、format表示日志内容、...是可变参数列表。这样使日志的使用跟printf()使用方法类似。

timebuffer:用于存储日志的等级和时间信息。

logBuffer:用于存储日志的内容。

内部解析

#define LOGFILE "./LOG.log"定义的一个日志文件,可以设置把打印的日志显示到这个文件里面。

    // 日志时间time_t timestamp = time(nullptr);tm* ltm = localtime(&timestamp);int year = ltm->tm_year+1900;int month = ltm->tm_mon+1;int day = ltm->tm_mday;int hour = ltm->tm_hour;int min = ltm->tm_min;int second = ltm->tm_sec;

time_t timestamp = time(nullptr);获取系统当前的时间戳。

tm* ltm = localtime(&timestamp);将时间戳转为用本地时区表示,比如Thu Aug 23 09:12:05 2012

localtime():原型(struct tm *localtime(const time_t *timer))localtime的函数声明。返回的是tm结构体,其结构如下:

struct tm {int tm_sec;         /* 秒,范围从 0 到 59*/int tm_min;         /* 分,范围从 0 到 59*/int tm_hour;        /* 小时,范围从 0 到 23*/int tm_mday;        /* 一月中的第几天,范围从 1 到 31 */int tm_mon;         /* 月份,范围从 0 到 11*/int tm_year;        /* 自 1900 起的年数 */int tm_wday;        /* 一周中的第几天,范围从 0 到 6 */int tm_yday;        /* 一年中的第几天,范围从 0 到 365 */int tm_isdst;       /* 夏令时*/    
};

所以通过调用ltm对象的内部变量,就可以获取想要的时间格式。例如int year = ltm->tm_year+1900;可以获取当前时间的年份(+1900是因为获取的年份是从1900年至今的)。

snprintf(timebuffer, sizeof timebuffer, "[%s][%04d-%02d-%02d %02d:%02d:%02d]",gLevelMap[level], year, month, day, hour, min, second);

使用格式化输出字符串snprintf函数,我们可以将当前的日志级别、时间,按指定的格式输入到缓冲区timebuffer中。这样,timebuffer中的内容就如同这个样子:([日志级别][时间])

    // 日志内容char logBuffer[1024];va_list args;  // 初始化参数信息va_start(args, format);  // 初始化参数列表vsnprintf(logBuffer, sizeof logBuffer, format, args);  //日志内容存入logBuffe中va_end(args);

format是传进来的日志内容,因为logMessge()有一个可变的参数列表...。所以需要va_list args;va_start(args, format);

va_list是C语言中的一个宏定义,用于表示一个变长参数列表。它是一个指向变长参数列表的指针,可以通过宏va_start、va_arg和va_end对变长参数列表进行访问和操作。在函数中需要接收不定数量的参数时,可以使用va_list来处理这些参数。

va_start:它的作用是初始化一个va_list类型的变量,使其指向可变参数列表的第一个参数。

vsnprintf()用于向一个字符串缓冲区打印格式化字符串,且可以限定打印的格式化字符串的最大长度。用它把日志的内容输入到logBuffer中。

va_end:是一个宏,用于结束使用 va_start 和 va_arg 宏定义的可变参数列表。它的作用是清理 va_list 类型变量,以便该变量可以被再次使用。

	// 打印日志信息printf("%s %s\n", timebuffer, logBuffer);// //往文件打印FILE *fp = fopen(LOGFILE, "a");fprintf(fp, "%s %s\n", timebuffer, logBuffer);fclose(fp);

打印日志内容有两种方式,一种是向显示器上打,一种是往文件里写。通过将timebufferlogBuffer把时间和内容组合到一起,就是一条完整的日志信息了。

测试

简单的测试,将日志信息打印在显示器上:

#include "log.hpp"int main()
{printf("ssd\n");int n=1;logMessage(DEBUG, "测试日志信息输出%d", n);return 0;
}

四、完整代码

#pragma once
#include <iostream>
#include <cstring>
#include <time.h>
#include <stdarg.h>
#include <cstdio>//日志级别
#define DEBUG 0
#define NORMAL 1
#define WARNING 2
#define ERROR 3
#define FATAL 4const char* gLevelMap[]={"DEBUG","NORMAL","WARNING","ERROR","FATAL"
};// 日志打印 文件名
#define LOGFILE "./LOG.log"void logMessage(int level, const char* format, ...)
{char timebuffer[1024];// 日志时间time_t timestamp = time(nullptr);tm* ltm = localtime(&timestamp);int year = ltm->tm_year+1900;int month = ltm->tm_mon+1;int day = ltm->tm_mday;int hour = ltm->tm_hour;int min = ltm->tm_min;int second = ltm->tm_sec;snprintf(timebuffer, sizeof timebuffer, "[%s][%04d-%02d-%02d %02d:%02d:%02d]",gLevelMap[level], year, month, day, hour, min, second);// 日志内容char logBuffer[1024];va_list args;  // 初始化参数信息va_start(args, format);  // 初始化参数列表vsnprintf(logBuffer, sizeof logBuffer, format, args);  //日志内容存入logBuffe中va_end(args);// 打印日志信息printf("%s %s\n", timebuffer, logBuffer);// //往文件打印// FILE *fp = fopen(LOGFILE, "a");// fprintf(fp, "%s %s\n", timebuffer, logBuffer);// fclose(fp);
}   

 

相关文章:

自定义日志打印功能--C++

一、介绍 日志是计算机程序中用于记录运行时事件和状态的重要工具。通过记录关键信息和错误情况&#xff0c;日志可以帮助程序开发人员和维护人员追踪程序的执行过程&#xff0c;排查问题和改进性能。 在软件开发中&#xff0c;日志通常记录如下类型的信息&#xff1a; 事件信…...

gitlab注册无中国区电话验证问题

众所周知gitlab对中国区不友好&#xff0c;无法直接注册&#xff0c;页面无法选择86的手机号进行验证码发送。 Google上众多的方案是修改dom&#xff0c;而且时间大约是21年以前。 修改dom&#xff0c;对于现在的VUE、React框架来说是没有用的&#xff0c;所以不用尝试。 直接看…...

【JAVA基础题目练习】----第二天

JAVA基础题目练习 1. 键盘录入数据&#xff0c;比较大小2. 代码重构&#xff08;简化代码&#xff0c;少做判断&#xff09;3. 键盘录入月份的值&#xff0c;输出对应的季节4. 获取三个数据中的最大值使用IF语句5. 用switch语句实现键盘录入月份&#xff0c;输出对应的季节6. 求…...

node.js和npm的安装与环境配置(2023最新版)

目录 安装node.js测试是否安装成功测试npm环境配置更改环境变量新建系统变量 安装node.js 1、进入官网下载&#xff1a;node.js官网 我选择的是windows64位的&#xff0c;你可以根据自己的实际情况选择对应的版本。 2、下载完成&#xff0c;安装。 打开安装程序 接受协议 选…...

ke14--10章-1数据库JDBC介绍

注册数据库(两种方式),获取连接,通过Connection对象获取Statement对象,使用Statement执行SQL语句。操作ResultSet结果集 ,回收数据库资源. 需要语句: 1Class.forName("DriverName");2Connection conn DriverManager.getConnection(String url, String user, String…...

【IC验证】perl脚本——分析前/后仿用例回归情况

目录 1 脚本名称 2 脚本使用说明 3 nocare_list文件示例 4 脚本执行方法 5 postsim_result.log文件示例 6 脚本代码 1 脚本名称 post_analysis 2 脚本使用说明 help&#xff1a;打印脚本说明信息 命令&#xff1a;post_analysis help 前/后仿结束后&#xff0c;首先填…...

Ansible适合的场景是什么?

Ansible将编排与配置管理、供应和应用程序部署结合并统一在一个易于使用的平台上。Ansible的一些主要场景包括: 配置管理&#xff1a;集中配置文件管理和部署是Ansible的一个常见场景。 应用程序部署&#xff1a;当使用Ansible定义应用程序&#xff0c;并使用Ansible Tower管…...

Flink 读写 HBase 总结

前言 总结 Flink 读写 HBase 版本 Flink 1.15.4HBase 2.0.2Hudi 0.13.0官方文档 https://nightlies.apache.org/flink/flink-docs-release-1.17/zh/docs/connectors/table/hbase/ Jar包 https://repo1.maven.org/maven2/org/apache/flink/flink-sql-connector-hbase-2.2/1…...

记录一次chatGPT人机协同实战辅助科研——根据词库自动进行情感分析

有一个Excel中的一列&#xff0c;读取文本判断文本包含积极情感词.txt和消极情感词.txt的个数&#xff0c;分别生成两列统计数据 请将 ‘your_file.xlsx’ 替换为你的Excel文件名&#xff0c;Your Text Column’替换为包含文本的列名。 这个程序首先读取了积极和消极情感词&…...

Java_LinkedList链表详解

目录 前言 ArrayList的缺陷 链表 链表的概念及结构 链表的种类 1.单向或双向 2.带头或不带头 3.循环或不循环 LinkedList的使用 什么是LinkedList LinkedList的使用 LinkedList的构造 LinkedList的其他常用方法介绍 LinkedList的遍历 ArrayList和LinkedList的…...

MacOS 12 开放指定端口 指定ip访问

MacOS 12 开放指定端口 指定ip访问 在 macOS 上开放一个端口&#xff0c;并指定只能特定的 IP 访问&#xff0c;你可以使用 macOS 内置的 pfctl&#xff08;Packet Filter&#xff09;工具来实现。 以下是一些基本的步骤&#xff1a; 1、 编辑 pf 配置文件&#xff1a; 打开 /…...

LeedCode刷题---滑动窗口问题

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、长度最小的子数组 题目链接&#xff1a;长度最小的子数组 题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。…...

leetcode24. 两两交换链表中的节点

题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#…...

TCP传输层详解(计算机网络复习)

介绍&#xff1a;TCP/IP包含了一系列的协议&#xff0c;也叫TCP/IP协议族&#xff0c;简称TCP/IP。该协议族提供了点对点的连接机制&#xff0c;并将传输数据帧的封装、寻址、传输、路由以及接收方式都予以标准化 TCP/IP的分层模型 在讲TCP/IP协议之前&#xff0c;首先介绍一…...

【LuatOS】简单案例网页点灯

材料 硬件&#xff1a;合宙ESP32C3简约版&#xff0c;BH1750光照度模块&#xff0c;0.96寸OLED(4P_IIC)&#xff0c;杜邦线若干 接线&#xff1a; ESP32C3.GND — OLED.GND — BH1750.GND ESP32C3.3.3V — OLED.VCC — BH1750.VCC ESP32C3.GPIO5 — OLED.SCL — BH1750.SCL E…...

百度APP iOS端包体积50M优化实践(七)编译器优化

一. 前言 百度APP iOS端包体积优化系列文章的前六篇重点介绍了包体积优化整体方案、图片优化、资源优化、代码优化、无用类优化、HEIC图片优化实践和无用方法清理&#xff0c;图片优化是从无用图片、Asset Catalog和HEIC格式三个角度做深度优化&#xff1b;资源优化包括大资源…...

STM32-新建工程(标准库)

目录 STM32F10x新建工程&#xff08;标准库&#xff09; 移植文件夹 新建工程 添加启动文件和必需文件 在工程中加载新添加的文件 在工程中添加文件路径 在工程中添加main函数 添加lib库 添加必需文件 添加宏定义 点亮LED&#xff08;标准库&#xff09; STM32F10x新…...

Android集成科大讯飞语音识别与语音唤醒简易封装

目录 一、语音唤醒部分 1、首先在科大讯飞官网注册开发者账号 2、配置唤醒词然后下载sdk 3、选择对应功能下载 4、语音唤醒lib包全部复制到工程目录下 5、把语音唤醒词文件复制到工程的assets目录 6、复制对应权限到AndroidManifest.xml中 7、唤醒工具类封装 二、语音识…...

【Linux】telnet命令使用

telnet命令 telnet命令用于使用telnet协议与另一台主机进行通信。如果在没有主机参数的情况下调用telnet&#xff0c;它将进入命令模式&#xff0c;由其提示&#xff08;telnet>&#xff09;指示。在这种模式下&#xff0c;它接受并执行下面列出的命令。如果使用参数调用它…...

VCG 标记使用(BitFlags)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 对于网格的每个单形,我们都有一个称为BitFlags的组件,该组件存储固定大小的32位向量,用于各种需求。管理这些标志的相关类:vcg::tri::UpdateFlags与vcg::tri::UpdateSelection。主要的标记有:删除标记、边界标记…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...