【问题标题】:How to reset metrics every X seconds?如何每 X 秒重置一次指标?
【发布时间】:2016-12-01 05:44:07
【问题描述】:

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

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

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 秒内发生的任何事情。

【问题讨论】:

  • 关于SendMetrics 类。 Dropwizard 已经有适当的抽象,您可以使用它们来实现您自己的报告。例如查看ConsoleReporter 它在stdoutstderr 上打印指标,并且可以为报告期间进行配置。另请查看dropwizard-metrics 子模块。您可以将那里的代码用作示例实现。
  • 关于你更大的问题:看这里 -> stackoverflow.com/questions/40807073/…metrics project 上检查the linked issueSome comment 有指向 this article 的链接以解决有关重置计数器的问题。
  • 我不太了解您给我的文章链接。我很困惑这将如何适合我的班级?你能帮我理解吗?或者你能给我举个例子吗?因为我正在调用 TestMetrics 类的增量方法来增加指标。

标签: java quartz-scheduler dropwizard metrics codahale-metrics


【解决方案1】:

作为答案,因为它太长了:

您想重置计数器。没有用于此的 API。原因在链接的github 问题中讨论。本文介绍了一种可能的解决方法。你有你的计数器并像往常一样使用它们——递增和递减。但是你不能重置它们。因此,添加新的Gauge,该值在您要在向您报告后重置的计数器之后。当您要报告 counter 值时,会调用 GaugegetValue() 方法。在存储当前值之后,该方法正在减少计数器的值。这有效地将计数器重置为0。所以你有你的报告,也有计数器重置。这在Step 1 中有描述。

Step 2 添加了一个过滤器,禁止报告实际计数器,因为您现在是通过仪表报告。

【讨论】:

  • 这意味着我的每个指标计数器都需要gauge?我有一个非常通用的方法来增加指标,因为我没有为所有指标定义计数器变量。我正在使用枚举来定义所有度量变量,然后在我的increment 方法中使用它来增加度量。所以这意味着我需要为所有指标手动定义仪表?
  • 有什么办法可以根据我的代码使其通用吗?
  • 1) 是的,每个要重置的计数器需要一个仪表; 2) 问题过多且超出范围 - 解决方法是否对您有帮助以及如何实施由您决定。
猜你喜欢
  • 2011-09-04
  • 1970-01-01
  • 2013-07-29
  • 2020-02-02
  • 1970-01-01
  • 2017-05-16
  • 2019-02-01
  • 2012-07-11
相关资源
最近更新 更多