1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,49 @@
# Merge Aggregator Plugin
This plugin merges metrics of the same series and timestamp into new metrics
with the super-set of fields. A series here is defined by the metric name and
the tag key-value set.
Use this plugin when fields are split over multiple metrics, with the same
measurement, tag set and timestamp.
⭐ Telegraf v1.13.0
🏷️ transformation
💻 all
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
In addition to the plugin-specific configuration settings, plugins support
additional global and plugin configuration settings. These settings are used to
modify metrics, tags, and field or create aliases and configure ordering, etc.
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
## Configuration
```toml @sample.conf
# Merge metrics into multifield metrics by series key
[[aggregators.merge]]
## General Aggregator Arguments:
## The period on which to flush & clear the aggregator.
# period = "30s"
## Precision to round the metric timestamp to
## This is useful for cases where metrics to merge arrive within a small
## interval and thus vary in timestamp. The timestamp of the resulting metric
## is also rounded.
# round_timestamp_to = "1ns"
## If true, the original metric will be dropped by the
## aggregator and will not get sent to the output plugins.
drop_original = true
```
## Example
```diff
- cpu,host=localhost usage_time=42 1567562620000000000
- cpu,host=localhost idle_time=42 1567562620000000000
+ cpu,host=localhost idle_time=42,usage_time=42 1567562620000000000
```

View file

@ -0,0 +1,63 @@
//go:generate ../../../tools/readme_config_includer/generator
package merge
import (
_ "embed"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/metric"
"github.com/influxdata/telegraf/plugins/aggregators"
)
//go:embed sample.conf
var sampleConfig string
type Merge struct {
RoundTimestamp config.Duration `toml:"round_timestamp_to"`
grouper *metric.SeriesGrouper
}
func (*Merge) SampleConfig() string {
return sampleConfig
}
func (a *Merge) Init() error {
a.grouper = metric.NewSeriesGrouper()
return nil
}
func (a *Merge) Add(m telegraf.Metric) {
gm := m
if a.RoundTimestamp > 0 {
if unwrapped, ok := m.(telegraf.UnwrappableMetric); ok {
gm = unwrapped.Unwrap().Copy()
} else {
gm = m.Copy()
}
ts := gm.Time()
gm.SetTime(ts.Round(time.Duration(a.RoundTimestamp)))
}
a.grouper.AddMetric(gm)
}
func (a *Merge) Push(acc telegraf.Accumulator) {
// Always use nanosecond precision to avoid rounding metrics that were
// produced at a precision higher than the agent default.
acc.SetPrecision(time.Nanosecond)
for _, m := range a.grouper.Metrics() {
acc.AddMetric(m)
}
}
func (a *Merge) Reset() {
a.grouper = metric.NewSeriesGrouper()
}
func init() {
aggregators.Add("merge", func() telegraf.Aggregator {
return &Merge{}
})
}

View file

@ -0,0 +1,374 @@
package merge
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/metric"
"github.com/influxdata/telegraf/testutil"
)
func TestSimple(t *testing.T) {
plugin := &Merge{}
require.NoError(t, plugin.Init())
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 42,
},
time.Unix(0, 0),
),
)
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 0),
),
)
var acc testutil.Accumulator
plugin.Push(&acc)
expected := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 42,
"time_guest": 42,
},
time.Unix(0, 0),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
}
func TestNanosecondPrecision(t *testing.T) {
plugin := &Merge{}
require.NoError(t, plugin.Init())
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 42,
},
time.Unix(0, 1),
),
)
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 1),
),
)
var acc testutil.Accumulator
acc.SetPrecision(time.Second)
plugin.Push(&acc)
expected := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 42,
"time_guest": 42,
},
time.Unix(0, 1),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
}
func TestNoRounding(t *testing.T) {
plugin := &Merge{}
require.NoError(t, plugin.Init())
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 23,
},
time.Unix(0, 1),
),
)
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 2),
),
)
var acc testutil.Accumulator
acc.SetPrecision(time.Second)
plugin.Push(&acc)
expected := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 23,
},
time.Unix(0, 1),
),
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 2),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
}
func TestWithRounding(t *testing.T) {
plugin := &Merge{RoundTimestamp: config.Duration(10 * time.Nanosecond)}
require.NoError(t, plugin.Init())
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 23,
},
time.Unix(0, 1),
),
)
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 2),
),
)
var acc testutil.Accumulator
acc.SetPrecision(time.Second)
plugin.Push(&acc)
expected := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 23,
"time_guest": 42,
},
time.Unix(0, 0),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
}
func TestReset(t *testing.T) {
plugin := &Merge{}
require.NoError(t, plugin.Init())
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 42,
},
time.Unix(0, 0),
),
)
var acc testutil.Accumulator
plugin.Push(&acc)
plugin.Reset()
plugin.Add(
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 0),
),
)
plugin.Push(&acc)
expected := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_idle": 42,
},
time.Unix(0, 0),
),
testutil.MustMetric(
"cpu",
map[string]string{
"cpu": "cpu0",
},
map[string]interface{}{
"time_guest": 42,
},
time.Unix(0, 0),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
}
func BenchmarkMergeOne(b *testing.B) {
var merger Merge
require.NoError(b, merger.Init())
m := metric.New(
"mymetric",
map[string]string{
"host": "host.example.com",
"mykey": "myvalue",
"another key": "another value",
},
map[string]interface{}{
"f1": 1,
"f2": 2,
"f3": 3,
"f4": 4,
"f5": 5,
"f6": 6,
"f7": 7,
"f8": 8,
},
time.Now(),
)
var acc testutil.NopAccumulator
for n := 0; n < b.N; n++ {
merger.Reset()
merger.Add(m)
merger.Push(&acc)
}
}
func BenchmarkMergeTwo(b *testing.B) {
var merger Merge
require.NoError(b, merger.Init())
now := time.Now()
m1 := metric.New(
"mymetric",
map[string]string{
"host": "host.example.com",
"mykey": "myvalue",
"another key": "another value",
},
map[string]interface{}{
"f1": 1,
"f2": 2,
"f3": 3,
"f4": 4,
"f5": 5,
"f6": 6,
"f7": 7,
"f8": 8,
},
now,
)
m2 := metric.New(
"mymetric",
map[string]string{
"host": "host.example.com",
"mykey": "myvalue",
"another key": "another value",
},
map[string]interface{}{
"f8": 8,
"f9": 9,
"f10": 10,
"f11": 11,
"f12": 12,
"f13": 13,
"f14": 14,
"f15": 15,
"f16": 16,
},
now,
)
var acc testutil.NopAccumulator
for n := 0; n < b.N; n++ {
merger.Reset()
merger.Add(m1)
merger.Add(m2)
merger.Push(&acc)
}
}

View file

@ -0,0 +1,15 @@
# Merge metrics into multifield metrics by series key
[[aggregators.merge]]
## General Aggregator Arguments:
## The period on which to flush & clear the aggregator.
# period = "30s"
## Precision to round the metric timestamp to
## This is useful for cases where metrics to merge arrive within a small
## interval and thus vary in timestamp. The timestamp of the resulting metric
## is also rounded.
# round_timestamp_to = "1ns"
## If true, the original metric will be dropped by the
## aggregator and will not get sent to the output plugins.
drop_original = true