diff --git a/plugins/inputs/gnmi/gnmi.go b/plugins/inputs/gnmi/gnmi.go index 02297913f..4c3f4f799 100644 --- a/plugins/inputs/gnmi/gnmi.go +++ b/plugins/inputs/gnmi/gnmi.go @@ -346,34 +346,25 @@ func (s *Subscription) buildFullPath(c *GNMI) error { } func (s *Subscription) buildAlias(aliases map[string]string) error { - var err error - var gnmiLongPath, gnmiShortPath *gnmiLib.Path - // Build the subscription path without keys - if gnmiLongPath, err = parsePath(s.Origin, s.Path, ""); err != nil { - return err - } - if gnmiShortPath, err = parsePath("", s.Path, ""); err != nil { + gnmiPath, err := parsePath(s.Origin, s.Path, "") + if err != nil { return err } - longPath, _, err := handlePath(gnmiLongPath, nil, nil, "") + origin, spath, _, err := handlePath(gnmiPath, nil, nil, "") if err != nil { - return fmt.Errorf("handling long-path failed: %w", err) - } - shortPath, _, err := handlePath(gnmiShortPath, nil, nil, "") - if err != nil { - return fmt.Errorf("handling short-path failed: %w", err) + return fmt.Errorf("handling path failed: %w", err) } // If the user didn't provide a measurement name, use last path element name := s.Name - if len(name) == 0 { - name = path.Base(shortPath) + if name == "" { + name = path.Base(spath) } - if len(name) > 0 { - aliases[longPath] = name - aliases[shortPath] = name + if name != "" { + aliases[origin+spath] = name + aliases[spath] = name } return nil } diff --git a/plugins/inputs/gnmi/handler.go b/plugins/inputs/gnmi/handler.go index 8871231f2..15947931b 100644 --- a/plugins/inputs/gnmi/handler.go +++ b/plugins/inputs/gnmi/handler.go @@ -174,10 +174,12 @@ func (h *handler) handleSubscribeResponseUpdate(acc telegraf.Accumulator, respon } if response.Update.Prefix != nil { + var origin string var err error - if prefix, prefixAliasPath, err = handlePath(response.Update.Prefix, prefixTags, h.aliases, ""); err != nil { + if origin, prefix, prefixAliasPath, err = handlePath(response.Update.Prefix, prefixTags, h.aliases, ""); err != nil { h.log.Errorf("handling path %q failed: %v", response.Update.Prefix, err) } + prefix = origin + prefix } prefixTags["source"], _, _ = net.SplitHostPort(h.address) @@ -287,7 +289,7 @@ func (h *handler) handleSubscribeResponseUpdate(acc telegraf.Accumulator, respon // HandleTelemetryField and add it to a measurement func (h *handler) handleTelemetryField(update *gnmiLib.Update, tags map[string]string, prefix string) (string, map[string]interface{}) { - gpath, aliasPath, err := handlePath(update.Path, tags, h.aliases, prefix) + _, gpath, aliasPath, err := handlePath(update.Path, tags, h.aliases, prefix) if err != nil { h.log.Errorf("handling path %q failed: %v", update.Path, err) } diff --git a/plugins/inputs/gnmi/testcases/issue_12931/expected.out b/plugins/inputs/gnmi/testcases/issue_12931/expected.out new file mode 100644 index 000000000..e00609bbc --- /dev/null +++ b/plugins/inputs/gnmi/testcases/issue_12931/expected.out @@ -0,0 +1 @@ +interface,name=ethernet-1/1,source=127.0.0.1 interface=1i,transceiver=2i,ethernet=3i,ethernet/flow_control="false",sflow="disable" 1679648530391910312 diff --git a/plugins/inputs/gnmi/testcases/issue_12931/responses.json b/plugins/inputs/gnmi/testcases/issue_12931/responses.json new file mode 100644 index 000000000..40e1abb10 --- /dev/null +++ b/plugins/inputs/gnmi/testcases/issue_12931/responses.json @@ -0,0 +1,94 @@ +[ + { + "update": { + "timestamp": "1679648530391910312", + "update": [ + { + "path": { + "origin": "srl_nokia-interfaces", + "elem": [ + { + "name": "interface", + "key":{"name":"ethernet-1/1"} + } + ] + }, + "val": { + "intVal": "1" + } + }, + { + "path": { + "origin": "srl_nokia-interfaces", + "elem": [ + { + "name": "interface", + "key":{"name":"ethernet-1/1"} + }, + { + "name": "transceiver" + } + ] + }, + "val": { + "intVal": "2" + } + }, + { + "path": { + "origin": "srl_nokia-interfaces", + "elem": [ + { + "name": "interface", + "key":{"name":"ethernet-1/1"} + }, + { + "name": "ethernet" + } + ] + }, + "val": { + "intVal": "3" + } + }, + { + "path": { + "origin": "srl_nokia-interfaces", + "elem": [ + { + "name": "interface", + "key":{"name":"ethernet-1/1"} + }, + { + "name": "ethernet" + }, + { + "name": "flow-control" + } + ] + }, + "val": { + "stringVal": "false" + } + }, + { + "path": { + "origin": "srl_nokia-interfaces", + "elem": [ + { + "name": "interface", + "key":{"name":"ethernet-1/1"} + }, + { + "name": "sflow" + } + ] + }, + "val": { + "stringVal": "disable" + } + } + ] + } + } +] \ No newline at end of file diff --git a/plugins/inputs/gnmi/testcases/issue_12931/telegraf.conf b/plugins/inputs/gnmi/testcases/issue_12931/telegraf.conf new file mode 100644 index 000000000..9dfececda --- /dev/null +++ b/plugins/inputs/gnmi/testcases/issue_12931/telegraf.conf @@ -0,0 +1,10 @@ +[[inputs.gnmi]] + addresses = ["dummy"] + name_override = "gnmi" + redial = "10s" + + [[inputs.gnmi.subscription]] + name = "interface" + path = "/interface" + subscription_mode = "sample" + sample_interval = "10s" \ No newline at end of file diff --git a/plugins/inputs/gnmi/utils.go b/plugins/inputs/gnmi/utils.go index 39c21ede4..dd9e97f40 100644 --- a/plugins/inputs/gnmi/utils.go +++ b/plugins/inputs/gnmi/utils.go @@ -13,7 +13,9 @@ import ( ) // Parse path to path-buffer and tag-field -func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[string]string, prefix string) (pathBuffer string, aliasPath string, err error) { +// +//nolint:revive //function-result-limit conditionally 4 return results allowed +func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[string]string, prefix string) (origin, path, alias string, err error) { builder := bytes.NewBufferString(prefix) // Some devices do report the origin in the first path element @@ -28,28 +30,25 @@ func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[stri // Prefix with origin if len(gnmiPath.Origin) > 0 { - if _, err := builder.WriteString(gnmiPath.Origin); err != nil { - return "", "", err - } - if _, err := builder.WriteRune(':'); err != nil { - return "", "", err - } + origin = gnmiPath.Origin + ":" } // Parse generic keys from prefix for _, elem := range gnmiPath.Elem { if len(elem.Name) > 0 { if _, err := builder.WriteRune('/'); err != nil { - return "", "", err + return "", "", "", err } if _, err := builder.WriteString(elem.Name); err != nil { - return "", "", err + return "", "", "", err } } name := builder.String() - if _, exists := aliases[name]; exists { - aliasPath = name + if _, exists := aliases[origin+name]; exists { + alias = origin + name + } else if _, exists := aliases[name]; exists { + alias = name } if tags != nil { @@ -66,7 +65,7 @@ func handlePath(gnmiPath *gnmiLib.Path, tags map[string]string, aliases map[stri } } - return builder.String(), aliasPath, nil + return origin, builder.String(), alias, nil } // equalPathNoKeys checks if two gNMI paths are equal, without keys