Skip to content

Commit

Permalink
Nima: MicroMeter now contains Nima and SE integration (#7090)
Browse files Browse the repository at this point in the history
* Nima: MicroMeter now contains Nima and SE integration

---------

Signed-off-by: Jorge Bescos Gascon <jorge.bescos.gascon@oracle.com>
Co-authored-by: Romain Grecourt <romain.grecourt@oracle.com>
  • Loading branch information
jbescos and romain-grecourt authored Jun 27, 2023
1 parent 067ee8f commit 29464db
Show file tree
Hide file tree
Showing 17 changed files with 177 additions and 560 deletions.
21 changes: 11 additions & 10 deletions examples/integrations/micrometer/se/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,39 +55,40 @@

<dependencies>
<dependency>
<groupId>io.helidon.reactive.webserver</groupId>
<artifactId>helidon-reactive-webserver</artifactId>
<groupId>io.helidon.nima.webserver</groupId>
<artifactId>helidon-nima-webserver</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.reactive.webserver</groupId>
<artifactId>helidon-reactive-webserver-cors</artifactId>
<groupId>io.helidon.nima.http.media</groupId>
<artifactId>helidon-nima-http-media-jsonp</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.integrations.micrometer</groupId>
<artifactId>helidon-integrations-micrometer</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.reactive.media</groupId>
<artifactId>helidon-reactive-media-jsonp</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.reactive.webclient</groupId>
<artifactId>helidon-reactive-webclient</artifactId>
<groupId>io.helidon.nima.webclient</groupId>
<artifactId>helidon-nima-webclient</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.nima.testing.junit5</groupId>
<artifactId>helidon-nima-testing-junit5-webserver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022 Oracle and/or its affiliates.
* Copyright (c) 2021, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,10 +20,11 @@

import io.helidon.common.http.Http;
import io.helidon.config.Config;
import io.helidon.reactive.webserver.Routing;
import io.helidon.reactive.webserver.ServerRequest;
import io.helidon.reactive.webserver.ServerResponse;
import io.helidon.reactive.webserver.Service;
import io.helidon.nima.webserver.http.HttpRequest;
import io.helidon.nima.webserver.http.HttpRules;
import io.helidon.nima.webserver.http.HttpService;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Timer;
Expand Down Expand Up @@ -51,7 +52,7 @@
* </p>
*/

public class GreetService implements Service {
public class GreetService implements HttpService {

/**
* The config value for the key {@code greeting}.
Expand All @@ -74,14 +75,14 @@ public class GreetService implements Service {
* @param rules the routing rules.
*/
@Override
public void update(Routing.Rules rules) {
public void routing(HttpRules rules) {
rules
.get((req, resp) -> getTimer.record((Runnable) req::next)) // Update the timer with every GET.
.get((req, resp) -> getTimer.record(resp::next)) // Update the timer with every GET.
.get("/", this::getDefaultMessageHandler)
.get("/{name}",
(req, resp) -> {
personalizedGetCounter.increment();
req.next();
resp.next();
}, // Count personalized GETs...
this::getMessageHandler) // ...and process them.
.put("/greeting", this::updateGreetingHandler);
Expand All @@ -92,7 +93,7 @@ public void update(Routing.Rules rules) {
* @param request the server request
* @param response the server response
*/
private void getDefaultMessageHandler(ServerRequest request,
private void getDefaultMessageHandler(HttpRequest request,
ServerResponse response) {
sendResponse(response, "World");
}
Expand All @@ -104,7 +105,7 @@ private void getDefaultMessageHandler(ServerRequest request,
*/
private void getMessageHandler(ServerRequest request,
ServerResponse response) {
String name = request.path().param("name");
String name = request.path().pathParameters().first("name").get();
sendResponse(response, name);
}

Expand Down Expand Up @@ -135,6 +136,7 @@ private void updateGreetingFromJson(JsonObject jo, ServerResponse response) {
*/
private void updateGreetingHandler(ServerRequest request,
ServerResponse response) {
request.content().as(JsonObject.class).thenAccept(jo -> updateGreetingFromJson(jo, response));
JsonObject obj = request.content().as(JsonObject.class);
updateGreetingFromJson(obj, response);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022 Oracle and/or its affiliates.
* Copyright (c) 2021, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,13 +16,11 @@

package io.helidon.examples.micrometer.se;

import io.helidon.common.reactive.Single;
import io.helidon.config.Config;
import io.helidon.integrations.micrometer.MicrometerSupport;
import io.helidon.integrations.micrometer.MicrometerFeature;
import io.helidon.logging.common.LogConfig;
import io.helidon.reactive.media.jsonp.JsonpSupport;
import io.helidon.reactive.webserver.Routing;
import io.helidon.reactive.webserver.WebServer;
import io.helidon.nima.webserver.WebServer;
import io.helidon.nima.webserver.http.HttpRouting;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Timer;
Expand All @@ -43,6 +41,7 @@ private Main() {

/**
* Application main entry point.
*
* @param args command line arguments.
*/
public static void main(final String[] args) {
Expand All @@ -51,48 +50,33 @@ public static void main(final String[] args) {

/**
* Start the server.
* @return the created {@link WebServer} instance
*/
static Single<WebServer> startServer() {
static WebServer startServer() {

// load logging configuration
LogConfig.configureRuntime();

// By default this will pick up application.yaml from the classpath
// By default, this will pick up application.yaml from the classpath
Config config = Config.create();

// Get webserver config from the "server" section of application.yaml
WebServer server = WebServer.builder(createRouting(config))
WebServer server = WebServer.builder()
.config(config.get("server"))
.port(-1)
.addMediaSupport(JsonpSupport.create())
.build();
.routing(r -> setupRouting(r, config))
.build()
.start();

// Try to start the server. If successful, print some info and arrange to
// print a message at shutdown. If unsuccessful, print the exception.
// Server threads are not daemon. No need to block. Just react.
return server.start()
.peek(ws -> {
System.out.println(
"WEB server is up! http://localhost:" + ws.port() + "/greet");
ws.whenShutdown().thenRun(()
-> System.out.println("WEB server is DOWN. Good bye!"));
})
.onError(t -> {
System.err.println("Startup failed: " + t.getMessage());
t.printStackTrace(System.err);
});
System.out.println("WEB server is up! http://localhost:" + server.port() + "/greet");
return server;
}

/**
* Creates new {@link Routing}.
* Setup routing.
*
* @return routing configured with JSON support, Micrometer metrics, and the greeting service
* @param config configuration of this server
* @param routing routing builder
* @param config config
*/
private static Routing createRouting(Config config) {

MicrometerSupport micrometerSupport = MicrometerSupport.create();
static void setupRouting(HttpRouting.Builder routing, Config config) {
MicrometerFeature micrometerSupport = MicrometerFeature.create(config);
Counter personalizedGetCounter = micrometerSupport.registry()
.counter(PERSONALIZED_GETS_COUNTER_NAME);
Timer getTimer = Timer.builder(ALL_GETS_TIMER_NAME)
Expand All @@ -101,9 +85,7 @@ private static Routing createRouting(Config config) {

GreetService greetService = new GreetService(config, getTimer, personalizedGetCounter);

return Routing.builder()
.register(micrometerSupport) // Micrometer support at "/micrometer"
.register("/greet", greetService)
.build();
routing.register("/greet", greetService)
.addFeature(micrometerSupport);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,83 +16,54 @@
package io.helidon.examples.micrometer.se;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

import io.helidon.common.http.Http;
import io.helidon.reactive.media.jsonp.JsonpSupport;
import io.helidon.reactive.webclient.WebClient;
import io.helidon.reactive.webclient.WebClientResponse;
import io.helidon.reactive.webserver.WebServer;
import io.helidon.config.Config;
import io.helidon.nima.testing.junit5.webserver.ServerTest;
import io.helidon.nima.testing.junit5.webserver.SetUpServer;
import io.helidon.nima.webclient.http1.Http1Client;
import io.helidon.nima.webclient.http1.Http1ClientResponse;
import io.helidon.nima.webserver.ServerConfig;
import io.helidon.nima.webserver.ServerConfig.Builder;

import jakarta.json.Json;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonObject;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.containsString;

// we need to first call the methods, before validating metrics
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@ServerTest
public class MainTest {

private static final JsonBuilderFactory JSON_BF = Json.createBuilderFactory(Collections.emptyMap());
private static final JsonObject TEST_JSON_OBJECT;
private static WebServer webServer;
private static WebClient webClient;

private static double expectedPersonalizedGets;
private static double expectedAllGets;
private final Http1Client client;

static {
TEST_JSON_OBJECT = JSON_BF.createObjectBuilder()
.add("greeting", "Hola")
.build();
}

@BeforeAll
public static void startTheServer() {
webServer = Main.startServer()
.await(10, TimeUnit.SECONDS);

webClient = WebClient.builder()
.baseUri("http://localhost:" + webServer.port())
.addMediaSupport(JsonpSupport.create())
.build();
public MainTest(Http1Client client) {
this.client = client;
}

@AfterAll
public static void stopServer() {
if (webServer != null) {
webServer.shutdown()
.await(10, TimeUnit.SECONDS);
}
}

private static JsonObject get() {
return get("/greet");
}

private static JsonObject get(String path) {
JsonObject jsonObject = webClient.get()
.path(path)
.request(JsonObject.class)
.await();
expectedAllGets++;
return jsonObject;
}

private static JsonObject personalizedGet(String name) {
JsonObject result = get("/greet/" + name);
expectedPersonalizedGets++;
return result;
@SetUpServer
public static void setup(Builder builder) {
builder.routing(r -> Main.setupRouting(r, Config.create()));
}

@Test
Expand All @@ -112,13 +83,12 @@ void testNamedGreeting() {
@Test
@Order(3)
void testUpdateGreeting() {

WebClientResponse response = webClient.put()
try (Http1ClientResponse response = client.put()
.path("/greet/greeting")
.submit(TEST_JSON_OBJECT)
.await();
.submit(TEST_JSON_OBJECT)) {

assertThat(response.status(), is(Http.Status.NO_CONTENT_204));
assertThat(response.status(), is(Http.Status.NO_CONTENT_204));
}

JsonObject jsonObject = personalizedGet("Joe");
assertThat(jsonObject.getString("greeting"), is("Hola Joe!"));
Expand All @@ -127,16 +97,13 @@ void testUpdateGreeting() {
@Test
@Order(4)
void testMicrometer() {
WebClientResponse response = webClient.get()
Http1ClientResponse response = client.get()
.path("/micrometer")
.request()
.await();
.request();

assertThat(response.status().code(), is(200));

String output = response.content()
.as(String.class)
.await();
String output = response.as(String.class);
String expected = Main.ALL_GETS_TIMER_NAME + "_seconds_count " + expectedAllGets;
assertThat("Unable to find expected all-gets timer count " + expected + "; output is " + output,
output, containsString(expected)); // all gets; the put
Expand All @@ -148,4 +115,22 @@ void testMicrometer() {
output, containsString(expected));
response.close();
}

private JsonObject get() {
return get("/greet");
}

private JsonObject get(String path) {
JsonObject jsonObject = client.get()
.path(path)
.request(JsonObject.class);
expectedAllGets++;
return jsonObject;
}

private JsonObject personalizedGet(String name) {
JsonObject result = get("/greet/" + name);
expectedPersonalizedGets++;
return result;
}
}
Loading

0 comments on commit 29464db

Please sign in to comment.