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.tomcat;
018
019import java.util.Collections;
020
021import io.micrometer.core.instrument.MeterRegistry;
022import io.micrometer.core.instrument.Tag;
023import io.micrometer.core.instrument.binder.tomcat.TomcatMetrics;
024import org.apache.catalina.Container;
025import org.apache.catalina.Context;
026import org.apache.catalina.Manager;
027
028import org.springframework.boot.context.event.ApplicationStartedEvent;
029import org.springframework.boot.web.context.WebServerApplicationContext;
030import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
031import org.springframework.boot.web.server.WebServer;
032import org.springframework.context.ApplicationContext;
033import org.springframework.context.ApplicationListener;
034
035/**
036 * Binds {@link TomcatMetrics} in response to the {@link ApplicationStartedEvent}.
037 *
038 * @author Andy Wilkinson
039 * @since 2.1.0
040 */
041public class TomcatMetricsBinder implements ApplicationListener<ApplicationStartedEvent> {
042
043        private final MeterRegistry meterRegistry;
044
045        private final Iterable<Tag> tags;
046
047        public TomcatMetricsBinder(MeterRegistry meterRegistry) {
048                this(meterRegistry, Collections.emptyList());
049        }
050
051        public TomcatMetricsBinder(MeterRegistry meterRegistry, Iterable<Tag> tags) {
052                this.meterRegistry = meterRegistry;
053                this.tags = tags;
054        }
055
056        @Override
057        public void onApplicationEvent(ApplicationStartedEvent event) {
058                ApplicationContext applicationContext = event.getApplicationContext();
059                Manager manager = findManager(applicationContext);
060                new TomcatMetrics(manager, this.tags).bindTo(this.meterRegistry);
061        }
062
063        private Manager findManager(ApplicationContext applicationContext) {
064                if (applicationContext instanceof WebServerApplicationContext) {
065                        WebServer webServer = ((WebServerApplicationContext) applicationContext)
066                                        .getWebServer();
067                        if (webServer instanceof TomcatWebServer) {
068                                Context context = findContext((TomcatWebServer) webServer);
069                                return context.getManager();
070                        }
071                }
072                return null;
073        }
074
075        private Context findContext(TomcatWebServer tomcatWebServer) {
076                for (Container container : tomcatWebServer.getTomcat().getHost().findChildren()) {
077                        if (container instanceof Context) {
078                                return (Context) container;
079                        }
080                }
081                return null;
082        }
083
084}