Logback - 以编程方式设置日志文件名

发布于 2024-12-10 23:33:17 字数 1100 浏览 0 评论 0原文

我正在使用 logback,并且尝试在 Java 程序中以编程方式设置日志文件名(类似于 以编程方式设置 Logback Appender 路径),我尝试按如下方式调整该解决方案:

在 logback-test.xml 中:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>log/${log_file_name}.log</file>
  ...

然后再次在我的 Java 程序中:

String logFileName = "" + System.currentTimeMillis(); // just for example
System.setProperty("log_file_name", logFileName);

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
ContextInitializer ci = new ContextInitializer(lc);
lc.reset();
try
{
    // I prefer autoConfig() over JoranConfigurator.doConfigure() so I
    // wouldn't need to find the file myself.
    ci.autoConfig();
}
catch (JoranException e)
{
    // StatusPrinter will try to log this
    e.printStackTrace();
}
StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

但是结果是两个日志,一个完整且命名正如我想要的,例如“1319041145343.log”,另一个是空的,名为“log_file_name_IS_UNDEFINED.log”。如何阻止创建另一个空日志文件?

I am using logback, and I am trying to set the log file name programmatically within my Java program (similar to Setting Logback Appender path programmatically), and I tried to adapt that solution as follows:

In logback-test.xml:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>log/${log_file_name}.log</file>
  ...

And then again in my Java program:

String logFileName = "" + System.currentTimeMillis(); // just for example
System.setProperty("log_file_name", logFileName);

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
ContextInitializer ci = new ContextInitializer(lc);
lc.reset();
try
{
    // I prefer autoConfig() over JoranConfigurator.doConfigure() so I
    // wouldn't need to find the file myself.
    ci.autoConfig();
}
catch (JoranException e)
{
    // StatusPrinter will try to log this
    e.printStackTrace();
}
StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

However the result is two logs, one full and named as I wanted, e.g., "1319041145343.log", and the other is empty and named "log_file_name_IS_UNDEFINED.log". How do I stop this other empty log file from being created?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

摘星┃星的人 2024-12-17 23:33:18

看起来记录器被初始化了两次。第一次,可能是在应用加载且无法解析 ${log_file_name} 时。如果您使用 -Dlog_file_name=*something* 启动应用程序,如果它创建另一个名为 *something* 的日志文件,您可以验证此行为

Looks like the logger is initialized twice. First time, probably when the app loads and it couldn't resolve the ${log_file_name}. If you start the app with -Dlog_file_name=*something* you can verify this behavior if it creates another log file with the name *something*

追风人 2024-12-17 23:33:18

这里肯定已经有一些有用的答案,而且 OP 似乎很满意,这很棒。但我来寻找最初提出的更精确问题的答案,我认为这个问题是“如何以编程方式设置现有文件附加器的文件名?”。由于我不会详细说明的原因,这就是我必须弄清楚该怎么做。

我确实弄清楚了,没有太多大惊小怪。如果有人来寻找我正在寻找的相同答案,这里是如何以编程方式设置现有 FileAppender 的日志文件名

String logFileName = "" + System.currentTimeMillis(); // just for example

LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
ch.qos.logback.classic.Logger logbackLogger = (ch.qos.logback.classic.Logger) loggerContext.getLogger("ROOT");
FileAppender<ILoggingEvent> fileAppender = (FileAppender<ILoggingEvent>)logbackLogger.getAppender("FILE");
fileAppender.setFile(logFileName);

请注意,此代码在“ROOT”记录器中查找附加程序,该记录器是所有伐木工。您通常会在此处找到现有附加程序,通过更改此记录器,您可以更改系统中所有日志记录的行为,这通常是您想要的。

Already some useful answers here for sure, and it seems that the OP was satisfied, which is great. But I came looking for an answer to the more precise question that was posed originally, which I believe was "how do I set the file name of AN EXISTING file appender programmatically?". For reasons I won't go into, this is what I had to figure out how to do.

I did figure it out without too much fuss. In case someone comes along looking for the same answer I was seeking, here is how to set the log file name of an existing FileAppender programmatically

String logFileName = "" + System.currentTimeMillis(); // just for example

LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
ch.qos.logback.classic.Logger logbackLogger = (ch.qos.logback.classic.Logger) loggerContext.getLogger("ROOT");
FileAppender<ILoggingEvent> fileAppender = (FileAppender<ILoggingEvent>)logbackLogger.getAppender("FILE");
fileAppender.setFile(logFileName);

