001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.impl.health;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.camel.CamelContext;
027import org.apache.camel.Route;
028import org.apache.camel.ServiceStatus;
029import org.apache.camel.api.management.mbean.ManagedRouteMBean;
030import org.apache.camel.health.HealthCheckResultBuilder;
031import org.apache.camel.util.ObjectHelper;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035public class RouteHealthCheck extends AbstractHealthCheck {
036    private static final Logger LOGGER = LoggerFactory.getLogger(RouteHealthCheck.class);
037
038    private final Route route;
039    private final List<PerformanceCounterEvaluator<ManagedRouteMBean>> evaluators;
040
041    public RouteHealthCheck(Route route) {
042        this(route, null);
043    }
044
045    public RouteHealthCheck(Route route, Collection<PerformanceCounterEvaluator<ManagedRouteMBean>> evaluators) {
046        super("camel", "route:" + route.getId());
047
048        this.route = route;
049
050        if (ObjectHelper.isNotEmpty(evaluators)) {
051            this.evaluators = new ArrayList<>(evaluators);
052        } else {
053            this.evaluators = Collections.emptyList();
054        }
055    }
056
057    @Override
058    protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) {
059        if (route.getId() != null) {
060            final CamelContext context = route.getRouteContext().getCamelContext();
061            final ServiceStatus status = context.getRouteStatus(route.getId());
062
063            builder.detail("route.id", route.getId());
064            builder.detail("route.status", status.name());
065            builder.detail("route.context.name", context.getName());
066
067            if (route.getRouteContext().getRouteController() != null || route.getRouteContext().isAutoStartup()) {
068                if (status.isStarted()) {
069                    builder.up();
070                } else if (status.isStopped()) {
071                    builder.down();
072                    builder.message(String.format("Route %s has status %s", route.getId(), status.name()));
073                }
074            } else {
075                LOGGER.debug("Route {} marked as UP (controlled={}, auto-startup={})",
076                    route.getId(),
077                    route.getRouteContext().getRouteController() != null,
078                    route.getRouteContext().isAutoStartup()
079                );
080
081                // Assuming that if no route controller is configured or if a
082                // route is configured to not to automatically start, then the
083                // route is always up as it is externally managed.
084                builder.up();
085            }
086
087            if (builder.state() != State.DOWN) {
088                // If JMX is enabled, use the Managed MBeans to determine route
089                // health based on performance counters.
090                ManagedRouteMBean managedRoute = context.getManagedRoute(route.getId(), ManagedRouteMBean.class);
091
092                if (managedRoute != null && !evaluators.isEmpty()) {
093                    Map<String, Object> details = new HashMap<>();
094
095                    for (PerformanceCounterEvaluator evaluator : evaluators) {
096                        details.clear();
097
098                        evaluator.test(managedRoute, builder, options);
099
100                        if (builder.state() == State.DOWN) {
101                            break;
102                        }
103                    }
104                }
105            }
106        }
107    }
108}