Skip to content

Commit

Permalink
Merge branch '1.12.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
shakuzen committed Jan 17, 2024
2 parents 64c9416 + bdfdf4c commit edc3289
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@
** xref:implementations/wavefront.adoc[Wavefront]
* xref:reference.adoc[Reference Instrumentations]
** xref:reference/commons-pool.adoc[Apache Commons Pool]
** xref:reference/httpcomponents.adoc[Apache HttpComponents Client]
** xref:reference/jvm.adoc[JVM]
** xref:reference/cache.adoc[Cache]
** xref:reference/grpc.adoc[gRPC]
** xref:reference/okhttpclient.adoc[OkHttpClient]
** xref:reference/jetty.adoc[Jetty and Jersey]
** xref:reference/netty.adoc[Netty]
Expand Down
35 changes: 35 additions & 0 deletions docs/modules/ROOT/pages/reference/grpc.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[[overview]]
= gRPC Instrumentation

https://grpc.io/[gRPC] is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment.

Below you can find an example of how to instrument gRPC with Micrometer.

First, client and server side interceptors need to be setup.

[source,java,subs=+attributes]
-----
// Setting up interceptors
include::{include-core-test-java}/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java[tags=setup, indent=0]
include::{include-core-test-java}/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java[tags=setup_2, indent=0]
-----

Next, server and channels need to have the interceptors added.

[source,java,subs=+attributes]
-----
// Adding them to the server and client side
include::{include-core-test-java}/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java[tags=example, indent=0]
-----

Below you have an example of usage with the result assertions.

[source,java,subs=+attributes]
-----
// Usage example
include::{include-core-test-java}/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java[tags=result, indent=0]
// Observation outcome
include::{include-core-test-java}/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java[tags=assertion, indent=0]
-----
30 changes: 30 additions & 0 deletions docs/modules/ROOT/pages/reference/httpcomponents.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[[overview]]
= Apache HttpComponents Client Instrumentation

IMPORTANT: This section requires usage of Apache HttpComponents Client at least in version 5.

https://hc.apache.org/index.html/[Apache HttpComponents Client] is an HTTP/1.1 compliant HTTP agent implementation.

Below you can find an example of how to instrument Apache HttpComponents Client with Micrometer.

Example of classic, blocking HTTP client.

[source,java,subs=+attributes]
-----
// Setting up instrumentation (you need to create a client from the builder)
include::{include-core-test-java}/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java[tags=setup_classic, indent=0]
// Usage example
include::{include-core-test-java}/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java[tags=example_classic, indent=0]
-----

Example of async HTTP client.

