• 售前

  • 售后

热门帖子
入门百科

Log4j 学习笔记

[复制链接]
天亮再走己 显示全部楼层 发表于 2022-1-13 04:09:05 |阅读模式 打印 上一主题 下一主题


1. 快速入门


  1.  public class log4jL {
  2.      public static void main(String[] args) {
  3.          //1 初始化 用于没有配置文件
  4.          BasicConfigurator.configure();
  5.  ​
  6.          //2 生成logger对象
  7.          Logger logger = Logger.getLogger(log4jL.class);
  8.  ​
  9.          //3 日志信息输出
  10.          logger.info("test");
  11.      }
  12.  }
复制代码
从快速入门的案例中可以学到 配置一个日志信息至少需要三步


  • 初始化 读取配置文件
  • 生成 Logger 对象
  • 输出日志信息
接下来由这三个步骤开始讲述


2. 配置信息

2.1 配置文件类型

首先进入Logger类 找到getLogger()
  1.    public
  2.    Logger getLogger(Class clazz) {
  3.      return LogManager.getLogger(clazz.getName());
  4.    }
复制代码
可以看到有一个LoggerManager的对象,点进这个loggerManager类中可以看到Log4j的配置信息以及加载管理方式。
  1.  ​
  2.    /**
  3.     * @deprecated This variable is for internal use only. It will
  4.     * become package protected in future versions.
  5.     * */
  6.    static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
  7.    
  8.    static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";  
  9.    
  10.    /**
  11.     * @deprecated This variable is for internal use only. It will
  12.     * become private in future versions.
  13.     * */
  14.    static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration";
  15.  ​
  16.    /**
  17.     * @deprecated This variable is for internal use only. It will
  18.     * become private in future versions.
  19.     * */
  20.    static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass";
  21.  ​
  22.    /**
  23.    * @deprecated This variable is for internal use only. It will
  24.    * become private in future versions.
  25.    */
  26.    public static final String DEFAULT_INIT_OVERRIDE_KEY =
  27.                                                   "log4j.defaultInitOverride";
复制代码
  1.  ​
