여기서는 요청과 관련된 부분을 등록하는 것을 다룬다.
@Getter
@AllArgsConstructor
public enum Request {
REQUESTS("undertow.requests", "Number of requests"),
REQUEST_TIME_MAX("undertow.request.time.max", "The longest request duration in time"),
REQUEST_TIME_MIN("undertow.request.time.min", "The shortest request duration in time"),
REQUEST_ERRORS("undertow.request.errors", "Total number of error requests");
private String name;
private String desc;
}
@Getter
@Component
public class UndertowMetricsHandlerWrapper implements HandlerWrapper {
private MetricHandler metricsHandler;
@Override
public HttpHandler wrap(HttpHandler httpHandler) {
metricsHandler = new MetricHandler(httpHandler);
return metricsHandler;
}
}
io.undertow.server.handlers.MetricHandler
는 내부에 MetricResult
클래스를 가지고 있는데, 여기에 접근해서 요청과 관련된 정보를 micrometer 가 사용할 수 있도록 등록할 수 있다.
public static class MetricResult {
private volatile long totalRequestTime;
private volatile int maxRequestTime;
private volatile int minRequestTime = -1;
private volatile long totalRequests;
private volatile long totalErrors;
public long getTotalRequestTime() { return this.totalRequestTime; }
public int getMaxRequestTime() { return this.maxRequestTime; }
public int getMinRequestTime() { return this.minRequestTime; }
public long getTotalRequests() { return this.totalRequests; }
public long getTotalErrors() { return this.totalErrors; }
...
}
@Configuration
public class UndertowConfig {
@Bean
public UndertowDeploymentInfoCustomizer undertowDeploymentInfoCustomizer(
UndertowMetricsHandlerWrapper undertowMetricsHandlerWrapper) {
return deploymentInfo -> deploymentInfo
.addOuterHandlerChainWrapper(undertowMetricsHandlerWrapper);
}
@Slf4j
@Component
@RequiredArgsConstructor
public class UndertowMeterBinder implements ApplicationListener<ApplicationReadyEvent> {
private final UndertowMetricsHandlerWrapper undertowMetricsHandlerWrapper;
@Override
public void onApplicationEvent(ApplicationReadyEvent aplicationReadyEvent) {
bindTo(applicationReadyEvent.getApplicationContext().getBean(MeterRegistry.class));
}
public void bindTo(MeterRegistry meterRegistry) {
bind(meterRegistry, undertowMetricshandlerWrapper.getMetricsHandler());
}
public void bind(MeterRegistry registry, MetricsHandler metricsHandler) {
//request 관련 metric 지표등록
bindTimer(registry, REQUEST.getName(), REQUESTS.getDesc(), metricsHandler,
m -> m.getMetrics().getTotalRequests(), m2 -> m2.getMetrics().getMinRequestTime());
bindTimeGauge(registry, REQUEST_TIME_MAX.getName(), REQUEST_TIME_MAX.getDesc(), metricsHandler,
m -> m.getMetrics().getMaxRequestTime());
bindTimeGauge(registry, REQUEST_TIME_MIN.getName(), REQUEST_TIME_MIN.getDesc(), metricsHandler,
m -> .getMetrics().getMinRequestTime());
bindCounter(registry, REQUEST_ERRORS.getName(), REQUEST_ERRORS.getDesc(), metricshandler,
m -> m.getMetrics().getTotalErrors());
}
private void bineTimer(
MeterRegistry registry, String name, String desc, MetricsHandler metricsHandler,
ToLongFunction<MetricsHandler> countFunc, ToDoubleFunction<Metricshadnler> consumer
) {
FunctionTimer.builder(name, metricsHandler, countFunc, consumer, TimeUnit.MILLISECONDS)
.description(desc)
.register(registry);
}
private void bindTimeGauge(
MeterRegistry registry, String name, String desc, MetricsHandler metricResult,
ToDoubleFunction<MetricsHandler> consucmer
) {
TimeGauge.builder(name, metricResult, TimeUnit.MILLISECONDS, consumer)
.description(desc)
.register(registry);
}
private void bindCounter(
MeterRegistry registry, String name, String desc, MetricsHandler metricsHandler,
ToDoubleFunction<MetricsHandler> consumer
) {
FunctionCounter.builder(name, metricsHandler, consumer)
.description(desc)
.register(registry);
}
}