Skip to content

Commit

Permalink
Refactorings and make the units for the metrics servlet configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffellis committed Nov 12, 2013
1 parent 7f2c2d8 commit 43082b6
Show file tree
Hide file tree
Showing 19 changed files with 182 additions and 148 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Expand Up @@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2012 Jeff Ellis
Copyright 2013 Jeff Ellis

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion NOTICE
@@ -1,5 +1,5 @@
Grails Metrics plugin
Copyright 2010-2012 Coda Hale and Yammer, Inc.
Copyright 2010-2013 Coda Hale and Yammer, Inc.

This product includes software developed by Coda Hale and Yammer, Inc.

Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -106,11 +106,11 @@ License
-------

This plugin is
Copyright (c) 2012 Jeff Ellis
Copyright (c) 2013 Jeff Ellis

Published under Apache Software License 2.0, see LICENSE

The metrics jars are:
Copyright (c) 2010-2012 Coda Hale, Yammer.com
Copyright (c) 2010-2013 Coda Hale, Yammer.com

Published under Apache Software License 2.0
62 changes: 47 additions & 15 deletions YammerMetricsGrailsPlugin.groovy
@@ -1,15 +1,14 @@
import com.codahale.metrics.MetricRegistry
import com.codahale.metrics.health.HealthCheckRegistry
import com.codahale.metrics.servlets.HealthCheckServlet
import com.codahale.metrics.servlets.MetricsServlet
import org.apache.commons.lang.StringUtils
import org.grails.plugins.yammermetrics.groovy.HealthCheckServletContextListener
import org.grails.plugins.yammermetrics.groovy.MetricsServletContextListener
import grails.util.Holders
import org.grails.plugins.yammermetrics.groovy.HealthCheckServletContextInitializer
import org.grails.plugins.yammermetrics.groovy.HealthCheckServletContextInitializer
import org.grails.plugins.yammermetrics.groovy.MetricsServletContextInitializer

import javax.servlet.ServletContextEvent
import java.util.concurrent.TimeUnit

