在独立的 java 应用程序中使用相同的 log4j 记录器

发布于 2024-09-05 13:45:03 字数 791 浏览 3 评论 0原文

我有一些代码,它是一个独立的 java 应用程序,由 30 多个类组成。

其中大部分继承自其他一些基类。

每个类都有这个方法来获取和使用 log4j 记录器

public static Logger getLogger() {
    if (logger != null) return logger;
    try {
        PropertyUtil propUtil = PropertyUtil.getInstance("app-log.properties");
        if (propUtil != null && propUtil.getProperties() != null)
            PropertyConfigurator.configure(propUtil.getProperties ());
        logger = Logger.getLogger(ExtractData.class);
        return logger;
    } catch (Exception exception) {
        exception.printStackTrace();
    }
}

A) 我的问题是是否应该将其重构为一些通用记录器,该记录器初始化一次并由所有类使用?这是更好的做法吗?

B) 如果是,如何做到这一点?我怎样才能传递记录器?

C) 这实际上在代码中使用的不是 Logger.debug(),而是 getLogger().debug()。 这对性能有何影响?

I have some code which is a standalone java application comprising of 30+ classes.

Most of these inherit from some other base classes.

Each and every class has this method to get and use a log4j logger

public static Logger getLogger() {
    if (logger != null) return logger;
    try {
        PropertyUtil propUtil = PropertyUtil.getInstance("app-log.properties");
        if (propUtil != null && propUtil.getProperties() != null)
            PropertyConfigurator.configure(propUtil.getProperties ());
        logger = Logger.getLogger(ExtractData.class);
        return logger;
    } catch (Exception exception) {
        exception.printStackTrace();
    }
}

A) My question is whether this should be refactored to some common logger which is initialized once and used across by all classes? Is that a better practice?

B) If yes, how can this be done ? How can I pass the logger around ?

C) This is actually being used in the code not as Logger.debug() but getLogger().debug().
What is the impact of this in terms of performance?

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

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

发布评论

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

评论(3

乖乖兔^ω^ 2024-09-12 13:45:03

A) 在 Log4J 中,您有记录器层次结构,而不是单个记录器。这通常归结为每个类一个记录器,其中记录器由类名标识。记录器的初始化如下:

private static final Logger logger = Logger.getLogger(MyClass.class);

这是一个很好的实践,因为它允许您微调应用程序中模块(包)甚至单个类的日志记录行为。因此,您可以禁用某些包的日志记录,在其他包中以 INFO 级别进行日志记录,并在某些关键类上以 DEBUG 级别进行日志记录,例如当您想要捕获错误时。

B) 但是,如果您希望到处都有一个记录器,只需在每个类中使用根记录器即可:

private static final Logger logger = Logger.getLogger();

C) 对于不太复杂的方法的调用,性能差异可能可以忽略不计,因为 JIT 编译器无论如何都会积极地内联调用。对于复杂的方法,这更是一个悬而未决的问题。

请注意,您显示的方法通过加载记录器配置完成了不必要的工作 - 如果您将配置文件命名为 log4j.properties 并将其放在类路径中,则 Log4J 会自动完成此操作。但是,即使您需要使用非标准配置文件名,您仍然可以在启动时在单个位置加载 Log4J 配置,并省略记录器的延迟加载。那么剩下的就是

private static final Logger logger = Logger.getLogger(ExtractData.class);

private static Logger getLogger() {
    return logger;
}

编译器肯定会内联它。尽管如此,您可能仍希望保留 getLogger,以避免修改大量调用者代码。

请注意,getLogger 没有必要是public,因为无论如何,所有类都应该有自己的记录器引用。

A) in Log4J, you have logger hierarchies, not a single logger. This typically boils down to one logger per class, where loggers are identified by classname. The logger is initialized like this:

private static final Logger logger = Logger.getLogger(MyClass.class);

This is a good practice in that it allows you to fine-tune logging behaviour for modules (packages) or even individual classes within your app. So you may disable logging for some packages, log at INFO level in others, and log on DEBUG level for some critical classes e.g. when you want to catch a bug.

B) However, if you want a single logger everywhere, simply use the root logger in every class:

private static final Logger logger = Logger.getLogger();

C) for calls to not too complex methods, the performance difference is likely negligible, as the JIT compiler will agressively inline calls anyway. For complicated methods it is more of an open question.

Note that the method you show does unnecessary work by loading logger configuration - this is done automatically by Log4J if you name your config file log4j.properties and put it on the classpath. However, even if you need to use a nonstandard config file name, you could still load the Log4J configuration in a single place upon startup, and omit the lazy loading of the logger. Then what is left is

private static final Logger logger = Logger.getLogger(ExtractData.class);

private static Logger getLogger() {
    return logger;
}

and this will surely be inlined by the compiler. You may want to retain getLogger nevertheless, to avoid modifying a lot of caller code.

Note that it is unnecessary for getLogger to be public, as all classes are supposed to have their own logger reference anyway.

浪推晚风 2024-09-12 13:45:03

A) 取决于,但我认为每类记录器的粒度是使用 log4j 的实用程序的一部分。如果需要,您可以重定向来自一个类的日志信息,或者将它们全部发送到同一文件。

B) 您不会传递记录器,只需使用 Logger.getLogger() 方法来使用根记录器。

C) 就性能而言可能并不大。如果它还不是静态的,则可以选择将您的 getLogger() 方法指示为 final 以建议应将其内联。 Peter 的答案在这里更好,正如他指出的,如果方法足够简单,无论如何它都可能会被内联。

A) Depends, but I think the granularity of per-class loggers is part of the utility of using log4j. You can redirect log information from one class if you want to or send them all to the same file.

B) You wouldn't pass a logger around, you would just use the Logger.getLogger() method to use the root logger.

C) Probably not big in terms of performance. If it wasn't already static, an option would be to indicate your getLogger() method as final to suggest that it should be inlined. Peter's answer is better here, and as he notes, if the method is simple enough, it will likely be inlined anyway.

木槿暧夏七纪年 2024-09-12 13:45:03

每个类都可以获得自己的记录器,因为

final static private Logger log = Logger.getLogger("com.company.package.MyClass");

这使您可以按类调整 log4j 设置,这比标准记录器更灵活。

Each class can get it's own logger as

final static private Logger log = Logger.getLogger("com.company.package.MyClass");

This enables you to tweak the log4j settings by class, which is more flexible than the standard logger.

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