55package metricset
66
77import (
8- "os"
9- "time"
8+ "errors"
9+ "fmt"
10+ "slices"
1011
1112 "github.com/elastic/beats/v7/metricbeat/module/elasticsearch"
1213 "github.com/elastic/beats/v7/x-pack/metricbeat/module/autoops_es/utils"
13- "github.com/elastic/elastic-agent-libs/logp"
1414 libversion "github.com/elastic/elastic-agent-libs/version"
1515)
1616
@@ -19,10 +19,20 @@ const MinimumEsVersion = "7.17.0"
1919var minVersion = libversion .MustNew (MinimumEsVersion )
2020var isVersionChecked = false
2121
22+ const (
23+ CLUSTER_INFO_INITIAL_ERROR = 1
24+ CLUSTER_INFO_RUNTIME_ERROR = 2
25+ )
26+
27+ // List of HTTP status codes that indicate the agent cannot recover
28+ var terminalHttpErrorStatusCodes = []int {401 , 403 , 404 }
29+
2230func GetInfo (m * elasticsearch.MetricSet ) (* utils.ClusterInfo , error ) {
2331 info , err := utils .FetchAPIData [utils.ClusterInfo ](m , "/" )
2432
2533 if err != nil {
34+ var httpResponse * utils.HTTPResponse
35+ handleClusterInfoError (m , err , httpResponse )
2636 return nil , err
2737 } else if info .ClusterID == "" || info .ClusterID == "_na_" {
2838 return nil , & utils.ClusterInfoError {Message : "cluster ID is unset, which means the cluster is not ready" }
@@ -32,7 +42,7 @@ func GetInfo(m *elasticsearch.MetricSet) (*utils.ClusterInfo, error) {
3242 if ! isVersionChecked {
3343 // for some reason log.Fatal() isn't working properly so we need to handle the error in a goroutine
3444 errChan := make (chan error )
35- go handleErrors (m .Logger (), errChan )
45+ go handleFatalErrors (m .Logger (), errChan , CLUSTER_INFO_INITIAL_ERROR )
3646
3747 if err := checkEsVersion (info .Version .Number , errChan ); err != nil {
3848 return nil , err
@@ -42,6 +52,19 @@ func GetInfo(m *elasticsearch.MetricSet) (*utils.ClusterInfo, error) {
4252 return info , nil
4353}
4454
55+ func handleClusterInfoError (m * elasticsearch.MetricSet , err error , httpResponse * utils.HTTPResponse ) {
56+ if errors .As (err , & httpResponse ) {
57+ if slices .Contains (terminalHttpErrorStatusCodes , httpResponse .StatusCode ) {
58+ // in these error cases Autoops agent can't recover itself, hence stop the agent
59+ errChan := make (chan error )
60+ go handleFatalErrors (m .Logger (), errChan , CLUSTER_INFO_RUNTIME_ERROR )
61+ customErr := fmt .Errorf ("autoops agent can't fetch the metrics due to http error! Code: %d, Status: %s" ,
62+ httpResponse .StatusCode , httpResponse .Status )
63+ errChan <- customErr
64+ }
65+ }
66+ }
67+
4568func checkEsVersion (esVersion * libversion.V , errChan chan error ) error {
4669 if esVersion .LessThan (minVersion ) {
4770 isVersionChecked = true
@@ -55,12 +78,3 @@ func checkEsVersion(esVersion *libversion.V, errChan chan error) error {
5578
5679 return nil
5780}
58-
59- func handleErrors (logger * logp.Logger , errChan chan error ) {
60- for err := range errChan {
61- logger .Error (err )
62- // sleep is needed to make sure the error is logged and error event is sent before exiting
63- time .Sleep (time .Second * 5 )
64- os .Exit (1 )
65- }
66- }
0 commit comments