模块一----------基于log4J模式的日志系统

开发环境

Centos 7.6
vim
Visual Studio 2022
Makefile
gdb
g++ 9

系统思想

仿照log4j的模式进行开发

格式如下:

	 %m--->消息体
	 %p--->日志级别
	 %r--->启动的时间
	 %c--->日志名称
	 %t--->进程id
	 %n--->回车
	 %d--->时间
	 %f--->文件名
	 %l--->行号

将日志抽象成Logger(日志器),LogAppender(输出落地点),LogFormat(日志格式器)三大模块。
Logger, 对外使用的类,输入的日志级别大于等于Logger的日志,才会被真正写入。可以有多个Logger,不同的logger,记录不同类型的日志,比如将系统框架日志和业务逻辑日志分离。
LogAppender, 定义日志的输出落地点,目前实现了控制台日志(StdoutLogAppender),文件日志(FileLogAppender).两种类型。拥有自己的日志级别和日志格式,可以灵活定义不同的输出。主要用于区分日志级别,将error日志,单独输出到一个文件,以防被其他类型的日志淹没
Formater,日志格式,通过字符串自定义日志的格式,仿printf格式。可以灵活定义日志格式

系统介绍

系统最大特点就是具有独立性,可以作为不同模块的日志系统,之间互不影响。可以实现不同模块之间的日志分离,系统还支持流式日志风格写日志和格式化风格写日志,支持日志格式自定义,日志级别,多日志分离等等功能 流式日志使用:LOG_INFO(logger) << “this is a log”; 格式化日志使用:LOG_FMT_INFO(logger, “%s”, “hello log”); 支持时间,线程id,线程名称,日志级别,日志名称,文件名,行号等内容的自由配置

系统主体框架

在这里插入图片描述

系统日志展示

控制台流式日志输出
在这里插入图片描述
文件格式日志输出
在这里插入图片描述

核心代码展示

日志系统最为核心的就是解析用户输出的日志格式,其算法和C标准库中printf的算法相似

void Formattor::Init() {
	string nstr;
	for (size_t i = 0;i < m_pattern.size();i++) {
		if (m_pattern[i] != '%') {
			nstr.append(1, m_pattern[i]);
			continue;
		}
		//其实还是一个%
		if ((i + 1) < m_pattern.size()) {
			if (m_pattern[i + 1] == '%') {
				nstr.append(1, '%');
				continue;
			}
		}
		size_t n = i + 1;
		int fmt_staus = 0;
		int fmt_beign = 0;
		string str;
		string fmt;
		while (n < m_pattern.size()) {
			//遇见空格
			if (!isalpha(m_pattern[n]) && m_pattern[n] != '}' && m_pattern[n] != '{') {
				str = m_pattern.substr(i + 1, n - i - 1);
				break;
			}
			if (fmt_staus == 0) {
				if (m_pattern[n] == '{') {
					//字符串分割
					str = m_pattern.substr(i + 1, n - i - 1);
					fmt_staus = 1;
					fmt_beign = n;
					n++;
					continue;
				}
			}
			else if (fmt_staus == 1) {
				if (m_pattern[n] == '}') {
					//字符串分割
					fmt = m_pattern.substr(fmt_beign + 1, n - fmt_beign - 1);
					//	cout << "#" << fmt << endl;
					fmt_staus = 0;
					++n;
					break;
				}
			}
			++n;
			if (n == m_pattern.size()) {
				if (str.empty()) {
					str = m_pattern.substr(i - 1);
				}
			}
		}
		if (fmt_staus == 0) {
			if (!nstr.empty()) {
				vec.push_back(make_tuple(nstr, string(), 0));
				nstr.clear();
			}
			str = m_pattern.substr(i + 1, n - i - 1);
			//解析日志将日志存储在数组中
			vec.push_back(make_tuple(str, fmt, 1));
			i = n - 1;
		}
		else if (fmt_staus == 1) {
			cout << "pattern parse error" << m_pattern << "-" << m_pattern.substr(i) << endl;
			//格式错误
			vec.push_back(make_tuple("<<pattern_error>>", fmt, 0));
		}
	}
	if (!nstr.empty()) {
		vec.push_back(make_tuple(nstr, "", 0));

	}
	for (auto& i : vec) {
		if (get<2>(i) == 0) {
			m_items.push_back(Formattor::Item::ptr(new stringitemforma(get<0>(i))));
		}
		else {
			auto it = formar_item.find(get<0>(i));
			if (it == formar_item.end()) {
				m_items.push_back(Formattor::Item::ptr(new stringitemforma("<<error_format %" + get<0>(i) + ">>")));
			}
			else {
				m_items.push_back(it->second(get<1>(i)));

			}

		}
		//cout << "(" << get<0>(i) << ")-(" << get<1>(i) << ")-(" << get<2>(i)<<")" << endl;
	}
	//	cout << m_items.size() << endl;
}