复制代码
可以看到 Log4j的配置文件支持上面几种


  • log4j.properties (过时
  • log4j.xml
  • log4j.configuration (过时
  • log4j.configuratorClass(过时
  • log4j.defaultInitOverride(过时
但是我还是用properties 比较方便

在这个类的108行可以看到这些配置文件都是由Loader.getResource的方式加载的,所以只需要将配置文件放在resource的文件夹中即可以被识别到。

2.2 配置文件内容

  1.   // If we have a non-null url, then delegate the rest of the
  2.   // configuration to the OptionConverter.selectAndConfigure
  3.   // method.
  4.   if(url != null) {
  5.  LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
  6.     try {
  7.         OptionConverter.selectAndConfigure(url, configuratorClassName,
  8.     LogManager.getLoggerRepository());
  9.     } catch (NoClassDefFoundError e) {
  10.         LogLog.warn("Error during default initialization", e);
  11.     }
  12.   } else {
  13.  LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
  14.   }
复制代码

还是在LogManager类的下方可以看到如果在类加载过程中找到配置文件,则执行OptionConverter.selectAndConfigure()这个函数,进入这个函数
  1.    static
  2.    public
  3.    void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {
  4.     Configurator configurator = null;
  5.     String filename = url.getFile();
  6.  ​
  7.     if(clazz == null && filename != null && filename.endsWith(".xml")) {
  8.       clazz = "org.apache.log4j.xml.DOMConfigurator";
  9.     }
  10.  ​
  11.     if(clazz != null) {
  12.       LogLog.debug("Preferred configurator class: " + clazz);
  13.       configurator = (Configurator) instantiateByClassName(clazz,
  14.                         Configurator.class,
  15.                         null);
  16.       if(configurator == null) {
  17.           LogLog.error("Could not instantiate configurator ["+clazz+"].");
  18.           return;
  19.       }
  20.     } else {
  21.       configurator = new PropertyConfigurator();
  22.     }
  23.  ​
  24.     configurator.doConfigure(url, hierarchy);
  25.    }
  26.  }
复制代码
在这个函数中,可以看到程序执行的步骤是 识别配置文件的类型 新建一个configurator对象 执行
configurator.doConfigure(url, hierarchy);方法,所以进入这个方法就可以看到配置信息的写法了。由于这个方法是一个抽象的方法,我们需要查看PropertyConfigurator类的具体实现。
进入这个类之后,如果是下载代码源的话,就可以看到非常详细的注释 包括每个参数的作用 配置的方法 还有样例提供,基本上通过阅读这个源码注释就可以完成对配置文件的学习。
2.2.1 RootLogger
定义每个appender的跟输出级别,这里就需要先登记一下日志的输出级别,从上到下递减


  • fatal 严重错误 影响系统运行
  • error 错误信息 不影响系统运行
  • warn 警告信息 可能会发生问题
  • info 运行信息 数据连接等信息
  • debug 调试信息 开发中使用
  • trace 追踪信息 记录查询程序运行
在rootLogger配置中可以配置每一个appender对应的最低日志输出级别 比如在console中输出bebug以上,在文件中输出error以上的日志级别
  1.  # 表示在console输出tarce级别以上的日志信息
  2.  # 格式为  级别,名称
  3.  # 例子
  4.  log4j.rootLogger=trace,console
复制代码
2.2.1.1 自定义logger
设定根logger是遵照所有logger对象的默认配置 自定义logger可以配置某一个logger的个性设置
  1.  /*<p>For non-root categories the syntax is almost the same:
  2.  <pre>
  3.  log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
  4.  </pre>
复制代码

   要注意的是 在PropertyConfigurator这个类中的parseCategory函数 可以看到 在while循环里面 他可以识别多个appendername 也就是说,配置Rootlogger可以向多个appender输出
  2.2.2 Appender
Appender 用于配置日志输出的方向
在代码注释中他提供的格式是
  1.  log4j.appender.appenderName=fully.qualified.name.of.appender.class
复制代码
appenderName可以自己定义 后面是对应输出append方法的全类名。
以下是所有appender的类型,常用的为前三种


  • ConsoleAppender
  • FileAppender
  • JDBCAppender
  • AppenderSkeleton
  • AsyncAppender
  • DailyRollingFileAppender
  • ExternallyRolledFileAppender
  • JMSAppender
  • LF5Appender
  • NTEventLogAppender
  • NullAppender
  • RollingFileAppender
  • SMTPAppender
  • SocketAppender
  • SocketHubAppender
  • SyslogAppender
  • TelnetAppender
  • WriterAppender
  1. # 例子
  2. log4j.appender.console=org.apache.log4j.ConsoleAppender
复制代码
在所有的Appender中有一些特殊的参数 在propertyconfigrator类中都指定了,你可以通过配置文件来设置
  1. /*
  2. # Set appender specific options.
  3. log4j.appender.appenderName.option1=value1
  4. ...
  5. log4j.appender.appenderName.optionN=valueN
  6. </pre>
复制代码
2.2.2.1 WriterAppender
在设置consoleAppender 和FilerAppender的时候我发现了中文都会乱码,但是实际生产情况中并不会,所以应该是我遗漏了哪个设置 结果在父类中找到了对应的设置参数,经过测试之后,也可以在配置文件中以option的格式进行定义
  1. protected boolean immediateFlush = true;
  2. /**
  3.    The encoding to use when writing.  <p>The
  4.    <code>encoding variable is set to <code>null</null> by
  5.    default which results in the utilization of the system's default
  6.    encoding.  */
  7. protected String encoding;
  8. /**
  9.    This is the {@link QuietWriter quietWriter} where we will write
  10.    to.
  11. */
  12. protected QuietWriter qw;
复制代码
2.2.2.2 FileAppender
FileAppender 可以设置的变量为下图。
  1. /**
  2.    The name of the log file. */
  3. protected String fileName = null;
  4. /**
  5.    Do we do bufferedIO? */
  6. protected boolean bufferedIO = false;
  7. /**
  8. * Determines the size of IO buffer be. Default is 8K.
  9. */
  10. protected int bufferSize = 8*1024;
复制代码
以下是例子
  1. log4j.appender.file=org.apache.log4j.FileAppender
  2. log4j.appender.file.layout=org.apache.log4j.PatternLayout
  3. log4j.appender.file.layout.ConversionPattern=[%15.15t] %-5p %l %x - %m%n
  4. # 设置文件的路径 这个文件会在你该程序的根目录下作为基路径 算是一种绝对路径的格式
  5. log4j.appender.file.file=/Doc/logs/log4j.log
  6. log4j.appender.file.encoding=UTF-8
复制代码
同时 FileAppender还发展出了RollingFileAppender、DailyRollingFileAppender 日常使用的话一般使用这两个,这样可以将日志文件分批管理。
RollingFileAppender有两个参数设置的文件的大小和备份数量,同样也可以在配置文件中配置。
  1. /**
  2.    The default maximum file size is 10MB.
  3. */
  4. protected long maxFileSize = 10*1024*1024;
  5. /**
  6.    There is one backup file by default.
  7. */
  8. protected int  maxBackupIndex  = 1;
  9. public
  10. void setMaxFileSize(String value) {
  11.   maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
  12. }
复制代码
在设置文件大小的时候有着这样一个函数,可以自动帮我们把文件大小转化为系统可以识别的大小,比如你写10MB,它可以自动转化为10 * 1024 * 1024,方便用户操作,具体的转换类型就是在toFileSize这文件里面。


2.2.3 Appender.Layout
配置完Appender之后,还需要配置对应的输出格式


  • EnhancedPatternLayout
  • HTMLLayout
  • PatternLayout
  • SimpleLayout
  • TTCCLayout
  1. log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
复制代码
2.2.3.1 PatternLayout
在PropertyConfigrator类中 在介绍这个PatternLayout的时候,提供了一个ConversionPattern参数,表示我们可以通过配置信息,自己配置pattern的格式
  1. /*
  2. # A1's layout is a PatternLayout, using the conversion pattern
  3. # <b>%r %-5p %c{2} %M.%L %x - %m\n</b>. Thus, the log output will
  4. # include # the relative time since the start of the application in
  5. # milliseconds, followed by the level of the log request,
  6. # followed by the two rightmost components of the logger name,
  7. # followed by the callers method name, followed by the line number,
  8. # the nested disgnostic context and finally the message itself.
  9. # Refer to the documentation of {@link PatternLayout} for further information
  10. # on the syntax of the ConversionPattern key.
  11. log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  12. log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
复制代码

我们查看PatternLayout这个类 发现确实有对于格式的定义 包括默认格式和设置自定义格式的方法
  1. /** Default pattern string for log output. Currently set to the
  2.     string <b>"%m%n"</b> which just prints the application supplied
  3.     message. */
  4. public final static String DEFAULT_CONVERSION_PATTERN ="%m%n";
复制代码
PatternLayout 默认的格式 记录
其中 该类提供了一个方法给我们设置 Pattern的格式
  1. /**
  2.    Set the <b>ConversionPattern</b> option. This is the string which
  3.    controls formatting and consists of a mix of literal content and
  4.    conversion specifiers.
  5. */
  6. public
  7. void setConversionPattern(String conversionPattern) {
  8.   pattern = conversionPattern;
  9.   head = createPatternParser(conversionPattern).parse();
  10. }
复制代码
于是,要想设置自己的Pattern 格式,也只需要在配置文件里面配置,以下是源码给的样例。
在PatternLayout源码上方也提供了很多格式可供参考,既提供了各个参数的含义,也提供了几个常用格式。
  1. log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
复制代码
2.3 内置日志记录

找到这个功能的原因是在阅读LogManager源码的时候发现,在LogManager找到的识别url之后要输出的识别记录 ,但是实际运行过程中并没有看到这些信息的输出,于是进入LogLog类查看原因,发现了这个内置日志记录的功能。


  • LogManager 使用到LogLog的代码
  1.   // If we have a non-null url, then delegate the rest of the
  2.   // configuration to the OptionConverter.selectAndConfigure
  3.   // method.
  4.   if(url != null) {
  5. LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
  6.     try {
  7.         OptionConverter.selectAndConfigure(url, configuratorClassName,
  8.       LogManager.getLoggerRepository());
  9.     } catch (NoClassDefFoundError e) {
  10.         LogLog.warn("Error during default initialization", e);
  11.     }
  12.   } else {
  13. LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
  14.   }
  15. } else {
  16.     LogLog.debug("Default initialization of overridden by " +
  17.         DEFAULT_INIT_OVERRIDE_KEY + "property.");
  18. }  
复制代码

发现LogLog类是用于记录Log状态的代码
  1. /**
  2.    This class used to output log statements from within the log4j package.
  3.    <p>Log4j components cannot make log4j logging calls. However, it is
  4.    sometimes useful for the user to learn about what log4j is
  5.    doing. You can enable log4j internal logging by defining the
  6.    <b>log4j.configDebug</b> variable.
  7.    <p>All log4j internal debug calls go to <code>System.out
  8.    where as internal error messages are sent to
  9.    <code>System.err. All internal messages are prepended with
  10.    the string "log4j: ".
  11.    
  12.    @since 0.8.2
  13.    @author Ceki Gülcü
  14. */
复制代码

LogManager使用的段落为
  1. /**
  2.    This method is used to output log4j internal debug
  3.    statements. Output goes to <code>System.out.
  4. */
  5. public
  6. static
  7. void debug(String msg) {
  8.   if(debugEnabled && !quietMode) {
  9.     System.out.println(PREFIX+msg);
  10.   }
  11. }
复制代码

默认情况下的这两个参数都为false
  1. protected static boolean debugEnabled = false;  
  2. /**
  3.    In quietMode not even errors generate any output.
  4. */
  5. private static boolean quietMode = false
复制代码

只需要将debugEnabled设置为true即可.

来源:https://blog.caogenba.net/weixin_47315963/article/details/122433841
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作