Skip to content

Commit

Permalink
[Refactoring] RouterService wrapRoutes -> filter
Browse files Browse the repository at this point in the history
  • Loading branch information
szysas committed Aug 11, 2023
1 parent a98c39c commit 3ddbc4c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 40 deletions.
23 changes: 4 additions & 19 deletions coap-core/src/main/java/com/mbed/coap/server/RouterService.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ private Service<CoapRequest, CoapResponse> findHandler(RequestMatcher requestMat
public static class RouteBuilder {
private final Map<RequestMatcher, Service<CoapRequest, CoapResponse>> handlers = new HashMap<>();
public Service<CoapRequest, CoapResponse> defaultHandler = NOT_FOUND_SERVICE;
private Filter<CoapRequest, CoapResponse, CoapRequest, CoapResponse> filter = Filter.identity();

public RouteBuilder get(String uriPath, Service<CoapRequest, CoapResponse> service) {
return add(Method.GET, uriPath, service);
Expand Down Expand Up @@ -122,7 +123,7 @@ public RouteBuilder any(String uriPath, Service<CoapRequest, CoapResponse> servi
}

private RouteBuilder add(Method method, String uriPath, Service<CoapRequest, CoapResponse> service) {
handlers.put(new RequestMatcher(method, uriPath), service);
handlers.put(new RequestMatcher(method, uriPath), filter.then(service));
return this;
}

Expand All @@ -137,31 +138,15 @@ public RouteBuilder mergeRoutes(RouteBuilder otherBuilder) {
return this;
}

public RouteBuilder wrapRoutes(WrapFilterProducer wrapperFilterProducer) {
Map<RequestMatcher, Service<CoapRequest, CoapResponse>> wrappedRouteHandlers = new HashMap<>();
for (Entry<RequestMatcher, Service<CoapRequest, CoapResponse>> e : handlers.entrySet()) {
RequestMatcher key = e.getKey();
Service<CoapRequest, CoapResponse> service = e.getValue();

wrappedRouteHandlers.put(key, wrapperFilterProducer.getFilter(key.method, key.uriPath).then(service));
}
handlers.putAll(wrappedRouteHandlers);
public RouteBuilder filter(Filter<CoapRequest, CoapResponse, CoapRequest, CoapResponse> wrapperFilterProducer) {
this.filter = this.filter.andThen(wrapperFilterProducer);

return this;
}

public RouteBuilder wrapRoutes(Filter<CoapRequest, CoapResponse, CoapRequest, CoapResponse> wrapperFilter) {
return wrapRoutes((WrapFilterProducer) (m, u) -> wrapperFilter);
}

public Service<CoapRequest, CoapResponse> build() {
return new RouterService(handlers, defaultHandler);
}

@FunctionalInterface
public interface WrapFilterProducer {
Filter<CoapRequest, CoapResponse, CoapRequest, CoapResponse> getFilter(Method method, String uriPath);
}
}

static final class RequestMatcher {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ public void shouldBuildSimpleService() throws ExecutionException, InterruptedExc
}

@Test
public void shouldWrapRoutes() throws ExecutionException, InterruptedException {
public void shouldFilterRoutes() throws ExecutionException, InterruptedException {
Service<CoapRequest, CoapResponse> svc = RouterService.builder()
.get("/test3", simpleHandler)
.filter((CoapRequest req, Service<CoapRequest, CoapResponse> nextSvc) -> CompletableFuture.completedFuture(ok("42")))
.get("/test1", simpleHandler)
.post("/test1", simpleHandler)
.get("/test2/*", simpleHandler)
.wrapRoutes((CoapRequest req, Service<CoapRequest, CoapResponse> nextSvc) -> CompletableFuture.completedFuture(ok("42")))
.get("/test3", simpleHandler)
.build();

assertEquals("42", svc.apply(CoapRequest.get("/test1")).get().getPayloadString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,21 @@
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

public class MicrometerMetricsFilter implements Filter.SimpleFilter<CoapRequest, CoapResponse> {
private final MeterRegistry registry;
private final String metricName;
private final String route;
private final Function<String, String> resolveRoute;

public static MicrometerMetricsFilterBuilder builder() {
return new MicrometerMetricsFilterBuilder();
}

MicrometerMetricsFilter(MeterRegistry registry, String metricName, DistributionStatisticConfig distributionStatisticConfig, String route) {
MicrometerMetricsFilter(MeterRegistry registry, String metricName, DistributionStatisticConfig distributionStatisticConfig, Function<String, String> resolveRoute) {
this.registry = registry;
this.metricName = metricName;
this.route = route;
this.resolveRoute = resolveRoute;

registry.config().meterFilter(new MeterFilter() {
@Override
Expand All @@ -67,29 +68,27 @@ public CompletableFuture<CoapResponse> apply(CoapRequest req, Service<CoapReques
}

private List<Tag> requestTags(CoapRequest req, CoapResponse resp, Throwable err) {
String uriPath = req.options().getUriPath();
return Arrays.asList(
Tag.of("method", req.getMethod().name()),
Tag.of("status", resp != null ? resp.getCode().codeToString() : "n/a"),
Tag.of("route", getRoute(uriPath)),
Tag.of("route", getRoute(req)),
Tag.of("throwable", err != null ? err.getClass().getCanonicalName() : "n/a")
);
}

private String getRoute(String uriPath) {
if (route != null) {
return route;
}
private String getRoute(CoapRequest req) {
String uriPath = req.options().getUriPath();
uriPath = uriPath != null ? uriPath : "/";

return uriPath != null ? uriPath : "/";
return resolveRoute.apply(uriPath);
}

public static class MicrometerMetricsFilterBuilder {
public String DEFAULT_METRIC_NAME = "coap.server.requests";
private MeterRegistry registry;
private String metricName;
private DistributionStatisticConfig distributionStatisticConfig;
private String route;
private Function<String, String> resolveRoute = Function.identity();

MicrometerMetricsFilterBuilder() {
}
Expand All @@ -109,8 +108,8 @@ public MicrometerMetricsFilterBuilder distributionStatisticConfig(DistributionSt
return this;
}

public MicrometerMetricsFilterBuilder route(String route) {
this.route = route;
public MicrometerMetricsFilterBuilder resolveRoute(Function<String, String> resolveRoute) {
this.resolveRoute = resolveRoute;
return this;
}

Expand All @@ -127,7 +126,7 @@ public MicrometerMetricsFilter build() {
this.distributionStatisticConfig = DistributionStatisticConfig.builder().percentiles(0.5, 0.9, 0.95, 0.99).build();
}

return new MicrometerMetricsFilter(this.registry, this.metricName, this.distributionStatisticConfig, this.route);
return new MicrometerMetricsFilter(this.registry, this.metricName, this.distributionStatisticConfig, resolveRoute);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@
import static com.mbed.coap.packet.CoapResponse.ok;
import static com.mbed.coap.utils.FutureHelpers.failedFuture;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.mbed.coap.packet.CoapRequest;
import com.mbed.coap.packet.CoapResponse;
import com.mbed.coap.utils.Service;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import io.micrometer.core.instrument.logging.LoggingMeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class MicrometerMetricsFilterTest {
private final MeterRegistry registry = new SimpleMeterRegistry();
Expand Down Expand Up @@ -95,10 +97,21 @@ public void shouldRegisterTimerMetric() {

@Test
public void shouldUseDefinedRouteForAllMeteredRequests() {
MicrometerMetricsFilter filterWithRoute = MicrometerMetricsFilter.builder().registry(registry).route("/test/DEVICE_ID").build();
MicrometerMetricsFilter filterWithRoute = MicrometerMetricsFilter.builder()
.resolveRoute(uriPath -> {
if (uriPath.startsWith("/test/")) {
return "/test/DEVICE_ID";
}

return uriPath;
})
.registry(registry)
.build();

Service<CoapRequest, CoapResponse> svc = filterWithRoute.then(__ -> completedFuture(ok("OK")));
svc.apply(get("/test/1")).join();
svc.apply(get("/test/2")).join();
svc.apply(get("/hello")).join();

assertNull(
registry.find("coap.server.requests")
Expand All @@ -114,5 +127,9 @@ public void shouldUseDefinedRouteForAllMeteredRequests() {
.tag("route", "/test/DEVICE_ID")
.timer().count()
);
assertEquals(1, registry.find("coap.server.requests")
.tag("route", "/hello")
.timer().count()
);
}
}

0 comments on commit 3ddbc4c

Please sign in to comment.