gatus icon indicating copy to clipboard operation
gatus copied to clipboard

feat: Support default endpoint config

Open Darkvater opened this issue 2 years ago • 2 comments

Describe the feature request

It is brilliant that for alerting one is able to setup defaults, but something similar could be very useful for the endpoint configuration as well. Functionality should be the same as for default-alerting, e.g. you set the defaults but you can still override it per endpoint if needed. It should properly mix in with default-alerting, if one is set up.

This will also open the paths for adding default-endpoint groups where one could for example say the below to define two different defaults for endpoints.

endpoints:
  default-endpoint:
    - name: service-group1
      ...
    - name: service-group2
      ...

After this you can use them and have a much more concise configuration file.

endpoints:
  - name: service1.1
     default-group: service-group1
    ...
  - name: service 1.2
      default-group: service-group1

Why do you personally want this feature to be implemented?

I am monitoring 13 endpoints per service for 4 services. My configuration file is about 700 lines long and I am basically duplicating the below snippet (all services are spring-boot /actuator/health endpoints).

endpoints:
  interval: 5m
  conditions:
    - "[STATUS] == 200"
    - "[BODY].status == UP"
    - "[RESPONSE_TIME] < 300"

My reasoning is the same as for alerting and will paste it here ad-verbatim ;)

While you can specify the alert configuration directly in the endpoint definition, it's tedious and may lead to a very long configuration file.

To avoid such problem, you can use the default-alert parameter present in each provider configuration:

How long have you been using this project?

1 week

Additional information

No response

Darkvater avatar May 03 '22 19:05 Darkvater

To be honest, I'm a little skeptical about adding this as a feature.

On one hand, it does help reduce the configuration file size as well as make it easier to apply certain configurations across all endpoints, but on the other hand, due to how much more complex endpoint configuration is than the alert configuration, it also makes it considerably harder to understand.

Furthermore, what about type-specific configuration? For instance, there's no headers for non-HTTP requests (e.g. DNS, ICMP, TCP, etc.), so what do I do about a default endpoint configuration that has headers configured?

Sure, programmatically, it's not a problem, but from the end user's point of view, it may lead to confusion -- something I'd like to avoid as much as possible.

TwiN avatar May 07 '22 21:05 TwiN

Actually I was thinking something much-much more general and this would also allow you to drop default-alerting which is a very specific implementation of groups/templates. The idea is that you define a completely free-style template, e.g.

templates:
  - template-endpoint:
       url: "some-url"
       interval: 5m
       ...
  - template-client:
     client:
       oauth2:
         token-url: "some-url"
         client-id: ...
         ...
  - template-email:
     type: email
     enabled: true

And wherever you want to use it it simply gets popped in, e.g.

endpoints:
  - template: template-endpoint
    name: website
    url: "some-other-url"
    alerts:
      - template: template-email

The template will be injected and you'll end up with

endpoints:
  - name: website
    interval: 5m
    url: "some-other-url" # not from template as it is overriden in actual config
    alerts:
      - type: email
        enabled: true

This is nothing more than a deep map-merge. The template bit is completely free-form (as you can drop it anywhere where we support it) and once it's dropped in and the actual resolved yaml is parsed it gets a meaning.

  • of course we don't need to go super fancy and define a limited entry-points to begin with. You can templatise an endpoint, condition, alert
  • the point is that we need to change the gatus configuration loader to load the config first into a map of objects (e.g. map[string][any] where any can be a map, or list, or value) then parse the templates block resolving the template keys. This would take whatever is under that template and merge it with the entries defined in place (e.g. the overrides)

Unfortunately I have zero knowledge of Go, but it's super easy in kotlin/java which I am familiar with. I thought of having a go at go, but it's very new to me, and I also see that the config is already strongly typed which obviously complicates things a lot. Perhaps we can add a pre-processor that processes the config with the template, writing out the resolved yaml and parsing that to the strongly typed gatus configuration?

As to your concern re user-confusion: it is the user's responsibility to use the configuration, and templating system properly. If the template is incorrect gatus will exit with an error - as it already does now when you supply it with an incorrect config - and the user can investigate. I do not think that this is/should be a blocking reason not to implement something that makes maintaining a configuration that much easier.

Darkvater avatar May 25 '22 20:05 Darkvater

Support for this will not be added, because you can technically leverage YAML anchors to achieve something nearly identical.

See Keeping your configuration small.

TwiN avatar Jan 29 '23 22:01 TwiN