diff --git a/go.mod b/go.mod index ea03acec18902..441a7abae2103 100644 --- a/go.mod +++ b/go.mod @@ -185,13 +185,13 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 go.opentelemetry.io/otel/sdk/metric v0.39.0 go.starlark.net v0.0.0-20220328144851-d1966c6b9fcd - golang.org/x/crypto v0.10.0 + golang.org/x/crypto v0.11.0 golang.org/x/mod v0.11.0 - golang.org/x/net v0.11.0 + golang.org/x/net v0.12.0 golang.org/x/oauth2 v0.9.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.9.0 - golang.org/x/term v0.9.0 + golang.org/x/sys v0.10.0 + golang.org/x/term v0.10.0 golang.org/x/text v0.11.0 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20211230205640-daad0b7ba671 gonum.org/v1/gonum v0.13.0 diff --git a/go.sum b/go.sum index 1b7acee39d240..a65da6fc2fad4 100644 --- a/go.sum +++ b/go.sum @@ -1610,8 +1610,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1728,8 +1728,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1860,8 +1860,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1873,8 +1873,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/plugins/outputs/influxdb_v2/README.md b/plugins/outputs/influxdb_v2/README.md index 892a814afdec7..fee1200afbe46 100644 --- a/plugins/outputs/influxdb_v2/README.md +++ b/plugins/outputs/influxdb_v2/README.md @@ -67,6 +67,18 @@ to use them. ## Enable or disable uint support for writing uints influxdb 2.0. # influx_uint_support = false + ## HTTP/2 Timeouts + ## The following values control the HTTP/2 client's timeouts. These settings + ## are generally not required unless a user is seeing issues with client + ## disconnects. If a user does see issues, then it is suggested to set these + ## values to "15s" for ping timeout and "30s" for read idle timeout and + ## retry. + ## + ## Note that the timer for read_idle_timeout begins at the end of the last + ## successful write and not at the beginning of the next write. + # ping_timeout = "0s" + # read_idle_timeout = "0s" + ## Optional TLS Config for use on HTTP connections. # tls_ca = "/etc/telegraf/ca.pem" # tls_cert = "/etc/telegraf/cert.pem" diff --git a/plugins/outputs/influxdb_v2/http.go b/plugins/outputs/influxdb_v2/http.go index e0ee2ec5fc631..e2cf57135319a 100644 --- a/plugins/outputs/influxdb_v2/http.go +++ b/plugins/outputs/influxdb_v2/http.go @@ -19,6 +19,7 @@ import ( "github.com/influxdata/telegraf/config" "github.com/influxdata/telegraf/internal" "github.com/influxdata/telegraf/plugins/serializers/influx" + "golang.org/x/net/http2" ) type APIError struct { @@ -52,6 +53,8 @@ type HTTPConfig struct { Proxy *url.URL UserAgent string ContentEncoding string + PingTimeout config.Duration + ReadIdleTimeout config.Duration TLSConfig *tls.Config Serializer *influx.Serializer @@ -126,6 +129,13 @@ func NewHTTPClient(cfg *HTTPConfig) (*httpClient, error) { Proxy: proxy, TLSClientConfig: cfg.TLSConfig, } + if cfg.ReadIdleTimeout != 0 || cfg.PingTimeout != 0 { + http2Trans, err := http2.ConfigureTransports(transport) + if err == nil { + http2Trans.ReadIdleTimeout = time.Duration(cfg.ReadIdleTimeout) + http2Trans.PingTimeout = time.Duration(cfg.PingTimeout) + } + } case "unix": transport = &http.Transport{ Dial: func(_, _ string) (net.Conn, error) { diff --git a/plugins/outputs/influxdb_v2/http_test.go b/plugins/outputs/influxdb_v2/http_test.go index aac87817f108c..2985400e0d246 100644 --- a/plugins/outputs/influxdb_v2/http_test.go +++ b/plugins/outputs/influxdb_v2/http_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/config" influxdb "github.com/influxdata/telegraf/plugins/outputs/influxdb_v2" "github.com/influxdata/telegraf/testutil" ) @@ -40,6 +41,13 @@ func TestNewHTTPClient(t *testing.T) { URL: genURL("unix://var/run/influxd.sock"), }, }, + { + cfg: &influxdb.HTTPConfig{ + URL: genURL("unix://var/run/influxd.sock"), + PingTimeout: config.Duration(15 * time.Second), + ReadIdleTimeout: config.Duration(30 * time.Second), + }, + }, } for i := range tests { @@ -56,6 +64,66 @@ func TestNewHTTPClient(t *testing.T) { } } +func TestWrite(t *testing.T) { + ts := httptest.NewServer( + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/api/v2/write": + err := r.ParseForm() + require.NoError(t, err) + require.Equal(t, r.Form["bucket"], []string{"foobar"}) + + body, err := io.ReadAll(r.Body) + require.NoError(t, err) + require.Contains(t, string(body), "cpu value=42.123") + + w.WriteHeader(http.StatusNoContent) + return + default: + w.WriteHeader(http.StatusNotFound) + return + } + }), + ) + defer ts.Close() + + addr := &url.URL{ + Scheme: "http", + Host: ts.Listener.Addr().String(), + } + + cfg := &influxdb.HTTPConfig{ + URL: addr, + Bucket: "telegraf", + BucketTag: "bucket", + ExcludeBucketTag: true, + PingTimeout: config.Duration(15 * time.Second), + ReadIdleTimeout: config.Duration(30 * time.Second), + } + + client, err := influxdb.NewHTTPClient(cfg) + require.NoError(t, err) + + metrics := []telegraf.Metric{ + testutil.MustMetric( + "cpu", + map[string]string{ + "bucket": "foobar", + }, + map[string]interface{}{ + "value": 42.123, + }, + time.Unix(0, 0), + ), + } + + ctx := context.Background() + err = client.Write(ctx, metrics) + require.NoError(t, err) + err = client.Write(ctx, metrics) + require.NoError(t, err) +} + func TestWriteBucketTagWorksOnRetry(t *testing.T) { ts := httptest.NewServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -84,14 +152,14 @@ func TestWriteBucketTagWorksOnRetry(t *testing.T) { Host: ts.Listener.Addr().String(), } - config := &influxdb.HTTPConfig{ + cfg := &influxdb.HTTPConfig{ URL: addr, Bucket: "telegraf", BucketTag: "bucket", ExcludeBucketTag: true, } - client, err := influxdb.NewHTTPClient(config) + client, err := influxdb.NewHTTPClient(cfg) require.NoError(t, err) metrics := []telegraf.Metric{ @@ -146,7 +214,7 @@ func TestTooLargeWriteRetry(t *testing.T) { Host: ts.Listener.Addr().String(), } - config := &influxdb.HTTPConfig{ + cfg := &influxdb.HTTPConfig{ URL: addr, Bucket: "telegraf", BucketTag: "bucket", @@ -154,7 +222,7 @@ func TestTooLargeWriteRetry(t *testing.T) { Log: testutil.Logger{}, } - client, err := influxdb.NewHTTPClient(config) + client, err := influxdb.NewHTTPClient(cfg) require.NoError(t, err) // Together the metric batch size is too big, split up, we get success diff --git a/plugins/outputs/influxdb_v2/influxdb_v2.go b/plugins/outputs/influxdb_v2/influxdb_v2.go index 4a3b7d0ccc1ba..660432f781dfc 100644 --- a/plugins/outputs/influxdb_v2/influxdb_v2.go +++ b/plugins/outputs/influxdb_v2/influxdb_v2.go @@ -46,6 +46,8 @@ type InfluxDB struct { UserAgent string `toml:"user_agent"` ContentEncoding string `toml:"content_encoding"` UintSupport bool `toml:"influx_uint_support"` + PingTimeout config.Duration `toml:"ping_timeout"` + ReadIdleTimeout config.Duration `toml:"read_idle_timeout"` tls.ClientConfig Log telegraf.Logger `toml:"-"` @@ -144,6 +146,8 @@ func (i *InfluxDB) getHTTPClient(address *url.URL, proxy *url.URL) (Client, erro ContentEncoding: i.ContentEncoding, TLSConfig: tlsConfig, Serializer: serializer, + PingTimeout: i.PingTimeout, + ReadIdleTimeout: i.ReadIdleTimeout, Log: i.Log, } diff --git a/plugins/outputs/influxdb_v2/sample.conf b/plugins/outputs/influxdb_v2/sample.conf index 6ad02d3d552fd..93acf0dae0651 100644 --- a/plugins/outputs/influxdb_v2/sample.conf +++ b/plugins/outputs/influxdb_v2/sample.conf @@ -43,6 +43,18 @@ ## Enable or disable uint support for writing uints influxdb 2.0. # influx_uint_support = false + ## HTTP/2 Timeouts + ## The following values control the HTTP/2 client's timeouts. These settings + ## are generally not required unless a user is seeing issues with client + ## disconnects. If a user does see issues, then it is suggested to set these + ## values to "15s" for ping timeout and "30s" for read idle timeout and + ## retry. + ## + ## Note that the timer for read_idle_timeout begins at the end of the last + ## successful write and not at the beginning of the next write. + # ping_timeout = "0s" + # read_idle_timeout = "0s" + ## Optional TLS Config for use on HTTP connections. # tls_ca = "/etc/telegraf/ca.pem" # tls_cert = "/etc/telegraf/cert.pem"