Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to control metric tag conversion #50

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ The adapter takes the following parameters:
-buffer-size int
Metric buffer size (ignored in proxy mode).
-convert-paths
Convert metric names/tags to use period instead of underscores. (default true)
Convert metric names to use period instead of underscores. (default true)
-convert-tag-paths
Convert metric tags to use period instead of underscores. (default true)
-debug
Print detailed debug messages.
-flush-interval int
Expand All @@ -44,8 +46,8 @@ The adapter takes the following parameters:
Port/address to listen to on the format '[address:]port'. If no address is specified, the adapter listens to all interfaces.
-metrics-name-override value
list of name and overrides in the format 'key1=value1, key2,value2...'
key = original name of the metrics which is coming from prometheus
value = name user wish to override with
key = original name of the metrics which is coming from prometheus
value = name user wish to override with
no prefix and pathConversion will be applied to these metrics.
-prefix string
Prefix for metric names. If omitted, no prefix is added.
Expand All @@ -72,7 +74,7 @@ The adapter is available as a Docker image.

To run it as a Docker container with the parameters discussed above:
```
docker run wavefronthq/prometheus-storage-adapter -proxy=localhost -proxy-port=2878 -listen=1234 -prefix=prom -convert-paths=true
docker run wavefronthq/prometheus-storage-adapter -proxy=localhost -proxy-port=2878 -listen=1234 -prefix=prom -convert-paths=true -convert-tag-paths=true
```

## Integrating with Prometheus
Expand Down
8 changes: 5 additions & 3 deletions adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func parseTags(s string) map[string]string {
return tags
}

