001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.actuate.metrics.web.reactive.server; 018 019import io.micrometer.core.instrument.Tag; 020 021import org.springframework.http.HttpStatus; 022import org.springframework.util.StringUtils; 023import org.springframework.web.reactive.HandlerMapping; 024import org.springframework.web.server.ServerWebExchange; 025import org.springframework.web.util.pattern.PathPattern; 026 027/** 028 * Factory methods for {@link Tag Tags} associated with a request-response exchange that 029 * is handled by WebFlux. 030 * 031 * @author Jon Schneider 032 * @author Andy Wilkinson 033 * @author Michael McFadyen 034 * @since 2.0.0 035 */ 036public final class WebFluxTags { 037 038 private static final Tag URI_NOT_FOUND = Tag.of("uri", "NOT_FOUND"); 039 040 private static final Tag URI_REDIRECTION = Tag.of("uri", "REDIRECTION"); 041 042 private static final Tag URI_ROOT = Tag.of("uri", "root"); 043 044 private static final Tag EXCEPTION_NONE = Tag.of("exception", "None"); 045 046 private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN"); 047 048 private static final Tag OUTCOME_INFORMATIONAL = Tag.of("outcome", "INFORMATIONAL"); 049 050 private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS"); 051 052 private static final Tag OUTCOME_REDIRECTION = Tag.of("outcome", "REDIRECTION"); 053 054 private static final Tag OUTCOME_CLIENT_ERROR = Tag.of("outcome", "CLIENT_ERROR"); 055 056 private static final Tag OUTCOME_SERVER_ERROR = Tag.of("outcome", "SERVER_ERROR"); 057 058 private WebFluxTags() { 059 } 060 061 /** 062 * Creates a {@code method} tag based on the 063 * {@link org.springframework.http.server.reactive.ServerHttpRequest#getMethod() 064 * method} of the {@link ServerWebExchange#getRequest()} request of the given 065 * {@code exchange}. 066 * @param exchange the exchange 067 * @return the method tag whose value is a capitalized method (e.g. GET). 068 */ 069 public static Tag method(ServerWebExchange exchange) { 070 return Tag.of("method", exchange.getRequest().getMethodValue()); 071 } 072 073 /** 074 * Creates a {@code status} tag based on the response status of the given 075 * {@code exchange}. 076 * @param exchange the exchange 077 * @return the status tag derived from the response status 078 */ 079 public static Tag status(ServerWebExchange exchange) { 080 HttpStatus status = exchange.getResponse().getStatusCode(); 081 if (status == null) { 082 status = HttpStatus.OK; 083 } 084 return Tag.of("status", String.valueOf(status.value())); 085 } 086 087 /** 088 * Creates a {@code uri} tag based on the URI of the given {@code exchange}. Uses the 089 * {@link HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE} best matching pattern. 090 * @param exchange the exchange 091 * @return the uri tag derived from the exchange 092 */ 093 public static Tag uri(ServerWebExchange exchange) { 094 PathPattern pathPattern = exchange 095 .getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); 096 if (pathPattern != null) { 097 return Tag.of("uri", pathPattern.getPatternString()); 098 } 099 HttpStatus status = exchange.getResponse().getStatusCode(); 100 if (status != null) { 101 if (status.is3xxRedirection()) { 102 return URI_REDIRECTION; 103 } 104 if (status == HttpStatus.NOT_FOUND) { 105 return URI_NOT_FOUND; 106 } 107 } 108 String path = exchange.getRequest().getPath().value(); 109 if (path.isEmpty()) { 110 return URI_ROOT; 111 } 112 return Tag.of("uri", path); 113 } 114 115 /** 116 * Creates an {@code exception} tag based on the {@link Class#getSimpleName() simple 117 * name} of the class of the given {@code exception}. 118 * @param exception the exception, may be {@code null} 119 * @return the exception tag derived from the exception 120 */ 121 public static Tag exception(Throwable exception) { 122 if (exception != null) { 123 String simpleName = exception.getClass().getSimpleName(); 124 return Tag.of("exception", StringUtils.hasText(simpleName) ? simpleName 125 : exception.getClass().getName()); 126 } 127 return EXCEPTION_NONE; 128 } 129 130 /** 131 * Creates an {@code outcome} tag based on the response status of the given 132 * {@code exchange}. 133 * @param exchange the exchange 134 * @return the outcome tag derived from the response status 135 * @since 2.1.0 136 */ 137 public static Tag outcome(ServerWebExchange exchange) { 138 HttpStatus status = exchange.getResponse().getStatusCode(); 139 if (status != null) { 140 if (status.is1xxInformational()) { 141 return OUTCOME_INFORMATIONAL; 142 } 143 if (status.is2xxSuccessful()) { 144 return OUTCOME_SUCCESS; 145 } 146 if (status.is3xxRedirection()) { 147 return OUTCOME_REDIRECTION; 148 } 149 if (status.is4xxClientError()) { 150 return OUTCOME_CLIENT_ERROR; 151 } 152 return OUTCOME_SERVER_ERROR; 153 } 154 return OUTCOME_UNKNOWN; 155 } 156 157}