Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

POC using yammer metrics ( http://metrics.codahale.com ) in NX.

  • Loading branch information...
commit 010d992c82d2e7567b2625af8d7b4941d272cb4f 1 parent 20ebbdb
@jdillon jdillon authored
View
21 nexus-core/pom.xml
@@ -257,6 +257,27 @@
<artifactId>javasimon-core</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-guice</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-httpclient</artifactId>
+ </dependency>
+
<!-- Testing -->
<dependency>
<groupId>org.sonatype.nexus</groupId>
View
3  nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/Hc4ProviderBase.java
@@ -265,9 +265,8 @@ protected void configureProxy( final DefaultHttpClient httpClient, final RemoteP
* Sub-classed here to customize the http processor and to keep a sane logger name.
*/
private static class DefaultHttpClientImpl
- extends DefaultHttpClient
+ extends InstrumentedHttpClient
{
-
private DefaultHttpClientImpl( final ClientConnectionManager conman, final HttpParams params )
{
super( conman, params );
View
3  nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/Hc4ProviderImpl.java
@@ -18,6 +18,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import com.yammer.metrics.httpclient.InstrumentedClientConnManager;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.scheme.PlainSocketFactory;
@@ -275,7 +276,7 @@ protected PoolingClientConnectionManager createClientConnectionManager(
schemeRegistry.register( new Scheme( "http", 80, PlainSocketFactory.getSocketFactory() ) );
schemeRegistry.register( new Scheme( "https", 443, SSLSocketFactory.getSocketFactory() ) );
- final PoolingClientConnectionManager connManager = new PoolingClientConnectionManager( schemeRegistry )
+ final PoolingClientConnectionManager connManager = new InstrumentedClientConnManager( schemeRegistry )
{
@Override
protected ClientConnectionOperator createConnectionOperator( final SchemeRegistry defaultSchemeRegistry )
View
74 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/InstrumentedHttpClient.java
@@ -0,0 +1,74 @@
+package org.sonatype.nexus.apachehttpclient;
+
+import com.yammer.metrics.Metrics;
+import com.yammer.metrics.core.MetricsRegistry;
+import com.yammer.metrics.httpclient.InstrumentedClientConnManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.client.*;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestExecutor;
+
+// NOTE: Duplicated and augmented from original 2.2.0 source to change signature of CTOR ClientConnectionManager parameter
+// NOTE: Should get this changes into metrics-httpclient and avoid needing this
+
+public class InstrumentedHttpClient extends DefaultHttpClient {
+ private final Log log = LogFactory.getLog(getClass());
+
+ private final MetricsRegistry registry;
+
+ public InstrumentedHttpClient(MetricsRegistry registry,
+ ClientConnectionManager manager,
+ HttpParams params) {
+ super(manager, params);
+ this.registry = registry;
+ }
+
+ public InstrumentedHttpClient(ClientConnectionManager manager, HttpParams params) {
+ this(Metrics.defaultRegistry(), manager, params);
+ }
+
+ public InstrumentedHttpClient(HttpParams params) {
+ this(new InstrumentedClientConnManager(), params);
+ }
+
+ public InstrumentedHttpClient() {
+ this(null);
+ }
+
+ @Override
+ protected RequestDirector createClientRequestDirector(HttpRequestExecutor requestExec,
+ ClientConnectionManager conman,
+ ConnectionReuseStrategy reustrat,
+ ConnectionKeepAliveStrategy kastrat,
+ HttpRoutePlanner rouplan,
+ HttpProcessor httpProcessor,
+ HttpRequestRetryHandler retryHandler,
+ RedirectStrategy redirectStrategy,
+ AuthenticationStrategy targetAuthStrategy,
+ AuthenticationStrategy proxyAuthStrategy,
+ UserTokenHandler userTokenHandler,
+ HttpParams params) {
+ return new InstrumentedRequestDirector(
+ registry,
+ log,
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectStrategy,
+ targetAuthStrategy,
+ proxyAuthStrategy,
+ userTokenHandler,
+ params);
+ }
+}
View
116 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/InstrumentedRequestDirector.java
@@ -0,0 +1,116 @@
+package org.sonatype.nexus.apachehttpclient;
+
+import com.yammer.metrics.core.MetricsRegistry;
+import com.yammer.metrics.core.Timer;
+import com.yammer.metrics.core.TimerContext;
+import org.apache.commons.logging.Log;
+import org.apache.http.*;
+import org.apache.http.client.*;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.impl.client.DefaultRequestDirector;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestExecutor;
+
+import java.io.IOException;
+
+// NOTE: Duplicated and unchanged from original 2.2.0 source to support change in InstrumentedHttpClient
+// NOTE: Should get this changes into metrics-httpclient and avoid needing this
+
+class InstrumentedRequestDirector
+ extends DefaultRequestDirector {
+ private final static String GET = "GET", POST = "POST", HEAD = "HEAD", PUT = "PUT",
+ OPTIONS = "OPTIONS", DELETE = "DELETE", TRACE = "TRACE",
+ CONNECT = "CONNECT", MOVE = "MOVE", PATCH = "PATCH";
+
+ private final Timer getTimer;
+ private final Timer postTimer;
+ private final Timer headTimer;
+ private final Timer putTimer;
+ private final Timer deleteTimer;
+ private final Timer optionsTimer;
+ private final Timer traceTimer;
+ private final Timer connectTimer;
+ private final Timer moveTimer;
+ private final Timer patchTimer;
+ private final Timer otherTimer;
+
+ InstrumentedRequestDirector(MetricsRegistry registry,
+ Log log,
+ HttpRequestExecutor requestExec,
+ ClientConnectionManager conman,
+ ConnectionReuseStrategy reustrat,
+ ConnectionKeepAliveStrategy kastrat,
+ HttpRoutePlanner rouplan,
+ HttpProcessor httpProcessor,
+ HttpRequestRetryHandler retryHandler,
+ RedirectStrategy redirectStrategy,
+ AuthenticationStrategy targetAuthStrategy,
+ AuthenticationStrategy proxyAuthStrategy,
+ UserTokenHandler userTokenHandler,
+ HttpParams params) {
+ super(log,
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectStrategy,
+ targetAuthStrategy,
+ proxyAuthStrategy,
+ userTokenHandler,
+ params);
+ getTimer = registry.newTimer(HttpClient.class, "get-requests");
+ postTimer = registry.newTimer(HttpClient.class, "post-requests");
+ headTimer = registry.newTimer(HttpClient.class, "head-requests");
+ putTimer = registry.newTimer(HttpClient.class, "put-requests");
+ deleteTimer = registry.newTimer(HttpClient.class, "delete-requests");
+ optionsTimer = registry.newTimer(HttpClient.class, "options-requests");
+ traceTimer = registry.newTimer(HttpClient.class, "trace-requests");
+ connectTimer = registry.newTimer(HttpClient.class, "connect-requests");
+ moveTimer = registry.newTimer(HttpClient.class, "move-requests");
+ patchTimer = registry.newTimer(HttpClient.class, "patch-requests");
+ otherTimer = registry.newTimer(HttpClient.class, "other-requests");
+ }
+
+ @Override
+ public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException, IOException {
+ final TimerContext timerContext = timer(request).time();
+ try {
+ return super.execute(target, request, context);
+ } finally {
+ timerContext.stop();
+ }
+ }
+
+ private Timer timer(HttpRequest request) {
+ final String method = request.getRequestLine().getMethod();
+ if (GET.equalsIgnoreCase(method)) {
+ return getTimer;
+ } else if (POST.equalsIgnoreCase(method)) {
+ return postTimer;
+ } else if (PUT.equalsIgnoreCase(method)) {
+ return putTimer;
+ } else if (HEAD.equalsIgnoreCase(method)) {
+ return headTimer;
+ } else if (DELETE.equalsIgnoreCase(method)) {
+ return deleteTimer;
+ } else if (OPTIONS.equalsIgnoreCase(method)) {
+ return optionsTimer;
+ } else if (TRACE.equalsIgnoreCase(method)) {
+ return traceTimer;
+ } else if (CONNECT.equalsIgnoreCase(method)) {
+ return connectTimer;
+ } else if (PATCH.equalsIgnoreCase(method)) {
+ return patchTimer;
+ } else if (MOVE.equalsIgnoreCase(method)) {
+ return moveTimer;
+ }
+ return otherTimer;
+ }
+}
View
4 nexus-core/src/main/java/org/sonatype/nexus/guice/NexusModules.java
@@ -14,6 +14,7 @@
package org.sonatype.nexus.guice;
import com.google.inject.AbstractModule;
+import com.yammer.metrics.guice.InstrumentationModule;
import org.apache.shiro.guice.aop.ShiroAopModule;
import org.sonatype.nexus.timing.TimingModule;
@@ -33,7 +34,8 @@
@Override
protected void configure() {
install(new ShiroAopModule());
- install(new TimingModule());
+ //install(new TimingModule());
+ install(new InstrumentationModule());
}
}
View
2  nexus-core/src/main/java/org/sonatype/nexus/plugins/DefaultNexusPluginManager.java
@@ -30,6 +30,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import com.yammer.metrics.annotation.Timed;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
@@ -132,6 +133,7 @@ public DefaultNexusPluginManager( final RepositoryTypeRegistry repositoryTypeReg
return new HashMap<GAVCoordinate, PluginResponse>( pluginResponses );
}
+ @Timed
public Collection<PluginManagerResponse> activateInstalledPlugins()
{
final List<PluginManagerResponse> result = new ArrayList<PluginManagerResponse>();
View
4 nexus-logging-extras/src/main/resources/META-INF/log/logback-nexus.xml
@@ -23,6 +23,7 @@
<pattern>${appender.pattern}</pattern>
</encoder>
</appender>
+
<appender name="logfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${appender.file}</File>
<Append>true</Append>
@@ -34,6 +35,8 @@
</rollingPolicy>
</appender>
+ <appender name="metrics" class="com.yammer.metrics.logback.InstrumentedAppender"/>
+
<logger name="org.sonatype.nexus.rest.NexusApplication" level="WARN" />
<logger name="httpclient" level="INFO" />
<logger name="org.apache.http" level="INFO" />
@@ -47,6 +50,7 @@
<root level="${root.level}">
<appender-ref ref="console" />
<appender-ref ref="logfile" />
+ <appender-ref ref="metrics" />
</root>
</included>
View
15 nexus-oss-webapp/pom.xml
@@ -123,6 +123,21 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-jetty</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-logback</artifactId>
+ </dependency>
</dependencies>
<build>
View
4 nexus-oss-webapp/src/main/assembly/bundle.xml
@@ -106,6 +106,7 @@
<exclude>WEB-INF/lib/logback-core*.jar</exclude>
<exclude>WEB-INF/lib/logback-classic*.jar</exclude>
<exclude>WEB-INF/lib/nexus-logging-extras-appender*.jar</exclude>
+ <exclude>WEB-INF/lib/metrics-core*.jar</exclude>
<exclude>WEB-INF/classes/logback.xml</exclude>
</excludes>
</unpackOptions>
@@ -128,6 +129,9 @@
<include>org.sonatype.appcontext:*</include>
<include>org.slf4j:*</include>
<include>ch.qos.logback:*</include>
+ <include>com.yammer.metrics:metrics-core</include>
+ <include>com.yammer.metrics:metrics-jetty</include>
+ <include>com.yammer.metrics:metrics-logback</include>
</includes>
</dependencySet>
</dependencySets>
View
9 nexus-oss-webapp/src/main/resources/content/conf/jetty.xml
@@ -24,13 +24,14 @@
<!-- ============================================================ -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Set name="threadPool">
- <New class="org.sonatype.sisu.jetty.thread.InstrumentedQueuedThreadPool"/>
+ <New class="com.yammer.metrics.jetty.InstrumentedQueuedThreadPool"/>
</Set>
<Call name="addConnector">
<Arg>
- <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
- <Set name="host">${application-host}</Set>
- <Set name="port">${application-port}</Set>
+ <New class="com.yammer.metrics.jetty.InstrumentedSelectChannelConnector">
+ <Arg type="int">${application-port}</Arg>
+ <!--<Set name="host">${application-host}</Set>-->
+ <!--<Set name="port">${application-port}</Set>-->
</New>
</Arg>
</Call>
View
10 nexus-webapp/pom.xml
@@ -73,6 +73,16 @@
</dependency>
<dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-web</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-oss-edition</artifactId>
</dependency>
View
70 nexus-webapp/src/main/java/org/sonatype/nexus/webapp/MetricsModule.java
@@ -0,0 +1,70 @@
+package org.sonatype.nexus.webapp;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.inject.AbstractModule;
+import com.google.inject.servlet.ServletModule;
+import com.yammer.metrics.HealthChecks;
+import com.yammer.metrics.Metrics;
+import com.yammer.metrics.core.Clock;
+import com.yammer.metrics.core.HealthCheckRegistry;
+import com.yammer.metrics.core.MetricsRegistry;
+import com.yammer.metrics.core.VirtualMachineMetrics;
+import com.yammer.metrics.reporting.HealthCheckServlet;
+import com.yammer.metrics.reporting.MetricsServlet;
+import com.yammer.metrics.reporting.PingServlet;
+import com.yammer.metrics.reporting.ThreadDumpServlet;
+import com.yammer.metrics.web.DefaultWebappMetricsFilter;
+
+import javax.inject.Named;
+
+/**
+ * ???
+ *
+ * @since 2.4
+ */
+public class MetricsModule
+ extends AbstractModule
+{
+ @Override
+ protected void configure() {
+ // NOTE: AdminServletModule (metrics-guice intgegration) generates invalid links, so wire up servlets ourselves
+
+ install(new ServletModule()
+ {
+ @Override
+ protected void configureServlets() {
+ JsonFactory jsonFactory = new JsonFactory(new ObjectMapper());
+ bind(JsonFactory.class).toInstance(jsonFactory);
+
+ HealthCheckRegistry healthCheckRegistry = HealthChecks.defaultRegistry();
+ bind(HealthCheckRegistry.class).toInstance(healthCheckRegistry);
+
+ MetricsRegistry metricsRegistry = Metrics.defaultRegistry();
+ bind(MetricsRegistry.class).toInstance(metricsRegistry);
+
+ Clock clock = Clock.defaultClock();
+ bind(Clock.class).toInstance(clock);
+
+ VirtualMachineMetrics virtualMachineMetrics = VirtualMachineMetrics.getInstance();
+ bind(VirtualMachineMetrics.class).toInstance(virtualMachineMetrics);
+
+ serve("/internal/ping").with(new PingServlet());
+
+ serve("/internal/threads").with(new ThreadDumpServlet(virtualMachineMetrics));
+
+ serve("/internal/metrics").with(new MetricsServlet(
+ clock,
+ virtualMachineMetrics,
+ metricsRegistry,
+ jsonFactory,
+ true
+ ));
+
+ serve("/internal/healthcheck").with(new HealthCheckServlet(healthCheckRegistry));
+
+ filter("/*").through(new DefaultWebappMetricsFilter());
+ }
+ });
+ }
+}
View
20 nexus-webapp/src/main/java/org/sonatype/nexus/webapp/WebappModule.java
@@ -0,0 +1,20 @@
+package org.sonatype.nexus.webapp;
+
+import com.google.inject.AbstractModule;
+
+import javax.inject.Named;
+
+/**
+ * ???
+ *
+ * @since 2.4
+ */
+@Named
+public class WebappModule
+ extends AbstractModule
+{
+ @Override
+ protected void configure() {
+ install(new MetricsModule());
+ }
+}
View
2  .../restlet1x/nexus-restlet1x-plugin/src/main/java/org/sonatype/nexus/rest/status/StatusPlexusResource.java
@@ -19,6 +19,7 @@
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
+import com.yammer.metrics.annotation.Timed;
import org.codehaus.enunciate.contract.jaxrs.ResourceMethodSignature;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
@@ -32,7 +33,6 @@
import org.sonatype.nexus.rest.model.NexusAuthenticationClientPermissions;
import org.sonatype.nexus.rest.model.StatusResource;
import org.sonatype.nexus.rest.model.StatusResourceResponse;
-import org.sonatype.nexus.timing.Timed;
import org.sonatype.plexus.rest.resource.ManagedPlexusResource;
import org.sonatype.plexus.rest.resource.PathProtectionDescriptor;
import org.sonatype.security.rest.authentication.AbstractUIPermissionCalculatingPlexusResource;
View
49 pom.xml
@@ -180,6 +180,7 @@
<shiro.version>1.2.1</shiro.version>
<jackson.version>1.9.10</jackson.version>
<goodies.version>1.6</goodies.version>
+ <metrics.version>2.2.0</metrics.version>
<!-- See 'idea' profile. -->
<nexus-plugin.type>nexus-plugin</nexus-plugin.type>
@@ -836,6 +837,54 @@
<version>3.3.0</version>
</dependency>
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-guice</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-servlet</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-jersey</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-jetty</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-httpclient</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-logback</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-web</artifactId>
+ <version>${metrics.version}</version>
+ </dependency>
+
<!-- INTERNAL -->
<dependency>
Please sign in to comment.
Something went wrong with that request. Please try again.