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.autoconfigure.metrics.jersey; 018 019import java.lang.annotation.Annotation; 020import java.lang.reflect.AnnotatedElement; 021 022import io.micrometer.core.instrument.MeterRegistry; 023import io.micrometer.core.instrument.config.MeterFilter; 024import io.micrometer.jersey2.server.AnnotationFinder; 025import io.micrometer.jersey2.server.DefaultJerseyTagsProvider; 026import io.micrometer.jersey2.server.JerseyTagsProvider; 027import io.micrometer.jersey2.server.MetricsApplicationEventListener; 028import org.glassfish.jersey.server.ResourceConfig; 029 030import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; 031import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties; 032import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Web.Server; 033import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter; 034import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; 035import org.springframework.boot.autoconfigure.AutoConfigureAfter; 036import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 037import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 038import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 039import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 040import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; 041import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer; 042import org.springframework.boot.context.properties.EnableConfigurationProperties; 043import org.springframework.context.annotation.Bean; 044import org.springframework.context.annotation.Configuration; 045import org.springframework.core.annotation.AnnotationUtils; 046import org.springframework.core.annotation.Order; 047 048/** 049 * {@link EnableAutoConfiguration Auto-configuration} for Jersey server instrumentation. 050 * 051 * @author Michael Weirauch 052 * @author Michael Simons 053 * @author Andy Wilkinson 054 * @since 2.1.0 055 */ 056@Configuration 057@AutoConfigureAfter({ MetricsAutoConfiguration.class, 058 SimpleMetricsExportAutoConfiguration.class }) 059@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) 060@ConditionalOnClass({ ResourceConfig.class, MetricsApplicationEventListener.class }) 061@ConditionalOnBean({ MeterRegistry.class, ResourceConfig.class }) 062@EnableConfigurationProperties(MetricsProperties.class) 063public class JerseyServerMetricsAutoConfiguration { 064 065 private final MetricsProperties properties; 066 067 public JerseyServerMetricsAutoConfiguration(MetricsProperties properties) { 068 this.properties = properties; 069 } 070 071 @Bean 072 @ConditionalOnMissingBean(JerseyTagsProvider.class) 073 public DefaultJerseyTagsProvider jerseyTagsProvider() { 074 return new DefaultJerseyTagsProvider(); 075 } 076 077 @Bean 078 public ResourceConfigCustomizer jerseyServerMetricsResourceConfigCustomizer( 079 MeterRegistry meterRegistry, JerseyTagsProvider tagsProvider) { 080 Server server = this.properties.getWeb().getServer(); 081 return (config) -> config.register(new MetricsApplicationEventListener( 082 meterRegistry, tagsProvider, server.getRequestsMetricName(), 083 server.isAutoTimeRequests(), new AnnotationUtilsAnnotationFinder())); 084 } 085 086 @Bean 087 @Order(0) 088 public MeterFilter jerseyMetricsUriTagFilter() { 089 String metricName = this.properties.getWeb().getServer().getRequestsMetricName(); 090 MeterFilter filter = new OnlyOnceLoggingDenyMeterFilter(() -> String 091 .format("Reached the maximum number of URI tags for '%s'.", metricName)); 092 return MeterFilter.maximumAllowableTags(metricName, "uri", 093 this.properties.getWeb().getServer().getMaxUriTags(), filter); 094 } 095 096 /** 097 * An {@link AnnotationFinder} that uses {@link AnnotationUtils}. 098 */ 099 private static class AnnotationUtilsAnnotationFinder implements AnnotationFinder { 100 101 @Override 102 public <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, 103 Class<A> annotationType) { 104 return AnnotationUtils.findAnnotation(annotatedElement, annotationType); 105 } 106 107 } 108 109}