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.juneau.rest.server.health;
018
019import org.apache.juneau.rest.server.*;
020import org.apache.juneau.rest.server.health.HealthAggregator.*;
021import org.apache.juneau.rest.server.servlet.*;
022
023/**
024 * Child-resource flavor of the built-in health/readiness/liveness probe capability.
025 *
026 * <p>
027 * Mounts as a <b>routed child</b> via {@link Rest#children() @Rest(children=HealthResource.class)}
028 * under a parent at the subtree {@code /health} and serves the {@code /healthz}, {@code /readyz}, and
029 * {@code /livez} probe endpoints by delegating to a shared {@link HealthAggregator} worker bean &mdash;
030 * the same logic the {@link HealthServlet servlet} and {@link HealthMixin mixin} flavors use, so the
031 * three forms cannot drift.
032 *
033 * <p>
034 * Indicators are resolved from the host's bean store, so a host registers its own
035 * {@link HealthIndicator} beans (e.g. via Spring {@code @Bean} or a Juneau {@code BeanStore}).
036 *
037 * <p>
038 * Extends {@link BasicRestResource} &mdash; the child-flavor mirror of {@link BasicRestServlet} that the
039 * {@link HealthServlet} servlet flavor extends &mdash; so the {@link HealthAggregator.HealthResponse}
040 * bean returned by the probe ops is serialized out of the box via the {@code BasicUniversalConfig}
041 * serializer set (JSON/XML/HTML/&hellip;). A bare {@code RestResource} child would carry no serializers
042 * and force every consumer to re-declare one; deriving from {@code BasicRestResource} keeps the child
043 * flavor at parity with its servlet twin.
044 *
045 * <h5 class='section'>See Also:</h5><ul>
046 *    <li class='jc'>{@link HealthServlet}
047 *    <li class='jc'>{@link HealthMixin}
048 *    <li class='jc'>{@link HealthAggregator}
049 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerComposition">REST Server — Mixins and Multi-Mount Paths</a>
050 * </ul>
051 *
052 * @since 10.0.0
053 */
054@Rest(path="/health")
055public class HealthResource extends BasicRestResource {
056
057   private final HealthAggregator aggregator = new HealthAggregator();
058
059   /**
060    * Health probe endpoint.
061    *
062    * @param req The request.
063    * @param res The response.
064    * @return Aggregated health payload.
065    */
066   @RestGet(path="/healthz")
067   public HealthResponse healthz(RestRequest req, RestResponse res) {
068      return aggregator.aggregate(req.getContext(), aggregator.indicators(req.getContext()), null, res);
069   }
070
071   /**
072    * Readiness probe endpoint.
073    *
074    * @param req The request.
075    * @param res The response.
076    * @return Aggregated health payload.
077    */
078   @RestGet(path="/readyz")
079   public HealthResponse readyz(RestRequest req, RestResponse res) {
080      return aggregator.aggregate(req.getContext(), aggregator.indicators(req.getContext()), HealthProbe.READY, res);
081   }
082
083   /**
084    * Liveness probe endpoint.
085    *
086    * @param req The request.
087    * @param res The response.
088    * @return Aggregated health payload.
089    */
090   @RestGet(path="/livez")
091   public HealthResponse livez(RestRequest req, RestResponse res) {
092      return aggregator.aggregate(req.getContext(), aggregator.indicators(req.getContext()), HealthProbe.LIVE, res);
093   }
094}