//
// Copyright (c) 2016-2017 Contributors to the Eclipse Foundation
//
// See the NOTICES file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

# Service Healthchecks

## Motivation

Health checks are used to probe the state of a computing node from another machine (i.e. kubernetes service controller) with the primary target being cloud infrastructure environments where automated processes maintain the state of computing nodes.

In this scenario, _health checks are used to determine if a computing node needs to be discarded (terminated, shutdown)_ and eventually replaced by another (healthy) instance.

It’s not intended (although could be used) as a monitoring solution for human operators.

## Proposed solution

The proposed solution breaks down into two parts:

- A health check protocol and wireformat
- A Java API to implement health check procedures

## Detailed design

### Protocol

This project defines a protocol (wireformat, semantics and possible forms of interactions) between system components that need to determine the “liveliness” of computing nodes in a bigger architecture.
A detailed description of the health check protocol can be found in the link:https://github.com/eclipse/microprofile-health/tree/master/spec/src/main/asciidoc/protocol-wireformat.adoc[companion document]

### API Usage

The main API to provide health check procedures on the application level is the `HealthCheck` interface:

```
@FunctionalInterface
public interface HealthCheck {

    HealthCheckResponse call();
}
```

Applications are expected to provide health check procedures (implementation of a `HealthCheck`), which will be used by the
the framework or runtime hosting the application to verify the healthiness of the computing node.

The runtime will `call()` the `HealthCheck` which in turn creates a `HealthCheckResponse` that signals the health status to a consuming end:

```
public abstract class HealthCheckResponse {

    public enum State { UP, DOWN }

    public abstract String getName();

    public abstract State getState();

    public abstract Optional<Map<String, Object>> getData();

    [...]
}
```
### Constructing `HealthCheckResponse`s

Application level code is expected to use one of static methods on `HealthCheckResponse` to retrieve a `HealthCheckResponseBuilder` used to construct a response, i.e. :

```
public class SuccessfulCheck implements HealthCheck {
    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.named("successful-check").up();
    }
}
```

### Integration with CDI

Within CDI contexts, beans that implement `HealthCheck` and annotated with `@Health` are discovered automatically and are invoked by the framework or runtime when the outermost protocol entry point (i.e. `http://HOST:PORT/health`) receives an inbound request.

```
@Health
@ApplicationScoped
public class CheckDiskpace implements HealthCheck {

    public HealthCheckResponse call() {
        [...]
    }
}
```

### On the wire

It's the responsibility of the runtime to gather all `HealthCheckResponse` s for `HealthCheck` s known to the runtime. This means an inbound HTTP request will lead to a series of invocations
 on health check procedures and the runtime will provide a composite response, with a single overall outcome, i.e.:

  ```
  {
    "outcome": "UP",
    "checks": [
      {
        "id": "first-check",
        "result": "UP",
        "data": {
          "key": "foo",
          "foo": "bar"
        }
      },
      {
          "id": "second-check",
          "result": "UP"
      }
    ]
  }
  ```

The link:https://github.com/eclipse/microprofile-health/tree/master/spec/src/main/asciidoc/protocol-wireformat.adoc[companion document] contains further information on forms of interaction and the wireformat.

# SPI Usage

Implementors of the API are expected to supply implementations of `HealthCheckResponse` and `HealthCheckResponseBuilder` by providing a `HealthCheckResponseProvider` to their implementation. The `HealthCheckResponseProvider` is discovered using the default JDK service loader.

A `HealthCheckResponseProvider` is used internally to create a `HealthCheckResponseBuilder` which is used to construct a `HealthCheckResponse`. This pattern allows implementors to extend a `HealthCheckResponse` and adapt it to their implementation needs. Common implementation details that fall into this category are invocation and security contexts or anything else required to map a `HealthCheckResponse` to the outermost invocation protocol (i.e. HTTP/JSON).
