当前位置: 首页 > 知识库问答 >
问题:

如何为log4j设置单独的日志记录流?

慕容安易
2023-03-14

说我有一堂这样的课:

public class MyClass
{

    private Logger log = LoggerFactory.getLogger(MyClass.class); //org.slf4j.LoggerFactory
 
    public void foo(Params p)
    {
         log.info("Foo params: " + p);
         long t1 = System.currentTimeMillis();

         Result r = someMethod(p);

         long t2 = System.currentTimeMillis();
         log.info("Foo result: " + r)
         log.info("Foo time taken: " + (t2-t1)/1000); 
    }

}

现在当涉及到打印这个信息时,我想要能够打开和关闭不同类型的信息(参数、结果、花费的时间)。

使用日志级别进行区分的问题是,粒度的较细级别也包含较粗的级别。

我怎样才能轻松地设置这个?

共有1个答案

危斯伯
2023-03-14

我想John Ament的意思是,记录器名称(或类别,有时也被称为)可以自由选择。呼叫

LoggerFactory.getLogger(MyClass.class)

主要是为了方便打电话

LoggerFactory.getLogger(MyClass.class.getName())

日志框架没有要求您根据类的全名来命名您的日志记录器。这只是上面第一个getLogger重载所支持的约定。

 private AbstractLogger l1= new LoggerOne(this.getClass());
 private AbstractLogger l2= new LoggerTwo(this.getClass());
 private AbstractLogger l3= new LoggerThree(this.getClass());

您可以简单地使用具有3个不同名称的标准记录器实现:

public class MyClass
{
    private static final String loggerBaseName = MyClass.class.getName();

    private final Logger paramsLogger = LoggerFactory.getLogger(loggerBaseName + ".params");
    private final Logger resultsLogger = LoggerFactory.getLogger(loggerBaseName + ".results");
    private final Logger durationLogger = LoggerFactory.getLogger(loggerBaseName + ".duration");

    public void foo(Params p)
    {
        paramsLogger.info("Foo params: {}", p);
        long t1 = System.currentTimeMillis();

        Result r = someMethod(p);

        long t2 = System.currentTimeMillis();
        resultsLogger.info("Foo result: {}", r)
        durationLogger.info("Foo time taken: {}", (t2-t1)/1000); 
    }
}

由于log4j记录器是分层的,您可以根据需要一起或单独地控制它们。因此,如果您想要启用所有这些功能:

log4j.logger.org.myproject.MyClass=DEBUG, stdout

如果以后需要关闭结果:

log4j.logger.org.myproject.MyClass=DEBUG, stdout
log4j.logger.org.myproject.MyClass.results=OFF
public class GlobalMarkers
{
    public static final Marker PARAMS = MarkerFactory.getMarker("PARAMS");
    public static final Marker RESULTS = MarkerFactory.getMarker("RESULTS");
    public static final Marker DURATION = MarkerFactory.getMarker("DURATION");
}

public class MyClass
{
    private Logger logger = LoggerFactory.getLogger(MyClass.class);

    public void foo(Params p)
    {
        logger.info(GlobalMarkers.PARAMS, "Foo params: {}", p);
        long t1 = System.currentTimeMillis();

        Result r = someMethod(p);

        long t2 = System.currentTimeMillis();
        logger.info(GlobalMarkers.RESULTS, "Foo result: {}", r)
        logger.info(GlobalMarkers.DURATION, "Foo time taken: {}", (t2-t1)/1000); 
    }
}

Log4J2.0在如何使用MarkerFilter方面为您提供了很大的灵活性:

  1. 您可以将其作为上下文范围的筛选器应用,从而关闭所有持续时间的日志记录,例如。
  2. 您可以将其应用于org.myproject.myClass记录器,以关闭该特定类的结果日志记录(例如)。
  3. 您可以将其应用于特定的附加程序,从而将参数日志记录到与结果日志记录或类似的html" target="_blank">文件中。