/*
* Copyright 2012 Jeff Ellis
* Copyright 2013 Jeff Ellis
*/
class YammerMetricsGrailsPlugin {

Expand Down Expand Up @@ -42,15 +41,48 @@ See the source code documentation on Github for more details.
def doWithWebDescriptor = { xml ->

if(application.config.metrics.servletEnabled!=false){
def count = xml.'servlet'.size()
def count

// It doesn't seem like context-params are where Coda meant for these to be defined based on the
// MetricsServlet.ContextListener, but this is where MetricsServlet actually reads them from. Need to
// file an issue or at least verify this is what he meant.

count = xml.'context-param'.size()
if(count > 0) {

def contextParamElement = xml.'context-param'[count - 1]

def unit = Holders.getConfig().yammermetrics.servlet.rateUnit
if(unit instanceof String) {
contextParamElement + {
'context-param' {
'param-name'(MetricsServlet.RATE_UNIT)
'param-value'(unit)
}
}
}

unit = Holders.getConfig().yammermetrics.servlet.durationUnit
if(unit instanceof String) {
contextParamElement + {
'context-param' {
'param-name'(MetricsServlet.DURATION_UNIT)
'param-value'(unit)
}
}
}

}

count = xml.'servlet'.size()
if(count > 0) {

def servletElement = xml.'servlet'[count - 1]

servletElement + {
'servlet' {
'servlet-name'("YammerMetrics")
'servlet-class'("org.grails.plugins.yammermetrics.reporting.GrailsAdminServlet")
'servlet-class'("com.codahale.metrics.servlets.AdminServlet")
}
}
println "***\nYammerMetrics servlet injected into web.xml"
Expand Down Expand Up @@ -88,16 +120,16 @@ See the source code documentation on Github for more details.
def doWithApplicationContext = { applicationContext ->

// Create registries for HealthChecks and Metrics here, and stuff them into the servlet context. Don't
// wait for the regular listener lifecycle because that happens after application BootStrap.groovy.
// wait for the regular listener lifecycle because that happens after application BootStrap.groovy. Since
// we're doing this here, there is no need to wire them as real listeners.

ServletContextEvent event = new ServletContextEvent(applicationContext.servletContext)
HealthCheckServletContextListener healthCheckServletContextListener = new HealthCheckServletContextListener()
healthCheckServletContextListener.contextInitialized(event)
HealthCheckServletContextInitializer healthCheckServletContextInitializer = new HealthCheckServletContextInitializer()
healthCheckServletContextInitializer.contextInitialized(event)

MetricsServletContextListener metricsServletContextListener = new MetricsServletContextListener()
metricsServletContextListener.contextInitialized(event)
MetricsServletContextInitializer metricsServletContextInitializer = new MetricsServletContextInitializer()
metricsServletContextInitializer.contextInitialized(event)

println "Registries in servletContext"
}

def onChange = { event ->
Expand Down
7 changes: 5 additions & 2 deletions example-app/grails-app/conf/Config.groovy
@@ -1,3 +1,5 @@
import java.util.concurrent.TimeUnit

// locations to search for config files that get merged into the main config;
// config files can be ConfigSlurper scripts, Java properties files, or classes
// in the classpath in ConfigSlurper format
Expand Down Expand Up @@ -90,5 +92,6 @@ log4j = {
'net.sf.ehcache.hibernate'
}

println "Setting metrics.servletUrlPattern"
//metrics.servletUrlPattern = "/groovy-metrics/*"
//metrics.servletUrlPattern = "/groovy-metrics/*"
yammermetrics.servlet.rateUnit = "days"
yammermetrics.servlet.durationUnit = "hours"
@@ -1,6 +1,8 @@
package metricstest

import com.codahale.metrics.Counter
import com.codahale.metrics.Gauge
import com.codahale.metrics.Histogram
import org.grails.plugins.yammermetrics.groovy.Metered
import org.grails.plugins.yammermetrics.groovy.Metrics
import org.grails.plugins.yammermetrics.groovy.Timed
Expand All @@ -16,6 +18,9 @@ class PegController {
}
}

Counter counter = Metrics.newCounter("count.something")
Histogram histogram = Metrics.newHistogram("sample.histogram")

PegController() {
Metrics.newGauge("DepthGauge", new DepthGauge())
}
Expand All @@ -31,4 +36,14 @@ class PegController {
render( contentType: "text/plain", text: "Timed!" )
}

def counter() {
counter.inc()
render( contentType: "text/plain", text: "Counted!" )
}

def histogram() {
histogram.update(1)
render( contentType: "text/plain", text: "Histogram updated!" )
}

}
2 changes: 2 additions & 0 deletions grails-app/conf/Config.groovy
@@ -1,3 +1,5 @@
import java.util.concurrent.TimeUnit

// configuration for plugin testing - will not be included in the plugin zip

log4j = {
Expand Down
Expand Up @@ -3,7 +3,7 @@ package org.grails.plugins.yammermetrics.groovy
import com.codahale.metrics.health.HealthCheckRegistry
import com.codahale.metrics.servlets.HealthCheckServlet

class HealthCheckServletContextListener extends HealthCheckServlet.ContextListener {
class HealthCheckServletContextInitializer extends HealthCheckServlet.ContextListener {

public final HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry()

Expand Down
Expand Up @@ -9,11 +9,20 @@ class HealthChecks {

private static final HealthCheckRegistry builtInRegistry = new HealthCheckRegistry()

static void register( String name, HealthCheck healthCheck) {
static void register( String name, HealthCheck healthCheck ) {
HealthCheckRegistry registry = getRegistry()
registry.register(name, healthCheck)
}

static HealthCheckRegistry getRegistry() {
// Use the registry from the servletContext if one has been configured in doWithApplicationContext (i.e., the
// normal runtime case for apps using the plugin) or fall back to the built in one otherwise (e.g., unit tests
// which happen to touch instrumented classes)

HealthCheckRegistry registry = Holders?.servletContext?.getAttribute(HealthCheckServlet.HEALTH_CHECK_REGISTRY)
if(!registry) {
if (!registry) {
registry = builtInRegistry
}
registry.register(name, healthCheck)
return registry
}
}
84 changes: 55 additions & 29 deletions src/groovy/org/grails/plugins/yammermetrics/groovy/Metrics.groovy
Expand Up @@ -4,72 +4,98 @@ import com.codahale.metrics.Counter
import com.codahale.metrics.Histogram
import com.codahale.metrics.JmxReporter
import com.codahale.metrics.Meter
import com.codahale.metrics.Metric
import com.codahale.metrics.MetricFilter
import com.codahale.metrics.MetricRegistry
import com.codahale.metrics.Reservoir
import com.codahale.metrics.servlets.MetricsServlet
import com.codahale.metrics.Gauge
import grails.util.Holders
import org.codehaus.groovy.reflection.ReflectionUtils

import java.util.concurrent.TimeUnit

class Metrics {

private static final MetricRegistry builtInRegistry = new MetricRegistry()

// ignore org.springsource.loaded.ri.ReflectiveInterceptor when not running as a war, and ignore this class for convenience
static final List<String> extraIgnoredPackages = ["org.springsource.loaded.ri", "org.grails.plugins.yammermetrics.groovy"]
// ignore org.springsource.loaded.ri.ReflectiveInterceptor when not running as a war, and ignore this class for convenience
static final List<String> extraIgnoredPackages = ["org.springsource.loaded.ri", "org.grails.plugins.yammermetrics.groovy"]

private Metrics() { super() }
private static String expandNameToIncludeCallingClass(String metricName) {
Class callingClass = ReflectionUtils.getCallingClass(0, extraIgnoredPackages)
return MetricRegistry.name(callingClass, metricName)
}

static Gauge newGauge(String gaugeName, Gauge gauge){
String metricName = MetricRegistry.name(ReflectionUtils.getCallingClass(0, extraIgnoredPackages), gaugeName)
def metric = registry.getGauges().get(metricName)
if(!metric) {
metric = registry.register(metricName, gauge)
static Metric getOrAdd(String name, Metric metricToAdd) {
String metricName = expandNameToIncludeCallingClass(name)
Metric metric = registry.getMetrics().get(metricName)
if (!metric) {
metric = registry.register(metricName, metricToAdd)
}
return metric
}

static Counter newCounter(String counterName){
return registry.counter(MetricRegistry.name(ReflectionUtils.getCallingClass(0, extraIgnoredPackages), counterName))
static Gauge newGauge(String name, Gauge gauge) {
return getOrAdd(name, gauge) as Gauge
}

static Histogram newHistogram(String name){
return registry.histogram(MetricRegistry.name(ReflectionUtils.getCallingClass(0, extraIgnoredPackages), name))
static Counter newCounter(String name) {
String metricName = expandNameToIncludeCallingClass(name)
return registry.counter(metricName)
}

static Histogram newHistogram(String name, Reservoir reservoir){
String metricName = MetricRegistry.name(ReflectionUtils.getCallingClass(0, extraIgnoredPackages), name)
def metric = registry.getHistograms().get(metricName)
if(!metric) {
Histogram histogram = new Histogram(reservoir)
metric = registry.register(metricName, histogram)
}
return metric
static Histogram newHistogram(String name) {
String metricName = expandNameToIncludeCallingClass(name)
return registry.histogram(metricName)
}

static Histogram newHistogram(String name, Reservoir reservoir) {
Histogram histogram = new Histogram(reservoir)
return getOrAdd(name, histogram) as Histogram
}

static Meter newMeter(String meterName){
return registry.meter(MetricRegistry.name(ReflectionUtils.getCallingClass(0, extraIgnoredPackages), meterName))
static Meter newMeter(String name) {
String metricName = expandNameToIncludeCallingClass(name)
return registry.meter(metricName)
}

static com.codahale.metrics.Timer newTimer(String timerName){
return registry.timer(MetricRegistry.name(ReflectionUtils.getCallingClass(0, extraIgnoredPackages), timerName))
static com.codahale.metrics.Timer newTimer(String name) {
String metricName = expandNameToIncludeCallingClass(name)
return registry.timer(metricName)
}

static com.codahale.metrics.Timer newTimer(Class owner, String timerName){
return registry.timer(MetricRegistry.name(owner, timerName))
static com.codahale.metrics.Timer newTimer(Class owner, String name) {
String metricName = MetricRegistry.name(owner, name)
return registry.timer(metricName)
}

static MetricRegistry getRegistry() {

// Use the registry from the servletContext if one has been configured in doWithApplicationContext (i.e., the
// normal runtime case for apps using the plugin) or fall back to the built in one otherwise (e.g., unit tests
// which happen to touch instrumented classes)

MetricRegistry metricRegistry = Holders?.servletContext?.getAttribute(MetricsServlet.METRICS_REGISTRY) as MetricRegistry
if(!metricRegistry) {
if (!metricRegistry) {
metricRegistry = builtInRegistry
}
return metricRegistry
}

static JmxReporter startJmxReporter() {
final JmxReporter reporter = JmxReporter.forRegistry(Metrics.getRegistry()).build();
static JmxReporter startJmxReporter(TimeUnit rateUnit = TimeUnit.SECONDS, TimeUnit durationUnit = TimeUnit.MILLISECONDS) {
final JmxReporter reporter = JmxReporter
.forRegistry(registry)
.convertRatesTo(rateUnit)
.convertDurationsTo(durationUnit)
.build();
reporter.start();
return reporter
}

static removeAll() {
registry.removeMatching(MetricFilter.ALL)
}

private Metrics() {}
}
@@ -0,0 +1,36 @@
package org.grails.plugins.yammermetrics.groovy

import com.codahale.metrics.MetricRegistry
import com.codahale.metrics.servlets.MetricsServlet
import grails.util.Holders

import java.util.concurrent.TimeUnit

class MetricsServletContextInitializer extends MetricsServlet.ContextListener {

public final MetricRegistry metricRegistry = new MetricRegistry()

@Override
protected MetricRegistry getMetricRegistry() {
return metricRegistry
}

@Override
protected TimeUnit getRateUnit() {
return getUnitFromConfig("rateUnit")
}

@Override
protected TimeUnit getDurationUnit() {
return getUnitFromConfig("durationUnit")
}

private TimeUnit getUnitFromConfig(String propertyName) {
def unit = Holders.config.yammermetrics.servlet[propertyName]
if (unit instanceof String) {
return TimeUnit.valueOf(unit.toUpperCase(Locale.US))
}
return null
}

}

This file was deleted.

0 comments on commit 43082b6

Please sign in to comment.