Codahale指标:在普通Java中使用@Timed指标注释

时间:2015-02-13 12:26:37

标签: java metrics codahale-metrics

我正在尝试使用codahale指标将指标添加到普通Java应用程序。我想使用@Timed注释,但我不清楚它使用哪种MetricRegistry,或者如何告诉它使用哪种MetricRegistry。该应用程序是一个简单的Java 8应用程序,使用Maven 3构建,没有Spring,没有Hibernate。

我在dropwizard文档中找不到有关如何实现@Timed的任何文档:https://dropwizard.github.io/metrics/3.1.0/manual/

我已经添加了这些依赖项:

<dependency>
  <groupId>io.dropwizard.metrics</groupId>
  <artifactId>metrics-core</artifactId>
  <version>3.1.0</version>
</dependency>
<dependency>
  <groupId>com.codahale.metrics</groupId>
  <artifactId>metrics-annotation</artifactId>
  <version>3.0.2</version>
</dependency>

当我使用对Timer的编程调用时,我可以获得报告,因为我知道使用了哪些MetricsRegistry:

static final MetricRegistry metrics = new MetricRegistry();
private void update() throws SQLException {
  Timer.Context time = metrics.timer("domainobject.update").time();
  try {
    [...]
  } finally {
    time.stop();
  }
}

但是当我使用更优雅的@Timed注释时,我不知道使用了哪个注册表,因此我无法创建一个记者,这意味着我无法获得报告的指标(我甚至没有确定这实际上是否有效):

@Timed(name = "domainobject.update")
private void update() throws SQLException {
    [...]
}

请告知如何使@Timed和其他Metrics注释在常规Java应用程序中运行。

其他信息:我发现这个奇怪的原因是我添加了Lombok框架并且@ Slf4j注释可以正常工作。我在maven pom.xml中添加了Lombok作为依赖项:

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.14.8</version>
</dependency>

我可以使用@ Sl4fj类注释向类中添加一个记录器,而不会使成员变量混乱:

@Slf4j
public class App {
  public void logsome(){
    log.info("Hello there");
  }
}

因此,如果只通过添加依赖项就可以实现,我认为我只是缺少一个依赖项或配置来获取codahale @Timed注释工作,如上所述。

(顺便说一句,看看龙目岛,它会让你的生活更轻松:http://projectlombok.org/

8 个答案:

答案 0 :(得分:16)

长话短说,如果没有某种AOP(无论是Spring AOP还是AspectJ),就不能使用@Timed

一两个星期前,我还决定为我们的项目添加指标,并选择AspectJ来完成这项任务(主要是因为我过去使用它来达到类似的目的,因为它允许编译时编织,而Spring只允许运行时通过代理)。

您应该可以在此处找到所有必要的信息和说明:https://github.com/astefanutti/metrics-aspectj

至于龙目岛,我猜他们使用内置的javac注释处理器:

  

另一个争论点是实现支持IDE集成的代码以及javac注释处理器。这两个项目Lombok都利用非公共API来完成他们的巫术。这意味着可能会因后续的IDE或JDK版本而破坏Project Lombok。

答案 1 :(得分:12)

使用@Timed实际上并不需要使用AOP,如前面在评分最高的答案中所声称的那样,如果你在容器内并使用Dropwizard的一个检测库。例如,如果您阅读source,请参阅Jersey 2.x模块,您可以看到它使用反射(与我查看的其他模块一样)。

您可以在the Dropwizard docs下相应的“ Instrumenting ____ ”项目符号下阅读所有这些模块。

我理解OP明确没有在这样的容器中工作,但是我想提供这个信息,因为我们许多寻找这个答案的人可能正在研究一种可以在其运行时环境中注册这些资源的现代Web服务。

答案 2 :(得分:5)

  

使用从应用程序类的initialize方法中的bootstrap参数访问的内置MetricRegistry。

@Override
public void initialize(final Bootstrap<Configuration> bootstrap) {
    final JmxReporter reporter = JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build();
    reporter.start();
}

答案 3 :(得分:3)

正如另一个答案所述,你必须在应用程序中有一些东西来监听你的实例化类并检查它们的@Timed注释。

如果您使用的是Guice,则可以使用:https://github.com/palominolabs/metrics-guice

答案 4 :(得分:3)

  

AOP过度杀伤,一般不适合@timed使用   言。

默认指标注册表将@timed指标写入ConcurrentHashMap,并且不会附加任何有意义的侦听器。

DropWizard Bootstrap构造函数:

/**
 * Creates a new {@link Bootstrap} for the given application.
 * @param application a Dropwizard {@link Application}
 */
public Bootstrap(Application<T> application) {
    this.application = application;
    this.objectMapper = Jackson.newObjectMapper();
    this.bundles = Lists.newArrayList();
    this.configuredBundles = Lists.newArrayList();
    this.commands = Lists.newArrayList();
    this.validatorFactory = Validators.newValidatorFactory();


    // returns new ConcurrentHashMap<String, Metric>(); 
    this.metricRegistry = new MetricRegistry(); 


    this.configurationSourceProvider = new FileConfigurationSourceProvider();
    this.classLoader = Thread.currentThread().getContextClassLoader();
    this.configurationFactoryFactory = new DefaultConfigurationFactoryFactory<T>();
}
  

因此,您需要构建/启动/注册相应的度量标准注册表   为了看到结果。

我在这里使用JMX:

@Override
public void initialize(Bootstrap<PayloadStorageConfiguration> bootstrap) {
    JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build().start();
}

这就是你需要做的一切。

以下是输出示例(针对Java应用程序/服务器运行jconsole以查看JMX结果):

enter image description here

答案 5 :(得分:1)

在较新的Dropwizard版本(我使用的是0.9.2)中,您可以通过设置环境MetricRegistry访问默认的io.dropwizard.setup.Environment。此默认MetricRegistry已与InstrumentedResourceMethodApplicationListener相关联,可监听您资源的所有指标。

如果您已注册资源JerseyEnvironment,则

environment.jersey().register(resource);

您只需使用@Timed@Metered@ExceptionMetered注释您的资源方法(或类)即可注册相应的指标。

@POST
@Timed
public String show() {
    return "yay";
}

您可以将Reporter(如Slf4jReporterJmxReporter)分配到默认MetricRegistry,如下

Slf4jReporter.forRegistry(environment.metrics()).build();

作为快速测试,看看您的指标是否实际已注册,您可以GET调用网址http://localhost:8081/metrics或测试环境中相应的管理指标网址。

其他一些版本要求您明确注册InstrumentedResourceMethodApplicationListener in this Doc

答案 6 :(得分:0)

你也可以使用stagemonitor-core。请参阅文档herehere。优点是stagemonitor(免费和开源btw)不依赖于任何基于容器的AOP,如Spring AOP或EJB拦截器。它通过运行时附件使用字节码操作,这意味着您甚至不必向应用程序启动添加-javaagent标志 - 简单依赖就足够了。

如果要测量Web应用程序或远程EJB应用程序中的执行时间,您甚至不必手动注释代码。此外,stagemonitor还提供预先配置的Grafana和Kibana仪表板。

免责声明:我是stagemonitor的开发者之一

答案 7 :(得分:0)