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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28499621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 06:20:18  来源:igfitidea点击:

Codahale Metrics: using @Timed metrics annotation in plain Java

javametricscodahale-metrics

提问by Rolf

I am trying to add metrics to a plain Java application using codahale metrics. I'd like to use the @Timed annotation, but it is unclear to me which MetricRegistry it uses, or how to tell it which MetricRegistry to use. The application is a plain Java 8 application, built with Maven 3, no Spring, no Hibernate.

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

I can not find any documentation on how to implement @Timed in the dropwizard documentation: https://dropwizard.github.io/metrics/3.1.0/manual/

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

I've added these dependencies:

我添加了这些依赖项:

<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>

When I use a programatic call to Timer, I can get reports because I know which MetricsRegistry is used:

当我使用对 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();
  }
}

But when I use the much more elegant @Timed annotation, I have no idea which registry is used, and therefore I can not create a reporter, which means I can not get the metrics reported (I'm not even sure if this actually does anything):

但是当我使用更优雅的 @Timed 注释时,我不知道使用哪个注册表,因此我无法创建报告器,这意味着我无法报告指标(我什至不确定这是否真的任何事物):

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

Please advise on how to make the @Timed and other Metrics annotations work in a regular Java application.

请就如何使 @Timed 和其他 Metrics 注释在常规 Java 应用程序中工作提供建议。

Additional info:The reason I am finding this strange is that I have added the Lombok framework and the @Slf4j annotations do work. I added Lombok as a dependency in the maven pom.xml:

附加信息:我觉得这很奇怪的原因是我添加了 Lombok 框架并且 @Slf4j 注释确实有效。我在 maven pom.xml 中添加了 Lombok 作为依赖项:

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

And I can use the @Sl4fj class annotation to add a logger to the class without cluttering up the member variables:

我可以使用@Sl4fj 类注释将记录器添加到类中,而不会弄乱成员变量:

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

So if that's possible by just adding a dependency, I reckon I am just missing a dependency or configuration to get the codahale @Timed annotation work, as described above.

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

(by the way, check out Lombok, it will make your life easier: http://projectlombok.org/)

(顺便说一下,看看 Lombok,它会让你的生活更轻松:http: //projectlombok.org/

采纳答案by Andrew Logvinov

Long story short, you cannot use @Timedwithout some kind of AOP (be it Spring AOP or AspectJ).

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

A week or two ago, I also decided to add metrics to our project and chose AspectJ for this task (mostly because I used it in the past for similar purpose and because it allows for compile-time weaving while Spring allows only runtime via proxies).

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

You should be able to find all the necessary information and instructions here: https://github.com/astefanutti/metrics-aspectj.

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

As for Lombok, I guess they use built-in javac annotations processor:

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

Another point of contention is the implementation of both the code supporting IDE integration as well as the javac annotation processor. Both of these pieces of Project Lombok make use of non-public APIs to accomplish their sorcery. This means that there is a risk that Project Lombok will be broken with subsequent IDE or JDK releases.

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

回答by woxwoxwoxwox

As the other answer stated, you have to have something in the application to listen for your instantiated classes and check them for the @Timed annotation.

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

If you're using Guice, you could use: https://github.com/palominolabs/metrics-guice

如果你使用 Guice,你可以使用:https: //github.com/palominolabs/metrics-guice

回答by joev

Use the built-in MetricRegistry accessed from the bootstrap parameter in the initialize method of your application class.

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

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

回答by Robert Christian

AOP is overkill and not appropriate for use of @timed, generally speaking.

一般来说,AOP 是矫枉过正,不适合使用@timed。

The default metrics registry writes @timed metrics to a ConcurrentHashMap and does not attach any meaningful listeners.

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

DropWizard Bootstrap constructor:

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 = Hymanson.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>();
}

So you need to build/start/register the appropriate metric registry in order to see results.

因此,您需要构建/启动/注册适当的指标注册表才能查看结果。

Here I use JMX:

这里我使用 JMX:

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

That's all you need to do.

这就是你需要做的。

Here's an example of the output (run jconsole against your Java application/server to view JMX results):

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

enter image description here

在此处输入图片说明

回答by Felix

You could also use stagemonitor-core for that. See documentation hereand here. The advantage is that stagemonitor (which is free & open source btw) does not depend on any container-based AOP like Spring AOP or EJB interceptors. It uses bytecode manipulation via runtime attachment which means that you do not even have to add a -javaagentflag to your application startup - a plain dependency is enough.

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

If you want to measure the execution time in a web application or in a remote EJB application, you don't even have to manually annotate your code. Also, stagemonitor offers preconfigured Grafana and Kibana dashboards.

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

Disclaimer: I'm one of the developers of stagemonitor

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

回答by Michael Zalimeni

Using @Timeddoesn't actually require the use of AOP, as was previously claimed in the top-rated answer, if you're inside a container and using one of Dropwizard's instrumentation libraries. See the Jersey 2.x module for example, which you can see uses reflection (as do the others I looked at), if you read the source.

使用@Timed实际上并不需要使用AOP,如以前声称在收视率最高的答案,如果你是一个容器内,并使用Dropwizard的仪表图书馆之一。例如,请参阅 Jersey 2.x 模块,如果您阅读源代码,您可以看到它使用了反射(就像我看过的其他模块一样)。

You can read up on all of these modules in the Dropwizard docsunder the corresponding "Instrumenting ____" bullets.

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

I understand the OP was explicitly NOT working within such a container, but I wanted to offer this info, since many of us looking for this answer may be working on a modern web service that can register such resources in its runtime environment.

我知道 OP 明确不能在这样的容器中工作,但我想提供这个信息,因为我们中的许多人正在寻找这个答案,可能正在开发一个可以在其运行时环境中注册此类资源的现代 Web 服务。

回答by Faraz

In newer Dropwizard versions (I am using 0.9.2), you can access the default MetricRegistrythrough the setup environment io.dropwizard.setup.Environment. This default MetricRegistryalready has an InstrumentedResourceMethodApplicationListenerassociated with it, which listens to all the metrics of your resources.

在较新的 Dropwizard 版本中(我使用的是 0.9.2),您可以MetricRegistry通过 setup environment访问默认值io.dropwizard.setup.Environment。这个默认值MetricRegistry已经有一个InstrumentedResourceMethodApplicationListener与之关联的,它会监听你资源的所有指标。

If you have registered a resource with the JerseyEnvironmentas under,

如果您已注册资源JerseyEnvironment如下,

environment.jersey().register(resource);

you need only annotate your resource method (or class) with @Timed, @Meteredor @ExceptionMeteredto register the respective metrics.

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

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

You can assign a Reporter(like an Slf4jReporteror JmxReporter) to the default MetricRegistryas under

您可以将 a Reporter(如 anSlf4jReporterJmxReporter)分配给默认值,MetricRegistry如下所示

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

As a quick test to see if your metrics have actually been registered, you can make a GETcall to the URL http://localhost:8081/metricsor the corresponding Admin Metrics URL in your test environment.

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

Some other versions require you to explicitly register an InstrumentedResourceMethodApplicationListeneras shown in this Doc

其他一些版本要求您显式注册一个InstrumentedResourceMethodApplicationListener,如本文档中所示

回答by gli00001

this simple/right-to-the-point example https://karollotkowski.wordpress.com/2015/10/19/api-endpoint-in-one-minute-with-dropwizard/just showed it only need the annotation

这个简单/正确的例子https://karollotkowski.wordpress.com/2015/10/19/api-endpoint-in-one-minute-with-dropwizard/只是表明它只需要注释

enter image description here

在此处输入图片说明