Skip to content

Nima: MicroMeter now contains Nima and SE integration #7090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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