feat(outputs.graphite): Allow to set the local address to bind (#14628)

This commit is contained in:
Sven Rebhan 2024-02-05 18:23:34 +01:00 committed by GitHub
parent 534289f3b4
commit f235fcc640
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 0 deletions

View File

@ -26,8 +26,14 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## If multiple endpoints are configured, the output will be load balanced.
## Only one of the endpoints will be written to with each iteration.
servers = ["localhost:2003"]
## Local address to bind when connecting to the server
## If empty or not set, the local address is automatically chosen.
# local_address = ""
## Prefix metrics name
prefix = ""
## Graphite output template
## see https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_OUTPUT.md
template = "host.tags.measurement.field"

View File

@ -9,6 +9,7 @@ import (
"io"
"math/rand"
"net"
"strconv"
"strings"
"time"
@ -37,6 +38,7 @@ type Graphite struct {
GraphiteStrictRegex string `toml:"graphite_strict_sanitize_regex"`
// URL is only for backwards compatibility
Servers []string `toml:"servers"`
LocalAddr string `toml:"local_address"`
Prefix string `toml:"prefix"`
Template string `toml:"template"`
Templates []string `toml:"templates"`
@ -104,6 +106,28 @@ func (g *Graphite) Connect() error {
// Dialer with timeout
d := net.Dialer{Timeout: time.Duration(g.Timeout)}
if g.LocalAddr != "" {
// Resolve the local address into IP address and the given port if any
addr, sPort, err := net.SplitHostPort(g.LocalAddr)
if err != nil && !strings.Contains(err.Error(), "missing port") {
return fmt.Errorf("invalid local address: %w", err)
}
local, err := net.ResolveIPAddr("ip", addr)
if err != nil {
return fmt.Errorf("cannot resolve local address: %w", err)
}
var port int
if sPort != "" {
p, err := strconv.ParseUint(sPort, 10, 16)
if err != nil {
return fmt.Errorf("invalid port: %w", err)
}
port = int(p)
}
d.LocalAddr = &net.TCPAddr{IP: local.IP, Port: port, Zone: local.Zone}
}
// Get secure connection if tls config is set
var conn net.Conn

View File

@ -585,6 +585,23 @@ func TestGraphiteOkWithTagsAndSeparatorUnderscore(t *testing.T) {
require.NoError(t, err)
}
func TestGraphiteLocalAddress(t *testing.T) {
t.Log("Starting server")
server, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
defer server.Close()
plugin := Graphite{
Servers: []string{server.Addr().String()},
LocalAddr: "localhost",
Prefix: "my.prefix",
Log: testutil.Logger{},
}
require.NoError(t, plugin.Init())
require.NoError(t, plugin.Connect())
require.NoError(t, plugin.Close())
}
func TestIntegration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")

View File

@ -4,8 +4,14 @@
## If multiple endpoints are configured, the output will be load balanced.
## Only one of the endpoints will be written to with each iteration.
servers = ["localhost:2003"]
## Local address to bind when connecting to the server
## If empty or not set, the local address is automatically chosen.
# local_address = ""
## Prefix metrics name
prefix = ""
## Graphite output template
## see https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_OUTPUT.md
template = "host.tags.measurement.field"