diff --git a/command/agent/command.go b/command/agent/command.go
index 453239677f..c4e6e51180 100644
--- a/command/agent/command.go
+++ b/command/agent/command.go
@@ -588,12 +588,13 @@ func (c *Command) Run(args []string) int {
*/
inm := metrics.NewInmemSink(10*time.Second, time.Minute)
metrics.DefaultInmemSignal(inm)
- metricsConf := metrics.DefaultConfig(config.StatsitePrefix)
+ metricsConf := metrics.DefaultConfig(config.Telemetry.StatsitePrefix)
+ metricsConf.EnableHostname = !config.Telemetry.DisableHostname
// Configure the statsite sink
var fanout metrics.FanoutSink
- if config.StatsiteAddr != "" {
- sink, err := metrics.NewStatsiteSink(config.StatsiteAddr)
+ if config.Telemetry.StatsiteAddr != "" {
+ sink, err := metrics.NewStatsiteSink(config.Telemetry.StatsiteAddr)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to start statsite sink. Got: %s", err))
return 1
@@ -602,8 +603,8 @@ func (c *Command) Run(args []string) int {
}
// Configure the statsd sink
- if config.StatsdAddr != "" {
- sink, err := metrics.NewStatsdSink(config.StatsdAddr)
+ if config.Telemetry.StatsdAddr != "" {
+ sink, err := metrics.NewStatsdSink(config.Telemetry.StatsdAddr)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to start statsd sink. Got: %s", err))
return 1
@@ -612,14 +613,14 @@ func (c *Command) Run(args []string) int {
}
// Configure the DogStatsd sink
- if config.DogStatsdAddr != "" {
+ if config.Telemetry.DogStatsdAddr != "" {
var tags []string
- if config.DogStatsdTags != nil {
- tags = config.DogStatsdTags
+ if config.Telemetry.DogStatsdTags != nil {
+ tags = config.Telemetry.DogStatsdTags
}
- sink, err := datadog.NewDogStatsdSink(config.DogStatsdAddr, metricsConf.HostName)
+ sink, err := datadog.NewDogStatsdSink(config.Telemetry.DogStatsdAddr, metricsConf.HostName)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to start DogStatsd sink. Got: %s", err))
return 1
diff --git a/command/agent/config.go b/command/agent/config.go
index c9e3464d12..5154439547 100644
--- a/command/agent/config.go
+++ b/command/agent/config.go
@@ -91,6 +91,32 @@ type DNSConfig struct {
OnlyPassing bool `mapstructure:"only_passing"`
}
+// Telemetry is the telemetry configuration for the server
+type Telemetry struct {
+ // StatsiteAddr is the address of a statsite instance. If provided,
+ // metrics will be streamed to that instance.
+ StatsiteAddr string `mapstructure:"statsite_address"`
+
+ // StatsdAddr is the address of a statsd instance. If provided,
+ // metrics will be sent to that instance.
+ StatsdAddr string `mapstructure:"statsd_address"`
+
+ // StatsitePrefix is the prefix used to write stats values to. By
+ // default this is set to 'consul'.
+ StatsitePrefix string `mapstructure:"statsite_prefix"`
+
+ // DisableHostname will disable hostname prefixing for all metrics
+ DisableHostname bool `mapstructure:"disable_hostname"`
+
+ // DogStatsdAddr is the address of a dogstatsd instance. If provided,
+ // metrics will be sent to that instance
+ DogStatsdAddr string `mapstructure:"dogstatsd_addr"`
+
+ // DogStatsdTags are the global tags that should be sent with each packet to dogstatsd
+ // It is a list of strings, where each string looks like "my_tag_name:my_tag_value"
+ DogStatsdTags []string `mapstructure:"dogstatsd_tags"`
+}
+
// Config is the configuration that can be set for an Agent.
// Some of this is configurable as CLI flags, but most must
// be set using a configuration file.
@@ -177,25 +203,7 @@ type Config struct {
// the INT signal. Defaults false. This can be changed on reload.
SkipLeaveOnInt bool `mapstructure:"skip_leave_on_interrupt"`
- // StatsiteAddr is the address of a statsite instance. If provided,
- // metrics will be streamed to that instance.
- StatsiteAddr string `mapstructure:"statsite_addr"`
-
- // StatsitePrefix is the prefix used to write stats values to. By
- // default this is set to 'consul'.
- StatsitePrefix string `mapstructure:"statsite_prefix"`
-
- // StatsdAddr is the address of a statsd instance. If provided,
- // metrics will be sent to that instance.
- StatsdAddr string `mapstructure:"statsd_addr"`
-
- // DogStatsdAddr is the address of a dogstatsd instance. If provided,
- // metrics will be sent to that instance
- DogStatsdAddr string `mapstructure:"dogstatsd_addr"`
-
- // DogStatsdTags are the global tags that should be sent with each packet to dogstatsd
- // It is a list of strings, where each string looks like "my_tag_name:my_tag_value"
- DogStatsdTags []string `mapstructure:"dogstatsd_tags"`
+ Telemetry Telemetry `mapstructure:"telemetry"`
// Protocol is the Consul protocol version to use.
Protocol int `mapstructure:"protocol"`
@@ -464,6 +472,10 @@ func (u UnixSocketPermissions) Mode() string {
return u.Perms
}
+func (s *Telemetry) GoString() string {
+ return fmt.Sprintf("*%#v", *s)
+}
+
// UnixSocketConfig stores information about various unix sockets which
// Consul creates and uses for communication.
type UnixSocketConfig struct {
@@ -504,7 +516,9 @@ func DefaultConfig() *Config {
DNSConfig: DNSConfig{
MaxStale: 5 * time.Second,
},
- StatsitePrefix: "consul",
+ Telemetry: Telemetry{
+ StatsitePrefix: "consul",
+ },
SyslogFacility: "LOCAL0",
Protocol: consul.ProtocolVersion2Compatible,
CheckUpdateInterval: 5 * time.Minute,
@@ -613,6 +627,30 @@ func DecodeConfig(r io.Reader) (*Config, error) {
}
result.Checks = append(result.Checks, check)
}
+
+ // A little hacky but upgrades the old stats config directives to the new way
+ if sub, ok := obj["statsd_addr"]; ok && result.Telemetry.StatsdAddr == "" {
+ result.Telemetry.StatsdAddr = sub.(string)
+ }
+
+ if sub, ok := obj["statsite_addr"]; ok && result.Telemetry.StatsiteAddr == "" {
+ result.Telemetry.StatsiteAddr = sub.(string)
+ }
+
+ if sub, ok := obj["statsite_prefix"]; ok && result.Telemetry.StatsitePrefix == "" {
+ result.Telemetry.StatsitePrefix = sub.(string)
+ }
+
+ if sub, ok := obj["dogstatsd_addr"]; ok && result.Telemetry.DogStatsdAddr == "" {
+ result.Telemetry.DogStatsdAddr = sub.(string)
+ }
+
+ if sub, ok := obj["dogstatsd_tags"].([]interface{}); ok && len(result.Telemetry.DogStatsdTags) == 0 {
+ result.Telemetry.DogStatsdTags = make([]string, len(sub))
+ for i := range sub {
+ result.Telemetry.DogStatsdTags[i] = sub[i].(string)
+ }
+ }
}
// Decode
@@ -632,7 +670,11 @@ func DecodeConfig(r io.Reader) (*Config, error) {
// Check unused fields and verify that no bad configuration options were
// passed to Consul. There are a few additional fields which don't directly
// use mapstructure decoding, so we need to account for those as well.
- allowedKeys := []string{"service", "services", "check", "checks"}
+ allowedKeys := []string{
+ "service", "services", "check", "checks", "statsd_addr", "statsite_addr", "statsite_prefix",
+ "dogstatsd_addr", "dogstatsd_tags",
+ }
+
var unused []string
for _, field := range md.Unused {
if !lib.StrContains(allowedKeys, field) {
@@ -947,20 +989,23 @@ func MergeConfig(a, b *Config) *Config {
if b.SkipLeaveOnInt == true {
result.SkipLeaveOnInt = true
}
- if b.StatsiteAddr != "" {
- result.StatsiteAddr = b.StatsiteAddr
+ if b.Telemetry.DisableHostname == true {
+ result.Telemetry.DisableHostname = true
}
- if b.StatsitePrefix != "" {
- result.StatsitePrefix = b.StatsitePrefix
+ if b.Telemetry.StatsdAddr != "" {
+ result.Telemetry.StatsdAddr = b.Telemetry.StatsdAddr
}
- if b.StatsdAddr != "" {
- result.StatsdAddr = b.StatsdAddr
+ if b.Telemetry.StatsiteAddr != "" {
+ result.Telemetry.StatsiteAddr = b.Telemetry.StatsiteAddr
}
- if b.DogStatsdAddr != "" {
- result.DogStatsdAddr = b.DogStatsdAddr
+ if b.Telemetry.StatsitePrefix != "" {
+ result.Telemetry.StatsitePrefix = b.Telemetry.StatsitePrefix
}
- if b.DogStatsdTags != nil {
- result.DogStatsdTags = b.DogStatsdTags
+ if b.Telemetry.DogStatsdAddr != "" {
+ result.Telemetry.DogStatsdAddr = b.Telemetry.DogStatsdAddr
+ }
+ if b.Telemetry.DogStatsdTags != nil {
+ result.Telemetry.DogStatsdTags = b.Telemetry.DogStatsdTags
}
if b.EnableDebug {
result.EnableDebug = true
diff --git a/command/agent/config_test.go b/command/agent/config_test.go
index 44da26901e..d06feb8cbc 100644
--- a/command/agent/config_test.go
+++ b/command/agent/config_test.go
@@ -635,10 +635,10 @@ func TestDecodeConfig(t *testing.T) {
t.Fatalf("err: %s", err)
}
- if config.StatsiteAddr != "127.0.0.1:7250" {
+ if config.Telemetry.StatsiteAddr != "127.0.0.1:7250" {
t.Fatalf("bad: %#v", config)
}
- if config.StatsdAddr != "127.0.0.1:7251" {
+ if config.Telemetry.StatsdAddr != "127.0.0.1:7251" {
t.Fatalf("bad: %#v", config)
}
@@ -648,19 +648,19 @@ func TestDecodeConfig(t *testing.T) {
if err != nil {
t.Fatalf("err: %s", err)
}
- if config.DogStatsdAddr != "127.0.0.1:7254" {
+ if config.Telemetry.DogStatsdAddr != "127.0.0.1:7254" {
t.Fatalf("bad: %#v", config)
}
- if len(config.DogStatsdTags) != 2 {
+ if len(config.Telemetry.DogStatsdTags) != 2 {
t.Fatalf("bad: %#v", config)
}
- if config.DogStatsdTags[0] != "tag_1:val_1" {
+ if config.Telemetry.DogStatsdTags[0] != "tag_1:val_1" {
t.Fatalf("bad: %#v", config)
}
- if config.DogStatsdTags[1] != "tag_2:val_2" {
+ if config.Telemetry.DogStatsdTags[1] != "tag_2:val_2" {
t.Fatalf("bad: %#v", config)
}
@@ -670,7 +670,32 @@ func TestDecodeConfig(t *testing.T) {
if err != nil {
t.Fatalf("err: %s", err)
}
- if config.StatsitePrefix != "my_prefix" {
+ if config.Telemetry.StatsitePrefix != "my_prefix" {
+ t.Fatalf("bad: %#v", config)
+ }
+
+ // New telemetry
+ input = `{"telemetry": { "statsite_prefix": "my_prefix", "statsite_address": "127.0.0.1:7250", "statsd_address":"127.0.0.1:7251", "disable_hostname": true, "dogstatsd_addr": "1.1.1.1:111", "dogstatsd_tags": [ "tag_1:val_1" ] } }`
+ config, err = DecodeConfig(bytes.NewReader([]byte(input)))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if config.Telemetry.StatsitePrefix != "my_prefix" {
+ t.Fatalf("bad: %#v", config)
+ }
+ if config.Telemetry.StatsiteAddr != "127.0.0.1:7250" {
+ t.Fatalf("bad: %#v", config)
+ }
+ if config.Telemetry.StatsdAddr != "127.0.0.1:7251" {
+ t.Fatalf("bad: %#v", config)
+ }
+ if config.Telemetry.DisableHostname != true {
+ t.Fatalf("bad: %#v", config)
+ }
+ if config.Telemetry.DogStatsdAddr != "1.1.1.1:111" {
+ t.Fatalf("bad: %#v", config)
+ }
+ if config.Telemetry.DogStatsdTags[0] != "tag_1:val_1" {
t.Fatalf("bad: %#v", config)
}
@@ -1191,6 +1216,14 @@ func TestMergeConfig(t *testing.T) {
CheckUpdateIntervalRaw: "8m",
RetryIntervalRaw: "10s",
RetryIntervalWanRaw: "10s",
+ Telemetry: Telemetry{
+ DisableHostname: false,
+ StatsdAddr: "nope",
+ StatsiteAddr: "nope",
+ StatsitePrefix: "nope",
+ DogStatsdAddr: "nope",
+ DogStatsdTags: []string{"nope"},
+ },
}
b := &Config{
@@ -1269,12 +1302,15 @@ func TestMergeConfig(t *testing.T) {
"handler": "foobar",
},
},
- DisableRemoteExec: true,
- StatsiteAddr: "127.0.0.1:7250",
- StatsitePrefix: "stats_prefix",
- StatsdAddr: "127.0.0.1:7251",
- DogStatsdAddr: "127.0.0.1:7254",
- DogStatsdTags: []string{"tag_1:val_1", "tag_2:val_2"},
+ DisableRemoteExec: true,
+ Telemetry: Telemetry{
+ StatsiteAddr: "127.0.0.1:7250",
+ StatsitePrefix: "stats_prefix",
+ StatsdAddr: "127.0.0.1:7251",
+ DisableHostname: true,
+ DogStatsdAddr: "127.0.0.1:7254",
+ DogStatsdTags: []string{"tag_1:val_1", "tag_2:val_2"},
+ },
DisableUpdateCheck: true,
DisableAnonymousSignature: true,
HTTPAPIResponseHeaders: map[string]string{
diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown
index 3b1eded12a..f59b3bb8d3 100644
--- a/website/source/docs/agent/options.html.markdown
+++ b/website/source/docs/agent/options.html.markdown
@@ -273,7 +273,10 @@ definitions support being updated during a reload.
"type": "checks",
"handler": "/usr/bin/health-check-handler.sh"
}
- ]
+ ],
+ "telemetry": {
+ "statsite_address": "127.0.0.1:2180"
+ }
}
```
@@ -572,29 +575,48 @@ definitions support being updated during a reload.
* `start_join_wan` An array of strings specifying
addresses of WAN nodes to [`-join-wan`](#_join_wan) upon startup.
-* `statsd_addr` This provides the address of a
- statsd instance in the format `host:port`. If provided, Consul will send various telemetry information
- to that instance for aggregation. This can be used to capture runtime information. This sends UDP packets
- only and can be used with statsd or statsite.
+* `telemetry` An object describing where to send telemetry to
-* `dogstatsd_addr` This provides the
- address of a DogStatsD instance in the format `host:port`. DogStatsD is a protocol-compatible flavor of
- statsd, with the added ability to decorate metrics with tags and event information. If provided, Consul will
- send various telemetry information to that instance for aggregation. This can be used to capture runtime
- information.
+ * `statsd_address` This provides the
+ address of a statsd instance. If provided, Consul will send various telemetry information to that instance for
+ aggregation. This can be used to capture runtime information. This sends UDP packets only and can be used with
+ statsd or statsite.
+
+ * `statsite_address` This provides
+ the address of a statsite instance. If provided, Consul will stream various telemetry information to that instance
+ for aggregation. This can be used to capture runtime information. This streams via TCP and can only be used with
+ statsite.
+
+ * `statsite_prefix`
+ The prefix used while writing all telemetry data to statsite. By default, this is set to "consul".
+
+ * `dogstatsd_addr` This provides the
+ address of a DogStatsD instance in the format `host:port`. DogStatsD is a protocol-compatible flavor of
+ statsd, with the added ability to decorate metrics with tags and event information. If provided, Consul will
+ send various telemetry information to that instance for aggregation. This can be used to capture runtime
+ information.
+
+ * `dogstatsd_tags` This provides a list of global tags
+ that will be added to all telemetry packets sent to DogStatsD. It is a list of strings, where each string
+ looks like "my_tag_name:my_tag_value".
+
+ * `disable_hostname`
+ Whether or not to prepend runtime telemetry with the machines hostname, defaults to false.
+
+* `statsd_addr` Deprecated, see
+ `statsd_address`
-* `dogstatsd_tags` This provides a list of global tags
- that will be added to all telemetry packets sent to DogStatsD. It is a list of strings, where each string
- looks like "my_tag_name:my_tag_value".
+* `statsite_addr` Deprecated, see
+ `statsite_address`
-* `statsite_addr` This provides the address of a
- statsite instance in the format `host:port`. If provided, Consul will stream various telemetry information
- to that instance for aggregation. This can be used to capture runtime information. This streams via TCP and
- can only be used with statsite.
+* `statsite_prefix` Deprecated, see
+ `statsite_prefix`
-* `statsite_prefix`
- The prefix used while writing all telemetry data to statsite. By default, this
- is set to "consul".
+* `dogstatsd_addr` Deprecated, see
+ `dogstatsd_addr`
+
+* `dogstatsd_tags` Deprecated, see
+ `dogstatsd_tags`
* `syslog_facility` When
[`enable_syslog`](#enable_syslog) is provided, this controls to which
diff --git a/website/source/docs/agent/telemetry.html.markdown b/website/source/docs/agent/telemetry.html.markdown
index 392edd59d0..a71d5deb9c 100644
--- a/website/source/docs/agent/telemetry.html.markdown
+++ b/website/source/docs/agent/telemetry.html.markdown
@@ -19,10 +19,10 @@ it will dump the current telemetry information to the agent's `stderr`.
This telemetry information can be used for debugging or otherwise
getting a better view of what Consul is doing.
-Additionally, if the [`statsite_addr` configuration option](/docs/agent/options.html#statsite_addr)
-is provided, the telemetry information will be streamed to a
-[statsite](http://github.com/armon/statsite) server where it can be
-aggregated and flushed to Graphite or any other metrics store.
+Additionally, if the [`telemetry` configuration options](/docs/agent/options.html#telemetry)
+are provided, the telemetry information will be streamed to a
+[statsite](http://github.com/armon/statsite) or [statsd](http://github.com/etsy/statsd) server where
+it can be aggregated and flushed to Graphite or any other metrics store.
Below is sample output of a telemetry dump: