如何每 X 秒重置一次指标?

问题描述 投票:0回答:1

我正在尝试使用 DropWizard Metrics 库测量应用程序上的应用程序和 jvm 级别指标。

下面是我的指标类,我在代码中使用它来增加/减少指标。我正在调用下面类的

increment
decrement
方法来递增和递减指标。

public class TestMetrics {
  private final MetricRegistry metricRegistry = new MetricRegistry();

  private static class Holder {
    private static final TestMetrics INSTANCE = new TestMetrics();
  }

  public static TestMetrics getInstance() {
    return Holder.INSTANCE;
  }

  private TestMetrics() {}

  public void increment(final Names... metricsName) {
    for (Names metricName : metricsName)
      metricRegistry.counter(name(TestMetrics.class, metricName.value())).inc();
  }

  public void decrement(final Names... metricsName) {
    for (Names metricName : metricsName)
      metricRegistry.counter(name(TestMetrics.class, metricName.value())).dec();
  }

  public MetricRegistry getMetricRegistry() {
    return metricRegistry;
  }

  public enum Names {
    // some more fields here
    INVALID_ID("invalid-id"), MESSAGE_DROPPED("drop-message");

    private final String value;

    private Names(String value) {
      this.value = value;
    }

    public String value() {
      return value;
    }
  };
}

这是我如何使用上面的

TestMetrics
类来根据我需要的情况增加指标。下面的方法被多线程调用。

  public void process(GenericRecord record) {
    // ... some other code here
    try {
      String clientId = String.valueOf(record.get("clientId"));
      String procId = String.valueOf(record.get("procId"));
      if (Strings.isNullOrEmpty(clientId) && Strings.isNullOrEmpty(procId)
          && !NumberUtils.isNumber(clientId)) {
        TestMetrics.getInstance().increment(Names.INVALID_ID,
            Names.MESSAGE_DROPPED);
        return;
      }
      // .. other code here

    } catch (Exception ex) {    
      TestMetrics.getInstance().increment(Names.MESSAGE_DROPPED);
    }
  }

现在我有另一个类,它每 30 秒运行一次(我使用 Quartz 框架),我想从其中打印出所有指标及其计数。一般来说,我会每 30 秒将这些指标发送到其他系统,但现在我在这里打印出来。下面是我的做法。

public class SendMetrics implements Job {

  @Override
  public void execute(final JobExecutionContext ctx) throws JobExecutionException {
    MetricRegistry metricsRegistry = TestMetrics.getInstance().getMetricRegistry();
    Map<String, Counter> counters = metricsRegistry.getCounters();
    for (Entry<String, Counter> counter : counters.entrySet()) {
      System.out.println(counter.getKey());
      System.out.println(counter.getValue().getCount());
    }
  }
}

现在我的问题是:我想每 30 秒重置一次所有指标计数。这意味着当我的

execute
方法打印出指标时,它应该仅打印那 30 秒的指标(对于所有指标),而不是打印程序运行时的整个持续时间。

有什么方法可以让我的所有指标只计算 30 秒。计算过去 30 秒内发生的情况。

java quartz-scheduler dropwizard metrics codahale-metrics
1个回答
1
投票

您想要重置计数器。没有用于此目的的 API。原因在 GitHub 问题指标上的 JMX 重置操作中讨论。

解决方法

EverTrue Engineering 的

文章可重置计数器与 codahale 指标描述了一种可能的解决方法。

第1步:

您拥有计数器并像往常一样使用它们 - 递增和递减。但你无法重置它们。因此,添加新的

Gauge
,该值跟随您想要在向您报告后重置的计数器。当您想要报告
counter
值时,会调用
getValue()
Gauge 方法。存储当前值后,该方法将随之减少计数器的值。这有效地将计数器重置为
0
。这样您就可以得到报告并重置计数器了。

metricsRegistry.register("my_resettable_gauge", new Gauge() {
    @Override
    public Long getValue() {
        Counter c = metrics.counter("my_counter_not_reported");
        long count = c.getCount();
        c.dec(count);
        return count;
    }
});

第2步:

添加一个过滤器,禁止报告实际计数器,因为您现在正在通过仪表进行报告。

GraphiteReporter.forRegistry(registry).filter(new MetricFilter() {
    @Override
    public boolean matches(String name, Metric metric) {
        return !name.contains("not_reported");
    }
}).build(client);

© www.soinside.com 2019 - 2024. All rights reserved.