-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
DataDog and StatsD Metrics Support #1701
Conversation
3de1539
to
01b45ba
Compare
Rebased on top of #1504 changes from Master. |
middlewares/datadog_test.go
Outdated
udp.ShouldReceiveAll(t, expected, func() { | ||
n.ServeHTTP(recorder, req1) | ||
n.ServeHTTP(recorder, req2) | ||
// body := recorder.Body.String() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code?
middlewares/datadog_test.go
Outdated
}) | ||
n.UseHandler(r) | ||
|
||
req1, err := http.NewRequest("GET", "http://localhost:3000/ok", nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
req1 := testhelpers.MustNewRequest(http.methodGet, "http://localhost:3000/ok", nil)
middlewares/datadog_test.go
Outdated
if err != nil { | ||
t.Error(err) | ||
} | ||
req2, err := http.NewRequest("GET", "http://localhost:3000/not-found", nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
req2 := testhelpers.MustNewRequest(http.methodGet, "http://localhost:3000/not-found", nil)
middlewares/datadog_test.go
Outdated
|
||
n.Use(metricsMiddlewareBackend) | ||
r := http.NewServeMux() | ||
//r.Handle("/metrics", promhttp.Handler()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead Code ?
middlewares/datadog.go
Outdated
} | ||
pushInterval, err := time.ParseDuration(config.PushInterval) | ||
if err != nil { | ||
pushInterval = 10 * time.Second |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe you can log the error.
middlewares/statsd_test.go
Outdated
if err != nil { | ||
t.Error(err) | ||
} | ||
req2, err := http.NewRequest("GET", "http://localhost:3000/not-found", nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
req2 := testhelpers.MustNewRequest(http.methodGet, "http://localhost:3000/not-found", nil)
middlewares/statsd_test.go
Outdated
udp.ShouldReceiveAll(t, expected, func() { | ||
n.ServeHTTP(recorder, req1) | ||
n.ServeHTTP(recorder, req2) | ||
// body := recorder.Body.String() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code ?
glide.lock
Outdated
subpackages: | ||
- log | ||
- swagger | ||
- name: github.com/fatih/color | ||
version: 9131ab34cf20d2f6d83fdc67168a5430d1c7dc23 | ||
- name: github.com/gambol99/go-marathon | ||
version: 15ea23e360abb8b25071e677aed344f31838e403 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add/update only your dependencies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not very sure why this shows up as a diff, the glide.yaml
has d672c6fbb499596869d95146a26e7d0746c06c54
version for github.com/gambol99/go-marathon
which came from a prior commit (https://github.com/containous/traefik/blame/master/glide.yaml#L96)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not only for go-marathon
. It's a side affect of the glide get
.
You must use a workaround:
- Revert the glide manifest and lock files.
- Use the github.com/multiplay/glide-pin plugin to pin all versions in the manifest file to the ones given in the lock file.
- Add your dependencies
glide get
- Run
glide update -v
to update the lock file. - Undo the pinning.
- Add your dependencies in
glide.yml
- Use glide-hash to get the manifest file hash and put it in the lock file to please
validate-glide
.
Look at #1332 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried to follow those steps, only to run into errors :(
Invoked glide pin
followed by glide get github.com/go-kit/kit/metrics/dogstatsd
commands and things exploded:
[ERROR] Error scanning github.com/docker/docker/cli/config: open /Users/aantonov/.glide/cache/src/https-github.com-docker-docker/cli/config: no such file or directory
[ERROR] This error means the referenced package was not found.
[ERROR] Missing file or directory errors usually occur when multiple packages
[ERROR] share a common dependency and the first reference encountered by the scanner
[ERROR] sets the version to one that does not contain a subpackage needed required
[ERROR] by another package that uses the shared dependency. Try setting a
[ERROR] version in your glide.yaml that works for all packages that share this
[ERROR] dependency.
[ERROR] Error scanning github.com/docker/docker/cli/config/configfile: open /Users/aantonov/.glide/cache/src/https-github.com-docker-docker/cli/config/configfile: no such file or directory
[ERROR] This error means the referenced package was not found.
[ERROR] Missing file or directory errors usually occur when multiple packages
[ERROR] share a common dependency and the first reference encountered by the scanner
[ERROR] sets the version to one that does not contain a subpackage needed required
[ERROR] by another package that uses the shared dependency. Try setting a
[ERROR] version in your glide.yaml that works for all packages that share this
[ERROR] dependency.
[INFO] --> Fetching updates for github.com/xeipuuv/gojsonpointer.
[ERROR] Error scanning github.com/docker/docker/cli/command/image/build: open /Users/aantonov/.glide/cache/src/https-github.com-docker-docker/cli/command/image/build: no such file or directory
[ERROR] This error means the referenced package was not found.
[ERROR] Missing file or directory errors usually occur when multiple packages
[ERROR] share a common dependency and the first reference encountered by the scanner
[ERROR] sets the version to one that does not contain a subpackage needed required
[ERROR] by another package that uses the shared dependency. Try setting a
[ERROR] version in your glide.yaml that works for all packages that share this
[ERROR] dependency.
[INFO] --> Fetching updates for golang.org/x/time.
[INFO] --> Setting version for golang.org/x/time to a4bde12657593d5e90d0533a3e4fd95e635124cb.
[INFO] --> Fetching updates for github.com/Azure/go-ansiterm.
[INFO] --> Fetching updates for github.com/gorilla/mux.
[INFO] --> Setting version for github.com/gorilla/mux to e444e69cbd2e2e3e0749a2f3c717cec491552bbf.
[INFO] --> Fetching updates for github.com/vbatts/tar-split.
[INFO] --> Fetching updates for github.com/opencontainers/runtime-spec.
[ERROR] Failed to retrieve a list of test dependencies: Error resolving imports
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try two things:
- Run
glide cc
first thing. (This will clear the glide cache which is sometimes known to cause problems.) - use
script/glide.sh <command>
instead ofglide <command>
everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, it becomes more and more likely that we are really running into the problem the glide error describes: conflicting dependencies.
I can double check on my end. Could you tell me which additional dependencies the PR needs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been trying to add:
github.com/go-kit/kit/metrics/dogstatsd
github.com/go-kit/kit/metrics/statsd
github.com/go-kit/kit/metrics/multi
github.com/go-kit/kit/log
github.com/go-kit/kit/util/conn
github.com/stvp/go-udp-testing
Would greatly appreciate if you could see if it will work on your end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid I ran into similar problem: Trying to upgrade github.com/stvp/go-udp-testing
alone yields many conflicts with the client-go library.
I'm having a hard time understanding why we run into these conflicts since go-udp-testing looks super simple and seemingly doesn't have any direct or transitive dependencies with go-client.
Maybe we're holding it wrong at some point...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aantono could you squash all commits and remove changes on glide.yml
, glide.lock
and vendor
? I will try to resolve the problem after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
middlewares/metrics.go
Outdated
histograms = append(histograms, m.getReqDurationHistogram()) | ||
retryCounters = append(retryCounters, m.getRetryCounter()) | ||
} | ||
var mm MultiMetrics |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this line after the next empty line.
middlewares/statsd_test.go
Outdated
udp.ShouldReceiveAll(t, expected, func() { | ||
n.ServeHTTP(recorder, req1) | ||
n.ServeHTTP(recorder, req2) | ||
// body := recorder.Body.String() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code ?
51a26e7
to
143dc17
Compare
Rebased against |
4741f30
to
c5d50d4
Compare
@aantono it's ready. 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use safe.Go
instead of the classic go routines.
middlewares/datadog.go
Outdated
|
||
report := time.NewTicker(pushInterval) | ||
|
||
go datadogClient.SendLoop(report.C, "udp", address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
safe.Go(func() {
datadogClient.SendLoop(report.C, "udp", address)
})
middlewares/statsd.go
Outdated
|
||
report := time.NewTicker(pushInterval) | ||
|
||
go statsdClient.SendLoop(report.C, "udp", address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
safe.Go(func() {
statsdClient.SendLoop(report.C, "udp", address)
})
No worries, You bet! Looks like the |
if datadogTicker == nil { | ||
address := config.Address | ||
if len(address) == 0 { | ||
address = "localhost:8125" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we default to this address? Is this somehow conventional in Datadog?
Instinctively, I tend to go with requiring proper configuration and -- if missing -- return an error, unless a default makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default DataDog statsD listener is running on localhost:8125, which is a well known port, so it is very common for people to not define it explicitly and use the default (be that in DataDog agent config, or in the clients) (See default dd-agent config for reference - https://github.com/DataDog/dd-agent/blob/master/datadog.conf.example#L163)
middlewares/datadog.go
Outdated
} | ||
pushInterval, err := time.ParseDuration(config.PushInterval) | ||
if err != nil { | ||
log.Warnf("Unable to parse %s into pushInterval", config.PushInterval) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the log message should mention that we'll be falling back to a default value.
|
||
// InitDatadogClient initializes metrics pusher and creates a datadogClient if not created already | ||
func InitDatadogClient(config *types.Datadog) *time.Ticker { | ||
if datadogTicker == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we do not enter this function from multiple goroutines concurrently, and hence don't need to synchronize access?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. We only call InitDatadogClient
once when the server starts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative to comparing the ticker could then be to use sync.Once
. This may also help us avoid accidentally initializing the client more than once if for whatever reason we toggle the ticker value inadvertently (say, due to a bug).
More of a suggestion though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sync.Once
sounds like a good idea. I've tried to add it, but realized that I still need to keep track of the ticker
reference, so that I could stop it once the shutdown occurs. Since I have to keep the ticker
variable around anyways, do you want to introduce another variable to store the once
, or just let it be and use the null check instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's good enough in this case. Thanks for giving it a shot. 👍
} | ||
|
||
// InitStatsdClient initializes metrics pusher and creates a statsdClient if not created already | ||
func InitStatsdClient(config *types.Statsd) *time.Ticker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The entire file, but especially this function look very similar to what is implemented in datadog.go
. Is there any chance to factor out the duplicated code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I thought about trying to generalize and factorize the code out, like @ldez mentioned, while the 2 files look very similar in pattern, they internally use different go-kit/metrics structures to initialize metrics, name them and return outbound structures, so there isn't much that can actually be shared, besides the logical steps of operation, which are similar due to the similarity in DataDog being an enhancement on top of StatsD protocol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aantono The initial function is what I was mostly after. They look pretty much identical except for the ticker they reference and the receiver they trigger the loop on. That should be fairly easy to parameterize.
More importantly to me, refactoring should allow us to squash two fairly big tests into a single one.
When you say
besides the logical steps of operation, which are similar due to the similarity in DataDog being an enhancement on top of StatsD protocol.
(emphasis by me)
to me that's really a signal for how the two share certain attributes (i.e., the function in question) that we could reflect code-wise by a central implementation.
So that's my view. Maybe @emilevauge can step in and become the tipping point. I'll be happy to follow whatever majority constitutes. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ldez tbh, seeing three k/v store implementations spanning 30+ LOC each that really only differ by a single store type they pass into a function is rather an anti-example to me. 😮
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I looked once again at the InitDataDogClient
and InitStatsDClient
code and the only part they share is this:
address := config.Address
if len(address) == 0 {
address = "localhost:8125"
}
pushInterval, err := time.ParseDuration(config.PushInterval)
if err != nil {
log.Warnf("Unable to parse %s into pushInterval", config.PushInterval)
pushInterval = 10 * time.Second
}
Given that it looks like boiler-plate code, it's really just a validation of config
properties (but keep in mind that config
is of different struct type: types.Datadog
vs. types.Statsd
), they just happen to both have address
and pushInterval
properties).
The rest of the function handles initializing different clients and each provider has their own ticker as well, which is a statically managed variable, so not that great for factorizing. IMHO it would be more code and will make it harder to read and reason about the code if we to try to come up with a base config type (not even sure what to call it) and then have the 2 concrete types encapsulate it. While I do agree that on the surface this does seem like a good possible case for boiler-plate reduction, once you look deeper, that does not turn out to be so, but curious to hear what @emilevauge thinks about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, you convinced me: I failed to see that the config structs are of different types as well. With that in mind, extracting anything doesn't seem too useful.
Appreciate the technical analysis to solve the matter. 👏
@@ -0,0 +1,52 @@ | |||
package middlewares |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests look very similar to datadog_test.go
too. Reuse opportunity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same thing here, it's two different features.
server/server.go
Outdated
} | ||
if globalConfig.Web.Metrics.Datadog != nil { | ||
metric := middlewares.NewDataDog(name) | ||
log.Debugf("Configured DataDog Metrics pushing to %s once every %s", globalConfig.Web.Metrics.Datadog.Address, globalConfig.Web.Metrics.Datadog.PushInterval) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Metrics/metrics/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just to clarify, are you asking to replace "DataDog Metrics" part of the string in the log.Debugf
with DataDog metrics
lowercased metrics
? If that's the case, I would argue that DataDog Metrics
is a name-proper of the monitoring provider (just like Prometheus Metrics
before it, but if you insist, would be happy to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I think I was being too complicated: Yes, I just meant to use lower case in the log message.
I'm only familiar with Prometheus where I'm not aware of a proper name like Prometheus Metrics
. If you could point me at any references (e.g., docs) showing this, I'll be happy to rest my case.
server/server.go
Outdated
return metrics | ||
if globalConfig.Web.Metrics.StatsD != nil { | ||
metric := middlewares.NewStatsD(name) | ||
log.Debugf("Configured StatsD Metrics pushing to %s once every %s", globalConfig.Web.Metrics.StatsD.Address, globalConfig.Web.Metrics.StatsD.PushInterval) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Metrics/metrics/
server/server.go
Outdated
metricsEnabled := globalConfig.Web != nil && globalConfig.Web.Metrics != nil | ||
if metricsEnabled { | ||
if globalConfig.Web.Metrics.Datadog != nil { | ||
middlewares.StopDatadogClient() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually need all those ifs before? It looks like StopDatadogClient
won't try to stop anything anyway unless the ticker was previously set (i.e., we have configured Datadog for sure).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably don't, at least not at the current moment, I just put them in there for security measure, in case later on the internals of StopDAtadogClient()
change in a way that would require such a check to be done, but we could forget to do it. I would be happy to remove the if
checks, if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd argue that StopDatadogClient
should decide if the client still needs to be stopped or not, rather than relying on static configuration parameters. The function already does this by means of using the ticker value as a flag, so overall I think we can remove the if blocks.
server/server.go
Outdated
middlewares.StopDatadogClient() | ||
} | ||
if globalConfig.Web.Metrics.StatsD != nil { | ||
middlewares.StopStatsdClient() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about the if'ing here.
I think we're also missing a docs update somewhere to inform our users about the possibility to use Datadog or Statsd for metrics collection. |
if statsdTicker == nil { | ||
address := config.Address | ||
if len(address) == 0 { | ||
address = "localhost:8125" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this use port 9125 given what you said here about the default ports?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, I confused StatsD with statsd-exporter project, which defaults to 9125. The default port for both StatsD and dogStatsD is indeed 8125, since the protocols are largely compatible (meaning you can send plain StatsD format data to dogStatsD agent, and it will accept it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Ready to merge once that dreaded merge conflict on the glide lock file (eek!) is resolved. :)
Sounds good... Looks like this is another opportunity for @ldez to shine and show off his mad "Glide" skills! 😜 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to comment on the closed PR. Didn't know a better place to raise my concerns. @aantono can you have a look at the comments and if necessary make a clean up PR?
Especially the point regarding DataDog/StatsD+Retries is concerning to me.
"github.com/go-kit/kit/metrics/dogstatsd" | ||
) | ||
|
||
var _ Metrics = (Metrics)(nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this statement have any effect? I saw these kind of constructs to verify a concrete implementation is implementing an interface. To have the Metrics
on the right hand side doesn't make any sense to me. Can you explain it or clean it up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The right hand side should have been (*DataDog)(nil)
. Fixed.
return dd.reqDurationHistogram | ||
} | ||
|
||
func (dd *Datadog) getRetryCounter() metrics.Counter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As retryCounter
never gets initialised won't this lead to a panic when having DataDog implementation (same for StatsD) + Retries activated? Did you try this out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marco-jantke Great catch... the retry metric was added after the PR was already open, so I must've lost the change during one of the numerous rebases. The good news is that the code won't panic
, since there is a m.retryMetrics != nil
check before the counter is used, but the bad news is that we are missing retry metrics for DataDog & StatsD. Thanks a lot for noticing, I'll add those to the initialization block and open another PR.
return mm.retryCounter | ||
} | ||
|
||
func (mm *MultiMetrics) getWrappedMetrics() *[]Metrics { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICS this method is used nowhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, you are correct... Same PR that added retryMetrics, removed the getWrappedMetrics()
method. It was originally present on the initial Metrics
interface. Will clean-up
// and the number of requests partitioned by status code and method. | ||
// - number of requests partitioned by status code and method | ||
// - request durations | ||
// - amount of retries happened |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not expose amount of retries happened
AFAICS. Same for DataDog implementation.
This merge removes the integration of DataDog and StatsD that was introduced with this PR: traefik#1701 This integration is highly incompatible with our current Prometheus metrics implementation that we have in dustify. Therefore everything specific to those metrics integration was removed, except the glide adaption. They don't hurt for now and better not to start getting merge conflicts in them in there.
While still waiting for #1504 to be merged and rebase on top, this is to get the review process for #834 started for DataDog and StatsD metrics support.
The solution is based on the same
go-kit/metrics
library as for Prometheus, except using the DataDog and StatsD providers. Given that there is a possible integration from DataDog being created by DataDog/integrations-extras#64, I've used the matching metric names to push the metrics to DD agent, as the Prometheus pull is mapping. Internally the DD agent puller is still pushing the collected data into DogStatsD listener, so it will end up flowing though the same ingestion gate, thus taking advantage of the "included integration metrics".I've had to add the additional dependencies into Glide, so after running
./scripts/glide.sh add <>
it has changed a bunch of files in the vendor, so hopefully that's done correctly.