feat(inputs.gnmi): Allow canonical field names (#13326)
This commit is contained in:
parent
60ee14d50b
commit
8f07761cba
|
|
@ -52,6 +52,9 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
## gRPC Maximum Message Size
|
## gRPC Maximum Message Size
|
||||||
# max_msg_size = "4MB"
|
# max_msg_size = "4MB"
|
||||||
|
|
||||||
|
## Enable to get the canonical path as field-name
|
||||||
|
# canonical_field_names = false
|
||||||
|
|
||||||
## enable client-side TLS and define CA to authenticate the device
|
## enable client-side TLS and define CA to authenticate the device
|
||||||
# enable_tls = false
|
# enable_tls = false
|
||||||
# tls_ca = "/etc/telegraf/ca.pem"
|
# tls_ca = "/etc/telegraf/ca.pem"
|
||||||
|
|
|
||||||
|
|
@ -42,23 +42,24 @@ var supportedExtensions = []string{"juniper_header"}
|
||||||
|
|
||||||
// gNMI plugin instance
|
// gNMI plugin instance
|
||||||
type GNMI struct {
|
type GNMI struct {
|
||||||
Addresses []string `toml:"addresses"`
|
Addresses []string `toml:"addresses"`
|
||||||
Subscriptions []Subscription `toml:"subscription"`
|
Subscriptions []Subscription `toml:"subscription"`
|
||||||
TagSubscriptions []TagSubscription `toml:"tag_subscription"`
|
TagSubscriptions []TagSubscription `toml:"tag_subscription"`
|
||||||
Aliases map[string]string `toml:"aliases"`
|
Aliases map[string]string `toml:"aliases"`
|
||||||
Encoding string `toml:"encoding"`
|
Encoding string `toml:"encoding"`
|
||||||
Origin string `toml:"origin"`
|
Origin string `toml:"origin"`
|
||||||
Prefix string `toml:"prefix"`
|
Prefix string `toml:"prefix"`
|
||||||
Target string `toml:"target"`
|
Target string `toml:"target"`
|
||||||
UpdatesOnly bool `toml:"updates_only"`
|
UpdatesOnly bool `toml:"updates_only"`
|
||||||
VendorSpecific []string `toml:"vendor_specific"`
|
VendorSpecific []string `toml:"vendor_specific"`
|
||||||
Username string `toml:"username"`
|
Username string `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password string `toml:"password"`
|
||||||
Redial config.Duration `toml:"redial"`
|
Redial config.Duration `toml:"redial"`
|
||||||
MaxMsgSize config.Size `toml:"max_msg_size"`
|
MaxMsgSize config.Size `toml:"max_msg_size"`
|
||||||
Trace bool `toml:"dump_responses"`
|
Trace bool `toml:"dump_responses"`
|
||||||
EnableTLS bool `toml:"enable_tls"`
|
CanonicalFieldNames bool `toml:"canonical_field_names"`
|
||||||
Log telegraf.Logger `toml:"-"`
|
EnableTLS bool `toml:"enable_tls"`
|
||||||
|
Log telegraf.Logger `toml:"-"`
|
||||||
internaltls.ClientConfig
|
internaltls.ClientConfig
|
||||||
|
|
||||||
// Internal state
|
// Internal state
|
||||||
|
|
@ -192,15 +193,18 @@ func (c *GNMI) Start(acc telegraf.Accumulator) error {
|
||||||
for _, addr := range c.Addresses {
|
for _, addr := range c.Addresses {
|
||||||
go func(addr string) {
|
go func(addr string) {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
confHandler := configHandler{
|
|
||||||
aliases: c.internalAliases,
|
h := handler{
|
||||||
subscriptions: c.TagSubscriptions,
|
address: addr,
|
||||||
maxSize: int(c.MaxMsgSize),
|
aliases: c.internalAliases,
|
||||||
log: c.Log,
|
tagsubs: c.TagSubscriptions,
|
||||||
trace: c.Trace,
|
maxMsgSize: int(c.MaxMsgSize),
|
||||||
vendorExt: c.VendorSpecific,
|
vendorExt: c.VendorSpecific,
|
||||||
|
tagStore: newTagStore(c.TagSubscriptions),
|
||||||
|
trace: c.Trace,
|
||||||
|
canonicalFieldNames: c.CanonicalFieldNames,
|
||||||
|
log: c.Log,
|
||||||
}
|
}
|
||||||
h := newHandler(addr, confHandler)
|
|
||||||
for ctx.Err() == nil {
|
for ctx.Err() == nil {
|
||||||
if err := h.subscribeGNMI(ctx, acc, tlscfg, request); err != nil && ctx.Err() == nil {
|
if err := h.subscribeGNMI(ctx, acc, tlscfg, request); err != nil && ctx.Err() == nil {
|
||||||
acc.AddError(err)
|
acc.AddError(err)
|
||||||
|
|
|
||||||
|
|
@ -28,38 +28,16 @@ import (
|
||||||
const eidJuniperTelemetryHeader = 1
|
const eidJuniperTelemetryHeader = 1
|
||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
address string
|
address string
|
||||||
aliases map[string]string
|
aliases map[string]string
|
||||||
tagsubs []TagSubscription
|
tagsubs []TagSubscription
|
||||||
maxMsgSize int
|
maxMsgSize int
|
||||||
emptyNameWarnShown bool
|
emptyNameWarnShown bool
|
||||||
vendorExt []string
|
vendorExt []string
|
||||||
tagStore *tagStore
|
tagStore *tagStore
|
||||||
trace bool
|
trace bool
|
||||||
log telegraf.Logger
|
canonicalFieldNames bool
|
||||||
}
|
log telegraf.Logger
|
||||||
|
|
||||||
// Allow to convey additionnal configuration elements
|
|
||||||
type configHandler struct {
|
|
||||||
aliases map[string]string
|
|
||||||
subscriptions []TagSubscription
|
|
||||||
maxSize int
|
|
||||||
log telegraf.Logger
|
|
||||||
trace bool
|
|
||||||
vendorExt []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHandler(addr string, confHandler configHandler) *handler {
|
|
||||||
return &handler{
|
|
||||||
address: addr,
|
|
||||||
aliases: confHandler.aliases,
|
|
||||||
tagsubs: confHandler.subscriptions,
|
|
||||||
maxMsgSize: confHandler.maxSize,
|
|
||||||
vendorExt: confHandler.vendorExt,
|
|
||||||
tagStore: newTagStore(confHandler.subscriptions),
|
|
||||||
trace: confHandler.trace,
|
|
||||||
log: confHandler.log,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeGNMI and extract telemetry data
|
// SubscribeGNMI and extract telemetry data
|
||||||
|
|
@ -266,15 +244,22 @@ func (h *handler) handleSubscribeResponseUpdate(acc telegraf.Accumulator, respon
|
||||||
// conversion on the key.
|
// conversion on the key.
|
||||||
key = key[len(aliasPath)+1:]
|
key = key[len(aliasPath)+1:]
|
||||||
} else if len(aliasPath) >= len(key) {
|
} else if len(aliasPath) >= len(key) {
|
||||||
// Otherwise use the last path element as the field key.
|
if h.canonicalFieldNames {
|
||||||
key = path.Base(key)
|
// Strip the origin is any for the field names
|
||||||
|
if parts := strings.SplitN(key, ":", 2); len(parts) == 2 {
|
||||||
|
key = parts[1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise use the last path element as the field key.
|
||||||
|
key = path.Base(key)
|
||||||
|
|
||||||
// If there are no elements skip the item; this would be an
|
// If there are no elements skip the item; this would be an
|
||||||
// invalid message.
|
// invalid message.
|
||||||
key = strings.TrimLeft(key, "/.")
|
key = strings.TrimLeft(key, "/.")
|
||||||
if key == "" {
|
if key == "" {
|
||||||
h.log.Errorf("invalid empty path: %q", k)
|
h.log.Errorf("invalid empty path: %q", k)
|
||||||
continue
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grouper.Add(name, tags, timestamp, key, v)
|
grouper.Add(name, tags, timestamp, key, v)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@
|
||||||
## gRPC Maximum Message Size
|
## gRPC Maximum Message Size
|
||||||
# max_msg_size = "4MB"
|
# max_msg_size = "4MB"
|
||||||
|
|
||||||
|
## Enable to get the canonical path as field-name
|
||||||
|
# canonical_field_names = false
|
||||||
|
|
||||||
## enable client-side TLS and define CA to authenticate the device
|
## enable client-side TLS and define CA to authenticate the device
|
||||||
# enable_tls = false
|
# enable_tls = false
|
||||||
# tls_ca = "/etc/telegraf/ca.pem"
|
# tls_ca = "/etc/telegraf/ca.pem"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
interfaces,name=eth42,path=openconfig-interfaces:/interfaces/interface,source=127.0.0.1 /interfaces/interface/descr="eth42",/interfaces/interface/config/id=42425u,/interfaces/interface/state/in_pkts=5678u,/interfaces/interface/state/out_pkts=5125u 1673608605875353770
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"update": {
|
||||||
|
"timestamp": "1673608605875353770",
|
||||||
|
"prefix": {
|
||||||
|
"origin": "openconfig-interfaces",
|
||||||
|
"elem": [
|
||||||
|
{
|
||||||
|
"name": "interfaces"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "interface",
|
||||||
|
"key":{"name":"eth42"}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"target": "subscription"
|
||||||
|
},
|
||||||
|
"update": [
|
||||||
|
{
|
||||||
|
"path": {
|
||||||
|
"elem": [
|
||||||
|
{
|
||||||
|
"name": "descr"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"val": {
|
||||||
|
"stringVal": "eth42"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": {
|
||||||
|
"elem": [
|
||||||
|
{
|
||||||
|
"name": "config"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"val": {
|
||||||
|
"uintVal": "42425"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": {
|
||||||
|
"elem": [
|
||||||
|
{
|
||||||
|
"name": "state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "in-pkts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"val": {
|
||||||
|
"uintVal": "5678"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": {
|
||||||
|
"elem": [
|
||||||
|
{
|
||||||
|
"name": "state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "out-pkts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"val": {
|
||||||
|
"uintVal": "5125"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
[[inputs.gnmi]]
|
||||||
|
addresses = ["dummy"]
|
||||||
|
name_override = "gnmi"
|
||||||
|
redial = "10s"
|
||||||
|
canonical_field_names = true
|
||||||
|
[[inputs.gnmi.subscription]]
|
||||||
|
name = "interfaces"
|
||||||
|
origin = "openconfig-interfaces"
|
||||||
|
path = "/interfaces/interface/descr"
|
||||||
|
subscription_mode = "sample"
|
||||||
|
sample_interval = "10s"
|
||||||
|
[[inputs.gnmi.subscription]]
|
||||||
|
name = "interfaces"
|
||||||
|
origin = "openconfig-interfaces"
|
||||||
|
path = "/interfaces/interface/config/id"
|
||||||
|
subscription_mode = "sample"
|
||||||
|
sample_interval = "10s"
|
||||||
|
[[inputs.gnmi.subscription]]
|
||||||
|
name = "interfaces"
|
||||||
|
origin = "openconfig-interfaces"
|
||||||
|
path = "/interfaces/interface/state/in-pkts"
|
||||||
|
subscription_mode = "sample"
|
||||||
|
sample_interval = "10s"
|
||||||
|
[[inputs.gnmi.subscription]]
|
||||||
|
name = "interfaces"
|
||||||
|
origin = "openconfig-interfaces"
|
||||||
|
path = "/interfaces/interface/state/out-pkts"
|
||||||
|
subscription_mode = "sample"
|
||||||
|
sample_interval = "10s"
|
||||||
Loading…
Reference in New Issue