Skip to content

Commit afb28b2

Browse files
authored
x-pack/filebeat/input/cel: attempt to harmonise single events with ECS (#45399)
If the object contains an error field, optimistically render the full object as an ECS-compliant document, otherwise fall back to the previously documented behaviour of rendering the document as an error.
1 parent 87f0e9c commit afb28b2

File tree

3 files changed

+18
-2
lines changed

3 files changed

+18
-2
lines changed

CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ otherwise no tag is added. {issue}42208[42208] {pull}42403[42403]
487487
- Allow empty HTTPJSON cursor template value evaluations to be ignored by Fleet health status updates. {pull}45361[45361]
488488
- Reuse OAuth2 clients in HTTP JSON input where possible. {issue}34834[34834] {pull}44976[44976]
489489
- Add support for generalized token authentication to CEL input. {pull}45359[45359]
490+
- Log CEL single object evaluation results as ECS compliant documents where possible. {issue}45254[45254] {pull}45399[45399]
490491

491492
*Auditbeat*
492493

docs/reference/filebeat/filebeat-input-cel.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ After completion of a program’s execution it should return a single object wit
115115
}
116116
```
117117

118-
1. The `events` field must be present, but may be empty or null. If it is not empty, it must only have objects as elements. The field should be an array, but in the case of an error condition in the CEL program it is acceptable to return a single object instead of an array; this will will be wrapped as an array for publication and an error will be logged. If the single object contains a key, "error", the error value will be used to update the status of the input to report to Elastic Agent. This can be used to more rapidly respond to API failures.
118+
1. The `events` field must be present, but may be empty or null. If it is not empty, it must only have objects as elements. The field should be an array, but in the case of an error condition in the CEL program it is acceptable to return a single object instead of an array; this will will be wrapped as an array for publication and an error will be logged. If the single object contains a key, "error", the error value will be used to update the status of the input to report to Elastic Agent. This can be used to more rapidly respond to API failures. It is recommended that the object conforms to ECS field definitions, but this is not enforced.
119119
2. If `cursor` is present it must be either be a single object or an array with the same length as events; each element *i* of the `cursor` will be the details for obtaining the events at and beyond event *i* in the `events` array. If the `cursor` is a single object it is will be the details for obtaining events after the last event in the `events` array and will only be retained on successful publication of all the events in the `events` array.
120120
3. If `rate_limit` is present it must be a map with numeric fields `rate` and `burst`. The `rate_limit` field may also have a string `error` field and other fields which will be logged. If it has an `error` field, the `rate` and `burst` will not be used to set rate limit behavior. The [Limit](https://pkg.go.dev/github.com/elastic/mito@v1.22.0/lib#Limit), and [Okta Rate Limit policy](https://pkg.go.dev/github.com/elastic/mito@v1.22.0/lib#OktaRateLimit) and [Draft Rate Limit policy](https://pkg.go.dev/github.com/elastic/mito@v1.22.0/lib#DraftRateLimit) documentation show how to construct this field.
121121
4. The evaluation is repeated with the new state, after removing the events field, if the "want_more" field is present and true, and a non-zero events array is returned. If the "want_more" field is present after a failed evaluation, it is set to false.

x-pack/filebeat/input/cel/input.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"fmt"
1616
"io"
1717
"io/fs"
18+
"maps"
1819
"net"
1920
"net/http"
2021
"net/url"
@@ -421,7 +422,21 @@ func (i input) run(env v2.Context, src *source, cursor map[string]interface{}, p
421422
if e == nil {
422423
return nil
423424
}
424-
log.Errorw("single event object returned by evaluation", "event", e)
425+
if _, ok := e["error"]; ok {
426+
// If we have an error, log the complete object on the basis
427+
// that it is ECS-conformant.
428+
if log.Core().Enabled(zapcore.ErrorLevel) {
429+
kv := make([]any, 0, 2*len(e))
430+
for k := range maps.Keys(e) {
431+
kv = append(kv, k, e[k])
432+
}
433+
log.Errorw("single event object returned by evaluation", kv...)
434+
}
435+
} else {
436+
// Otherwise, be consistent with the existing documented
437+
// behaviour and log the entire object as the error.
438+
log.Errorw("single event object returned by evaluation", "error", e)
439+
}
425440
if err, ok := e["error"]; ok {
426441
env.UpdateStatus(status.Degraded, fmt.Sprintf("single event error object returned by evaluation: %s", mapstr.M{"error": err}))
427442
} else {

0 commit comments

Comments
 (0)