diff --git a/config/config.go b/config/config.go index dd7f9c8..0bd079d 100644 --- a/config/config.go +++ b/config/config.go @@ -45,9 +45,10 @@ type Config struct { } `json:"network"` Stats struct { StatsD struct { - Enabled bool `json:"enabled"` - Address TypeHostPort `json:"address"` - MetricPrefix TypeMetricPrefix `json:"metric-prefix"` + Enabled bool `json:"enabled"` + Address TypeHostPort `json:"address"` + MetricPrefix TypeMetricPrefix `json:"metric-prefix"` + TagFormat TypeStatsdTagFormat `json:"tag-format"` } `json:"statsd"` Prometheus struct { Enabled bool `json:"enabled"` @@ -122,6 +123,7 @@ type configRaw struct { Enabled bool `toml:"enabled" json:"enabled,omitempty"` Address string `toml:"address" json:"address,omitempty"` MetricPrefix string `toml:"metric-prefix" json:"metric-prefix,omitempty"` + TagFormat string `toml:"tag-format" json:"tag-format,omitempty"` } `toml:"statsd" json:"statsd,omitempty"` Prometheus struct { Enabled bool `toml:"enabled" json:"enabled,omitempty"` diff --git a/config/type_statsd_tag_format.go b/config/type_statsd_tag_format.go new file mode 100644 index 0000000..7903b0c --- /dev/null +++ b/config/type_statsd_tag_format.go @@ -0,0 +1,49 @@ +package config + +import ( + "fmt" + "strings" +) + +const ( + TypeStatsdTagFormatInfluxdb = "influxdb" + TypeStatsdTagFormatDatadog = "datadog" + TypeStatsdTagFormatGraphite = "graphite" +) + +type TypeStatsdTagFormat struct { + value string +} + +func (c *TypeStatsdTagFormat) UnmarshalText(data []byte) error { + if len(data) == 0 { + return nil + } + + text := strings.ToLower(string(data)) + + switch text { + case TypeStatsdTagFormatInfluxdb, TypeStatsdTagFormatDatadog, TypeStatsdTagFormatGraphite: + c.value = text + default: + return fmt.Errorf("incorrect tag format value: %s", string(data)) + } + + return nil +} + +func (c TypeStatsdTagFormat) MarshalText() ([]byte, error) { + return []byte(c.value), nil +} + +func (c *TypeStatsdTagFormat) String() string { + return c.value +} + +func (c *TypeStatsdTagFormat) Value(defaultValue string) string { + if c.value == "" { + return defaultValue + } + + return c.value +} diff --git a/config/type_statsd_tag_format_test.go b/config/type_statsd_tag_format_test.go new file mode 100644 index 0000000..2c7074f --- /dev/null +++ b/config/type_statsd_tag_format_test.go @@ -0,0 +1,130 @@ +package config_test + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/9seconds/mtg/v2/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type typeStatsdTagFormatTestStruct struct { + Value config.TypeStatsdTagFormat `json:"value"` +} + +type TypeStatsdTagFormat struct { + suite.Suite +} + +func (suite *TypeStatsdTagFormat) TestUnmarshalFail() { + testData := []string{ + "p", + "ipv4", + "onlyipv4", + "ipv6prefer", + } + + for _, v := range testData { + data, err := json.Marshal(map[string]string{ + "value": v, + }) + suite.NoError(err) + + suite.T().Run(v, func(t *testing.T) { + assert.Error(t, json.Unmarshal(data, &typeStatsdTagFormatTestStruct{})) + }) + } +} + +func (suite *TypeStatsdTagFormat) TestUnmarshalOk() { + testData := []string{ + config.TypeStatsdTagFormatDatadog, + config.TypeStatsdTagFormatInfluxdb, + config.TypeStatsdTagFormatGraphite, + strings.ToUpper(config.TypeStatsdTagFormatDatadog), + strings.ToUpper(config.TypeStatsdTagFormatInfluxdb), + strings.ToUpper(config.TypeStatsdTagFormatGraphite), + strings.ToLower(config.TypeStatsdTagFormatDatadog), + strings.ToLower(config.TypeStatsdTagFormatInfluxdb), + strings.ToLower(config.TypeStatsdTagFormatGraphite), + } + + for _, v := range testData { + value := v + + data, err := json.Marshal(map[string]string{ + "value": v, + }) + suite.NoError(err) + + suite.T().Run(v, func(t *testing.T) { + testStruct := &typeStatsdTagFormatTestStruct{} + + assert.NoError(t, json.Unmarshal(data, testStruct)) + assert.EqualValues(t, + strings.ToLower(value), + testStruct.Value.Value(config.TypeStatsdTagFormatDatadog)) + }) + } +} + +func (suite *TypeStatsdTagFormat) TestMarshalOk() { + testData := []string{ + config.TypeStatsdTagFormatDatadog, + config.TypeStatsdTagFormatInfluxdb, + config.TypeStatsdTagFormatGraphite, + strings.ToUpper(config.TypeStatsdTagFormatDatadog), + strings.ToUpper(config.TypeStatsdTagFormatInfluxdb), + strings.ToUpper(config.TypeStatsdTagFormatGraphite), + strings.ToLower(config.TypeStatsdTagFormatDatadog), + strings.ToLower(config.TypeStatsdTagFormatInfluxdb), + strings.ToLower(config.TypeStatsdTagFormatGraphite), + } + + for _, v := range testData { + value := v + + data, err := json.Marshal(map[string]string{ + "value": v, + }) + suite.NoError(err) + + suite.T().Run(v, func(t *testing.T) { + testStruct := &typeStatsdTagFormatTestStruct{} + + assert.NoError(t, json.Unmarshal(data, testStruct)) + assert.Equal(t, strings.ToLower(value), testStruct.Value.String()) + + marshalled, err := testStruct.Value.MarshalText() + assert.NoError(t, err) + assert.Equal(t, strings.ToLower(value), string(marshalled)) + }) + } +} + +func (suite *TypeStatsdTagFormat) TestValue() { + testStruct := &typePreferIPTestStruct{} + + suite.EqualValues(config.TypePreferIPPreferIPv4, + testStruct.Value.Value(config.TypePreferIPPreferIPv4)) + suite.EqualValues(config.TypePreferIPPreferIPv6, + testStruct.Value.Value(config.TypePreferIPPreferIPv6)) + + data, err := json.Marshal(map[string]string{ + "value": config.TypePreferOnlyIPv4, + }) + suite.NoError(err) + suite.NoError(json.Unmarshal(data, testStruct)) + + suite.EqualValues(config.TypePreferOnlyIPv4, + testStruct.Value.Value(config.TypePreferOnlyIPv6)) + suite.EqualValues(config.TypePreferOnlyIPv4, + testStruct.Value.Value(config.TypePreferIPPreferIPv6)) +} + +func TestTypeStatsdTagFormat(t *testing.T) { + t.Parallel() + suite.Run(t, &TypeStatsdTagFormat{}) +} diff --git a/example.config.toml b/example.config.toml index c3d3fbb..d573a16 100644 --- a/example.config.toml +++ b/example.config.toml @@ -174,6 +174,10 @@ enabled = false address = "127.0.0.1:8888" # prefix of metric for statsd metric-prefix = "mtg" +# tag format to use +# supported values are 'datadog', 'influxdb' and 'graphite' +# default format is graphite. +tag-format = "datadog" # prometheus metrics integration. [stats.prometheus]