在 Logback 自动扫描中配置日志记录操作

Configure Logging operations in Logback auto scan

Logback 文档说,自动扫描与日志记录操作一起工作,即

the check whether the scan period has elapsed or not, is too costly in itself. In order to improve performance, ReconfigureOnChangeFilter is in reality "alive" only once every N logging operations. Depending on how often your application logs, the value of N can be modified on the fly by logback. By default N is 16, although it can go as high as 2^16 (= 65536) for CPU-intensive applications.

有什么方法可以在您的 xml 中或通过任何其他方式配置 'N' 的值。

快速查看 ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter class 中的源代码 (logback 1.1.3) 会发现以下内容:

N 的起始值是硬编码的,如下所示:

  private volatile long mask = 0xF;

除非自己更改源代码并重新编译对此常量的更改,否则代码不提供任何类型的配置选项来更改它。

如何使用mask变量可以在这段代码中看到:

// for performance reasons, skip change detection (MASK-1) times out of MASK.
// Only once every MASK calls is change detection code executed
// Note that MASK is a variable itself.
if (((invocationCounter++) & mask) != mask) {
  return FilterReply.NEUTRAL;
}

但是,正如文档所建议的那样,此 mask(或 N)值由 logback 动态调整,因为它认为需要这样做以保持良好的性能。

文档只在感觉需要时才谈到向上调整 N 的值。但是代码显示,当感觉N的值过高时,也会动态向下调整的值。 =25=]

注意下面的代码,它决定了如何动态调整 N 的值:

  // experiments indicate that even for CPU intensive applications with 200 or more threads MASK
  // values in the order of 0xFFFF is appropriate
  private static final int MAX_MASK = 0xFFFF;


  // if less  than MASK_INCREASE_THRESHOLD milliseconds elapse between invocations of updateMaskIfNecessary() method,
  // then the mask should be increased
  private static final long MASK_INCREASE_THRESHOLD = 100;

  // if more than MASK_DECREASE_THRESHOLD milliseconds elapse between invocations of updateMaskIfNecessary() method,
  // then the mask should be decreased
  private static final long MASK_DECREASE_THRESHOLD = MASK_INCREASE_THRESHOLD*8;

  // update the mask so as to execute change detection code about once every 100 to 8000 milliseconds.
  private void updateMaskIfNecessary(long now) {
    final long timeElapsedSinceLastMaskUpdateCheck = now - lastMaskCheck;
    lastMaskCheck = now;
    if (timeElapsedSinceLastMaskUpdateCheck < MASK_INCREASE_THRESHOLD && (mask < MAX_MASK)) {
        mask = (mask << 1) | 1;
    } else if (timeElapsedSinceLastMaskUpdateCheck > MASK_DECREASE_THRESHOLD) {
      mask = mask >>> 2;
    }
  }

最后一个条件是说,如果最后一次检查是在超过 800 毫秒之前执行的,那么 N 的值太高了,需要向下调整。

假设您没有非常频繁的日志,那么您可以预期最终 mask 的值将降低到 0,更改检测将不再被跳过,并且它正如您所期望的那样,实际上将开始遵循您的 scan period 配置。