-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Feature/datadog #411
Feature/datadog #411
Conversation
Hm, could you revert the core-js version bump there? I don't mind if you want me to update it/send a PR that does it, but it doesn't seem relevant to this PR. |
My biggest question wrt the design in general: is this specific to Datadog, or is it general-purpose for any StatsD server? I see that Datadog extended the StatsD protocol a bit, but are those changes portable to other servers? What I'd probably do is PR this as two collectors in one: one that just talks to a statsd server, one that wraps that one (with its own configuration/login) and talks specifically to datadog (hardcoding their statsd address, using their login system if any, etc.). |
AFIK the major difference is that dogstatsd extends statsd and adds tags. If tags are sent to a generic statsd server the server will output bad line packet. Taking the path of a double collector both implementations would be very similar varying only the ability to pass extra tags. |
I'd like it a lot if you did that, and then changed the environment variables, etc. of this collector to be datadog-specific (defaulting to their server address!), that'll avoid a lot of confusion. |
Of course, if you'd rather just contribute the datadog collector, that's fine too! |
Sure I can do that. Currently they still use the same ENVs but in order to avoid confusion I'll split them out. Just gets a bit tricky whilst trying to avoid duplication because both collectors a roughly the same. |
The cloud collector/executor (currently only on a feature branch) puts shared code in one place and the other is more like a skeleton that calls stuff from the other place, you could do something like that? |
Yep I'm not happy with my current implementation either, I'll have a look how the cloud bit is handled. |
Ah, |
Sure I've made that change. Anything else you see that needs improvement? |
Please don't change |
cmd/collectors.go
Outdated
collectorJSON = "json" | ||
collectorCloud = "cloud" | ||
collectorStatsD = "statsd" | ||
collectorDogStatsD = "dogstatsd" |
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.
Hm, I kinda feel like "datadog" would be a more obvious name here.
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 that the only benefit of having as datadog is that it's a shorter name, other than that statsd and dogstatsd makes more sense in terms of convention because in practice it's an implementation of a statsd protocol. Both implement statsd protocal but dogstatsd extends it. I believe is more transparent that way.
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.
What I'm thinking is that most people will come looking for "datadog" and instead find "dogstatsd", then get confused by what the difference is, while people who are running dogstatsd know what they're doing. I could be wrong.
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.
That's a fair point. Do you think that can be solved with documentation?
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.
Possibly, but I feel like it's better to avoid the confusion in the first place.
Unfortunately, a lot of people seem to really hate reading the effing manual.
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.
@liclac I've updated the collector name to be datadog
stats/dogstatsd/collector.go
Outdated
Config: conf, | ||
Logger: log.WithField("type", statsd.DogStatsD.String()), | ||
Type: statsd.DogStatsD, | ||
Tagger: tagHandler, |
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.
Wouldn't it be cleaner to do &TagHandler{}
here?
I don't see it used anywhere else in this function...
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.
Well spotted.
stats/dogstatsd/config.go
Outdated
import ( | ||
"encoding/json" | ||
|
||
statsd "github.com/loadimpact/k6/stats/statsd/shared" |
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.
common
as a package name would be more consistent with how the JS runner is organised.
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'll update
stats/statsd/collector.go
Outdated
Config: conf, | ||
Logger: log.WithField("type", statsd.StatsD.String()), | ||
Type: statsd.StatsD, | ||
Tagger: tagHandler, |
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 comment here, &TagHandler{}
here seems cleaner?
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.
Updated
stats/dogstatsd/config.go
Outdated
type Config ConfigFields | ||
|
||
// Address returns client address | ||
func (c Config) Address() 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.
Hm, why are these accessors? They don't seem to do anything.
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.
They are being used to normalise StatsD and DogStatsD config.
https://github.com/uswitch/k6/blob/cf72b91566cbd1dc886ad58ef0ff8f60c215f420/stats/statsd/common/config.go#L10
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.
Couldn't you use the same struct and just ignore the fields one doesn't use?
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.
Possible workaround:
// package shared
type Config {
Addr string `envconfig:"ADDR"`
}
// package statsd
type Config struct {
shared.Config `envconfig:"STATSD"`
}
// package dogstatsd
type Config struct {
shared.Config `envconfig:"DOGSTATSD"`
}
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.
hmm not sure about this. Just feels a bit weird and the interface solutions looks cleaner. What do you think the trade-off is here?
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.
Your version is… really verbose, and it's essentially solving a parsing problem by adapting the data, which feels backwards 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.
You could also do something like just setting envconfig:"ADDR"
and then using a different prefix in envconfig.Process()
.
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 agree, is really verbose. I think using process is a good idea, let me give it a go.
stats/statsd/shared/collector.go
Outdated
|
||
// Run the collector | ||
func (c *Collector) Run(ctx context.Context) { | ||
c.Logger.Debugf("%s: Running!", c.Type.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.
Use WithField()
/WithFields()
rather than Levelf()
.
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 sure what you mean here. Type is used to prefix the string not as a meta/tagging. I guess if that goes again't any project convention I'll have to change all of the other similar instances.
Getting there! The only big question I have is about the naming - Also: consider implementing |
@liclac What do you mean with k6 login datadog and statsd? There's no need to authenticate with statsd / dogstatsd. |
Huh, how do you push metrics to datadog in that case? (I've never used it before ^^;;) |
Ah! That makes sense. Maybe you could just add a login command that lets you specify a default endpoint? Because what saved credentials essentially do is just let you store default configs for when you just do |
That's a good point. In the case of passing an url I guess passing addr and port becomes redundant. What's the difference between constructing the url via |
@@ -56,8 +56,8 @@ func parseCollector(s string) (t, arg string) { | |||
} | |||
|
|||
func newCollector(t, arg string, src *lib.SourceData, conf Config) (lib.Collector, error) { | |||
loadConfig := func(out encoding.TextUnmarshaler) error { | |||
if err := envconfig.Process("k6", out); err != nil { | |||
loadConfig := func(out encoding.TextUnmarshaler, namespace string) error { |
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 added an extra arg to loadConfig func. What are the use cases for K6 env var?
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.
What do you mean?
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 extracted the hard-coded k6 string and made it a var that is set when the config is loaded. The question was to understand what are the use cases for k6 usage and if we would need to provide a k6+statsd / k6+datadog combination.
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, what I answered in my other 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.
I'm sorry, I'm not sure what the question is here... ^^;;
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.
^^:: No worries. Probably I'm just overcomplicating things. Are you happy with this change?
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.
Definitely!
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.
Honestly, at this point you could just change the loadConfig
calls to envconfig.Process
calls wholesale. That function basically existed to not have to type (and potentially typo "k6") all the time.
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 agree but I tried to keep it consistent to how was done before. Happy to do other PR to simplify loadConfig stuff.
Optimally, people should be able to use whichever one they prefer, and possibly whichever works better in the context they're working in. On my laptop, I have one local InfluxDB server, so I want to just be able to do |
stats/statsd/common/api.go
Outdated
@@ -0,0 +1,30 @@ | |||
package statsd |
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.
This package should be called common
.
StatsD - Basic statsd functionality (Count / TimeInMiliseconds / Gauge) DogStatsD - The same as StatsD + ability to send Tags
core/statsd contains a generic statsd implementation that stats/dogstatsd and stats/statsd extends. The collector implementation only contains the config for itself and the method to generate a new Container instance.
This reverts commit 3b43b6c.
accepted shape is ADDR:PORT
Codecov Report
@@ Coverage Diff @@
## master #411 +/- ##
==========================================
- Coverage 62.52% 62.43% -0.09%
==========================================
Files 89 89
Lines 6234 6246 +12
==========================================
+ Hits 3898 3900 +2
- Misses 2122 2132 +10
Partials 214 214
Continue to review full report at Codecov.
|
@ivoreis I'm going to have a look at this. What is still WIP so I know when testing? |
closed in favour of #893 |
I have a use case for this tool but I need to integrate with our current StatsD report tool.
The goal of this PR is to create a simple Datadog integration and it's still a WIP.
DogStatsD implements the StatsD protocol (doc)
Based on the feedback the idea is to provide 2 new collectors:
Usage:
Relates to #343, #196.
Feedback welcome :)