| 251 | } |
| 252 | |
| 253 | func (n *Node) processLeaves( |
| 254 | p *pipeline.Event, |
| 255 | ctx UnixParserCtx, |
| 256 | cachedExprEnv map[string]any, |
| 257 | initialState bool, |
| 258 | nodeHasOKGrok bool, |
| 259 | ) (bool, error) { |
| 260 | nodeState := initialState |
| 261 | |
| 262 | for idx := range n.LeavesNodes { |
| 263 | child := &n.LeavesNodes[idx] |
| 264 | |
| 265 | ret, err := child.process(p, ctx, cachedExprEnv) |
| 266 | if err != nil { |
| 267 | n.Logger.Tracef("\tNode (%s) failed: %v", child.rn, err) |
| 268 | n.Logger.Debugf("Event leaving node: ko") |
| 269 | |
| 270 | return false, err |
| 271 | } |
| 272 | |
| 273 | n.Logger.Tracef("\tsub-node (%s) ret: %v (strategy:%s)", child.rn, ret, n.OnSuccess) |
| 274 | |
| 275 | if ret { |
| 276 | nodeState = true |
| 277 | /* if child is successful, stop processing */ |
| 278 | if n.OnSuccess == "next_stage" { |
| 279 | n.Logger.Debugf("child is success, OnSuccess=next_stage, skip") |
| 280 | break |
| 281 | } |
| 282 | } else if !nodeHasOKGrok { |
| 283 | /* |
| 284 | If the parent node has a successful grok pattern, its state will stay successful even if one or more childs fail. |
| 285 | If the parent node is a skeleton node (no grok pattern), then at least one child must be successful for it to be a success. |
| 286 | */ |
| 287 | nodeState = false |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | return nodeState, nil |
| 292 | } |
| 293 | |
| 294 | func (n *Node) process(p *pipeline.Event, ctx UnixParserCtx, expressionEnv map[string]any) (bool, error) { |
| 295 | clog := n.Logger |