github.com/influxdata/telegraf@v1.30.3/internal/templating/engine.go (about) 1 package templating 2 3 import ( 4 "sort" 5 "strings" 6 ) 7 8 const ( 9 // DefaultSeparator is the default separation character to use when separating template parts. 10 DefaultSeparator = "." 11 ) 12 13 // Engine uses a Matcher to retrieve the appropriate template and applies the template 14 // to the input string 15 type Engine struct { 16 joiner string 17 matcher *matcher 18 } 19 20 // Apply extracts the template fields from the given line and returns the measurement 21 // name, tags and field name 22 // 23 //nolint:revive //function-result-limit conditionally 4 return results allowed 24 func (e *Engine) Apply(line string) (measurementName string, tags map[string]string, field string, err error) { 25 return e.matcher.match(line).Apply(line, e.joiner) 26 } 27 28 // NewEngine creates a new templating engine 29 func NewEngine(joiner string, defaultTemplate *Template, templates []string) (*Engine, error) { 30 engine := Engine{ 31 joiner: joiner, 32 matcher: newMatcher(defaultTemplate), 33 } 34 templateSpecs := parseTemplateSpecs(templates) 35 36 for _, templateSpec := range templateSpecs { 37 if err := engine.matcher.addSpec(templateSpec); err != nil { 38 return nil, err 39 } 40 } 41 42 return &engine, nil 43 } 44 45 func parseTemplateSpecs(templates []string) templateSpecs { 46 tmplts := templateSpecs{} 47 for _, pattern := range templates { 48 tmplt := templateSpec{ 49 separator: DefaultSeparator, 50 } 51 52 // Format is [separator] [filter] <template> [tag1=value1,tag2=value2] 53 parts := strings.Fields(pattern) 54 partsLength := len(parts) 55 if partsLength < 1 { 56 // ignore 57 continue 58 } 59 if partsLength == 1 { 60 tmplt.template = pattern 61 } else if partsLength == 4 { 62 tmplt.separator = parts[0] 63 tmplt.filter = parts[1] 64 tmplt.template = parts[2] 65 tmplt.tagstring = parts[3] 66 } else { 67 hasTagstring := strings.Contains(parts[partsLength-1], "=") 68 if hasTagstring { 69 tmplt.tagstring = parts[partsLength-1] 70 tmplt.template = parts[partsLength-2] 71 if partsLength == 3 { 72 tmplt.filter = parts[0] 73 } 74 } else { 75 tmplt.template = parts[partsLength-1] 76 if partsLength == 2 { 77 tmplt.filter = parts[0] 78 } else { // length == 3 79 tmplt.separator = parts[0] 80 tmplt.filter = parts[1] 81 } 82 } 83 } 84 tmplts = append(tmplts, tmplt) 85 } 86 sort.Sort(tmplts) 87 return tmplts 88 }