diff --git a/glide.lock b/glide.lock index ab51bab5..f19bf407 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: a15f875f47ee23f61d18d37812ef104f915f724fecd41178e8c4219973d63713 -updated: 2017-10-23T15:30:26.971475424-07:00 +hash: 63daf51f6fff142e7b13003e7fcc5972abd4ddcb67bfa6046ae6d95e7f7b7e64 +updated: 2018-05-16T23:30:35.54451-04:00 imports: - name: github.com/apache/thrift version: 9549b25c77587b29be4e0b5c258221a4ed85d37a @@ -17,29 +17,27 @@ imports: version: 130e6b02ab059e7b717a096f397c5b60111cae74 subpackages: - proto -- name: github.com/matttproud/golang_protobuf_extensions - version: c12348ce28de40eed0136aa2b644d0ee0650e56c - subpackages: - - pbutil -- name: github.com/prometheus/client_golang - version: c5b7fccd204277076155f10851dad72b76a49317 +- name: github.com/m3db/prometheus_client_golang + version: 8ae269d24972b8695572fa6b2e3718b5ea82d6b4 subpackages: - prometheus - prometheus/promhttp -- name: github.com/prometheus/client_model +- name: github.com/m3db/prometheus_client_model version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6 subpackages: - go -- name: github.com/prometheus/common - version: 6d76b79f239843a04e8ad8dfd8fcadfa3920236f +- name: github.com/m3db/prometheus_common + version: 25aaa3dff79bb48116615ebe1dea6a494b74ce77 subpackages: - expfmt - internal/bitbucket.org/ww/goautoneg - model -- name: github.com/prometheus/procfs - version: e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2 +- name: github.com/m3db/prometheus_procfs + version: 1878d9fbb537119d24b21ca07effd591627cd160 +- name: github.com/matttproud/golang_protobuf_extensions + version: c12348ce28de40eed0136aa2b644d0ee0650e56c subpackages: - - xfs + - pbutil - name: go.uber.org/atomic version: 4e336646b2ef9fc6e47be8e21594178f98e5ebcf - name: gopkg.in/validator.v2 diff --git a/glide.yaml b/glide.yaml index 046e2de5..12df40d6 100644 --- a/glide.yaml +++ b/glide.yaml @@ -5,10 +5,16 @@ import: version: ~3.1.0 subpackages: - statsd -- package: github.com/prometheus/client_golang - version: ^0.8.0 +- package: github.com/m3db/prometheus_client_golang + version: 8ae269d24972b8695572fa6b2e3718b5ea82d6b4 subpackages: - prometheus +- package: github.com/m3db/prometheus_client_model + version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6 +- package: github.com/m3db/prometheus_common + version: 25aaa3dff79bb48116615ebe1dea6a494b74ce77 +- package: github.com/m3db/prometheus_procfs + version: 1878d9fbb537119d24b21ca07effd591627cd160 - package: github.com/apache/thrift version: 9549b25c77587b29be4e0b5c258221a4ed85d37a subpackages: diff --git a/m3/sanitize.go b/m3/sanitize.go index eb5d0f1a..05fce7b6 100644 --- a/m3/sanitize.go +++ b/m3/sanitize.go @@ -25,7 +25,7 @@ import ( ) var ( - // DefaultSanitizerOpts are the options for the default M3 Sanitizer + // DefaultSanitizerOpts are the options for the default M3 sanitizer. DefaultSanitizerOpts = tally.SanitizeOptions{ NameCharacters: tally.ValidCharacters{ Ranges: tally.AlphanumericRange, diff --git a/prometheus/config.go b/prometheus/config.go new file mode 100644 index 00000000..93bd4ea0 --- /dev/null +++ b/prometheus/config.go @@ -0,0 +1,121 @@ +// Copyright (c) 2018 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package prometheus + +import ( + "net/http" + "strings" +) + +// Configuration is a configuration for a Prometheus reporter. +type Configuration struct { + // HandlerPath if specified will be used instead of using the default + // HTTP handler path "/metrics". + HandlerPath string `yaml:"handlerPath"` + + // ListenAddress if specified will be used instead of just registering the + // handler on the default HTTP serve mux without listening. + ListenAddress string `yaml:"listenAddress"` + + // TimerType is the default Prometheus type to use for Tally timers. + TimerType string `yaml:"timerType"` + + // DefaultHistogramBuckets if specified will set the default histogram + // buckets to be used by the reporter. + DefaultHistogramBuckets []HistogramObjective `yaml:"defaultHistogramBuckets"` + + // DefaultSummaryObjectives if specified will set the default summary + // objectives to be used by the reporter. + DefaultSummaryObjectives []SummaryObjective `yaml:"defaultSummaryObjectives"` +} + +// HistogramObjective is a Prometheus histogram bucket. +// See: https://godoc.org/github.com/prometheus/client_golang/prometheus#HistogramOpts +type HistogramObjective struct { + Upper float64 `yaml:"upper"` +} + +// SummaryObjective is a Prometheus summary objective. +// See: https://godoc.org/github.com/prometheus/client_golang/prometheus#SummaryOpts +type SummaryObjective struct { + Percentile float64 `yaml:"percentile"` + AllowedError float64 `yaml:"allowedError"` +} + +// ConfigurationOptions allows some error callbacks to be registered. +type ConfigurationOptions struct { + OnError func(e error) + onRegisterError func(e error) +} + +// NewReporter creates a new M3 reporter from this configuration. +func (c Configuration) NewReporter( + configOpts ConfigurationOptions, +) (Reporter, error) { + var opts Options + opts.OnRegisterError = configOpts.onRegisterError + + switch c.TimerType { + case "summary": + opts.DefaultTimerType = SummaryTimerType + case "histogram": + opts.DefaultTimerType = HistogramTimerType + } + + if len(c.DefaultHistogramBuckets) > 0 { + var values []float64 + for _, value := range c.DefaultHistogramBuckets { + values = append(values, value.Upper) + } + opts.DefaultHistogramBuckets = values + } + + if len(c.DefaultSummaryObjectives) > 0 { + values := make(map[float64]float64) + for _, value := range c.DefaultSummaryObjectives { + values[value.Percentile] = value.AllowedError + } + opts.DefaultSummaryObjectives = values + } + + reporter := NewReporter(opts) + + path := "/metrics" + if handlerPath := strings.TrimSpace(c.HandlerPath); handlerPath != "" { + path = handlerPath + } + + if addr := strings.TrimSpace(c.ListenAddress); addr == "" { + http.Handle(path, reporter.HTTPHandler()) + } else { + mux := http.NewServeMux() + mux.Handle(path, reporter.HTTPHandler()) + go func() { + if err := http.ListenAndServe(addr, mux); err != nil { + if configOpts.OnError != nil { + configOpts.OnError(err) + } + } + }() + } + + return reporter, nil +} diff --git a/prometheus/reporter.go b/prometheus/reporter.go index 4ae315d9..4b15636e 100644 --- a/prometheus/reporter.go +++ b/prometheus/reporter.go @@ -28,8 +28,8 @@ import ( "github.com/uber-go/tally" - prom "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" + prom "github.com/m3db/prometheus_client_golang/prometheus" + "github.com/m3db/prometheus_client_golang/prometheus/promhttp" ) const ( diff --git a/prometheus/reporter_test.go b/prometheus/reporter_test.go index 1049eb10..9c97b957 100644 --- a/prometheus/reporter_test.go +++ b/prometheus/reporter_test.go @@ -25,8 +25,8 @@ import ( "testing" "time" - prom "github.com/prometheus/client_golang/prometheus" - dto "github.com/prometheus/client_model/go" + prom "github.com/m3db/prometheus_client_golang/prometheus" + dto "github.com/m3db/prometheus_client_model/go" "github.com/uber-go/tally" "github.com/stretchr/testify/assert" diff --git a/prometheus/sanitize.go b/prometheus/sanitize.go new file mode 100644 index 00000000..18bf13d0 --- /dev/null +++ b/prometheus/sanitize.go @@ -0,0 +1,44 @@ +// Copyright (c) 2018 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package prometheus + +import ( + "github.com/uber-go/tally" +) + +var ( + // DefaultSanitizerOpts are the options for the default Prometheus sanitizer. + DefaultSanitizerOpts = tally.SanitizeOptions{ + NameCharacters: tally.ValidCharacters{ + Ranges: tally.AlphanumericRange, + Characters: tally.UnderscoreDashCharacters, + }, + KeyCharacters: tally.ValidCharacters{ + Ranges: tally.AlphanumericRange, + Characters: tally.UnderscoreDashCharacters, + }, + ValueCharacters: tally.ValidCharacters{ + Ranges: tally.AlphanumericRange, + Characters: tally.UnderscoreDashCharacters, + }, + ReplacementCharacter: tally.DefaultReplacementCharacter, + } +)