1
0
Fork 0
telegraf/plugins/serializers/nowmetric/nowmetric.go
Daniel Baumann 4978089aab
Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-24 07:26:29 +02:00

137 lines
3.3 KiB
Go

package nowmetric
import (
"encoding/json"
"fmt"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/serializers"
)
type Serializer struct {
Format string `toml:"nowmetric_format"`
}
type OIMetric struct {
Metric string `json:"metric_type"`
Resource string `json:"resource"`
Node string `json:"node"`
Value interface{} `json:"value"`
Timestamp int64 `json:"timestamp"`
CiMapping map[string]string `json:"ci2metric_id"`
Source string `json:"source"`
}
type OIMetrics []OIMetric
type OIMetricsObj struct {
Records []OIMetric `json:"records"`
}
func (s *Serializer) Init() error {
switch s.Format {
case "":
s.Format = "oi"
case "oi", "jsonv2":
default:
return fmt.Errorf("invalid format %q", s.Format)
}
return nil
}
func (s *Serializer) Serialize(metric telegraf.Metric) (out []byte, err error) {
m := createObject(metric)
if s.Format == "jsonv2" {
obj := OIMetricsObj{Records: m}
return json.Marshal(obj)
}
return json.Marshal(m)
}
func (s *Serializer) SerializeBatch(metrics []telegraf.Metric) (out []byte, err error) {
objects := make([]OIMetric, 0)
for _, metric := range metrics {
objects = append(objects, createObject(metric)...)
}
if s.Format == "jsonv2" {
obj := OIMetricsObj{Records: objects}
return json.Marshal(obj)
}
return json.Marshal(objects)
}
func createObject(metric telegraf.Metric) OIMetrics {
/* ServiceNow Operational Intelligence supports an array of JSON objects.
** Following elements accepted in the request body:
** metric_type: The name of the metric
** resource: Information about the resource for which metric data is being collected.
In the example below, C:\ is the resource for which metric data is collected
** node: IP, FQDN, name of the CI, or host
** value: Value of the metric
** timestamp: Epoch timestamp of the metric in milliseconds
** ci2metric_id: List of key-value pairs to identify the CI.
** source: Data source monitoring the metric type
*/
var allmetrics OIMetrics //nolint:prealloc // Pre-allocating may change format of marshaled JSON
var oimetric OIMetric
oimetric.Source = "Telegraf"
// Process Tags to extract node & resource name info
for _, tag := range metric.TagList() {
if tag.Key == "" || tag.Value == "" {
continue
}
if tag.Key == "objectname" {
oimetric.Resource = tag.Value
}
if tag.Key == "host" {
oimetric.Node = tag.Value
}
}
// Format timestamp to UNIX epoch
oimetric.Timestamp = metric.Time().UnixNano() / int64(time.Millisecond)
// Loop of fields value pair and build datapoint for each of them
for _, field := range metric.FieldList() {
if !verifyValue(field.Value) {
// Ignore String
continue
}
if field.Key == "" {
// Ignore Empty Key
continue
}
oimetric.Metric = field.Key
oimetric.Value = field.Value
if oimetric.Node != "" {
oimetric.CiMapping = map[string]string{"node": oimetric.Node}
}
allmetrics = append(allmetrics, oimetric)
}
return allmetrics
}
func verifyValue(v interface{}) bool {
_, ok := v.(string)
return !ok
}
func init() {
serializers.Add("nowmetric",
func() telegraf.Serializer {
return &Serializer{}
},
)
}