refact pkg/parser: extract method, avoid calling defer in loop (#3564)

This commit is contained in:
mmetc 2025-05-06 16:11:24 +02:00 committed by GitHub
parent 15dcbdeec9
commit 3b9130469c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -37,103 +37,132 @@ type Stagefile struct {
}
func LoadStages(stageFiles []Stagefile, pctx *UnixParserCtx, ectx EnricherCtx) ([]Node, error) {
var nodes []Node
tmpstages := make(map[string]bool)
var allNodes []Node
tmpStages := make(map[string]bool)
pctx.Stages = []string{}
for _, stageFile := range stageFiles {
if !strings.HasSuffix(stageFile.Filename, ".yaml") && !strings.HasSuffix(stageFile.Filename, ".yml") {
log.Warningf("skip non yaml : %s", stageFile.Filename)
continue
}
log.Debugf("loading parser file '%s'", stageFile)
st, err := os.Stat(stageFile.Filename)
for _, sf := range stageFiles {
nodes, err := processStageFile(sf, pctx, ectx)
if err != nil {
return nil, fmt.Errorf("failed to stat %s : %v", stageFile, err)
return nil, err
}
if st.IsDir() {
continue
for _, n := range nodes { //nolint:gocritic // rangeValCopy
allNodes = append(allNodes, n)
tmpStages[n.Stage] = true
}
yamlFile, err := os.Open(stageFile.Filename)
if err != nil {
return nil, fmt.Errorf("can't access parsing configuration file %s : %s", stageFile.Filename, err)
}
defer yamlFile.Close()
//process the yaml
dec := yaml.NewDecoder(yamlFile)
dec.SetStrict(true)
nodesCount := 0
for {
node := Node{}
node.OnSuccess = "continue" //default behavior is to continue
err = dec.Decode(&node)
if err != nil {
if errors.Is(err, io.EOF) {
log.Tracef("End of yaml file")
break
}
return nil, fmt.Errorf("error decoding parsing configuration file '%s': %v", stageFile.Filename, err)
}
//check for empty bucket
if node.Name == "" && node.Description == "" && node.Author == "" {
log.Infof("Node in %s has no name, author or description. Skipping.", stageFile.Filename)
continue
}
//check compat
if node.FormatVersion == "" {
log.Tracef("no version in %s, assuming '1.0'", node.Name)
node.FormatVersion = "1.0"
}
ok, err := constraint.Satisfies(node.FormatVersion, constraint.Parser)
if err != nil {
return nil, fmt.Errorf("failed to check version : %s", err)
}
if !ok {
log.Errorf("%s : %s doesn't satisfy parser format %s, skip", node.Name, node.FormatVersion, constraint.Parser)
continue
}
node.Stage = stageFile.Stage
if _, ok := tmpstages[stageFile.Stage]; !ok {
tmpstages[stageFile.Stage] = true
}
//compile the node : grok pattern and expression
err = node.compile(pctx, ectx)
if err != nil {
if node.Name != "" {
return nil, fmt.Errorf("failed to compile node '%s' in '%s' : %s", node.Name, stageFile.Filename, err)
}
return nil, fmt.Errorf("failed to compile node in '%s' : %s", stageFile.Filename, err)
}
/* if the stage is empty, the node is empty, it's a trailing entry in users yaml file */
if node.Stage == "" {
continue
}
for _, data := range node.Data {
err = exprhelpers.FileInit(pctx.DataFolder, data.DestPath, data.Type)
if err != nil {
log.Error(err.Error())
}
if data.Type == "regexp" { //cache only makes sense for regexp
if err = exprhelpers.RegexpCacheInit(data.DestPath, *data); err != nil {
log.Error(err.Error())
}
}
}
nodes = append(nodes, node)
nodesCount++
}
log.WithFields(log.Fields{"file": stageFile.Filename, "stage": stageFile.Stage}).Infof("Loaded %d parser nodes", nodesCount)
}
for k := range tmpstages {
for k := range tmpStages {
pctx.Stages = append(pctx.Stages, k)
}
sort.Strings(pctx.Stages)
log.Infof("Loaded %d nodes from %d stages", len(nodes), len(pctx.Stages))
log.Infof("Loaded %d nodes from %d stages", len(allNodes), len(pctx.Stages))
return allNodes, nil
}
func processStageFile(stageFile Stagefile, pctx *UnixParserCtx, ectx EnricherCtx) ([]Node, error) {
if !strings.HasSuffix(stageFile.Filename, ".yaml") && !strings.HasSuffix(stageFile.Filename, ".yml") {
log.Warningf("skip non yaml : %s", stageFile.Filename)
return nil, nil
}
log.Debugf("loading parser file '%s'", stageFile)
st, err := os.Stat(stageFile.Filename)
if err != nil {
return nil, fmt.Errorf("failed to stat %s : %v", stageFile, err)
}
if st.IsDir() {
return nil, nil
}
yamlFile, err := os.Open(stageFile.Filename)
if err != nil {
return nil, fmt.Errorf("can't access parsing configuration file %s : %s", stageFile.Filename, err)
}
defer yamlFile.Close()
// process the yaml
dec := yaml.NewDecoder(yamlFile)
dec.SetStrict(true)
var nodes []Node
nodesCount := 0
for {
node := Node{}
node.OnSuccess = "continue" // default behavior is to continue
if err = dec.Decode(&node); err != nil {
if errors.Is(err, io.EOF) {
log.Tracef("End of yaml file")
break
}
return nil, fmt.Errorf("error decoding parsing configuration file '%s': %v", stageFile.Filename, err)
}
// check for empty bucket
if node.Name == "" && node.Description == "" && node.Author == "" {
log.Infof("Node in %s has no name, author or description. Skipping.", stageFile.Filename)
continue
}
// check compat
if node.FormatVersion == "" {
log.Tracef("no version in %s, assuming '1.0'", node.Name)
node.FormatVersion = "1.0"
}
ok, err := constraint.Satisfies(node.FormatVersion, constraint.Parser)
if err != nil {
return nil, fmt.Errorf("failed to check version : %s", err)
}
if !ok {
log.Errorf("%s : %s doesn't satisfy parser format %s, skip", node.Name, node.FormatVersion, constraint.Parser)
continue
}
node.Stage = stageFile.Stage
// compile the node : grok pattern and expression
err = node.compile(pctx, ectx)
if err != nil {
if node.Name != "" {
return nil, fmt.Errorf("failed to compile node '%s' in '%s' : %s", node.Name, stageFile.Filename, err)
}
return nil, fmt.Errorf("failed to compile node in '%s' : %s", stageFile.Filename, err)
}
/* if the stage is empty, the node is empty, it's a trailing entry in users yaml file */
if node.Stage == "" {
continue
}
for _, data := range node.Data {
err = exprhelpers.FileInit(pctx.DataFolder, data.DestPath, data.Type)
if err != nil {
log.Error(err.Error())
}
if data.Type == "regexp" { // cache only makes sense for regexp
if err = exprhelpers.RegexpCacheInit(data.DestPath, *data); err != nil {
log.Error(err.Error())
}
}
}
nodes = append(nodes, node)
nodesCount++
}
log.WithFields(log.Fields{"file": stageFile.Filename, "stage": stageFile.Stage}).Infof("Loaded %d parser nodes", nodesCount)
return nodes, nil
}