Kludex / fastapi-health

Implement the Health Check API pattern on your FastAPI application! :rocket:
https://kludex.github.io/fastapi-health/
MIT License
175 stars 13 forks source link

Should implement RFC draft for health check #10

Open christianhujer opened 2 years ago

christianhujer commented 2 years ago

The health check module should implement the RFC draft for health check.

The latest official version of the draft can be found here: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06

To participate in the development of the draft: https://github.com/inadarei/rfc-healthcheck/

For an example of a Python library that implements the Health Check API: https://github.com/Colin-b/healthpy

Kludex commented 2 years ago

I'm going to read the draft later on. Thanks @christianhujer ! :)

Kludex commented 2 years ago

1. Add right mime type

Health Check Response Format for HTTP APIs uses the JSON format described in [RFC8259] and has the media type "application/ health+json".

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3

2. Add status field on response

status: (required) indicates whether the service status is acceptable or not. API publishers SHOULD use following values for the field:

  • "pass": healthy (acceptable aliases: "ok" to support Node's Terminus and "up" for Java's SpringBoot),
  • "fail": unhealthy (acceptable aliases: "error" to support Node's Terminus and "down" for Java's SpringBoot), and
  • "warn": healthy, with some concerns.

Should we follow recommendation? Should we allow custom? As it's SHOULD, we probably should allow custom...

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.1

3. Validate input status

The value of the status field is case-insensitive and is tightly related with the HTTP response code returned by the health endpoint. For "pass" status, HTTP response code in the 2xx-3xx range MUST be used. For "fail" status, HTTP response code in the 4xx-5xx range MUST be used. In case of the "warn" status, endpoints MUST return HTTP status in the 2xx-3xx range, and additional information SHOULD be provided, utilizing optional fields of the response.

We should probably validate the MUSTs here i.e. not allow the user to add 400 on "pass", even if it's obvious.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.1

4. Version ?

version: (optional) public version of the service.

Should we use FastAPI(version=...) here? Even if it's optional, should it really be optional? If yes, should we make the default the FastAPI.version? I'd say "yes" for the questions here... But allow disabling/using another version.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.2

5. Add releaseId callable

releaseId: (optional) in well-designed APIs, backwards-compatible changes in the service should not update a version number. APIs usually change their version number as infrequently as possible, to preserve stable interface. However, implementation of an API may change much more frequently, which leads to the importance of having separate "release number" or "releaseId" that is different from the public version of the API.

We should probably add a callable to retrieve this value. If callable provided, releaseId will be on the response, otherwise the field will not be available. If callable result is None, should we send the releaseId? I would say yes, to make every response follow the same pattern. But I'm open here.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.3

6. Add notes field

notes: (optional) array of notes relevant to current state of health

I need to think about this. Should we give power to the user or have fastapi-health give a summary by itself? Should we have this field at all?

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.4

7. Add serviceId

serviceId (optional) is a unique identifier of the service, in the application scope.

Add a str field, if None, don't provide.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.8

8. Add description

description (optional) is a human-friendly description of the service.

Add a str field, if None, don't provide.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.9

9. Output ?

output: (optional) raw error output, in case of "fail" or "warn" states. This field SHOULD be omitted for "pass" state.

Need to think about it.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.5

10. Add checks object

checks (optional) is an object that provides detailed health statuses of additional downstream systems and endpoints which can affect the overall health of the main API. Please refer to the "The Checks Object" section for more information.

Reference:

11. Links ?

links (optional) is an object containing link relations and URIs [RFC3986] for external links that MAY contain more information about the health of the endpoint. All values of this object SHALL be URIs. Keys MAY also be URIs. Per web-linking standards [RFC8288] a link relationship SHOULD either be a common/registered one or be indicated as a URI, to avoid name clashes. If a "self" link is provided, it MAY be used by clients to check health via HTTP response code, as mentioned above.

Need to think about it.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-3.7

12. Security concerns

Clients need to exercise care when reporting health information. Malicious actors could use this information for orchestrating attacks. In some cases, the health check endpoints may need to be authenticated and institute role-based access control.

Maybe use a dependency to validate the usage of the endpoint - allowing the client to choose the best authentication method.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-6

13. Cache control ?

Health check responses SHOULD be assigned a freshness lifetime (e.g., "Cache-Control: max-age=3600") so that clients can determine how long they could cache them, to avoid overly frequent fetching and unintended DDOS-ing of the service. Any method of cache lifetime negotiation provided by HTTP spec is acceptable (e.g. ETags are just fine).

Need to think about it.

Reference: https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-06#section-9

Kludex commented 2 years ago

I'll have to introduce breaking changes to be compliant with the draft, or introduce a new structure to handle the draft.

I'll probably opt for the latter. Add HealthRoute and a deprecation warning on the health sounds reasonable. I'd like to maintain the basic usage as simple as possible, but I may have to enforce some output from the condition callables.

Kludex commented 2 years ago

Most of the implementation can be found here: https://github.com/Kludex/fastapi-health/pull/11/

I'll finish it tomorrow. Feedback is welcome in the meantime.

EDIT: I didn't finish "tomorrow". I'll see whenever I can.

simplylu commented 1 year ago

Any updates on that? Did you manage to finish the implementation as of now?

Kludex commented 1 year ago

I'm going to check this week. I have a week off from work. :eyes:

Kludex commented 1 year ago

I'll continue to work on it in the following days. I'll need to add a documentation as well.