Help with Timer in SpringBoot/Web app?

648 views
Skip to first unread message

griff

unread,
Jan 20, 2016, 10:29:43 AM1/20/16
to metrics-user
I have been trying to implement DW metrics 3.1.0 in my spring boot/web app. I have a registry configured as such:

@WebListener
public class MetricsServletContextListener extends MetricsServlet.ContextListener {

public final MetricRegistry METRIC_REGISTRY=new MetricRegistry();

@Override
protected MetricRegistry getMetricRegistry() {

registerAll("gc", new GarbageCollectorMetricSet(), METRIC_REGISTRY);
registerAll("buffers", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()), METRIC_REGISTRY);
registerAll("memory", new MemoryUsageGaugeSet(), METRIC_REGISTRY);
registerAll("threads", new ThreadStatesGaugeSet(), METRIC_REGISTRY);

return METRIC_REGISTRY;
}

private void registerAll(String prefix, MetricSet metricSet, MetricRegistry registry) {
for (Map.Entry<String, Metric> entry : metricSet.getMetrics().entrySet()) {
if (entry.getValue() instanceof MetricSet) {
registerAll(prefix + "." + entry.getKey(), (MetricSet) entry.getValue(), registry);
} else {
registry.register(prefix + "." + entry.getKey(), entry.getValue());
}
}
}

}

I have a class annotated as a service and I am allowing spring to inject the metrics registry as such:

@Service
public class ImageTransformer implements MediaTransformer<MediaAsset> {

    @Autowired
MetricRegistry registry;
    for (String objectId : transformObjects) {
Timer timer= registry.timer(name(ImageTransformer.class, "image.transformer.setup"));
Timer.Context context= timer.time();
if (!setupTransform(mediaAsset, objectId)) {
// Bail if cannot setup environment.
context.stop();
return retVal;
}
context.stop();




}

griff

unread,
Jan 20, 2016, 10:33:09 AM1/20/16
to metrics-user
Grrr! Stupid fatfinger posted before I was ready.  

The point is that all the object references seem valid when I step through them in the debugger, however when I try to see the timer(s) I have in the health-registry they do not appear:
       ...
   "threads.waiting.count" : {
      "value" : 8
    }
  },
  "counters" : { },
  "histograms" : { },
  "meters" : { },
  "timers" : { }
}

What am I missing here? Do I need to somehow tie the timer to the healthRegistry if I want them to be returned by the DW Heath Metrics servlet? 

Any/All replies appreciated, thanks in advance! 

--griff

Ryan Tenney

unread,
Jan 20, 2016, 10:54:38 AM1/20/16
to metrics-user
The problem is that you're constructing a MetricRegistry in MetricsServletContextListener, so Spring isn't aware of it, and therefore the MetricRegistry that is injected into ImageTransformer isn't the same object.

This is the MetricsServletContextListener I use to share a MetricRegistry instance:

public class MetricsServletContextListener extends MetricsServlet.ContextListener {

@Autowired
MetricRegistry metricRegistry;

@Override
public void contextInitialized(ServletContextEvent event) {
// Since this class isn't instantiated by Spring, we need to find the Spring Context and instruct it to process this bean
WebApplicationContextUtils
 .getRequiredWebApplicationContext(event.getServletContext())
 .getAutowireCapableBeanFactory()
 .autowireBean(this);

super.contextInitialized(event);
}

@Override
protected MetricRegistry getMetricRegistry() {
return metricRegistry;
}

}

Hope that helps.

Ryan

griff

unread,
Jan 20, 2016, 10:57:53 AM1/20/16
to metrics-user
Thanks for the reply Ryan, 

Would I also need a bean then for the autowired injection of the MetricRegistry into the MetricsServletContextListener too? 

-- griff

griff

unread,
Jan 20, 2016, 11:11:06 AM1/20/16
to metrics-user
I'm confused by this.  If I don't create a bean in my configuration of the type MetricRegistry, the reference is null in the MetricsServletContextListener.  If I do define the bean, I get an spring wiring error:

@SpringBootApplication
@EnableJms
@EnableMetrics(proxyTargetClass=true)
@EnableMBeanExport
public class MediaTransformApplication extends SpringBootServletInitializer {

public static void main(String[] args) {
SpringApplication.run(MediaTransformApplication.class, args);
}

@Bean
public ServletRegistrationBean servletRegistrationBean() {
return new ServletRegistrationBean(new AdminServlet(), "/metrics/*");
}

@Bean
public MetricRegistry metricRegistry(){
return new MetricRegistry();
}
    ...


Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'imageTransformer': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.codahale.metrics.MetricRegistry com.pearson.media.ImageTransformer.registry; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.codahale.metrics.MetricRegistry] is defined: expected single matching bean but found 2: getMetricRegistry,metricRegistry

Griffith, Michael

unread,
Jan 20, 2016, 11:22:18 AM1/20/16
to metric...@googlegroups.com
Okay, I made a mistake with the contextInitialized method.  That works, thanks for the help!

  1. Michael Griffith
    Sr. Software Architect
    M  +44 (1) 507-299-0004
    michael....@pearson.com

    Learn more at pearson.com

    ALWAYS LEARNING


--
You received this message because you are subscribed to a topic in the Google Groups "metrics-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/metrics-user/puWVXHcYEf8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to metrics-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages