Merge pull request #60 from rlinehan/TK-402-configurable-metric-namespace
(TK-402) Allow metric namespace to be configurable
This commit is contained in:
commit
c038015730
19 changed files with 306 additions and 57 deletions
|
@ -38,6 +38,13 @@ The following are the base set of options supported by the `create-client` funct
|
|||
to. If provided, metrics will automatically be registered for all requests
|
||||
made by the client. See the [metrics documentation](./metrics.md) for more
|
||||
info.
|
||||
* `:server-id`: a string for the name of the server the request is being made
|
||||
from. If specified, used in the namespace for metrics:
|
||||
`puppetlabs.<server-id>.http-client.experimental`.
|
||||
* `:metric-prefix`: a string for the prefix for metrics. If specified, metric
|
||||
namespace is `<metric-prefix>.http-client.experimental`. If both
|
||||
`metric-prefix` and `server-id` are specified, `metric-prefix` takes
|
||||
precendence.
|
||||
|
||||
### SSL Options
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ change.
|
|||
For using metrics with either the Java client or the Clojure client you must
|
||||
already have created a Dropwizard `MetricRegistry`.
|
||||
|
||||
- [Metrics prefix](#metrics-prefix)
|
||||
- [Metric namespace](#metric-namespace)
|
||||
- [Types of metrics](#types-of-metrics)
|
||||
- [Getting back metrics](#getting-back-metrics)
|
||||
- [Clojure API](#clojure-api)
|
||||
|
@ -29,9 +29,26 @@ already have created a Dropwizard `MetricRegistry`.
|
|||
- [Filtering by metric-id](#filtering-by-metric-id-1)
|
||||
|
||||
|
||||
## Metrics prefix
|
||||
## Metric namespace
|
||||
|
||||
All http metrics are prefixed with `puppetlabs.http-client.experimental`.
|
||||
By default, http metrics are prefixed with the namespace
|
||||
`puppetlabs.http-client.experimental`. This namespace can be customized with two
|
||||
client options, `server-id` and `metric-prefix`.
|
||||
|
||||
When `server-id` is set, the metric namespace becomes
|
||||
`puppetlabs.<server-id>.http-client.experimental`.
|
||||
|
||||
When `metric-prefix` is set, the metric namespace becomes
|
||||
`<metric-prefix>.http-client.experimental`.
|
||||
|
||||
If both `server-id` and `metric-prefix` are set, `metric-prefix` wins out and
|
||||
a warning message is logged.
|
||||
|
||||
For a Clojure client, the `get-client-metric-namespace` protocol method can
|
||||
be used to get back the metric namespace set for the client.
|
||||
|
||||
For a Java client, the `getMetricNamespace` method can be used to get back the
|
||||
configured metric namespace.
|
||||
|
||||
## Types of metrics
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(def ks-version "1.2.0")
|
||||
(def tk-version "1.1.1")
|
||||
(def ks-version "1.3.0")
|
||||
(def tk-version "1.5.1")
|
||||
(def tk-jetty-version "1.5.0")
|
||||
|
||||
(defproject puppetlabs/http-client "0.5.1-SNAPSHOT"
|
||||
|
@ -17,7 +17,7 @@
|
|||
[org.apache.httpcomponents/httpasyncclient "4.1.2"]
|
||||
[org.apache.commons/commons-lang3 "3.4"]
|
||||
[prismatic/schema "1.0.4"]
|
||||
[org.slf4j/slf4j-api "1.7.13"]
|
||||
[org.slf4j/slf4j-api "1.7.20"]
|
||||
[commons-io "2.4"]
|
||||
[io.dropwizard.metrics/metrics-core "3.1.2"]
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
(org.apache.http.nio.client HttpAsyncClient)
|
||||
(com.codahale.metrics MetricRegistry))
|
||||
(:require [puppetlabs.http.client.common :as common]
|
||||
[schema.core :as schema])
|
||||
[schema.core :as schema]
|
||||
[puppetlabs.http.client.metrics :as metrics])
|
||||
(:refer-clojure :exclude (get)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -25,7 +26,8 @@
|
|||
(schema/defn ^:always-validate create-default-client :- HttpAsyncClient
|
||||
[{:keys [ssl-context ssl-ca-cert ssl-cert ssl-key ssl-protocols cipher-suites
|
||||
follow-redirects force-redirects connect-timeout-milliseconds
|
||||
socket-timeout-milliseconds metric-registry]}:- common/ClientOptions]
|
||||
socket-timeout-milliseconds metric-registry server-id
|
||||
metric-prefix]}:- common/ClientOptions]
|
||||
(let [client-options (ClientOptions.)]
|
||||
(cond-> client-options
|
||||
(some? ssl-context) (.setSslContext ssl-context)
|
||||
|
@ -40,7 +42,9 @@
|
|||
(.setConnectTimeoutMilliseconds connect-timeout-milliseconds)
|
||||
(some? socket-timeout-milliseconds)
|
||||
(.setSocketTimeoutMilliseconds socket-timeout-milliseconds)
|
||||
(some? metric-registry) (.setMetricRegistry metric-registry))
|
||||
(some? metric-registry) (.setMetricRegistry metric-registry)
|
||||
(some? server-id) (.setServerId server-id)
|
||||
(some? metric-prefix) (.setMetricPrefix metric-prefix))
|
||||
(JavaClient/createClient client-options)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -161,11 +165,12 @@
|
|||
([opts :- common/RawUserRequestOptions
|
||||
callback :- common/ResponseCallbackFn
|
||||
client :- HttpAsyncClient]
|
||||
(request-with-client opts callback client nil))
|
||||
(request-with-client opts callback client nil nil))
|
||||
([opts :- common/RawUserRequestOptions
|
||||
callback :- common/ResponseCallbackFn
|
||||
client :- HttpAsyncClient
|
||||
metric-registry :- (schema/maybe MetricRegistry)]
|
||||
metric-registry :- (schema/maybe MetricRegistry)
|
||||
metric-namespace :- (schema/maybe schema/Str)]
|
||||
(let [result (promise)
|
||||
defaults {:headers {}
|
||||
:body nil
|
||||
|
@ -176,7 +181,8 @@
|
|||
java-method (clojure-method->java opts)
|
||||
response-delivery-delegate (get-response-delivery-delegate opts result)]
|
||||
(JavaClient/requestWithClient java-request-options java-method callback
|
||||
client response-delivery-delegate metric-registry)
|
||||
client response-delivery-delegate metric-registry
|
||||
metric-namespace)
|
||||
result)))
|
||||
|
||||
(schema/defn create-client :- (schema/protocol common/HTTPClient)
|
||||
|
@ -223,7 +229,8 @@
|
|||
* :ssl-ca-cert - path to a PEM file containing the CA cert"
|
||||
[opts :- common/ClientOptions]
|
||||
(let [client (create-default-client opts)
|
||||
metric-registry (:metric-registry opts)]
|
||||
metric-registry (:metric-registry opts)
|
||||
metric-namespace (metrics/build-metric-namespace (:metric-prefix opts) (:server-id opts))]
|
||||
(reify common/HTTPClient
|
||||
(get [this url] (common/get this url {}))
|
||||
(get [this url opts] (common/make-request this url :get opts))
|
||||
|
@ -244,6 +251,8 @@
|
|||
(make-request [this url method] (common/make-request this url method {}))
|
||||
(make-request [_ url method opts] (request-with-client
|
||||
(assoc opts :method method :url url)
|
||||
nil client metric-registry))
|
||||
nil client metric-registry
|
||||
metric-namespace))
|
||||
(close [_] (.close client))
|
||||
(get-client-metric-registry [_] metric-registry))))
|
||||
(get-client-metric-registry [_] metric-registry)
|
||||
(get-client-metric-namespace [_] metric-namespace))))
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
(patch [this url] [this url opts])
|
||||
(make-request [this url method] [this url method opts])
|
||||
(close [this])
|
||||
(get-client-metric-registry [this]))
|
||||
(get-client-metric-registry [this])
|
||||
(get-client-metric-namespace [this]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Schemas
|
||||
|
@ -113,7 +114,9 @@
|
|||
(ok :follow-redirects) schema/Bool
|
||||
(ok :connect-timeout-milliseconds) schema/Int
|
||||
(ok :socket-timeout-milliseconds) schema/Int
|
||||
(ok :metric-registry) MetricRegistry})
|
||||
(ok :metric-registry) MetricRegistry
|
||||
(ok :server-id) schema/Str
|
||||
(ok :metric-prefix) schema/Str})
|
||||
|
||||
(def UserRequestOptions
|
||||
"A cleaned-up version of RawUserRequestClientOptions, which is formed after
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(:require [schema.core :as schema]
|
||||
[puppetlabs.http.client.common :as common])
|
||||
(:import (com.puppetlabs.http.client.metrics Metrics$MetricType Metrics
|
||||
ClientMetricData)
|
||||
ClientMetricData)
|
||||
(com.codahale.metrics MetricRegistry)))
|
||||
|
||||
(schema/defn get-base-metric-data :- common/BaseMetricData
|
||||
|
@ -33,6 +33,10 @@
|
|||
[method]
|
||||
(clojure.string/upper-case (name method)))
|
||||
|
||||
(defn build-metric-namespace
|
||||
[metric-prefix server-id]
|
||||
(Metrics/buildMetricNamespace metric-prefix server-id))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Public
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
(ns puppetlabs.http.client.sync
|
||||
(:require [puppetlabs.http.client.async :as async]
|
||||
[schema.core :as schema]
|
||||
[puppetlabs.http.client.common :as common])
|
||||
[puppetlabs.http.client.common :as common]
|
||||
[puppetlabs.http.client.metrics :as metrics])
|
||||
(:refer-clojure :exclude (get)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -24,10 +25,10 @@
|
|||
|
||||
(defn request-with-client
|
||||
([req client]
|
||||
(request-with-client req client nil))
|
||||
([req client metric-registry]
|
||||
(request-with-client req client nil nil))
|
||||
([req client metric-registry metric-namespace]
|
||||
(let [{:keys [error] :as resp} @(async/request-with-client
|
||||
req nil client metric-registry)]
|
||||
req nil client metric-registry metric-namespace)]
|
||||
(if error
|
||||
(throw error)
|
||||
resp))))
|
||||
|
@ -37,12 +38,13 @@
|
|||
(defn request
|
||||
[req]
|
||||
(with-open [client (async/create-default-client (extract-client-opts req))]
|
||||
(request-with-client (extract-request-opts req) client nil)))
|
||||
(request-with-client (extract-request-opts req) client)))
|
||||
|
||||
(schema/defn create-client :- (schema/protocol common/HTTPClient)
|
||||
[opts :- common/ClientOptions]
|
||||
(let [client (async/create-default-client opts)
|
||||
metric-registry (:metric-registry opts)]
|
||||
metric-registry (:metric-registry opts)
|
||||
metric-namespace (metrics/build-metric-namespace (:metric-prefix opts) (:server-id opts))]
|
||||
(reify common/HTTPClient
|
||||
(get [this url] (common/get this url {}))
|
||||
(get [this url opts] (common/make-request this url :get opts))
|
||||
|
@ -63,9 +65,10 @@
|
|||
(make-request [this url method] (common/make-request this url method {}))
|
||||
(make-request [_ url method opts] (request-with-client
|
||||
(assoc opts :method method :url url)
|
||||
client metric-registry))
|
||||
client metric-registry metric-namespace))
|
||||
(close [_] (.close client))
|
||||
(get-client-metric-registry [_] metric-registry))))
|
||||
(get-client-metric-registry [_] metric-registry)
|
||||
(get-client-metric-namespace [_] metric-namespace))))
|
||||
|
||||
(defn get
|
||||
"Issue a synchronous HTTP GET request. This will raise an exception if an
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package com.puppetlabs.http.client;
|
||||
|
||||
import com.puppetlabs.http.client.impl.SslUtils;
|
||||
import com.puppetlabs.http.client.impl.JavaClient;
|
||||
import com.puppetlabs.http.client.impl.PersistentAsyncHttpClient;
|
||||
import com.puppetlabs.http.client.impl.CoercedClientOptions;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.puppetlabs.http.client.metrics.Metrics;
|
||||
|
||||
/**
|
||||
* This class allows you to create an AsyncHttpClient for use in making
|
||||
|
@ -21,7 +19,9 @@ public class Async {
|
|||
* @return an AsyncHttpClient that can be used to make requests
|
||||
*/
|
||||
public static AsyncHttpClient createClient(ClientOptions clientOptions) {
|
||||
final String metricNamespace = Metrics.buildMetricNamespace(clientOptions.getMetricPrefix(),
|
||||
clientOptions.getServerId());
|
||||
return new PersistentAsyncHttpClient(JavaClient.createClient(clientOptions),
|
||||
clientOptions.getMetricRegistry());
|
||||
clientOptions.getMetricRegistry(),metricNamespace);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,11 @@ public interface AsyncHttpClient extends Closeable{
|
|||
*/
|
||||
public MetricRegistry getMetricRegistry();
|
||||
|
||||
/**
|
||||
* @return the String metricNamespace for this Client
|
||||
*/
|
||||
public String getMetricNamespace();
|
||||
|
||||
/**
|
||||
* Performs a GET request
|
||||
* @param url the URL against which to make the GET request
|
||||
|
|
|
@ -27,6 +27,8 @@ public class ClientOptions {
|
|||
private int connectTimeoutMilliseconds = -1;
|
||||
private int socketTimeoutMilliseconds = -1;
|
||||
private MetricRegistry metricRegistry;
|
||||
private String metricPrefix;
|
||||
private String serverId;
|
||||
|
||||
/**
|
||||
* Constructor for the ClientOptions class. When this constructor is called,
|
||||
|
@ -183,4 +185,22 @@ public class ClientOptions {
|
|||
this.metricRegistry = metricRegistry;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMetricPrefix() {
|
||||
return metricPrefix;
|
||||
}
|
||||
|
||||
public ClientOptions setMetricPrefix(String metricPrefix) {
|
||||
this.metricPrefix = metricPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
|
||||
public ClientOptions setServerId(String serverId) {
|
||||
this.serverId = serverId;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.puppetlabs.http.client;
|
|||
|
||||
import com.puppetlabs.http.client.impl.JavaClient;
|
||||
import com.puppetlabs.http.client.impl.PersistentSyncHttpClient;
|
||||
import com.puppetlabs.http.client.metrics.Metrics;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -84,8 +85,10 @@ public class Sync {
|
|||
* @return A persistent synchronous HTTP client
|
||||
*/
|
||||
public static SyncHttpClient createClient(ClientOptions clientOptions) {
|
||||
final String metricNamespace = Metrics.buildMetricNamespace(clientOptions.getMetricPrefix(),
|
||||
clientOptions.getServerId());
|
||||
return new PersistentSyncHttpClient(JavaClient.createClient(clientOptions),
|
||||
clientOptions.getMetricRegistry());
|
||||
clientOptions.getMetricRegistry(), metricNamespace);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,11 @@ public interface SyncHttpClient extends Closeable {
|
|||
*/
|
||||
public MetricRegistry getMetricRegistry();
|
||||
|
||||
/**
|
||||
* @return the String metricNamespace for this Client
|
||||
*/
|
||||
public String getMetricNamespace();
|
||||
|
||||
/**
|
||||
* Makes a configurable HTTP request
|
||||
* @param requestOptions the options to configure the request
|
||||
|
|
|
@ -263,7 +263,8 @@ public class JavaClient {
|
|||
final FutureCallback<HttpResponse> futureCallback,
|
||||
final HttpRequestBase request,
|
||||
final MetricRegistry metricRegistry,
|
||||
final String[] metricId) {
|
||||
final String[] metricId,
|
||||
final String metricNamespace) {
|
||||
|
||||
/*
|
||||
* Create an Apache AsyncResponseConsumer that will return the response to us as soon as it is available,
|
||||
|
@ -315,7 +316,7 @@ public class JavaClient {
|
|||
|
||||
TimedFutureCallback<HttpResponse> timedStreamingCompleteCallback =
|
||||
new TimedFutureCallback<>(streamingCompleteCallback,
|
||||
TimerUtils.startFullResponseTimers(metricRegistry, request, metricId));
|
||||
TimerUtils.startFullResponseTimers(metricRegistry, request, metricId, metricNamespace));
|
||||
client.execute(HttpAsyncMethods.create(request), consumer, timedStreamingCompleteCallback);
|
||||
}
|
||||
|
||||
|
@ -324,7 +325,8 @@ public class JavaClient {
|
|||
final IResponseCallback callback,
|
||||
final CloseableHttpAsyncClient client,
|
||||
final ResponseDeliveryDelegate responseDeliveryDelegate,
|
||||
final MetricRegistry registry) {
|
||||
final MetricRegistry registry,
|
||||
final String metricNamespace) {
|
||||
|
||||
final CoercedRequestOptions coercedRequestOptions = coerceRequestOptions(requestOptions, method);
|
||||
|
||||
|
@ -355,11 +357,11 @@ public class JavaClient {
|
|||
|
||||
final String[] metricId = requestOptions.getMetricId();
|
||||
if (requestOptions.getAs() == ResponseBodyType.UNBUFFERED_STREAM) {
|
||||
executeWithConsumer(client, futureCallback, request, registry, metricId);
|
||||
executeWithConsumer(client, futureCallback, request, registry, metricId, metricNamespace);
|
||||
} else {
|
||||
TimedFutureCallback<HttpResponse> timedFutureCallback =
|
||||
new TimedFutureCallback<>(futureCallback,
|
||||
TimerUtils.startFullResponseTimers(registry, request, metricId));
|
||||
TimerUtils.startFullResponseTimers(registry, request, metricId, metricNamespace));
|
||||
client.execute(request, timedFutureCallback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,14 @@ import java.net.URISyntaxException;
|
|||
public class PersistentAsyncHttpClient implements AsyncHttpClient {
|
||||
private CloseableHttpAsyncClient client;
|
||||
private MetricRegistry metricRegistry;
|
||||
private String metricNamespace;
|
||||
|
||||
public PersistentAsyncHttpClient(CloseableHttpAsyncClient client,
|
||||
MetricRegistry metricRegistry) {
|
||||
MetricRegistry metricRegistry,
|
||||
String metricNamespace) {
|
||||
this.client = client;
|
||||
this.metricRegistry = metricRegistry;
|
||||
this.metricNamespace = metricNamespace;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
|
@ -29,11 +32,15 @@ public class PersistentAsyncHttpClient implements AsyncHttpClient {
|
|||
return metricRegistry;
|
||||
}
|
||||
|
||||
public String getMetricNamespace() {
|
||||
return metricNamespace;
|
||||
}
|
||||
|
||||
private Promise<Response> request(RequestOptions requestOptions, HttpMethod method) {
|
||||
final Promise<Response> promise = new Promise<>();
|
||||
final JavaResponseDeliveryDelegate responseDelivery = new JavaResponseDeliveryDelegate(promise);
|
||||
JavaClient.requestWithClient(requestOptions, method, null,
|
||||
client, responseDelivery, metricRegistry);
|
||||
client, responseDelivery, metricRegistry, metricNamespace);
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,15 @@ import java.net.URISyntaxException;
|
|||
public class PersistentSyncHttpClient implements SyncHttpClient {
|
||||
private CloseableHttpAsyncClient client;
|
||||
private MetricRegistry metricRegistry;
|
||||
private String metricNamespace;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PersistentSyncHttpClient.class);
|
||||
|
||||
public PersistentSyncHttpClient(CloseableHttpAsyncClient client,
|
||||
MetricRegistry metricRegistry) {
|
||||
MetricRegistry metricRegistry,
|
||||
String metricNamespace) {
|
||||
this.client = client;
|
||||
this.metricRegistry = metricRegistry;
|
||||
this.metricNamespace = metricNamespace;
|
||||
}
|
||||
|
||||
private static void logAndRethrow(String msg, Throwable t) {
|
||||
|
@ -34,11 +37,15 @@ public class PersistentSyncHttpClient implements SyncHttpClient {
|
|||
return metricRegistry;
|
||||
}
|
||||
|
||||
public String getMetricNamespace() {
|
||||
return metricNamespace;
|
||||
}
|
||||
|
||||
public Response request(RequestOptions requestOptions, HttpMethod method) {
|
||||
final Promise<Response> promise = new Promise<>();
|
||||
final JavaResponseDeliveryDelegate responseDelivery = new JavaResponseDeliveryDelegate(promise);
|
||||
JavaClient.requestWithClient(requestOptions, method, null, client,
|
||||
responseDelivery, metricRegistry);
|
||||
responseDelivery, metricRegistry, metricNamespace);
|
||||
Response response = null;
|
||||
try {
|
||||
response = promise.deref();
|
||||
|
|
|
@ -41,7 +41,8 @@ public class TimerUtils {
|
|||
}
|
||||
|
||||
private static ArrayList<Timer.Context> startFullResponseMetricIdTimers(MetricRegistry registry,
|
||||
String[] metricId) {
|
||||
String[] metricId,
|
||||
String metricPrefix) {
|
||||
ArrayList<Timer.Context> timerContexts = new ArrayList<>();
|
||||
for (int i = 0; i < metricId.length; i++) {
|
||||
ArrayList<String> currentId = new ArrayList<>();
|
||||
|
@ -52,7 +53,7 @@ public class TimerUtils {
|
|||
currentIdWithNamespace.add(Metrics.NAMESPACE_METRIC_ID);
|
||||
currentIdWithNamespace.addAll(currentId);
|
||||
currentIdWithNamespace.add(Metrics.NAMESPACE_FULL_RESPONSE);
|
||||
String metric_name = MetricRegistry.name(Metrics.NAMESPACE_PREFIX,
|
||||
String metric_name = MetricRegistry.name(metricPrefix,
|
||||
currentIdWithNamespace.toArray(new String[currentIdWithNamespace.size()]));
|
||||
|
||||
ClientTimer timer = new MetricIdClientTimer(metric_name, currentId, Metrics.MetricType.FULL_RESPONSE);
|
||||
|
@ -62,16 +63,17 @@ public class TimerUtils {
|
|||
}
|
||||
|
||||
private static ArrayList<Timer.Context> startFullResponseUrlTimers(MetricRegistry registry,
|
||||
HttpRequest request) {
|
||||
HttpRequest request,
|
||||
String metricPrefix) {
|
||||
ArrayList<Timer.Context> timerContexts = new ArrayList<>();
|
||||
try {
|
||||
final RequestLine requestLine = request.getRequestLine();
|
||||
final String strippedUrl = Metrics.urlToMetricUrl(requestLine.getUri());
|
||||
final String method = requestLine.getMethod();
|
||||
|
||||
final String urlName = MetricRegistry.name(Metrics.NAMESPACE_PREFIX, Metrics.NAMESPACE_URL,
|
||||
final String urlName = MetricRegistry.name(metricPrefix, Metrics.NAMESPACE_URL,
|
||||
strippedUrl, Metrics.NAMESPACE_FULL_RESPONSE);
|
||||
final String urlAndMethodName = MetricRegistry.name(Metrics.NAMESPACE_PREFIX, Metrics.NAMESPACE_URL_AND_METHOD,
|
||||
final String urlAndMethodName = MetricRegistry.name(metricPrefix, Metrics.NAMESPACE_URL_AND_METHOD,
|
||||
strippedUrl, method, Metrics.NAMESPACE_FULL_RESPONSE);
|
||||
|
||||
ClientTimer urlTimer = new UrlClientTimer(urlName, strippedUrl, Metrics.MetricType.FULL_RESPONSE);
|
||||
|
@ -91,13 +93,14 @@ public class TimerUtils {
|
|||
|
||||
public static ArrayList<Timer.Context> startFullResponseTimers(MetricRegistry clientRegistry,
|
||||
HttpRequest request,
|
||||
String[] metricId) {
|
||||
String[] metricId,
|
||||
String metricNamespace) {
|
||||
if (clientRegistry != null) {
|
||||
ArrayList<Timer.Context> urlTimerContexts = startFullResponseUrlTimers(clientRegistry,request);
|
||||
ArrayList<Timer.Context> urlTimerContexts = startFullResponseUrlTimers(clientRegistry, request, metricNamespace);
|
||||
ArrayList<Timer.Context> allTimerContexts = new ArrayList<>(urlTimerContexts);
|
||||
if (metricId != null) {
|
||||
ArrayList<Timer.Context> metricIdTimers =
|
||||
startFullResponseMetricIdTimers(clientRegistry, metricId);
|
||||
startFullResponseMetricIdTimers(clientRegistry, metricId, metricNamespace);
|
||||
allTimerContexts.addAll(metricIdTimers);
|
||||
}
|
||||
return allTimerContexts;
|
||||
|
|
|
@ -8,6 +8,8 @@ import com.puppetlabs.http.client.impl.metrics.MetricIdClientTimerFilter;
|
|||
import com.puppetlabs.http.client.impl.metrics.TimerMetricData;
|
||||
import com.puppetlabs.http.client.impl.metrics.UrlAndMethodClientTimerFilter;
|
||||
import com.puppetlabs.http.client.impl.metrics.UrlClientTimerFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -17,11 +19,31 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
public class Metrics {
|
||||
public static final String NAMESPACE_PREFIX = "puppetlabs.http-client.experimental";
|
||||
public static final String PUPPETLABS_NAMESPACE_PREFIX = "puppetlabs";
|
||||
public static final String HTTP_CLIENT_NAMESPACE_PREFIX = "http-client.experimental";
|
||||
public static final String DEFAULT_NAMESPACE_PREFIX = PUPPETLABS_NAMESPACE_PREFIX +
|
||||
"." + HTTP_CLIENT_NAMESPACE_PREFIX;
|
||||
public static final String NAMESPACE_URL = "with-url";
|
||||
public static final String NAMESPACE_URL_AND_METHOD = "with-url-and-method";
|
||||
public static final String NAMESPACE_METRIC_ID = "with-metric-id";
|
||||
public static final String NAMESPACE_FULL_RESPONSE = "full-response";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Metrics.class);
|
||||
|
||||
public static String buildMetricNamespace(String metricPrefix, String serverId) {
|
||||
if (metricPrefix != null) {
|
||||
if (serverId != null) {
|
||||
Metrics.LOGGER.warn("Metric prefix and server id both set. Using metric prefix '"
|
||||
+ metricPrefix + "' for metric namespace.");
|
||||
}
|
||||
return metricPrefix + "." + HTTP_CLIENT_NAMESPACE_PREFIX;
|
||||
} else if (serverId != null) {
|
||||
return PUPPETLABS_NAMESPACE_PREFIX + "." + serverId + "."
|
||||
+ HTTP_CLIENT_NAMESPACE_PREFIX;
|
||||
} else {
|
||||
return DEFAULT_NAMESPACE_PREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MetricType { FULL_RESPONSE }
|
||||
public enum MetricCategory { URL, URL_AND_METHOD, METRIC_ID }
|
||||
|
||||
|
|
|
@ -22,19 +22,22 @@
|
|||
(let [metric-registry (MetricRegistry.)]
|
||||
(TimerUtils/startFullResponseTimers metric-registry
|
||||
(BasicHttpRequest. "GET" "http://localhost/foo")
|
||||
nil)
|
||||
nil
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(is (= (set (list url-id url-method-id)) (set (keys (.getTimers metric-registry)))))))
|
||||
(testing "metric id timers are not created for a request with an empty metric id"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(TimerUtils/startFullResponseTimers metric-registry
|
||||
(BasicHttpRequest. "GET" "http://localhost/foo")
|
||||
(into-array String []))
|
||||
(into-array String [])
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(is (= (set (list url-id url-method-id)) (set (keys (.getTimers metric-registry)))))))
|
||||
(testing "metric id timers are created correctly for a request with a metric id"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(TimerUtils/startFullResponseTimers metric-registry
|
||||
(BasicHttpRequest. "GET" "http://localhost/foo")
|
||||
(into-array ["foo" "bar" "baz"]))
|
||||
(into-array ["foo" "bar" "baz"])
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(is (= (set (list url-id url-method-id
|
||||
(add-metric-ns "with-metric-id.foo.full-response")
|
||||
(add-metric-ns "with-metric-id.foo.bar.full-response")
|
||||
|
@ -45,21 +48,25 @@
|
|||
(TimerUtils/startFullResponseTimers
|
||||
metric-registry
|
||||
(BasicHttpRequest. "GET" "http://user:pwd@localhost:1234/foo%2cbar/baz?te%2cst=one")
|
||||
nil)
|
||||
nil
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(TimerUtils/startFullResponseTimers
|
||||
metric-registry
|
||||
(BasicHttpRequest. "GET" "http://user:pwd@localhost:1234/foo%2cbar/baz#x%2cyz")
|
||||
nil)
|
||||
nil
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(TimerUtils/startFullResponseTimers
|
||||
metric-registry
|
||||
(BasicHttpRequest.
|
||||
"GET" "http://user:pwd@localhost:1234/foo%2cbar/baz?te%2cst=one#x%2cyz")
|
||||
nil)
|
||||
nil
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(TimerUtils/startFullResponseTimers
|
||||
metric-registry
|
||||
(BasicHttpRequest.
|
||||
"GET" "http://user:pwd@localhost:1234/foo%2cbar/baz?#x%2cyz")
|
||||
nil)
|
||||
nil
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)
|
||||
(is (= (set (list
|
||||
(add-metric-ns
|
||||
"with-url.http://localhost:1234/foo,bar/baz.full-response")
|
||||
|
@ -81,7 +88,8 @@
|
|||
(doseq [timer (TimerUtils/startFullResponseTimers
|
||||
registry
|
||||
req
|
||||
id)]
|
||||
id
|
||||
Metrics/DEFAULT_NAMESPACE_PREFIX)]
|
||||
(.stop timer)))
|
||||
|
||||
(deftest get-client-metrics-data-test
|
||||
|
|
|
@ -613,3 +613,127 @@
|
|||
(catch TimeoutException e
|
||||
;; Expected whenever a server-side failure is generated
|
||||
))))))
|
||||
|
||||
(deftest metric-namespace-test
|
||||
(let [metric-prefix "my-metric-prefix"
|
||||
server-id "my-server"
|
||||
metric-name-with-prefix
|
||||
(format "%s.http-client.experimental.with-url.%s.full-response" metric-prefix hello-url)
|
||||
metric-name-with-server-id
|
||||
(format "puppetlabs.%s.http-client.experimental.with-url.%s.full-response"
|
||||
server-id hello-url)
|
||||
get-metric-name (fn [metric-registry]
|
||||
(.getMetricName (first (Metrics/getClientMetricsDataByUrl
|
||||
metric-registry hello-url))))]
|
||||
(testlogging/with-test-logging
|
||||
(testutils/with-app-with-config
|
||||
app
|
||||
[jetty9/jetty9-service test-metric-web-service]
|
||||
{:webserver {:port 10000}}
|
||||
(testing "custom metric namespace works for java async client"
|
||||
(testing "metric prefix works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-metric-prefix (Async/createClient
|
||||
(doto (ClientOptions.)
|
||||
(.setMetricRegistry metric-registry)
|
||||
(.setMetricPrefix metric-prefix)))]
|
||||
(is (= (format "%s.http-client.experimental" metric-prefix)
|
||||
(.getMetricNamespace client-with-metric-prefix)))
|
||||
(-> client-with-metric-prefix (.get (RequestOptions. hello-url)))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry))))))
|
||||
(testing "server id works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (Async/createClient
|
||||
(doto (ClientOptions.)
|
||||
(.setMetricRegistry metric-registry)
|
||||
(.setServerId server-id)))]
|
||||
(-> client-with-server-id (.get (RequestOptions. hello-url)))
|
||||
(is (= metric-name-with-server-id (get-metric-name metric-registry))))))
|
||||
(testing "metric prefix overrides server id if both are set"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (Async/createClient
|
||||
(doto (ClientOptions.)
|
||||
(.setMetricRegistry metric-registry)
|
||||
(.setMetricPrefix metric-prefix)
|
||||
(.setServerId server-id)))]
|
||||
(-> client-with-server-id (.get (RequestOptions. hello-url)))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry)))
|
||||
(is (logged? #"Metric prefix and server id both set.*" :warn))))))
|
||||
(testing "custom metric namespace works for clojure async client"
|
||||
(testing "metric prefix works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-metric-prefix (async/create-client
|
||||
{:metric-registry metric-registry
|
||||
:metric-prefix metric-prefix})]
|
||||
(is (= (format "%s.http-client.experimental" metric-prefix)
|
||||
(common/get-client-metric-namespace client-with-metric-prefix)))
|
||||
(-> client-with-metric-prefix (common/get hello-url))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry))))))
|
||||
(testing "server id works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (async/create-client
|
||||
{:metric-registry metric-registry
|
||||
:server-id server-id})]
|
||||
(-> client-with-server-id (common/get hello-url))
|
||||
(is (= metric-name-with-server-id (get-metric-name metric-registry))))))
|
||||
(testing "metric prefix overrides server id if both are set"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (async/create-client
|
||||
{:metric-registry metric-registry
|
||||
:metric-prefix metric-prefix
|
||||
:server-id server-id})]
|
||||
(-> client-with-server-id (common/get hello-url))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry)))))))
|
||||
(testing "custom metric namespace works for Java sync client"
|
||||
(testing "metric prefix works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-metric-prefix (Sync/createClient
|
||||
(doto (ClientOptions.)
|
||||
(.setMetricRegistry metric-registry)
|
||||
(.setMetricPrefix metric-prefix)))]
|
||||
(is (= (format "%s.http-client.experimental" metric-prefix)
|
||||
(.getMetricNamespace client-with-metric-prefix)))
|
||||
(-> client-with-metric-prefix (.get (RequestOptions. hello-url)))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry))))))
|
||||
(testing "server id works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (Sync/createClient
|
||||
(doto (ClientOptions.)
|
||||
(.setMetricRegistry metric-registry)
|
||||
(.setServerId server-id)))]
|
||||
(-> client-with-server-id (.get (RequestOptions. hello-url)))
|
||||
(is (= metric-name-with-server-id (get-metric-name metric-registry))))))
|
||||
(testing "metric prefix overrides server id if both are set"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (Sync/createClient
|
||||
(doto (ClientOptions.)
|
||||
(.setMetricRegistry metric-registry)
|
||||
(.setMetricPrefix metric-prefix)
|
||||
(.setServerId server-id)))]
|
||||
(-> client-with-server-id (.get (RequestOptions. hello-url)))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry)))))))
|
||||
(testing "custom metric namespace works for clojure sync client"
|
||||
(testing "metric prefix works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-metric-prefix (sync/create-client
|
||||
{:metric-registry metric-registry
|
||||
:metric-prefix metric-prefix})]
|
||||
(is (= (format "%s.http-client.experimental" metric-prefix)
|
||||
(common/get-client-metric-namespace client-with-metric-prefix)))
|
||||
(-> client-with-metric-prefix (common/get hello-url))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry))))))
|
||||
(testing "server id works"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (sync/create-client
|
||||
{:metric-registry metric-registry
|
||||
:server-id server-id})]
|
||||
(-> client-with-server-id (common/get hello-url))
|
||||
(is (= metric-name-with-server-id (get-metric-name metric-registry))))))
|
||||
(testing "metric prefix overrides server id if both are set"
|
||||
(let [metric-registry (MetricRegistry.)]
|
||||
(with-open [client-with-server-id (sync/create-client
|
||||
{:metric-registry metric-registry
|
||||
:metric-prefix metric-prefix
|
||||
:server-id server-id})]
|
||||
(-> client-with-server-id (common/get hello-url))
|
||||
(is (= metric-name-with-prefix (get-metric-name metric-registry)))))))))))
|
||||
|
|
Loading…
Reference in a new issue