代码之家  ›  专栏  ›  技术社区  ›  Rolf

Codahale Metrics:在纯Java中使用@Timed Metrics注释

  •  44
  • Rolf  · 技术社区  · 10 年前

    我正在尝试使用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 {
        [...]
    }
    

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

    其他信息: 我之所以觉得这很奇怪,是因为我添加了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注释,如上所述。

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

    8 回复  |  直到 10 年前
        1
  •  19
  •   Andrew Logvinov    10 年前

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

    一两周前,我还决定将度量添加到我们的项目中,并为此任务选择了AspectJ(主要是因为我过去使用它的目的类似,而且它允许编译时编织,而Spring只允许通过代理运行时)。

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

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

    另一个争论点是支持IDE集成的代码以及javac注释处理器的实现。Lombok项目的这两个部分都使用了非公开的API来实现其魔法。这意味着Lombok项目有可能在随后的IDE或JDK版本中被破坏。

        2
  •  12
  •   Michael Zalimeni    8 年前

    使用 @Timed 如果您在一个容器内并使用Dropwizard的一个工具库,那么实际上不需要使用AOP,正如前面在顶级答案中所说的那样。例如,如果您阅读 source .

    您可以在 the Dropwizard docs 在相应的“ 仪表化____ “子弹。

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

        3
  •  5
  •   woxwoxwoxwox    10 年前

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

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

        4
  •  5
  •   joev    9 年前

    使用从应用程序类的初始化方法中的引导参数访问的内置MetricRegistry。

    @Override
    public void initialize(final Bootstrap<Configuration> bootstrap) {
        final JmxReporter reporter = JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build();
        reporter.start();
    }
    
        5
  •  3
  •   Robert Christian    9 年前

    AOP是过度的,通常不适合使用@timed 讲话。

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

    DropWizard引导构造函数:

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

        6
  •  1
  •   gli00001    7 年前

    这个简单/切中要害的例子 https://karollotkowski.wordpress.com/2015/10/19/api-endpoint-in-one-minute-with-dropwizard/ 只是显示它只需要注释

    enter image description here

        7
  •  0
  •   Felix    9 年前

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

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

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

        8
  •  0
  •   kfaraz    7 年前

    在较新的Dropwizard版本(我使用的是0.9.2)中,您可以访问默认值 MetricRegistry 通过设置环境 io.dropwizard.setup.Environment 。此默认值 公制注册表 已经有了 InstrumentedResourceMethodApplicationListener 与之相关联的,它监听资源的所有度量。

    如果您已向 JerseyEnvironment 如下所述,

    environment.jersey().register(resource);
    

    您只需要使用 @Timed , @Metered @ExceptionMetered 以注册相应的度量。

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

    您可以指定 Reporter (像一个 Slf4jReporter JmxReporter )默认为 公制注册表 根据

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

    作为一个快速测试,看看你的指标是否已经注册,你可以做一个 GET 调用URL http://localhost:8081/metrics 或测试环境中相应的管理度量URL。

    某些其他版本要求您显式注册 检测的资源方法应用程序侦听器 如图所示 in this Doc