JerseyKeyValues.java
/*
* Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.micrometer.server;
import io.micrometer.common.KeyValue;
import io.micrometer.common.util.StringUtils;
import io.micrometer.core.instrument.binder.http.Outcome;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ContainerResponse;
import org.glassfish.jersey.server.ExtendedUriInfo;
import org.glassfish.jersey.server.monitoring.RequestEvent;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
/**
* Factory methods for {@link KeyValue KeyValues} associated with a request-response
* exchange that is handled by Jersey server.
*/
class JerseyKeyValues {
private static final KeyValue URI_NOT_FOUND = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
.withValue("NOT_FOUND");
private static final KeyValue URI_REDIRECTION = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
.withValue("REDIRECTION");
private static final KeyValue URI_ROOT = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
.withValue("root");
private static final KeyValue URI_UNKNOWN = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
.withValue("UNKNOWN");
private static final KeyValue EXCEPTION_NONE = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.EXCEPTION
.withValue("None");
private static final KeyValue STATUS_SERVER_ERROR = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.STATUS
.withValue("500");
private static final KeyValue METHOD_UNKNOWN = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.METHOD
.withValue("UNKNOWN");
private JerseyKeyValues() {
}
/**
* Creates a {@code method} KeyValue based on the {@link ContainerRequest#getMethod()
* method} of the given {@code request}.
* @param request the container request
* @return the method KeyValue whose value is a capitalized method (e.g. GET).
*/
static KeyValue method(ContainerRequest request) {
return (request != null)
? JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.METHOD.withValue(request.getMethod())
: METHOD_UNKNOWN;
}
/**
* Creates a {@code status} KeyValue based on the status of the given
* {@code response}.
* @param response the container response
* @return the status KeyValue derived from the status of the response
*/
static KeyValue status(ContainerResponse response) {
/* In case there is no response we are dealing with an unmapped exception. */
return (response != null) ? JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.STATUS
.withValue(Integer.toString(response.getStatus())) : STATUS_SERVER_ERROR;
}
/**
* Creates a {@code uri} KeyValue based on the URI of the given {@code event}. Uses
* the {@link ExtendedUriInfo#getMatchedTemplates()} if available. {@code REDIRECTION}
* for 3xx responses, {@code NOT_FOUND} for 404 responses.
* @param event the request event
* @return the uri KeyValue derived from the request event
*/
static KeyValue uri(RequestEvent event) {
int status = 0;
if (event.getContainerResponse() != null) {
status = event.getContainerResponse().getStatus();
} else if (WebApplicationException.class.isInstance(event.getException())) {
Response webAppResponse = ((WebApplicationException) event.getException()).getResponse();
if (webAppResponse != null) {
status = webAppResponse.getStatus();
}
}
if (status != 0) {
if (JerseyTags.isRedirection(status) && event.getUriInfo().getMatchedResourceMethod() == null) {
return URI_REDIRECTION;
}
if (status == 404 && event.getUriInfo().getMatchedResourceMethod() == null) {
return URI_NOT_FOUND;
}
if (status >= 500 && status <= 599) {
return STATUS_SERVER_ERROR;
}
}
String matchingPattern = JerseyTags.getMatchingPattern(event);
if (matchingPattern == null) {
return URI_UNKNOWN;
}
if (matchingPattern.equals("/")) {
return URI_ROOT;
}
return JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI.withValue(matchingPattern);
}
/**
* Creates an {@code exception} KeyValue based on the {@link Class#getSimpleName()
* simple name} of the class of the given {@code exception}.
* @param event the request event
* @return the exception KeyValue derived from the exception
*/
static KeyValue exception(RequestEvent event) {
Throwable exception = event.getException();
if (exception == null) {
return EXCEPTION_NONE;
}
ContainerResponse response = event.getContainerResponse();
if (response != null) {
int status = response.getStatus();
if (status == 404 || JerseyTags.isRedirection(status)) {
return EXCEPTION_NONE;
}
}
if (exception.getCause() != null) {
exception = exception.getCause();
}
String simpleName = exception.getClass().getSimpleName();
return JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.EXCEPTION
.withValue(StringUtils.isNotEmpty(simpleName) ? simpleName : exception.getClass().getName());
}
/**
* Creates an {@code outcome} KeyValue based on the status of the given
* {@code response}.
* @param response the container response
* @return the outcome KeyValue derived from the status of the response
*/
static KeyValue outcome(ContainerResponse response) {
if (response != null) {
Outcome outcome = Outcome.forStatus(response.getStatus());
return JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.OUTCOME.withValue(outcome.name());
}
/* In case there is no response we are dealing with an unmapped exception. */
return JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.OUTCOME
.withValue(Outcome.SERVER_ERROR.name());
}
}