log4j几个tips

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

log4j是很常用的日志框架,这里总结几个小知识点:

1. logger是以名称为key,logger为value的形式存储在Hashtable里,所以,logger作为入参不需要传入引用,直接输入名称get即可。

LogFactoryImpl.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/**

* The {@link org.apache.commons.logging.Log} instances that have

* already been created, keyed by logger name.

*/

protected Hashtable instances = new Hashtable();

public Log getInstance(String name) throws LogConfigurationException {

Log instance = (Log) instances.get(name);

if (instance == null) {

instance = newInstance(name);

instances.put(name, instance);

}

return (instance);

}

2. logger的继承关系是根据名称的“.”分割来区分,表现为子logger打印日志时遍历父logger里的appender的进行日志打印。

Category.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public

void callAppenders(LoggingEvent event) {

int writes = 0;

for(Category c = this; c != null; c=c.parent) {

// Protected against simultaneous call to addAppender, removeAppender,...

synchronized(c) {

if(c.aai != null) {

writes += c.aai.appendLoopOnAppenders(event);

}

if(!c.additive) {

break;

}

}

}

if(writes == 0) {

repository.emitNoAppenderWarning(this);

}

}

3.定义模块名为常量,按模块名称取logger,解决项目里包名类名相同日志无法区分问题。

贴代码:
示例一

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

package com.zoo;

import java.util.Properties;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.log4j.PropertyConfigurator;

/**

*

* @author yankai913@gmail.com

* @date 2014年12月22日

*/

public class LogTest {

static final Log log = LogFactory.getLog(LogTest.class);

public static void main(String[] args) {

Properties properties = new Properties();

properties.setProperty("log4j.rootLogger", "DEBUG,stdout");

properties.setProperty("log4j.appender.stdout", "org.apache.log4j.ConsoleAppender");

properties.setProperty("log4j.appender.stdout.layout", "org.apache.log4j.PatternLayout");

properties.setProperty("log4j.appender.stdout.layout.ConversionPattern",

"%d [%t] %-5p %C{6} (%F:%L) - %m%n");

// log4j的继承关系是"."

// log --> com.zoo.LogTest

// log2(父log) --> com.zoo

// log3(父log2) --> com

// 以此类推

// 子logger的继承关系表现是,子logger打印日志时,遍历父logger里的appender

// 进行日志打印,"com.zoo.LogTest"的父子logger分别是:

// "com.zoo.LogTest"的logger -> "com.zoo"的logger -> "root"的logger。

// 以下这句话定义了上述的log2(即父log),导致日志打印2次。

properties.setProperty("log4j.logger.com.zoo", "INFO, stdout");

// 以下这句话定义com.zoo包的logger(即log2)的appender不被继承,日志打印只有一条。

properties.setProperty("log4j.additivity.com.zoo", "false");

PropertyConfigurator.configure(properties);

System.out.println(log);

log.info("Hello World!");

System.out.println("end");

}

}

示例二

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

package com.zoo;

import java.util.Properties;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.log4j.PropertyConfigurator;

/**

*

* @author yankai913@gmail.com

* @date 2014年12月22日

*/

public class LogTest2 {

// 定义公共的logerName,按module分

static final String Module1_LogName = "Module1";

static final String Module2_LogName = "Module2";

public static void main(String[] args) {

Properties properties = new Properties();

properties.setProperty("log4j.rootLogger", "DEBUG,file");

properties.setProperty("log4j.appender.file", "org.apache.log4j.FileAppender");

properties.setProperty("log4j.appender.file.layout", "org.apache.log4j.PatternLayout");

properties.setProperty("log4j.appender.file.layout.ConversionPattern",

"%d [%t] %-5p %c{1} %C{6} (%F:%L) - %m%n");

properties.setProperty("log4j.appender.file.append", "true");

properties.setProperty("log4j.appender.file.file", "logtest2.log");

PropertyConfigurator.configure(properties);

// 比较同名称的log,结果为true,所以log作为入参不需要传入引用,直接get即可。

System.out.println(Module1.log.equals(ServiceImpl_1.log));

System.out.println(Module2.log.equals(ServiceImpl_2.log));

// 按模块搜索查看日志,关键词就是模块名称,即上面的Module1,Module2。

// 解决包名类名完全一样,但是在不同模块的日志查询。

Module1.println();

Module2.println();

ServiceImpl_1.println();

ServiceImpl_2.println();

System.out.println("end");

}

public static class Module1 {

public static Log log = LogFactory.getLog(Module1_LogName);

public static void println() {

log.info("this is module1");

}

}

public static class Module2 {

public static Log log = LogFactory.getLog(Module2_LogName);

public static void println() {

log.info("this is module2");

}

}

public static class ServiceImpl_1 {

public static Log log = LogFactory.getLog(Module1_LogName);

public static void println() {

log.info("this is service");

}

}

public static class ServiceImpl_2 {

public static Log log = LogFactory.getLog(Module2_LogName);

public static void println() {

log.info("this is service");

}

}

}