在logback中,故事更加复杂,这取决于您希望实现的目标。若要全局关闭给定标记的所有日志记录,只需使用MarkerFilter。这是一个TurboFilter,因此它适用于整个日志上下文。如果希望将不同的标记记录到不同的源中,可以使用SiftingAppender并通过扩展AbstractDiscriminator编写一个基于标记的鉴别器。由于logback不支持直接在记录器上进行筛选,如果您需要配置每个类每个标记的输出,比如关闭MyClass的结果日志记录,但对其他类保持记录,那么您应该使用特定于类的标记,而不是全局标记。

下面是用于SiftingAppender的基于标记的鉴别器的示例实现:

public class MarkerBasedDiscriminator extends AbstractDiscriminator<ILoggingEvent> {
    private static final String KEY = "markerName";
    private String defaultValue;

    public String getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }

    public String getKey() {
        return KEY;
    }

    public void setKey() {
        throw new UnsupportedOperationException("Key not settable. Using " + KEY);
    }

    public String getDiscriminatingValue(ILoggingEvent e) {
        Marker eventMarker = e.getMarker();

        if (eventMarker == null)
            return defaultValue;

        return eventMarker.getName();
    }
}

这个实现很大程度上受到了标准ContextBasedDiscriminator的启发。您可以像这样使用MarkerBasedDiscriminator:

<configuration>
  <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
    <discriminator class="org.myproject.MarkerBasedDiscriminator">
      <defaultValue>general</defaultValue>
    </discriminator>
    <sift>
      <appender name="FILE-${markerName}" class="ch.qos.logback.core.FileAppender">
        <file>${markerName}.log</file>
        <append>false</append>
        <encoder>
          <pattern>%d [%thread] %level %logger{35} - %msg%n</pattern>
        </encoder>
      </appender>
    </sift>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="SIFT" />
  </root>
</configuration>
 类似资料:
  • 说我有一堂这样的课: 现在当涉及到打印这个信息时,我想要能够打开和关闭不同类型的信息(参数、结果、花费的时间)。 使用日志级别进行区分的问题是,粒度的较细级别也包含较粗的级别。 我怎样才能轻松地设置这个?

  • ,日志记录将进入一个文件; (路径)/service_name/service_name.log 我想用logback复制这种行为,但在logback.xml配置中获取“logger”名称时遇到了真正的困难。它可以在log encoder.pattern中看到,即“%d%-5level%logger{35}-%msg%n”。

  • 主要内容:Logger日志方法的例子,Logger的日志方法Logger 类有多种方法来处理日志记录活动。Logger 类不允许我们实例化一个新的 Logger 实例,但它支持两种获取 Logger 对象的静态方法: 两个方法中的第一个返回应用程序实例的根记录器,它没有名称。 任何其他命名的 Logger 对象实例都是通过传递记录器的名称由第二种方法获得的。记录器的名称可以是您传递的任何字符串,通常是类或包名称,如下所述: Logger日志方法的例子 Lo

  • 当前的日志阈值是关于日志级别(TRACE,DEBUG,INFO,WARN,ERROR和FATAL)对我来说是不够的。我有一个千兆字节的日志从第三方库写入紧急情况下的错误类别。我不想打开这个日志,因为我想看到这个问题日志。大多数日志都是连续重复的堆栈跟踪。所以我想要一种可以 1)跳过日志,如果阈值(kb/sec)是真实的(我的意思是当我们写很多日志-我们可能会跳过一些)或 2)如果在一段时间内打印了

  • 问题是它不在catalina- .log中记录,而是在catalina中记录。似乎没有正确配置appender。文件catalina似乎是从log4j.appender.catalina.file=${catalina.home}/logs/catalina创建的。在配置中。 有人能帮我解决这个问题吗?

  • 我下载了kafka-clients-0.9.0.0。jar与maven一起使用,我希望我会看到类似于Kafka日志链接中的日志记录 然而,我不知道为什么我没有得到任何日志记录,即使我设置了引导。purpuse上的服务器错误,但它只是在没有发出任何警告的情况下被卡住了。我添加了几行代码以使用log4j打印到一个文件中,这似乎是可行的,但不知道为什么Kafka不能将事件记录到log4j中。 请注意,s