7

这是我使用 yammer 计时注释的斗争的后续行动,如此处所述

我的弹簧上下文文件很简单:

<metrics:annotation-driven />

我有以下课程:

import com.yammer.metrics.annotation.ExceptionMetered;
import com.yammer.metrics.annotation.Metered;
import com.yammer.metrics.annotation.Timed;

...

@Component
public class GetSessionServlet extends HttpServlet {

  private final static Logger log = LoggerFactory.getLogger(GetSessionServlet.class);


  @Override
  public void init(final ServletConfig config) throws ServletException {
    super.init(config);
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(
            this, config.getServletContext());
  }

  @Override
  @Timed(name = "get-session", rateUnit = TimeUnit.MILLISECONDS)
  @Metered
  @ExceptionMetered(name = "get-session-failures", rateUnit = TimeUnit.MILLISECONDS)
  public void doGet(final HttpServletRequest req,
          final HttpServletResponse resp) throws ServletException, IOException {
    final String sessionId = req.getParameter("sessionId");
    final String fields = req.getParameter("fields");
    final String format = req.getParameter("format");
    if (StringUtils.isEmpty(sessionId)) {
      resp.getWriter().write("sessionId parameter missing!\n");
      return;
    }
    ...
  }

我在本地运行我的应用程序mvn clean tomcat7:run,然后连接 jconsole。

在 MBeans 选项卡中,我可以看到一个条目,其中包含我的GetSessionServlet类的包名称以及三个子文件夹doGet(用于 @Metered 数字)、get-session 和 get-session-failures。

但是,无论我调用多少次 servlet,上面子文件夹中的所有值都保持为零。我错过了什么?此外,任何有关这些计量指标的文档比官方文档更详细,我们将不胜感激。

4

2 回答 2

5

我想我得到了这个工作。

我注意到的第一件事是示例 spring 上下文文件的 schemaLocation 属性中的 URI: http ://www.yammer.com/schema/metrics/metrics.xsd 返回 404 错误。

我用谷歌搜索了这个问题,看看是否有人抱怨架构无法访问并找到了这个线程,github.com/codahale/metrics/issues/322,其中用户评论说metrics-spring模块已从核心指标存储库中删除并移至:github.com/ryantenney/metrics-spring。

按照该网站上的示例,我从我的 pom 中删除了旧的 metrics-spring 依赖项并添加了以下内容:

  <dependency>
      <groupId>com.ryantenney.metrics</groupId>
      <artifactId>metrics-spring</artifactId>
      <version>2.1.4</version>
  </dependency>

然后我更新了 spring-context.xml 文件中的 xmlns 声明:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:metrics="http://www.ryantenney.com/schema/metrics"
       xsi:schemaLocation="
           http://www.ryantenney.com/schema/metrics 
           http://www.ryantenney.com/schema/metrics/metrics.xsd 
           ...other schemas...">

添加了注释驱动元素:

<metrics:annotation-driven proxy-target-class="true" />

我启用了 proxy-target-class 以使基于类的自动装配工作。

在 bean 中,我想 Time 添加了 @Timed 注释和 @PostConstruct 方法,以使 ConsoleReporter 每 10 秒转储一次统计信息:

@PostConstruct
public void init() {
    ConsoleReporter.enable(10, TimeUnit.SECONDS);    
} 

@Timed
public void doService(...) {
    .... do stuff ....
}

然后我启动了我的 webapp .... 并从 sax 解析器解析 spring context.xml 文件中得到了一个令人讨厌的错误。

似乎 www.ryantenney.com/schema/metrics/metrics.xsd 404s 也是如此!

解决方法很简单,但是,我从 github 存储库下载了 xsd: https ://github.com/ryantenney/metrics-spring/blob/master/src/main/resources/com/ryantenney/metrics/spring/配置/metrics-3.0.xsd

然后在我的 maven 项目的 src/main/resources/META-INF 目录中添加以下文件:

META-INF/
    - spring.schemas
    - xsd/
         - metrics.xsd

其中metrics.xsd是从github下载的xsd文件,spring.schemas是一个文本文件,包含:

http\://www.ryantenney.com/schema/metrics/metrics.xsd=META-INF/xsd/metrics.xsd

spring.schemas 文件在启动时由 spring 读取,并告诉它从本地文件中拉下 xsd。

完成上述操作后,我能够成功启动我的应用程序并点击使用服务方法的端点。

看着控制台,我确实看到每 10 秒转储一次以下内容:

com.sample.service.MyServiceClass:
doService:
    count = 8
    mean rate = 0.27 calls/s
    1-minute rate = 0.23 calls/s
    5-minute rate = 0.21 calls/s
    15-minute rate = 0.20 calls/s
    min = 0.13ms
    max = 19.59ms
    mean = 2.59ms
    stddev = 6.87ms
    median = 0.18ms
于 2013-02-20T03:10:06.093 回答
3

我在这里发布了一个类似的问题,并没有进一步深入。有人向我指出,我可能得到 0 个数字,因为“当从类本身调用该方法时,Spring 无法拦截带注释的方法。” 虽然我之前读过那条评论,但我并没有意识到我处于这种情况,但是查看 HttpServlet 的源代码,我确实看到了像 doHead 这样调用 doGet 的方法。

虽然这个限制本身就是一个挫折,但我继续从我的 doGet 调用另一个类中的方法,看看我是否可以以这种方式执行计时(麻烦但愿意尝试一下):

import org.springframework.stereotype.Component;
import com.yammer.metrics.annotation.Metered;
import com.yammer.metrics.annotation.Timed;

@Component
public class Delay {
  //      @Metered
  @Timed
  public void time() {
    System.out.println("Timing...");
    try {
      Thread.sleep(1000);
    } catch (final InterruptedException e) {
      e.printStackTrace();
    }
  }
}

然而,从我的 servlet getter 调用这个方法如下:

public void doGet(final HttpServletRequest req,
      final HttpServletResponse resp) throws ServletException, IOException {

  final Delay delay = new Delay().time();

无论我执行多少次,Delay.time 方法仍然没有显示任何非空数字。

在这一点上,我将采取挑衅性的立场,即由于这些注释带来的任何限制以及缺乏完整的文档和有用的代码示例,这些注释没有用处,至少在计时 servlet 的上下文中是这样。

我确实希望被证明是错误的,并且很乐意改变我的投票以接受另一个答案,因为这些注释看起来很有希望并且比 Metrics.newTimer 和类似方法更实用。

于 2013-02-18T18:19:33.997 回答