feat(api): Add optional duration to external endpoint results (#1092)
* feat(api): Add optional duration to external endpoint results * Fix failing tests * Parse duration regardless of success * Use len instead of equality * Update README.md * Include error in output * Fix result numbering * Update README.md * Update api/external_endpoint.go --------- Co-authored-by: TwiN <twin@linux.com>
This commit is contained in:
@@ -321,13 +321,14 @@ external-endpoints:
|
|||||||
|
|
||||||
To push the status of an external endpoint, the request would have to look like this:
|
To push the status of an external endpoint, the request would have to look like this:
|
||||||
```
|
```
|
||||||
POST /api/v1/endpoints/{key}/external?success={success}&error={error}
|
POST /api/v1/endpoints/{key}/external?success={success}&error={error}&duration={duration}
|
||||||
```
|
```
|
||||||
Where:
|
Where:
|
||||||
- `{key}` has the pattern `<GROUP_NAME>_<ENDPOINT_NAME>` in which both variables have ` `, `/`, `_`, `,`, `.` and `#` replaced by `-`.
|
- `{key}` has the pattern `<GROUP_NAME>_<ENDPOINT_NAME>` in which both variables have ` `, `/`, `_`, `,`, `.` and `#` replaced by `-`.
|
||||||
- Using the example configuration above, the key would be `core_ext-ep-test`.
|
- Using the example configuration above, the key would be `core_ext-ep-test`.
|
||||||
- `{success}` is a boolean (`true` or `false`) value indicating whether the health check was successful or not.
|
- `{success}` is a boolean (`true` or `false`) value indicating whether the health check was successful or not.
|
||||||
- `{error}`: a string describing the reason for a failed health check. If {success} is false, this should contain the error message; if the check is successful, it can be omitted or left empty.
|
- `{error}` (optional): a string describing the reason for a failed health check. If {success} is false, this should contain the error message; if the check is successful.
|
||||||
|
- `{duration}` (optional): the time that the request took as a duration string (e.g. 10s).
|
||||||
|
|
||||||
You must also pass the token as a `Bearer` token in the `Authorization` header.
|
You must also pass the token as a `Bearer` token in the `Authorization` header.
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,14 @@ func CreateExternalEndpointResult(cfg *config.Config) fiber.Handler {
|
|||||||
Success: c.QueryBool("success"),
|
Success: c.QueryBool("success"),
|
||||||
Errors: []string{},
|
Errors: []string{},
|
||||||
}
|
}
|
||||||
|
if len(c.Query("duration")) > 0 {
|
||||||
|
parsedDuration, err := time.ParseDuration(c.Query("duration"))
|
||||||
|
if err != nil {
|
||||||
|
logr.Errorf("[api.CreateExternalEndpointResult] Invalid duration from string=%s with error: %s", c.Query("duration"), err.Error())
|
||||||
|
return c.Status(400).SendString("invalid duration: " + err.Error())
|
||||||
|
}
|
||||||
|
result.Duration = parsedDuration
|
||||||
|
}
|
||||||
if !result.Success && c.Query("error") != "" {
|
if !result.Success && c.Query("error") != "" {
|
||||||
result.Errors = append(result.Errors, c.Query("error"))
|
result.Errors = append(result.Errors, c.Query("error"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
|||||||
AuthorizationHeaderBearerToken: "Bearer token",
|
AuthorizationHeaderBearerToken: "Bearer token",
|
||||||
ExpectedCode: 400,
|
ExpectedCode: 400,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "bad-duration-value",
|
||||||
|
Path: "/api/v1/endpoints/g_n/external?success=true&duration=invalid",
|
||||||
|
AuthorizationHeaderBearerToken: "Bearer token",
|
||||||
|
ExpectedCode: 400,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "good-token-success-true",
|
Name: "good-token-success-true",
|
||||||
Path: "/api/v1/endpoints/g_n/external?success=true",
|
Path: "/api/v1/endpoints/g_n/external?success=true",
|
||||||
@@ -82,6 +88,12 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
|||||||
AuthorizationHeaderBearerToken: "Bearer token",
|
AuthorizationHeaderBearerToken: "Bearer token",
|
||||||
ExpectedCode: 200,
|
ExpectedCode: 200,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "good-duration-success-true",
|
||||||
|
Path: "/api/v1/endpoints/g_n/external?success=true&duration=10s",
|
||||||
|
AuthorizationHeaderBearerToken: "Bearer token",
|
||||||
|
ExpectedCode: 200,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "good-token-success-false",
|
Name: "good-token-success-false",
|
||||||
Path: "/api/v1/endpoints/g_n/external?success=false",
|
Path: "/api/v1/endpoints/g_n/external?success=false",
|
||||||
@@ -118,7 +130,7 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
t.Run("verify-end-results", func(t *testing.T) {
|
t.Run("verify-end-results", func(t *testing.T) {
|
||||||
endpointStatus, err := store.Get().GetEndpointStatus("g", "n", paging.NewEndpointStatusParams().WithResults(1, 10))
|
endpointStatus, err := store.Get().GetEndpointStatus("g", "n", paging.NewEndpointStatusParams().WithResults(1, 11))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to get endpoint status: %s", err.Error())
|
t.Errorf("failed to get endpoint status: %s", err.Error())
|
||||||
return
|
return
|
||||||
@@ -126,8 +138,8 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
|||||||
if endpointStatus.Key != "g_n" {
|
if endpointStatus.Key != "g_n" {
|
||||||
t.Errorf("expected key to be g_n but got %s", endpointStatus.Key)
|
t.Errorf("expected key to be g_n but got %s", endpointStatus.Key)
|
||||||
}
|
}
|
||||||
if len(endpointStatus.Results) != 5 {
|
if len(endpointStatus.Results) != 6 {
|
||||||
t.Errorf("expected 3 results but got %d", len(endpointStatus.Results))
|
t.Errorf("expected 6 results but got %d", len(endpointStatus.Results))
|
||||||
}
|
}
|
||||||
if !endpointStatus.Results[0].Success {
|
if !endpointStatus.Results[0].Success {
|
||||||
t.Errorf("expected first result to be successful")
|
t.Errorf("expected first result to be successful")
|
||||||
@@ -138,8 +150,8 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
|||||||
if len(endpointStatus.Results[1].Errors) > 0 {
|
if len(endpointStatus.Results[1].Errors) > 0 {
|
||||||
t.Errorf("expected second result to have no errors")
|
t.Errorf("expected second result to have no errors")
|
||||||
}
|
}
|
||||||
if endpointStatus.Results[2].Success {
|
if endpointStatus.Results[2].Duration == 0 || endpointStatus.Results[2].Duration.Seconds() != 10 {
|
||||||
t.Errorf("expected third result to be unsuccessful")
|
t.Errorf("expected third result to have a duration of 10 seconds")
|
||||||
}
|
}
|
||||||
if endpointStatus.Results[3].Success {
|
if endpointStatus.Results[3].Success {
|
||||||
t.Errorf("expected fourth result to be unsuccessful")
|
t.Errorf("expected fourth result to be unsuccessful")
|
||||||
@@ -147,8 +159,11 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
|||||||
if endpointStatus.Results[4].Success {
|
if endpointStatus.Results[4].Success {
|
||||||
t.Errorf("expected fifth result to be unsuccessful")
|
t.Errorf("expected fifth result to be unsuccessful")
|
||||||
}
|
}
|
||||||
if len(endpointStatus.Results[4].Errors) == 0 || endpointStatus.Results[4].Errors[0] != "failed" {
|
if endpointStatus.Results[5].Success {
|
||||||
t.Errorf("expected fifth result to have errors: failed")
|
t.Errorf("expected sixth result to be unsuccessful")
|
||||||
|
}
|
||||||
|
if len(endpointStatus.Results[5].Errors) == 0 || endpointStatus.Results[5].Errors[0] != "failed" {
|
||||||
|
t.Errorf("expected sixth result to have errors: failed")
|
||||||
}
|
}
|
||||||
externalEndpointFromConfig := cfg.GetExternalEndpointByKey("g_n")
|
externalEndpointFromConfig := cfg.GetExternalEndpointByKey("g_n")
|
||||||
if externalEndpointFromConfig.NumberOfFailuresInARow != 3 {
|
if externalEndpointFromConfig.NumberOfFailuresInARow != 3 {
|
||||||
|
|||||||
Reference in New Issue
Block a user