Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
106
plugins/inputs/internal/README.md
Normal file
106
plugins/inputs/internal/README.md
Normal file
|
@ -0,0 +1,106 @@
|
|||
# Telegraf Internal Input Plugin
|
||||
|
||||
This plugin collects metrics about the telegraf agent and its plugins.
|
||||
|
||||
> [!NOTE]
|
||||
> Some metrics are aggregates across all instances of a plugin type.
|
||||
|
||||
⭐ Telegraf v1.2.0
|
||||
🏷️ applications
|
||||
💻 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
|
||||
# Collect statistics about itself
|
||||
[[inputs.internal]]
|
||||
## If true, collect telegraf memory stats.
|
||||
# collect_memstats = true
|
||||
|
||||
## If true, collect metrics from Go's runtime.metrics. For a full list see:
|
||||
## https://pkg.go.dev/runtime/metrics
|
||||
# collect_gostats = false
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
memstats are collected using the [Go runtime framework][memstats]
|
||||
|
||||
- internal_memstats
|
||||
- alloc_bytes
|
||||
- frees
|
||||
- heap_alloc_bytes
|
||||
- heap_idle_bytes
|
||||
- heap_in_use_bytes
|
||||
- heap_objects_bytes
|
||||
- heap_released_bytes
|
||||
- heap_sys_bytes
|
||||
- mallocs
|
||||
- num_gc
|
||||
- pointer_lookups
|
||||
- sys_bytes
|
||||
- total_alloc_bytes
|
||||
|
||||
agent stats collect aggregate stats on all telegraf plugins.
|
||||
|
||||
- internal_agent
|
||||
- gather_errors
|
||||
- gather_timeouts
|
||||
- metrics_dropped
|
||||
- metrics_gathered
|
||||
- metrics_written
|
||||
|
||||
internal_gather stats collect aggregate stats on all input plugins
|
||||
that are of the same input type. They are tagged with `input=<plugin_name>`
|
||||
`version=<telegraf_version>` and `go_version=<go_build_version>`.
|
||||
|
||||
- internal_gather
|
||||
- gather_time_ns
|
||||
- metrics_gathered
|
||||
- gather_timeouts
|
||||
|
||||
internal_write stats collect aggregate stats on all output plugins
|
||||
that are of the same input type. They are tagged with `output=<plugin_name>`
|
||||
and `version=<telegraf_version>`.
|
||||
|
||||
- internal_write
|
||||
- buffer_limit
|
||||
- buffer_size
|
||||
- metrics_added
|
||||
- metrics_written
|
||||
- metrics_dropped
|
||||
- metrics_filtered
|
||||
- write_time_ns
|
||||
|
||||
internal_<plugin_name> are metrics which are defined on a per-plugin basis, and
|
||||
usually contain tags which differentiate each instance of a particular type of
|
||||
plugin and `version=<telegraf_version>`.
|
||||
|
||||
- internal_<plugin_name>
|
||||
- individual plugin-specific fields, such as requests counts.
|
||||
|
||||
All measurements for specific plugins are tagged with information relevant
|
||||
to each particular plugin and with `version=<telegraf_version>`.
|
||||
|
||||
[memstats]: https://golang.org/pkg/runtime/#MemStats
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
internal_memstats,host=tyrion alloc_bytes=4457408i,sys_bytes=10590456i,pointer_lookups=7i,mallocs=17642i,frees=7473i,heap_sys_bytes=6848512i,heap_idle_bytes=1368064i,heap_in_use_bytes=5480448i,heap_released_bytes=0i,total_alloc_bytes=6875560i,heap_alloc_bytes=4457408i,heap_objects_bytes=10169i,num_gc=2i 1480682800000000000
|
||||
internal_agent,host=tyrion,go_version=1.12.7,version=1.99.0 metrics_written=18i,metrics_dropped=0i,metrics_gathered=19i,gather_errors=0i,gather_timeouts=0i 1480682800000000000
|
||||
internal_write,output=file,host=tyrion,version=1.99.0 buffer_limit=10000i,write_time_ns=636609i,metrics_added=18i,metrics_written=18i,buffer_size=0i 1480682800000000000
|
||||
internal_gather,input=internal,host=tyrion,version=1.99.0 metrics_gathered=19i,gather_time_ns=442114i,gather_timeouts=0i 1480682800000000000
|
||||
internal_gather,input=http_listener,host=tyrion,version=1.99.0 metrics_gathered=0i,gather_time_ns=167285i,gather_timeouts=0i 1480682800000000000
|
||||
internal_http_listener,address=:8186,host=tyrion,version=1.99.0 queries_received=0i,writes_received=0i,requests_received=0i,buffers_created=0i,requests_served=0i,pings_received=0i,bytes_received=0i,not_founds_served=0i,pings_served=0i,queries_served=0i,writes_served=0i 1480682800000000000
|
||||
internal_mqtt_consumer,host=tyrion,version=1.99.0 messages_received=622i,payload_size=37942i 1657282270000000000
|
||||
```
|
142
plugins/inputs/internal/internal.go
Normal file
142
plugins/inputs/internal/internal.go
Normal file
|
@ -0,0 +1,142 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package internal
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"runtime/metrics"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
inter "github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/selfstat"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type Internal struct {
|
||||
CollectMemstats bool `toml:"collect_memstats"`
|
||||
CollectGostats bool `toml:"collect_gostats"`
|
||||
}
|
||||
|
||||
func (*Internal) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (s *Internal) Gather(acc telegraf.Accumulator) error {
|
||||
for _, m := range selfstat.Metrics() {
|
||||
if m.Name() == "internal_agent" {
|
||||
m.AddTag("go_version", strings.TrimPrefix(runtime.Version(), "go"))
|
||||
}
|
||||
m.AddTag("version", inter.Version)
|
||||
acc.AddFields(m.Name(), m.Fields(), m.Tags(), m.Time())
|
||||
}
|
||||
|
||||
if s.CollectMemstats {
|
||||
collectMemStat(acc)
|
||||
}
|
||||
|
||||
if s.CollectGostats {
|
||||
collectGoStat(acc)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectMemStat(acc telegraf.Accumulator) {
|
||||
m := &runtime.MemStats{}
|
||||
runtime.ReadMemStats(m)
|
||||
fields := map[string]any{
|
||||
"alloc_bytes": m.Alloc, // bytes allocated and not yet freed
|
||||
"total_alloc_bytes": m.TotalAlloc, // bytes allocated (even if freed)
|
||||
"sys_bytes": m.Sys, // bytes obtained from system (sum of XxxSys below)
|
||||
"pointer_lookups": m.Lookups, // number of pointer lookups
|
||||
"mallocs": m.Mallocs, // number of mallocs
|
||||
"frees": m.Frees, // number of frees
|
||||
|
||||
// Main allocation heap statistics.
|
||||
"heap_alloc_bytes": m.HeapAlloc, // bytes allocated and not yet freed (same as Alloc above)
|
||||
"heap_sys_bytes": m.HeapSys, // bytes obtained from system
|
||||
"heap_idle_bytes": m.HeapIdle, // bytes in idle spans
|
||||
"heap_in_use_bytes": m.HeapInuse, // bytes in non-idle span
|
||||
"heap_released_bytes": m.HeapReleased, // bytes released to the OS
|
||||
"heap_objects": m.HeapObjects, // total number of allocated objects
|
||||
"num_gc": m.NumGC,
|
||||
}
|
||||
acc.AddFields("internal_memstats", fields, make(map[string]string))
|
||||
}
|
||||
|
||||
func collectGoStat(acc telegraf.Accumulator) {
|
||||
descs := metrics.All()
|
||||
samples := make([]metrics.Sample, len(descs))
|
||||
for i := range samples {
|
||||
samples[i].Name = descs[i].Name
|
||||
}
|
||||
metrics.Read(samples)
|
||||
|
||||
fields := make(map[string]any, len(samples))
|
||||
for _, sample := range samples {
|
||||
name := sanitizeName(sample.Name)
|
||||
|
||||
switch sample.Value.Kind() {
|
||||
case metrics.KindUint64:
|
||||
fields[name] = sample.Value.Uint64()
|
||||
case metrics.KindFloat64:
|
||||
fields[name] = sample.Value.Float64()
|
||||
case metrics.KindFloat64Histogram:
|
||||
// The histogram may be quite large, so let's just pull out
|
||||
// a crude estimate for the median for the sake of this example.
|
||||
fields[name] = medianBucket(sample.Value.Float64Histogram())
|
||||
default:
|
||||
// This may happen as new metrics get added.
|
||||
//
|
||||
// The safest thing to do here is to simply log it somewhere
|
||||
// as something to look into, but ignore it for now.
|
||||
// In the worst case, you might temporarily miss out on a new metric.
|
||||
fmt.Printf("%s: unexpected metric Kind: %v\n", name, sample.Value.Kind())
|
||||
}
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"go_version": strings.TrimPrefix(runtime.Version(), "go"),
|
||||
}
|
||||
acc.AddFields("internal_gostats", fields, tags)
|
||||
}
|
||||
|
||||
// Converts /cpu/classes/gc/mark/assist:cpu-seconds to cpu_classes_gc_mark_assist_cpu_seconds
|
||||
func sanitizeName(name string) string {
|
||||
name = strings.TrimPrefix(name, "/")
|
||||
name = strings.ReplaceAll(name, "/", "_")
|
||||
name = strings.ReplaceAll(name, ":", "_")
|
||||
name = strings.ReplaceAll(name, "-", "_")
|
||||
return name
|
||||
}
|
||||
|
||||
func medianBucket(h *metrics.Float64Histogram) float64 {
|
||||
total := uint64(0)
|
||||
for _, count := range h.Counts {
|
||||
total += count
|
||||
}
|
||||
thresh := total / 2
|
||||
total = 0
|
||||
for i, count := range h.Counts {
|
||||
total += count
|
||||
if total >= thresh {
|
||||
return h.Buckets[i]
|
||||
}
|
||||
}
|
||||
|
||||
// default value in case something above did not work
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("internal", func() telegraf.Input {
|
||||
return &Internal{
|
||||
CollectMemstats: true,
|
||||
}
|
||||
})
|
||||
}
|
113
plugins/inputs/internal/internal_test.go
Normal file
113
plugins/inputs/internal/internal_test.go
Normal file
|
@ -0,0 +1,113 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf/selfstat"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestSelfPlugin(t *testing.T) {
|
||||
s := Internal{
|
||||
CollectMemstats: true,
|
||||
}
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
require.NoError(t, s.Gather(acc))
|
||||
require.True(t, acc.HasMeasurement("internal_memstats"))
|
||||
|
||||
// test that a registered stat is incremented
|
||||
stat := selfstat.Register("mytest", "test", map[string]string{"test": "foo"})
|
||||
stat.Incr(1)
|
||||
stat.Incr(2)
|
||||
require.NoError(t, s.Gather(acc))
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "internal_mytest",
|
||||
map[string]interface{}{
|
||||
"test": int64(3),
|
||||
},
|
||||
map[string]string{
|
||||
"test": "foo",
|
||||
"version": "unknown",
|
||||
},
|
||||
)
|
||||
acc.ClearMetrics()
|
||||
|
||||
// test that a registered stat is set properly
|
||||
stat.Set(101)
|
||||
require.NoError(t, s.Gather(acc))
|
||||
acc.AssertContainsTaggedFields(t, "internal_mytest",
|
||||
map[string]interface{}{
|
||||
"test": int64(101),
|
||||
},
|
||||
map[string]string{
|
||||
"test": "foo",
|
||||
"version": "unknown",
|
||||
},
|
||||
)
|
||||
acc.ClearMetrics()
|
||||
|
||||
// test that regular and timing stats can share the same measurement, and
|
||||
// that timings are set properly.
|
||||
timing := selfstat.RegisterTiming("mytest", "test_ns", map[string]string{"test": "foo"})
|
||||
timing.Incr(100)
|
||||
timing.Incr(200)
|
||||
require.NoError(t, s.Gather(acc))
|
||||
acc.AssertContainsTaggedFields(t, "internal_mytest",
|
||||
map[string]interface{}{
|
||||
"test": int64(101),
|
||||
"test_ns": int64(150),
|
||||
},
|
||||
map[string]string{
|
||||
"test": "foo",
|
||||
"version": "unknown",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestNoMemStat(t *testing.T) {
|
||||
s := Internal{
|
||||
CollectMemstats: false,
|
||||
CollectGostats: false,
|
||||
}
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
require.NoError(t, s.Gather(acc))
|
||||
require.False(t, acc.HasMeasurement("internal_memstats"))
|
||||
require.False(t, acc.HasMeasurement("internal_gostats"))
|
||||
}
|
||||
|
||||
func TestGostats(t *testing.T) {
|
||||
s := Internal{
|
||||
CollectMemstats: false,
|
||||
CollectGostats: true,
|
||||
}
|
||||
acc := &testutil.Accumulator{}
|
||||
|
||||
require.NoError(t, s.Gather(acc))
|
||||
require.False(t, acc.HasMeasurement("internal_memstats"))
|
||||
require.True(t, acc.HasMeasurement("internal_gostats"))
|
||||
|
||||
var metric *testutil.Metric
|
||||
for _, m := range acc.Metrics {
|
||||
if m.Measurement == "internal_gostats" {
|
||||
metric = m
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.NotNil(t, metric)
|
||||
require.Equal(t, "internal_gostats", metric.Measurement)
|
||||
require.Len(t, metric.Tags, 1)
|
||||
require.Contains(t, metric.Tags, "go_version")
|
||||
|
||||
for name, value := range metric.Fields {
|
||||
switch value.(type) {
|
||||
case int64, uint64, float64:
|
||||
default:
|
||||
require.Failf(t, "Wrong type of field", "Field %s is of non-numeric type %T", name, value)
|
||||
}
|
||||
}
|
||||
}
|
8
plugins/inputs/internal/sample.conf
Normal file
8
plugins/inputs/internal/sample.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Collect statistics about itself
|
||||
[[inputs.internal]]
|
||||
## If true, collect telegraf memory stats.
|
||||
# collect_memstats = true
|
||||
|
||||
## If true, collect metrics from Go's runtime.metrics. For a full list see:
|
||||
## https://pkg.go.dev/runtime/metrics
|
||||
# collect_gostats = false
|
Loading…
Add table
Add a link
Reference in a new issue