feat: Add RedisTimeSeries plugin (#11054)

This commit is contained in:
Guy Korland 2022-07-19 16:08:51 +03:00 committed by GitHub
parent f29f6cf6a1
commit 3c5d71b7cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 281 additions and 118 deletions

View File

@ -21,96 +21,96 @@
## Environment variables can be used as tags, and throughout the config file
# user = "$USER"
# Configuration for telegraf agent
[agent]
## Default data collection interval for all inputs
interval = "10s"
## Rounds collection interval to 'interval'
## ie, if interval="10s" then always collect on :00, :10, :20, etc.
round_interval = true
## Telegraf will send metrics to outputs in batches of at most
## metric_batch_size metrics.
## This controls the size of writes that Telegraf sends to output plugins.
metric_batch_size = 1000
## Maximum number of unwritten metrics per output. Increasing this value
## allows for longer periods of output downtime without dropping metrics at the
## cost of higher maximum memory usage.
metric_buffer_limit = 10000
## Collection jitter is used to jitter the collection by a random amount.
## Each plugin will sleep for a random time within jitter before collecting.
## This can be used to avoid many plugins querying things like sysfs at the
## same time, which can have a measurable effect on the system.
collection_jitter = "0s"
## Collection offset is used to shift the collection by the given amount.
## This can be be used to avoid many plugins querying constraint devices
## at the same time by manually scheduling them in time.
# collection_offset = "0s"
## Default flushing interval for all outputs. Maximum flush_interval will be
## flush_interval + flush_jitter
flush_interval = "10s"
## Jitter the flush interval by a random amount. This is primarily to avoid
## large write spikes for users running a large number of telegraf instances.
## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s
flush_jitter = "0s"
## Collected metrics are rounded to the precision specified. Precision is
## specified as an interval with an integer + unit (e.g. 0s, 10ms, 2us, 4s).
## Valid time units are "ns", "us" (or "µs"), "ms", "s".
##
## By default or when set to "0s", precision will be set to the same
## timestamp order as the collection interval, with the maximum being 1s:
## ie, when interval = "10s", precision will be "1s"
## when interval = "250ms", precision will be "1ms"
##
## Precision will NOT be used for service inputs. It is up to each individual
## service input to set the timestamp at the appropriate precision.
precision = "0s"
## Log at debug level.
# debug = false
## Log only error level messages.
# quiet = false
## Log target controls the destination for logs and can be one of "file",
## "stderr" or, on Windows, "eventlog". When set to "file", the output file
## is determined by the "logfile" setting.
# logtarget = "file"
## Name of the file to be logged to when using the "file" logtarget. If set to
## the empty string then logs are written to stderr.
# logfile = ""
## The logfile will be rotated after the time interval specified. When set
## to 0 no time based rotation is performed. Logs are rotated only when
## written to, if there is no log activity rotation may be delayed.
# logfile_rotation_interval = "0h"
## The logfile will be rotated when it becomes larger than the specified
## size. When set to 0 no size based rotation is performed.
# logfile_rotation_max_size = "0MB"
## Maximum number of rotated archives to keep, any older logs are deleted.
## If set to -1, no archives are removed.
# logfile_rotation_max_archives = 5
## Pick a timezone to use when logging or type 'local' for local time.
## Example: America/Chicago
# log_with_timezone = ""
## Override default hostname, if empty use os.Hostname()
hostname = ""
## If set to true, do no set the "host" tag in the telegraf agent.
omit_hostname = false
## Method of translating SNMP objects. Can be "netsnmp" which
## translates by calling external programs snmptranslate and snmptable,
## or "gosmi" which translates using the built-in gosmi library.
# snmp_translator = "netsnmp"
# Configuration for telegraf agent
[agent]
## Default data collection interval for all inputs
interval = "10s"
## Rounds collection interval to 'interval'
## ie, if interval="10s" then always collect on :00, :10, :20, etc.
round_interval = true
## Telegraf will send metrics to outputs in batches of at most
## metric_batch_size metrics.
## This controls the size of writes that Telegraf sends to output plugins.
metric_batch_size = 1000
## Maximum number of unwritten metrics per output. Increasing this value
## allows for longer periods of output downtime without dropping metrics at the
## cost of higher maximum memory usage.
metric_buffer_limit = 10000
## Collection jitter is used to jitter the collection by a random amount.
## Each plugin will sleep for a random time within jitter before collecting.
## This can be used to avoid many plugins querying things like sysfs at the
## same time, which can have a measurable effect on the system.
collection_jitter = "0s"
## Collection offset is used to shift the collection by the given amount.
## This can be be used to avoid many plugins querying constraint devices
## at the same time by manually scheduling them in time.
# collection_offset = "0s"
## Default flushing interval for all outputs. Maximum flush_interval will be
## flush_interval + flush_jitter
flush_interval = "10s"
## Jitter the flush interval by a random amount. This is primarily to avoid
## large write spikes for users running a large number of telegraf instances.
## ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s
flush_jitter = "0s"
## Collected metrics are rounded to the precision specified. Precision is
## specified as an interval with an integer + unit (e.g. 0s, 10ms, 2us, 4s).
## Valid time units are "ns", "us" (or "µs"), "ms", "s".
##
## By default or when set to "0s", precision will be set to the same
## timestamp order as the collection interval, with the maximum being 1s:
## ie, when interval = "10s", precision will be "1s"
## when interval = "250ms", precision will be "1ms"
##
## Precision will NOT be used for service inputs. It is up to each individual
## service input to set the timestamp at the appropriate precision.
precision = "0s"
## Log at debug level.
# debug = false
## Log only error level messages.
# quiet = false
## Log target controls the destination for logs and can be one of "file",
## "stderr" or, on Windows, "eventlog". When set to "file", the output file
## is determined by the "logfile" setting.
# logtarget = "file"
## Name of the file to be logged to when using the "file" logtarget. If set to
## the empty string then logs are written to stderr.
# logfile = ""
## The logfile will be rotated after the time interval specified. When set
## to 0 no time based rotation is performed. Logs are rotated only when
## written to, if there is no log activity rotation may be delayed.
# logfile_rotation_interval = "0h"
## The logfile will be rotated when it becomes larger than the specified
## size. When set to 0 no size based rotation is performed.
# logfile_rotation_max_size = "0MB"
## Maximum number of rotated archives to keep, any older logs are deleted.
## If set to -1, no archives are removed.
# logfile_rotation_max_archives = 5
## Pick a timezone to use when logging or type 'local' for local time.
## Example: America/Chicago
# log_with_timezone = ""
## Override default hostname, if empty use os.Hostname()
hostname = ""
## If set to true, do no set the "host" tag in the telegraf agent.
omit_hostname = false
## Method of translating SNMP objects. Can be "netsnmp" which
## translates by calling external programs snmptranslate and snmptable,
## or "gosmi" which translates using the built-in gosmi library.
# snmp_translator = "netsnmp"
###############################################################################
# OUTPUT PLUGINS #
@ -1677,6 +1677,23 @@
# ## Export metric collection time.
# # export_timestamp = false
# # Configuration for the RedisTimeSeries server to send metrics to
# [[outputs.redistimeseries]]
# ## The address of the RedisTimeSeries server.
# address = "127.0.0.1:6379"
# ## password to login Redis
# password = ""
#
# ## username (optional)
# username = ""
# # redis database number (optional, must be an integer)
# database = 0
#
# ## optional TLS configurations
# tls_ca = "/etc/telegraf/ca.pem
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"
# insecure_skip_verify = false
# # Configuration for Riemann to send metrics to
# [[outputs.riemann]]
@ -6216,9 +6233,9 @@
# # A plugin to collect stats from Opensmtpd - a validating, recursive, and caching DNS resolver
# [[inputs.opensmtpd]]
# ## If running as a restricted user you can prepend sudo for additional access:
# #use_sudo = false
# [[inputs.opensmtpd]]
# ## If running as a restricted user you can prepend sudo for additional access:
# #use_sudo = false
#
# ## The default location of the smtpctl binary can be overridden with:
# binary = "/usr/sbin/smtpctl"
@ -8403,35 +8420,35 @@
# # Read Intel RDT metrics
# [[inputs.intel_rdt]]
# ## Optionally set sampling interval to Nx100ms.
# ## This value is propagated to pqos tool. Interval format is defined by pqos itself.
# ## If not provided or provided 0, will be set to 10 = 10x100ms = 1s.
# # sampling_interval = "10"
# ## Optionally set sampling interval to Nx100ms.
# ## This value is propagated to pqos tool. Interval format is defined by pqos itself.
# ## If not provided or provided 0, will be set to 10 = 10x100ms = 1s.
# # sampling_interval = "10"
#
# ## Optionally specify the path to pqos executable.
# ## If not provided, auto discovery will be performed.
# # pqos_path = "/usr/local/bin/pqos"
# ## Optionally specify the path to pqos executable.
# ## If not provided, auto discovery will be performed.
# # pqos_path = "/usr/local/bin/pqos"
#
# ## Optionally specify if IPC and LLC_Misses metrics shouldn't be propagated.
# ## If not provided, default value is false.
# # shortened_metrics = false
# ## Optionally specify if IPC and LLC_Misses metrics shouldn't be propagated.
# ## If not provided, default value is false.
# # shortened_metrics = false
#
# ## Specify the list of groups of CPU core(s) to be provided as pqos input.
# ## Mandatory if processes aren't set and forbidden if processes are specified.
# ## e.g. ["0-3", "4,5,6"] or ["1-3,4"]
# # cores = ["0-3"]
# ## Specify the list of groups of CPU core(s) to be provided as pqos input.
# ## Mandatory if processes aren't set and forbidden if processes are specified.
# ## e.g. ["0-3", "4,5,6"] or ["1-3,4"]
# # cores = ["0-3"]
#
# ## Specify the list of processes for which Metrics will be collected.
# ## Mandatory if cores aren't set and forbidden if cores are specified.
# ## e.g. ["qemu", "pmd"]
# # processes = ["process"]
# ## Specify the list of processes for which Metrics will be collected.
# ## Mandatory if cores aren't set and forbidden if cores are specified.
# ## e.g. ["qemu", "pmd"]
# # processes = ["process"]
#
# ## Specify if the pqos process should be called with sudo.
# ## Mandatory if the telegraf process does not run as root.
# # use_sudo = false
# ## Specify if the pqos process should be called with sudo.
# ## Mandatory if the telegraf process does not run as root.
# # use_sudo = false
# # Subscribe and receive OpenConfig Telemetry data using JTI
# # Read JTI OpenConfig Telemetry from listed sensors
# [[inputs.jti_openconfig_telemetry]]
# ## List of device addresses to collect telemetry from
# servers = ["localhost:1883"]

3
go.mod
View File

@ -60,7 +60,6 @@ require (
github.com/go-ldap/ldap/v3 v3.4.1
github.com/go-logfmt/logfmt v0.5.1
github.com/go-ping/ping v0.0.0-20210201095549-52eed920f98c
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-redis/redis/v8 v8.11.5
github.com/go-sql-driver/mysql v1.6.0
github.com/go-stomp/stomp v2.1.4+incompatible
@ -174,6 +173,8 @@ require (
modernc.org/sqlite v1.17.3
)
require github.com/go-redis/redis/v7 v7.4.1
require (
cloud.google.com/go v0.102.1 // indirect
cloud.google.com/go/compute v1.6.1 // indirect

2
go.sum
View File

@ -918,6 +918,8 @@ github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3yg
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI=
github.com/go-redis/redis/v7 v7.4.1/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-redis/redis/v8 v8.0.0-beta.6/go.mod h1:g79Vpae8JMzg5qjk8BiwU9tK+HmU3iDVyS4UAJLFycI=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=

View File

@ -28,7 +28,8 @@ The Redis input plugin gathers metrics from one or many Redis servers.
# # Can be "string", "integer", or "float"
# type = "string"
## specify server password
## specify server connection parameters
# username = "myuser"
# password = "s#cr@t%"
## specify username for ACL auth (Redis 6.0+)

View File

@ -11,7 +11,7 @@ import (
"strings"
"sync"
"github.com/go-redis/redis"
"github.com/go-redis/redis/v7"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/common/tls"

View File

@ -41,6 +41,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/outputs/opentelemetry"
_ "github.com/influxdata/telegraf/plugins/outputs/opentsdb"
_ "github.com/influxdata/telegraf/plugins/outputs/prometheus_client"
_ "github.com/influxdata/telegraf/plugins/outputs/redistimeseries"
_ "github.com/influxdata/telegraf/plugins/outputs/riemann"
_ "github.com/influxdata/telegraf/plugins/outputs/riemann_legacy"
_ "github.com/influxdata/telegraf/plugins/outputs/sensu"

View File

@ -0,0 +1,24 @@
# RedisTimeSeries Producer Output Plugin
The RedisTimeSeries output plugin writes metrics to the RedisTimeSeries server.
## Configuration
```toml
[[outputs.redistimeseries]]
## The address of the RedisTimeSeries server.
address = "127.0.0.1:6379"
## password to login Redis
password = ""
## username (optional)
# username = ""
# redis database number (optional, must be an integer)
# database = 0
## optional TLS configurations
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"
# insecure_skip_verify = false
```

View File

@ -0,0 +1,91 @@
package redistimeseries
import (
"errors"
"fmt"
"github.com/go-redis/redis/v7"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/common/tls"
"github.com/influxdata/telegraf/plugins/outputs"
)
const sampleConfig = `
## The address of the RedisTimeSeries server.
address = "127.0.0.1:6379"
## Redis ACL credentials
# username = ""
# password = ""
# database = 0
## Optional TLS Config
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"
# insecure_skip_verify = false
`
type RedisTimeSeries struct {
Address string `toml:"address"`
Username string `toml:"username"`
Password string `toml:"password"`
Database int `toml:"database"`
Log telegraf.Logger `toml:"-"`
tls.ClientConfig
client *redis.Client
}
func (r *RedisTimeSeries) Connect() error {
if r.Address == "" {
return errors.New("redis address must be specified")
}
r.client = redis.NewClient(&redis.Options{
Addr: r.Address,
Password: r.Password,
Username: r.Username,
DB: r.Database,
})
return r.client.Ping().Err()
}
func (r *RedisTimeSeries) Close() error {
return r.client.Close()
}
func (r *RedisTimeSeries) Description() string {
return "Plugin for sending metrics to RedisTimeSeries"
}
func (r *RedisTimeSeries) SampleConfig() string {
return sampleConfig
}
func (r *RedisTimeSeries) Write(metrics []telegraf.Metric) error {
for _, m := range metrics {
now := m.Time().UnixNano() / 1000000 // in milliseconds
name := m.Name()
var tags []interface{}
for k, v := range m.Tags() {
tags = append(tags, k, v)
}
for fieldName, value := range m.Fields() {
key := name + "_" + fieldName
addSlice := []interface{}{"TS.ADD", key, now, value}
addSlice = append(addSlice, tags...)
if err := r.client.Do(addSlice...).Err(); err != nil {
return fmt.Errorf("adding sample failed: %v", err)
}
}
}
return nil
}
func init() {
outputs.Add("redistimeseries", func() telegraf.Output {
return &RedisTimeSeries{}
})
}

View File

@ -0,0 +1,26 @@
package redistimeseries
import (
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
"testing"
)
func TestConnectAndWrite(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
address := testutil.GetLocalHost() + ":6379"
redis := &RedisTimeSeries{
Address: address,
}
// Verify that we can connect to the RedisTimeSeries server
err := redis.Connect()
require.NoError(t, err)
// Verify that we can successfully write data to the RedisTimeSeries server
err = redis.Write(testutil.MockMetrics())
require.NoError(t, err)
}