//struct to define the custom type to handle the arguments in key=value pair format.
// struct to define the custom type to handle the arguments in key=value pair format.
type metricsFilter struct {
filter map[string]string
}
Expand Down Expand Up @@ -78,6 +78,7 @@ func main() {
var bufferSize int
var flushInterval int
var convertPaths bool
var convertTagPaths bool
var metricsFilter metricsFilter

flag.StringVar(&prefix, "prefix", "", "Prefix for metric names. If omitted, no prefix is added.")
Expand All @@ -91,7 +92,8 @@ func main() {
flag.IntVar(&batchSize, "batch-size", 0, "Metric sending batch size (ignored in proxy mode).")
flag.IntVar(&bufferSize, "buffer-size", 0, "Metric buffer size (ignored in proxy mode).")
flag.IntVar(&flushInterval, "flush-interval", 0, "Metric flush interval (in seconds).")
flag.BoolVar(&convertPaths, "convert-paths", true, "Convert metric names/tags to use period instead of underscores.")
flag.BoolVar(&convertPaths, "convert-paths", true, "Convert metric names to use period instead of underscores.")
flag.BoolVar(&convertTagPaths, "convert-tag-paths", true, "Convert metric tags to use period instead of underscores.")
flag.Var(&metricsFilter, "metrics-name-override", " list of name and overrides in the format 'key1=value1, key2,value2...'\n"+
" key = original name of the metrics which is coming from prometheus \n"+
" value = name user wish to override with \n"+
Expand Down Expand Up @@ -145,7 +147,7 @@ func main() {
log.Fatal(err)
return
}
mw := backend.NewMetricWriter(sender, prefix, parseTags(tags), convertPaths, metricsFilter.filter)
mw := backend.NewMetricWriter(sender, prefix, parseTags(tags), convertPaths, convertTagPaths, metricsFilter.filter)

// Install metric receiver
http.HandleFunc("/receive", func(w http.ResponseWriter, r *http.Request) {
Expand Down
32 changes: 17 additions & 15 deletions backend/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,27 @@ import (
)

type MetricWriter struct {
prefix string
tags map[string]string
sender senders.Sender
convertPaths bool
metricsSent int64
numErrors int64
errorRate float64
filters map[string]string
prefix string
tags map[string]string
sender senders.Sender
convertPaths bool
convertTagPaths bool
metricsSent int64
numErrors int64
errorRate float64
filters map[string]string
}

var tagValueReplacer = strings.NewReplacer("\"", "\\\"", "*", "-")

func NewMetricWriter(sender senders.Sender, prefix string, tags map[string]string, convertPaths bool, filters map[string]string) *MetricWriter {
func NewMetricWriter(sender senders.Sender, prefix string, tags map[string]string, convertPaths bool, convertTagPaths bool, filters map[string]string) *MetricWriter {
return &MetricWriter{
sender: sender,
prefix: prefix,
tags: tags,
convertPaths: convertPaths,
filters: filters,
sender: sender,
prefix: prefix,
tags: tags,
convertPaths: convertPaths,
convertTagPaths: convertTagPaths,
filters: filters,
}
}

Expand Down Expand Up @@ -94,7 +96,7 @@ func (w *MetricWriter) buildMetricName(name string) string {
}

func (w *MetricWriter) buildTagName(name string) string {
if name != "__name__" && w.convertPaths {
if name != "__name__" && w.convertTagPaths {
name = strings.Replace(name, "_", ".", -1)
}
return name
Expand Down
42 changes: 35 additions & 7 deletions backend/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func TestRoundtrips(t *testing.T) {
Host: "localhost", MetricsPort: 4711,
})
require.NoError(t, err)
w := NewMetricWriter(sender, "prom", map[string]string{}, false, map[string]string{
w := NewMetricWriter(sender, "prom", map[string]string{}, false, false, map[string]string{
"status_request_per_second": "status.request_per_second",
})
for _, test := range testCases {
Expand Down Expand Up @@ -186,22 +186,22 @@ func TestBuildName(t *testing.T) {
testName := "metric_name_with_underscore"
filters := make(map[string]string, 0)
// empty prefix and convert=true
w := NewMetricWriter(sender, "", map[string]string{}, true, filters)
w := NewMetricWriter(sender, "", map[string]string{}, true, true, filters)
name := w.buildMetricName(testName)
require.Equal(t, "metric.name.with.underscore", name)

// empty prefix and convert=false
w = NewMetricWriter(sender, "", map[string]string{}, false, filters)
w = NewMetricWriter(sender, "", map[string]string{}, false, false, filters)
name = w.buildMetricName(testName)
require.Equal(t, testName, name)

// non-empty prefix and convert=true
w = NewMetricWriter(sender, "prom", map[string]string{}, true, filters)
w = NewMetricWriter(sender, "prom", map[string]string{}, true, true, filters)
name = w.buildMetricName(testName)
require.Equal(t, "prom.metric.name.with.underscore", name)

// non-empty prefix and convert=false
w = NewMetricWriter(sender, "prom", map[string]string{}, false, filters)
w = NewMetricWriter(sender, "prom", map[string]string{}, false, false, filters)
name = w.buildMetricName(testName)
require.Equal(t, "prom_"+testName, name)

Expand All @@ -211,13 +211,41 @@ func TestBuildName(t *testing.T) {
}

//filter metrics that should not have any prefix and names would be set to custom value
w = NewMetricWriter(sender, "prom", map[string]string{}, true, filters)
w = NewMetricWriter(sender, "prom", map[string]string{}, true, true, filters)
name = w.buildMetricName("metrics_availability")
require.Equal(t, "metrics.availability", name)

//filter metrics that should have prefix
w = NewMetricWriter(sender, "prom", map[string]string{}, true, filters)
w = NewMetricWriter(sender, "prom", map[string]string{}, true, true, filters)
name = w.buildMetricName("metrics_availability_1")
require.Equal(t, "prom.metrics.availability.1", name)

testTagName := "tag_name_with_underscore"
// empty prefix, convertPaths=true and convertTagPaths=true
w = NewMetricWriter(sender, "", map[string]string{}, true, true, filters)
name = w.buildMetricName(testName)
tag := w.buildTagName(testTagName)
require.Equal(t, "metric.name.with.underscore", name)
require.Equal(t, "tag.name.with.underscore", tag)

// empty prefix, convertPaths=true and convertTagPaths=false
w = NewMetricWriter(sender, "", map[string]string{}, true, false, filters)
name = w.buildMetricName(testName)
tag = w.buildTagName(testTagName)
require.Equal(t, "metric.name.with.underscore", name)
require.Equal(t, testTagName, tag)

// empty prefix, convertPaths=false and convertTagPaths=true
w = NewMetricWriter(sender, "", map[string]string{}, false, true, filters)
name = w.buildMetricName(testName)
tag = w.buildTagName(testTagName)
require.Equal(t, testName, name)
require.Equal(t, "tag.name.with.underscore", tag)

// empty prefix, convertPaths=false and convertTagPaths=false
w = NewMetricWriter(sender, "", map[string]string{}, false, false, filters)
name = w.buildMetricName(testName)
tag = w.buildTagName(testTagName)
require.Equal(t, testName, name)
require.Equal(t, testTagName, tag)
}