管理所有的日志器,并且可以通过解析类模板,动态创建或修改日志器相关的内容(日志级别,日志格式,输出落地点等等)

//日志管理器
class LogMessage {
public:
	LogMessage() {
		//默认为stdout
		root.reset(new Logger());
		root->AddAppender(LogAppender::ptr(new stdoutAppender()));
	}
	map<string, Logger::ptr> mp;
	Logger::ptr root;
public:
	//获取日志器
	Logger::ptr getlogger(string name);
	void Init();
}

日志落地点抽象。目前只实现了输出到控制台(StdoutAppender)和输出到文件(FileAppender),LogAppender可以拥有自己的LogFormat。
一个日志器,可以对应多个LogAppender。也就是说写一条日志,可以落到多个输出,并且每个输出的格式都可以不一样。
Appender有单独的日志级别,可以自定义不同级别的日志,输出到不同的Appender,常用于将错误日志统一输出到一个地方。

//日志输出器
class LogAppender {
public:
	typedef shared_ptr<LogAppender> ptr;
	virtual~LogAppender() {}
	virtual void Log(shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) = 0;
	//设置日志格式
	void setformattor(Formattor::ptr val) ;
	//返回日志格式
	Formattor::ptr getformattor() { return m_forattor; }
	void setlevel(LogLevel::Level level);
	LogLevel::Level getlevel();

protected:
	LogLevel::Level m_level;//日志级别
	Formattor::ptr m_forattor;//输出日志格式//将用于输出日志
};
//控制台输出器
class stdoutAppender :public LogAppender {
public:
	typedef shared_ptr<stdoutAppender> ptr;
	virtual void Log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event);
};
//文件输出器
class FileAppender :public LogAppender {
public:
	FileAppender(string filename);
	typedef shared_ptr<FileAppender> ptr;
	void Log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event);
   //重新打开文件,打开文件成功返回true
	bool repoen();
private:
	string m_file_name;//日志文件
	ofstream m_filestream;//文件流
};

日志器,包含一个日志格式器,一个root Logger,N个LogAppender提供日志写入方法。根据日志器的配置格式和内容。将日志写到对应的地方

//日志器
class Logger :public enable_shared_from_this<Logger> {
public:
	typedef shared_ptr<Logger> ptr;
	Logger(string _name = "root");
	void Log(LogLevel::Level level, LogEvent::ptr event);
	void AddAppender(LogAppender::ptr appender);//添加日志
	void DelAppendrt(LogAppender::ptr appender);//删除日志

	//日志级别
	void debug(LogEvent::ptr event);
	void info(LogEvent::ptr event);
	void warn(LogEvent::ptr event);
	void error(LogEvent::ptr event);
	void fatal(LogEvent::ptr event);
	LogLevel::Level getlevel() { return m_level; }//获取leve
	void setleve(LogLevel::Level level) { m_level = level; }
	void setformat(Formattor::ptr fmt) { format = fmt; }
	string getname()const { return m_name; }

private:
	string m_name;             //日志名称
	LogLevel::Level m_level;	  //日志级别(满足这各级别就会输出)
	list<LogAppender::ptr> m_appender;  //日志列表
	Formattor::ptr format;
};

日志格式器,执行日志格式化,负责日志格式的初始化。
解析日志格式,将用户自定义的日志格式,解析为对应的Item。
格式解析:
%t : 线程id ThreadIdFormatItem
%N : 线程名称 ThreadNameFormatItem
%F : 协程id FiberIdFormatItem
%p : 日志级别 LevelFormatItem
%c : 日志名称 NameFormatItem
%f : 文件名 FilenameFormatItem
%l : 行号 LineFormatItem
%m : 日志内容 MessageFormatItem

//日志格式控制
class Forater{
public:
	typedef shared_ptr<Formattor> ptr;
	Forater(string pattern) ;
	//通过pattern解析出item中的信息

	//日志解析
	string format(shared_ptr<Logger> logger, LogLevel::Level leve, LogEvent::ptr event);
public:
	//日志解析子模块
	class Item {
	public:
		typedef shared_ptr<Item> ptr;
		virtual ~Item() {}
		//日志解析
		virtual void format(ostream& os, shared_ptr<Logger> logger, LogLevel::Level leve, LogEvent::ptr event) = 0;
	};
	//对pattern解析
	void Init();
private:
	string m_pattern;//输出的是日志得一部分
	vector<Item::ptr> m_items;
};