Note that this code looks for the appender in the "ROOT" logger, the logger that is the parent of all loggers. This is where you'll usually find existing appenders, and by making changes to this logger, you are changing the behavior of all of the logging in your system, which is usually what you want .

枕头说它不想醒 2024-12-17 23:33:17

我相信以下内容更接近您想要的。

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.util.StatusPrinter;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;

public class Main {
  public static void main(String[] args) {
    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

    FileAppender fileAppender = new FileAppender();
    fileAppender.setContext(loggerContext);
    fileAppender.setName("timestamp");
    // set the file name
    fileAppender.setFile("log/" + System.currentTimeMillis()+".log");

    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    encoder.setContext(loggerContext);
    encoder.setPattern("%r %thread %level - %msg%n");
    encoder.start();

    fileAppender.setEncoder(encoder);
    fileAppender.start();

    // attach the rolling file appender to the logger of your choice
    Logger logbackLogger = loggerContext.getLogger("Main");
    logbackLogger.addAppender(fileAppender);

    // OPTIONAL: print logback internal status messages
    StatusPrinter.print(loggerContext);

    // log something
    logbackLogger.debug("hello");
  }
}

如果您只需要添加日志文件名的时间戳,logback 已经支持时间戳元素。因此,您实际上根本不需要任何自定义代码。

I believe the following to be closer to what you want.

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.util.StatusPrinter;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;

public class Main {
  public static void main(String[] args) {
    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

    FileAppender fileAppender = new FileAppender();
    fileAppender.setContext(loggerContext);
    fileAppender.setName("timestamp");
    // set the file name
    fileAppender.setFile("log/" + System.currentTimeMillis()+".log");

    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    encoder.setContext(loggerContext);
    encoder.setPattern("%r %thread %level - %msg%n");
    encoder.start();

    fileAppender.setEncoder(encoder);
    fileAppender.start();

    // attach the rolling file appender to the logger of your choice
    Logger logbackLogger = loggerContext.getLogger("Main");
    logbackLogger.addAppender(fileAppender);

    // OPTIONAL: print logback internal status messages
    StatusPrinter.print(loggerContext);

    // log something
    logbackLogger.debug("hello");
  }
}

If all you need is to add a timestamp of the log file name, logback already supports the timestamp element. Thus, you actually don't need any custom code at all.

一个人练习一个人 2024-12-17 23:33:17

要根据运行时属性将日志消息分离/筛选到不同的文件,您可能需要使用 ch .qos.logback.classic.sift.SiftingAppender

简而言之,这允许您使用 ${userid}.log 设置 FileAppender (或任何其他附加程序),其中 ${userId} 基于MDC(映射诊断上下文) (例如,MDC.put("userid", "Alice");)。有关完整示例,请参阅第一个链接。

To separate/sift log messages to different files depending on a runtime attribute, you might want to use ch.qos.logback.classic.sift.SiftingAppender.

In a nutshell, this allows you to set up a FileAppender (or any other appender) with <file>${userid}.log</file> where ${userId} is substituted based on the MDC (Mapped Diagnostic Context) (e.g., MDC.put("userid", "Alice");). See the first link for the complete example.

贩梦商人 2024-12-17 23:33:17

这是您可以忽略那些额外文件创建的方法。下面是配置文件

<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<!-- "application-name" is a variable -->
<File>c:/logs/${application-name}.log</File>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %p %t %c - %m%n</Pattern>
</layout>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>  

这是java部分,

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset(); // override default configuration
// inject the name of the current application as "application-name"
// property of the LoggerContext
context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION);
jc.doConfigure("/path/to/the/above/configuration/file.xml");

我从这里得到的http://logback.qos.ch/faq.html#sharedConfiguration

Here is what you can do to ignore those extra file creation.Below is the config file

<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<!-- "application-name" is a variable -->
<File>c:/logs/${application-name}.log</File>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %p %t %c - %m%n</Pattern>
</layout>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>  

Here is the java part,

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset(); // override default configuration
// inject the name of the current application as "application-name"
// property of the LoggerContext
context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION);
jc.doConfigure("/path/to/the/above/configuration/file.xml");

I got this from here http://logback.qos.ch/faq.html#sharedConfiguration

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文