[source,java,subs=+attributes]
-----
// Setting up instrumentation (you need to create a client from the builder)
include::{include-core-test-java}/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java[tags=setup_async, indent=0]
// Usage example
include::{include-core-test-java}/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java[tags=example_async, indent=0]
-----
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public AnnotationHandler(BiConsumer<KeyValue, T> keyValueConsumer,
public void addAnnotatedParameters(T objectToModify, ProceedingJoinPoint pjp) {
try {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
method = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
method = pjp.getTarget().getClass().getDeclaredMethod(method.getName(), method.getParameterTypes());
List<AnnotatedParameter> annotatedParameters = AnnotationUtils.findAnnotatedParameters(annotationClass,
method, pjp.getArgs());
getAnnotationsFromInterfaces(pjp, method, annotatedParameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,23 @@ void meterTagsWithExpression(AnnotatedTestClass annotatedClass) {
assertThat(registry.get("method.timed").tag("test", "hello characters").timer().count()).isEqualTo(1);
}

@Test
void meterTagOnPackagePrivateMethod() {
MeterRegistry registry = new SimpleMeterRegistry();
TimedAspect timedAspect = new TimedAspect(registry);
timedAspect.setMeterTagAnnotationHandler(meterTagAnnotationHandler);

AspectJProxyFactory pf = new AspectJProxyFactory(new MeterTagClass());
pf.setProxyTargetClass(true);
pf.addAspect(timedAspect);

MeterTagClass service = pf.getProxy();

service.getAnnotationForPackagePrivateMethod("bar");

assertThat(registry.get("method.timed").tag("foo", "bar").timer().count()).isEqualTo(1);
}

enum AnnotatedTestClass {

CLASS_WITHOUT_INTERFACE(MeterTagClass.class), CLASS_WITH_INTERFACE(MeterTagClassChild.class);
Expand Down Expand Up @@ -492,6 +509,10 @@ public void getAnnotationForTagValueExpression(
public void getAnnotationForArgumentToString(@MeterTag("test") Long param) {
}

@Timed
void getAnnotationForPackagePrivateMethod(@MeterTag("foo") String foo) {
}

}

static class MeterTagClassChild implements MeterTagClassInterface {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,13 @@ class GrpcObservationTest {

ContextAndEventHoldingObservationHandler<GrpcClientObservationContext> clientHandler;

// tag::setup[]
ObservationGrpcServerInterceptor serverInterceptor;

ObservationGrpcClientInterceptor clientInterceptor;

// end::setup[]

TestObservationRegistry observationRegistry = TestObservationRegistry.create();

@BeforeEach
Expand All @@ -109,8 +112,10 @@ void setUp() {
.observationHandler(serverHandler)
.observationHandler(clientHandler);

// tag::setup_2[]
this.serverInterceptor = new ObservationGrpcServerInterceptor(observationRegistry);
this.clientInterceptor = new ObservationGrpcClientInterceptor(observationRegistry);
// end::setup_2[]
}

@AfterEach
Expand All @@ -128,6 +133,7 @@ class WithEchoService {

@BeforeEach
void setUpEchoService() throws Exception {
// tag::example[]
EchoService echoService = new EchoService();
server = InProcessServerBuilder.forName("sample")
.addService(echoService)
Expand All @@ -139,15 +145,18 @@ void setUpEchoService() throws Exception {
channel = InProcessChannelBuilder.forName("sample")
.intercept(new ClientHeaderInterceptor(), clientInterceptor)
.build();
// end::example[]
}

@Test
void unaryRpc() {
// tag::result[]
SimpleServiceBlockingStub stub = SimpleServiceGrpc.newBlockingStub(channel);

SimpleRequest request = SimpleRequest.newBuilder().setRequestMessage("Hello").build();
SimpleResponse response = stub.unaryRpc(request);
assertThat(response.getResponseMessage()).isEqualTo("Hello");
// end::result[]

verifyServerContext("grpc.testing.SimpleService", "UnaryRpc", "grpc.testing.SimpleService/UnaryRpc",
MethodType.UNARY);
Expand All @@ -159,6 +168,11 @@ void unaryRpc() {
GrpcServerEvents.MESSAGE_SENT);
assertThat(clientHandler.getEvents()).containsExactly(GrpcClientEvents.MESSAGE_SENT,
GrpcClientEvents.MESSAGE_RECEIVED);
// tag::assertion[]
TestObservationRegistryAssert.assertThat(observationRegistry)
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.client"))
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.server"));
// end::assertion[]
verifyHeaders();
}

Expand Down Expand Up @@ -190,6 +204,9 @@ public void onFailure(Throwable t) {

await().until(() -> futures.stream().allMatch(Future::isDone));
assertThat(responses).hasSize(count).containsExactlyInAnyOrderElementsOf(messages);
TestObservationRegistryAssert.assertThat(observationRegistry)
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.client"))
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.server"));
verifyHeaders();
}

Expand Down Expand Up @@ -230,6 +247,9 @@ void clientStreamingRpc() {
verifyServerContext("grpc.testing.SimpleService", "ClientStreamingRpc",
"grpc.testing.SimpleService/ClientStreamingRpc", MethodType.CLIENT_STREAMING);
assertThat(serverHandler.getContext().getStatusCode()).isEqualTo(Code.OK);
TestObservationRegistryAssert.assertThat(observationRegistry)
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.client"))
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.server"));
verifyHeaders();
}

Expand Down Expand Up @@ -262,6 +282,9 @@ void serverStreamingRpc() {
assertThat(clientHandler.getContext().getStatusCode()).isEqualTo(Code.OK);
assertThat(clientHandler.getEvents()).containsExactly(GrpcClientEvents.MESSAGE_SENT,
GrpcClientEvents.MESSAGE_RECEIVED, GrpcClientEvents.MESSAGE_RECEIVED);
TestObservationRegistryAssert.assertThat(observationRegistry)
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.client"))
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.server"));
verifyHeaders();
}

Expand Down Expand Up @@ -312,6 +335,9 @@ void bidiStreamingRpc() {

assertThat(serverHandler.getContext().getStatusCode()).isEqualTo(Code.OK);
assertThat(clientHandler.getContext().getStatusCode()).isEqualTo(Code.OK);
TestObservationRegistryAssert.assertThat(observationRegistry)
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.client"))
.hasAnObservation(observationContextAssert -> observationContextAssert.hasNameEqualTo("grpc.server"));
verifyHeaders();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class ClassicClient {
@Test
void recordSuccessfulExchanges(@WiremockResolver.Wiremock WireMockServer server) throws Exception {
server.stubFor(any(anyUrl()));
// tag::example_classic[]
try (CloseableHttpClient client = classicClient()) {
executeClassic(client, new HttpGet(server.baseUrl()));
}
Expand All @@ -88,6 +89,7 @@ void recordSuccessfulExchanges(@WiremockResolver.Wiremock WireMockServer server)
.hasLowCardinalityKeyValue("outcome", "SUCCESS")
.hasLowCardinalityKeyValue("status", "200")
.hasLowCardinalityKeyValue("method", "GET");
// end::example_classic[]
}

@Test
Expand Down Expand Up @@ -227,6 +229,7 @@ class AsyncClient {
@Test
void recordSuccessfulExchanges(@WiremockResolver.Wiremock WireMockServer server) throws Exception {
server.stubFor(any(anyUrl()));
// tag::example_async[]
try (CloseableHttpAsyncClient client = asyncClient()) {
SimpleHttpRequest request = SimpleRequestBuilder.get(server.baseUrl()).build();
executeAsync(client, request);
Expand All @@ -236,6 +239,7 @@ void recordSuccessfulExchanges(@WiremockResolver.Wiremock WireMockServer server)
.hasLowCardinalityKeyValue("outcome", "SUCCESS")
.hasLowCardinalityKeyValue("status", "200")
.hasLowCardinalityKeyValue("method", "GET");
// end::example_async[]
}

@Test
Expand Down Expand Up @@ -384,12 +388,14 @@ private CloseableHttpClient classicClient() {
.setConnectTimeout(2000L, TimeUnit.MILLISECONDS)
.build();

// tag::setup_classic[]
HttpClientBuilder clientBuilder = HttpClients.custom()
.setRetryStrategy(retryStrategy)
.addExecInterceptorLast("micrometer", new ObservationExecChainHandler(observationRegistry))
.setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
.setDefaultConnectionConfig(connectionConfig)
.build());
// end::setup_classic[]

return clientBuilder.build();
}
Expand All @@ -413,12 +419,14 @@ private CloseableHttpAsyncClient asyncClient() {
.setConnectTimeout(1000, TimeUnit.MILLISECONDS)
.build();

// tag::setup_async[]
HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom()
.addExecInterceptorLast("micrometer", new ObservationExecChainHandler(observationRegistry))
.setRetryStrategy(retryStrategy)
.setConnectionManager(PoolingAsyncClientConnectionManagerBuilder.create()
.setDefaultConnectionConfig(connectionConfig)
.build());
// end::setup_async[]

return clientBuilder.build();
}
Expand Down

0 comments on commit edc3289

Please sign in to comment.