Hi Remy,

I'm not sure whether GitHub notified you about my comment on this commit:
https://github.com/apache/tomcat/commit/2ff7bba79946a3716b136b0752c9fe7126b50499#r42227542

On Fri, Sep 11, 2020 at 2:27 PM <r...@apache.org> wrote:

> This is an automated email from the ASF dual-hosted git repository.
>
> remm pushed a commit to branch master
> in repository https://gitbox.apache.org/repos/asf/tomcat.git
>
>
> The following commit(s) were added to refs/heads/master by this push:
>      new 2ff7bba  Improve the quality of the health check
> 2ff7bba is described below
>
> commit 2ff7bba79946a3716b136b0752c9fe7126b50499
> Author: remm <r...@apache.org>
> AuthorDate: Fri Sep 11 13:26:44 2020 +0200
>
>     Improve the quality of the health check
>
>     The valve will check if its associated container and all its children
>     are available. Will return down if any is not available.
> ---
>  .../apache/catalina/valves/HealthCheckValve.java   | 43
> +++++++++++++++++++++-
>  webapps/docs/changelog.xml                         |  8 ++++
>  webapps/docs/config/valve.xml                      | 15 +++++---
>  3 files changed, 60 insertions(+), 6 deletions(-)
>
> diff --git a/java/org/apache/catalina/valves/HealthCheckValve.java
> b/java/org/apache/catalina/valves/HealthCheckValve.java
> index be9c487..c111b3b 100644
> --- a/java/org/apache/catalina/valves/HealthCheckValve.java
> +++ b/java/org/apache/catalina/valves/HealthCheckValve.java
> @@ -19,11 +19,14 @@ package org.apache.catalina.valves;
>  import java.io.IOException;
>
>  import jakarta.servlet.ServletException;
> +import jakarta.servlet.http.HttpServletResponse;
>
> +import org.apache.catalina.Container;
>  import org.apache.catalina.Context;
>  import org.apache.catalina.LifecycleException;
>  import org.apache.catalina.connector.Request;
>  import org.apache.catalina.connector.Response;
> +import org.apache.catalina.util.LifecycleBase;
>  import org.apache.tomcat.util.buf.MessageBytes;
>
>
> @@ -38,6 +41,12 @@ public class HealthCheckValve extends ValveBase {
>              "  \"checks\": []\n" +
>              "}";
>
> +    private static final String DOWN =
> +            "{\n" +
> +            "  \"status\": \"DOWN\",\n" +
> +            "  \"checks\": []\n" +
> +            "}";
> +
>      private String path = "/health";
>
>      /**
> @@ -45,6 +54,11 @@ public class HealthCheckValve extends ValveBase {
>       */
>      protected boolean context = false;
>
> +    /**
> +     * Check if all child containers are available.
> +     */
> +    protected boolean checkContainersAvailable = true;
> +
>      public HealthCheckValve() {
>          super(true);
>      }
> @@ -57,6 +71,14 @@ public class HealthCheckValve extends ValveBase {
>          this.path = path;
>      }
>
> +    public boolean getCheckContainersAvailable() {
> +        return this.checkContainersAvailable;
> +    }
> +
> +    public void setCheckContainersAvailable(boolean
> checkContainersAvailable) {
> +        this.checkContainersAvailable = checkContainersAvailable;
> +    }
> +
>      @Override
>      protected synchronized void startInternal() throws LifecycleException
> {
>          super.startInternal();
> @@ -74,9 +96,28 @@ public class HealthCheckValve extends ValveBase {
>                  context ? request.getRequestPathMB() :
> request.getDecodedRequestURIMB();
>          if (urlMB.equals(path)) {
>              response.setContentType("application/json");
> -            response.getOutputStream().print(UP);
> +            if (isAvailable(getContainer())) {
> +                response.getOutputStream().print(UP);
> +            } else {
> +
> response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
> +                response.getOutputStream().print(DOWN);
> +            }
>          } else {
>              getNext().invoke(request, response);
>          }
>      }
> +
> +    protected boolean isAvailable(Container container) {
> +        for (Container child : container.findChildren()) {
> +            if (!isAvailable(child)) {
> +                return false;
> +            }
> +        }
> +        if (container instanceof LifecycleBase) {
> +            return ((LifecycleBase) container).getState().isAvailable();
> +        } else {
> +            return true;
> +        }
> +    }
> +
>  }
> diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
> index 737bf79..d8695c1 100644
> --- a/webapps/docs/changelog.xml
> +++ b/webapps/docs/changelog.xml
> @@ -45,6 +45,14 @@
>    issues do not "pop up" wrt. others).
>  -->
>  <section name="Tomcat 10.0.0-M9 (markt)" rtext="in development">
> +  <subsection name="Catalina">
> +    <changelog>
> +      <update>
> +        The health check valve will now check the state of its associated
> +        containers to report availability. (remm)
> +      </update>
> +    </changelog>
> +  </subsection>
>  </section>
>  <section name="Tomcat 10.0.0-M8 (markt)" rtext="release in progress">
>    <subsection name="Catalina">
> diff --git a/webapps/docs/config/valve.xml b/webapps/docs/config/valve.xml
> index 557ee32..3111fce 100644
> --- a/webapps/docs/config/valve.xml
> +++ b/webapps/docs/config/valve.xml
> @@ -2236,10 +2236,7 @@
>    <subsection name="Introduction">
>
>      <p>The <strong>Health Check Valve</strong> responds to
> -    cloud orchestrators health checks. Note that it checks
> -    that a context is mapped (so that an application is deployed),
> -    for example if you don't have a ROOT context but demo-1.0
> -    you have to check for <code>/demo-1.0/health</code></p>
> +    cloud orchestrators health checks.</p>
>    </subsection>
>
>    <subsection name="Attributes">
> @@ -2255,10 +2252,18 @@
>        </attribute>
>
>        <attribute name="path" required="false">
> -        <p>Path by the cloud orchestrators health check logic.
> +        <p>Path by the cloud orchestrators health check logic. If the
> valve
> +        is associated with a context, then this will be relative to the
> context
> +        path. Otherwise, the valve will match the full URI.
>          The default value is <strong>/health</strong>.</p>
>        </attribute>
>
> +      <attribute name="checkContainersAvailable" required="false">
> +        <p>If <code>true</code> the valve will check if its associated
> +        container and all its children are available.
> +        The default value is <strong>true</strong>.</p>
> +      </attribute>
> +
>      </attributes>
>
>    </subsection>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: dev-h...@tomcat.apache.org
>
>

Reply via email to