日志事件的封装,将要写的日志,填充到LogEvent中。填充完毕之后,写入到对应的logger中

//日志事件
class LogEvent {
public:
	//默认构造函数
	LogEvent() {};
	typedef shared_ptr<LogEvent> ptr;
	void format(const char* fmt, ...);
	void format(const char* fmt, va_list al);
	//获取日志器
	shared_ptr<Logger> GetLogger() { return logger; }
	stringstream& getSS() { return m_ss; }

	//获取日志级别
	LogLevel::Level GetLevel() { return level; }

private:
	//日志器
	shared_ptr<Logger> logger;
	//日志级别
	LogLevel::Level level;

	const char* m_file = NULL;     		 //文件名
	int32_t m_line = 0;				 	 //行号
	uint32_t m_please = 0;           	  //程序运行时间(毫秒)
	uint32_t m_threadid = 0;           //线程id
	uint64_t m_time = 0;               //时间戳
	stringstream m_ss;				  //格式流	

};
日志级别
enum Level {
		UNKNOW = 0,
		DEBUG = 1,
		INFO = 2,
		WARN = 3,
		ERROR = 4,
		FATAL = 5
	};
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Lerx 网站内容管理系统 v5.5 更新日志 1.修复了短信验证码发送时间间隔无效,可能引起连续恶意验证的问题。 2.来访IP记录,如果来源Reffer和当前地址相同,则不记录Reffer。 3.记录来访IP记录的总访问数。(注:若间隔6小时以上,则重新记录) 4.解决站点手机监控平台中url地址不自动断行引起的美观和左右滑摆问题。 5.增加QQ帐号互联登录方式 6.增加微博帐号互联登录方式 7.增加微信帐号互联登录方式 8.网站的手机监控端增加最新评论列表 9.修复评论不记录客户端IP的问题 10.完全启动后5秒执行首页及栏目的静态文件生成、更新。 11.更换富文本编辑器。 12.发布文章的同时可以上传附件。 13.美化网站自动地图(导航)页。 14.更新了IP地址库(纯真)。 Lerx 网站内容管理系统软件简介 Lerx 网站内容管理系统是一套开源免费的基于Java环境的,采用Spring 4和Hibernate 5 开发的各类门户网站内容管理。采用了低耦合式模块化设计。拥有版本更新自动提醒、智能网站模板市场、文件上传防重、智能裁剪等等独特优势功能。 Lerx CMS V5版(以下简称V5版)采用了基于Java的SpringMVC框架,抛弃了V2-V3版本使用的Struts 2。SpringMVC框架更加安全、稳定。ORM持久化框架依旧使用Hibernate,版本为5.4。开发时采用的数据库为MySQL。是一个能快速上手的开源的网站建设CMS。 SpringMVC Hibernate ORM MySQL Hibernate Search(Apache Lucence) IK中文分词 Log4J ... 主要采用Jquery 1.9.1,使用Layui 2模块化前端框架。 Jquery Layui JSON Ajax Lerx 网站内容管理系统主要功能 前后台用户及角色管理、站点管理、栏目、文章管理、模板管理、自由开放的模板市场、系统监测、调查(投票及点赞)、评论、全面的日志系统、来访登记统计系统。 实现功能(标记★的为关键的或独特的内容) 1.跨平台系统,能无差别的运行于Windows、Linux、Mac OS等操作系统。 2.★拥有云端版本更新通知服务器,可在后台获取官方的最新版本及每次更新的版本更新信息,及时通知用户进行升级。 3.★验证码支持短信、邮箱发送。短信模板已支持国内常用短信平台的接口,支持腾讯云短信接口。配置简单。 4.支持最高权限后台登录的限制登录IP功能。IP或IP范围设置灵活,可以同时设多个IP及IP范围的任间组合。 5.在忘记后台登录密码时,支持临时配置文件获取用户名和密码登录模式。 6.用户组(角色)权限利用鼠标点击在权限细节上打勾即可完成。能对用户组(角色)整体禁用,能查看各用户组的会员人数。 7.★前后台用户登录均支持首次不显示验证码模式。拥有多次失败登录后限时锁定及解锁机制。 8.用户模块记录用户的注册时间IP,每次登录的IP、手机、邮箱等细节,能通过简单的标记查看用户的密码修改情况。。每次登录均记录在日志文件中。 9.★可以使用用户名、邮箱、手机号码任一方式进行登录。具有忘记密码功能,可以通过短信、邮箱发送验证码给用户,验证后修改登录密码。 10.★具有深度的来访记录及统计功能。站点、每个栏目、每篇文章均拥有独立的来访IP记录节点模块,可完成从站点开放以来各个节点的年度、季度、月度、星期、天、小时的统计和报表功能。能获得站点、每个栏目、每篇文章的来访IP量及阅读量,能生成独立的报表。 11.每篇文章都各自拥有独立的调查模块,可以完成点赞功能或赞成、反对和中立的页面操作。★能获得每篇文章的调查统计数据及详细报表。 12.每篇文章均拥有独立的评论模块。支持匿名评论,支持评论后审核通过模式,支持文章发布者管理评论,支持前台管理员评论管理。 13.拥有强壮的栏目树功能,移动、排序栏目非常方便。 14.可以设定各个栏目是否对外面,及限制访问IP。可以一键关闭栏目下的所有文章的调查、评论。可以采用聚集功能配合模块调整栏目在前台页面上的栏目及栏目下文章显示。 15.★具有智能裁剪功能。能获知图片的中央矩片后裁剪后并按照设定的尺寸进行缩放。能对指定栏目设定特定的裁剪宽度和高度。能对指定栏目下的文章设定原图上传。 16.★每个栏目可拥有独立的私有特定的HTML,可以无损后显示在栏目的显示页中。 17.可以设定栏目的静态化文件夹名。 18.首页、栏目页、文章页均采用HTML静态化措施。静态化文件为真实静态方式。文章在审核通过时会自动生成HTML文件,在取消审核状态后会自动删除HTML文件。能
Lerx 开源网站内容管理系统(CMS)是一个以Java+MySQL进行开发的内容管理系统源码。 一.简介 1.跨平台设计,能无差别运行于Windows、Linux、MacOS等系统平台。 2.采用了安全、稳定的基于Java的SpringMVC框架。 3.数据库ORM持久化框架使用Hibernate 5.4,通过加载不同的驱动程序支持MySQL、Oracle、Microsoft SQL Server等数据库。 4.具有云端软件版本更新提示服务器。 5.具有能提供一键式打包、解包、上传、下载、无配置式布署的自由开放的智能模板市场。 6.提供手机端模块进行服务器及网站状态实时状态监测。 7.提供了防重式文件上传模块。通过上传文件去重复功能,避免了不必要的空间资源浪费。 8.支持市场上大多数的短信平台,支持腾讯云短信。支持验证码的短信和邮件发送一键式切换。 9.HTML页面真静态化技术,页面刷新快。 10.具有独立的投票、点赞、访问统计、结构树状图模块,全面的日志系统,低耦合设计。绑定到不同的对象即能完成相应的功能。 11. 具有专辑功能,可以实现站中站、博客、个人主页、工作室、专题等功能  。   12. 支持LayEditor、WangEditor、KindEditor、UEditor、CKEditor 4&5 五种在线富文本编辑器  。 13.具有整站全文搜索功能。可同时搜索门户和专辑内文章。亦可在专辑频道和单个专辑中定向搜索。 14.拥有类似于微信和微博的消息系统,可以向当前用户四种类型的消息:1.涨粉消息。即专辑被其它用户关注产生的消息。2.关注对象发文消息。3.评论消息。4.私密消息。 二.主要框架 后端:SpringMVC + Hibernate ORM + MySQL + Hibernate Search(Apache Lucence) + IK中文分词 + Log4J + ... 前端:Jquery + Layui + wangEditor/KindEditor + JSON + Ajax 三.实现功能(标记★的为关键的或独特的内容) 1.★拥有云端版本更新通知服务器,可在后台获取官方的最新版本及每次更新的版本更新信息,及时通知用户进行升级。 2.★验证码支持利用短信或邮箱发送。短信模板已支持国内常用短信平台的接口,支持腾讯云短信接口。配置简单。 3.针对整个站点能一键开启或关闭用户注册、投票、评论、匿名评论、评论自动审核、文章自动审核功能。 4.具有简单高效的用户和角色(用户组)管理功能,用户权限利用鼠标点击在权限细节上打勾即可完成。能对用户组(角色)整体禁用,能查看各用户组的会员人数。 5.★前后台用户登录均支持首次不显示验证码模式。拥有多次失败登录后限时锁定及解锁机制。 6.★可以使用用户名、邮箱、手机号码或利用QQ、微信、微博等社交平台互联任一方式进行登录。每个用户拥有一个身份名片,在PC端和移动端智能排版显示。可以通过二维码分享名片。名片包含了用户的绝大部分信息和改密码等操作按钮。 7.具有忘记密码功能,可以通过短信、邮箱发送验证码给用户,验证后修改登录密码。 8.可以对用户进行禁言操作。禁言后用户不可发文和评论。 9.用户模块记录用户的注册时间IP,每次登录的IP、手机、邮箱等细节,能通过简单的标记查看用户的密码修改情况。。每次登录均记录在日志文件中。 10.拥有强壮的栏目树状结构功能,移动、排序栏目非常方便。 11.每个栏目均能设置独立的模板,可以使用不同栏目及主站能呈现不同的网站风格。可以采用聚集功能配合模板调整栏目在前台页面上的栏目及栏目下文章显示。 12.每个栏目均有独立的访问统计、评论等模块,能查看每个栏目(包含下级栏目及栏目下的文章)的访问量。可以一键关闭栏目下的所有文章的调查、评论。 13.★每个栏目可拥有独立的私有特定的HTML,可以无损后出现在栏目的HTML代码中。 14.可以设定栏目的静态化文件夹名。 15.可以设定各个栏目是否对外开放,能针对不同的栏目设置不同的来访IP限制。 16.文章发布可以附加多种图片、视频、附件。支持正文内的多图片同时上传。支持精简标题、附加标题,支持文章强制URL跳转。 17.★所有上传的文件均有除重功能。即同一文件在当前站点中只会上传一次,后面的上传结果会获取以前的上传文件URL,避免过多的文件上传挤压服务器的有限空间。 18.★具有智能文章标题截取功能。 19.★具有智能裁剪功能。能智能感知图片(包括JPG、PNG、GIF等格式)的中央矩片后裁剪后并按照设定的尺寸进行缩放。能对指定栏目设定特定的裁剪宽度和高度。能对指定栏目下的文章设定原图上传。 20.每篇文章都各自拥有独立的调查模块,可以完成点赞功能或赞成、反对和中立的页面操作。★能获得每篇文
iBase4J是Java语言的分布式系统架构。使用Spring整合的开源框架。 iBase4J特点: 使用Maven对项目进行模块化管理,提高项目的易开发性、扩展性。 系统包括4个子系统系统管理Service、系统管理Web、业务Service、业务Web。 系统管理:包括用户管理、权限管理、数据字典、系统参数管理等等。 业务相关:您的业务开发。 可以无限的扩展子系统,子系统之间使用Dubbo或MQ进行通信。 iBase4J主要功能: 1、数据库:Druid数据库连接池,监控数据库访问性能,统计SQL的执行性能。数据库密码加密,加密方式请查看PropertiesUtil,decryptProperties属性配置需要解密的key。 2、持久层:mybatis持久化,使用MyBatis-Plus优化,减少sql开发量;aop切换数据库实现读写分离。Transaction注解事务。 3、MVC:基于spring mvc注解,Rest风格Controller。Exception统一管理。 4、调度:Spring+quartz, 可以查询、修改周期、暂停、删除、新增、立即执行,查询执行记录等。 5、基于session的国际化提示信息,职责链模式的本地语言拦截器,Shiro登录、URL权限管理。会话管理,强制结束会话。 6、缓存和Session:注解redis缓存数据;shiro实现redis分布式session同步,重启服务会话不丢失。 7、多系统交互:Dubbo,ActiveMQ多系统交互,ftp/sftp/fastdafs发送文件到独立服务器,使文件服务分离。 8、前后端分离:没有权限的文件只用nginx代理即可。 9、日志log4j2打印日志,业务日志和调试日志分开打印。同时基于时间和文件大小分割日志文件。 10、QQ、微信、新浪微博第三方登录。 11、工具类:excel导入导出,汉字转拼音,身份证号码验证,数字转大写人民币,FTP/SFTP/fastDFS上传下载,发送邮件,redis缓存,加密等等。 技术选型: 核心框架:Sring boot + Spring Framework + Dubbo + ibase4j-common 安全框架:Apache Shiro 任务调度:Spring + Quartz 持久层框架:MyBatis + MyBatis-Plus 数据库连接池:Alibaba Druid 缓存框架:Redis 会话管理:Spring-Session 日志管理:SLF4J、Log4j2 前端框架:Angular JS + Bootstrap + Jquery 启动说明: * 项目依赖activemq、Redis和ZooKeeper服务。 * 使用nginx代理UI:修改配置里的UI目录后重启nginx。 * 启动方法: SysServiceApplication.java SysWebApplication.java * 测试环境打包命令: clean package -P test * 生产环境打包命令: clean package -P product

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值