练习代码看这里


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
5月前
|
存储 大数据 数据处理
【HarmonyOS 5】鸿蒙中的UIAbility详解(三)
本文是鸿蒙中的UIAbility详解系列的最终章。主要针对UIAbility的冷启动和热启动,对于want数据的处理。UIAbility的备份恢复,UIAbility的接续等高级功能的概念和使用讲解。
269 0
|
5月前
|
数据采集 人工智能 搜索推荐
解决语义搜索痛点,基于对比学习的领域特定文本嵌入模型微调实践
本文深入探讨了基于对比学习的嵌入模型微调技术,并通过AI职位匹配的实际案例验证了该方法的有效性。微调后的模型在测试集上实现了100%的准确率,充分证明了针对特定领域进行模型优化的必要性和可行性。
193 5
解决语义搜索痛点,基于对比学习的领域特定文本嵌入模型微调实践
|
5月前
|
Java 计算机视觉
医院证明图片制作生成工具,病假条证明图片生成器, 医院报告单p图软件【仅供娱乐】
报告单P图软件的Java实现,包含多个模块,仅供娱乐用途。代码实现了基本的图像处理和文本叠加功能。
|
负载均衡 Java 应用服务中间件
Gateway服务网关
Gateway服务网关
316 1
Gateway服务网关
|
机器学习/深度学习 人工智能 自然语言处理
大模型强崩溃!Meta新作:合成数据有剧毒,1%即成LLM杀手
在人工智能领域,大型语言模型(LLMs)的快速发展令人瞩目,但递归生成数据可能导致“模型崩溃”。Meta的研究揭示,模型在训练过程中会逐渐遗忘低概率事件,导致数据分布偏差。即使少量合成数据(如1%)也会显著影响模型性能,最终导致崩溃。研究强调保留原始数据的重要性,并提出社区合作和技术手段来区分合成数据和真实数据。论文地址:https://www.nature.com/articles/s41586-024-07566-y
382 2
|
缓存 JavaScript 前端开发
Vue 中动态导入的注意事项
【10月更文挑战第12天】 在 Vue 项目中,动态导入是一种常用的按需加载模块的技术,可以提升应用性能和效率。本文详细探讨了动态导入的基本原理及注意事项,包括模块路径的正确性、依赖关系、加载时机、错误处理、缓存问题和兼容性等,并通过具体案例分析和解决方案,帮助开发者更好地应用动态导入技术。
|
自然语言处理 安全 数据安全/隐私保护
不影响输出质量还能追踪溯源,大模型无偏水印入选ICLR 2024 Spotlight
【6月更文挑战第7天】研究人员提出了一种无偏水印技术,能在不降低大型语言模型(LLMs)输出质量的情况下实现追踪和归属。此方法被ICLR 2024选为Spotlight论文,保证水印不影响模型性能,保护知识产权,防止滥用。无偏水印的挑战包括设计无损模型质量的实现、有效检测及安全防范措施。[论文链接: https://openreview.net/pdf?id=uWVC5FVidc]
281 2
|
存储 关系型数据库 数据库
关系型数据库表结构设计规范化(Normalization)
【5月更文挑战第13天】关系型数据库表结构设计规范化(Normalization)
718 5
基于simulink的双摆运动系统建模与仿真
在MATLAB 2022a的Simulink环境中,构建并仿真了一个双摆运动模型,展示运动效果和轨迹。双摆系统由两个质量不等、长度和转动惯量各异的摆锤构成,受重力影响作非线性周期运动。拉格朗日方程用于描述其动力学,广义坐标θ1和θ2定义系统状态。系统动能T涉及摆锤质量和角度,体现了系统的非线性特性。该模型应用于物理、工程和生物学中的非线性动力学研究。
|
Shell Linux Python
Shell 数学计算:轻松掌握算术运算基本功
在Shell脚本中进行数学计算需借助特定方法。`(())`用于高效整数运算,如`((1+1))`,而`bc`处理小数,如`echo "3.14 + 2.86" | bc`。`let`与`(())`相似,`expr`较繁琐,`declare -i`仅限基础整数运算。使用`bc`时,`scale`定义小数精度。通过这些工具,Shell脚本也能实现复杂的数学计算。
326 0