diff --git a/internal/elasticsearch/error.go b/internal/elasticsearch/error.go index 0a1bdf160b..fb717f300b 100644 --- a/internal/elasticsearch/error.go +++ b/internal/elasticsearch/error.go @@ -13,19 +13,64 @@ import ( // NewError returns a new error constructed from the given response body. // This assumes the body contains a JSON encoded error. If the body cannot // be parsed then an error is returned that contains the raw body. -func NewError(body []byte) error { - type ErrorBody struct { - Error struct { - Type string `json:"type"` - Reason string `json:"reason"` - } `json:"error"` - } +type ErrorBody struct { + Error struct { + RootCause []struct { + Type string `json:"type"` + Reason string `json:"reason"` + ProcessorType string `json:"processor_type,omitempty"` + ScriptStack []string `json:"script_stack,omitempty"` + Script string `json:"script,omitempty"` + Lang string `json:"lang,omitempty"` + Position struct { + Offset int `json:"offset"` + Start int `json:"start"` + End int `json:"end"` + } `json:"position,omitempty"` + Suppressed []struct { + Type string `json:"type"` + Reason string `json:"reason"` + ProcessorType string `json:"processor_type"` + } `json:"suppressed,omitempty"` + } `json:"root_cause,omitempty"` + Type string `json:"type"` + Reason string `json:"reason"` + ProcessorType string `json:"processor_type,omitempty"` + ScriptStack []string `json:"script_stack,omitempty"` + Script string `json:"script,omitempty"` + Lang string `json:"lang,omitempty"` + Position struct { + Offset int `json:"offset"` + Start int `json:"start"` + End int `json:"end"` + } `json:"position,omitempty"` + CausedBy struct { + Type string `json:"type"` + Reason string `json:"reason"` + CausedBy struct { + Type string `json:"type"` + Reason interface{} `json:"reason"` + } `json:"caused_by,omitempty"` + } `json:"caused_by,omitempty"` + Suppressed []struct { + Type string `json:"type"` + Reason string `json:"reason"` + ProcessorType string `json:"processor_type"` + } `json:"suppressed,omitempty"` + } `json:"error"` + Status int `json:"status"` +} +func NewError(body []byte) error { var errBody ErrorBody if err := json.NewDecoder(bytes.NewReader(body)).Decode(&errBody); err == nil { + if len(errBody.Error.RootCause) > 0 { + rootCause, _ := json.MarshalIndent(errBody.Error.RootCause, "", " ") + return fmt.Errorf("elasticsearch error (type=%v): %v\nRoot cause:\n%v", errBody.Error.Type, + errBody.Error.Reason, string(rootCause)) + } return fmt.Errorf("elasticsearch error (type=%v): %v", errBody.Error.Type, errBody.Error.Reason) } - // Fall back to including to raw body if it cannot be parsed. return fmt.Errorf("elasticsearch error: %v", string(body)) } diff --git a/internal/elasticsearch/error_test.go b/internal/elasticsearch/error_test.go index a9c4a94d4b..0f248ef3fb 100644 --- a/internal/elasticsearch/error_test.go +++ b/internal/elasticsearch/error_test.go @@ -29,6 +29,20 @@ func TestNewError(t *testing.T) { "status" : 400 }` + const expected = `elasticsearch error (type=parse_exception): processor [set] doesn't support one or more provided configuration parameters [fail] +Root cause: +[ + { + "type": "parse_exception", + "reason": "processor [set] doesn't support one or more provided configuration parameters [fail]", + "processor_type": "set", + "position": { + "offset": 0, + "start": 0, + "end": 0 + } + } +]` err := elasticsearch.NewError([]byte(resp)) - assert.Equal(t, err.Error(), "elasticsearch error (type=parse_exception): processor [set] doesn't support one or more provided configuration parameters [fail]") + assert.Equal(t, err.Error(), expected) }