-
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
Adding run tags option, apply default tags to all samples per run #553
Adding run tags option, apply default tags to all samples per run #553
Conversation
Codecov Report
@@ Coverage Diff @@
## master #553 +/- ##
==========================================
+ Coverage 62.3% 62.87% +0.57%
==========================================
Files 96 96
Lines 7191 7221 +30
==========================================
+ Hits 4480 4540 +60
+ Misses 2445 2429 -16
+ Partials 266 252 -14
Continue to review full report at Codecov.
|
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.
Thanks! Looks mostly good, I think that only some fixes in the tests are necessary and to establish the tag precedence.
@robingustafsson, @luizbafilho: please take a look as well when you have some time
core/engine.go
Outdated
} | ||
|
||
for k, v := range e.Options.RunTags { | ||
samples[i].Tags[k] = v |
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'm not sure what the precedence for the tags should be. If the user specifies a tag with --run-tags mytag=myval1
and then has export let options = { runTags : {mytag: "myval2"} }
and http.get("https://httpbin.org/", { tags: { mytag: "myval3" } });
in the code, what tag value should be emitted? I think the order should be myval3
, if not present myval1
, finally (with the least priority) myval2
, but I'm not completely sure that's the correct approach.
@robingustafsson: thoughts?
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, yeah I think the cascading order should be Request level -> CLI -> Env vars -> Options -> Config file (where -> means it overrides whatever is on the right). So more or less the same as we do already, besides the request-level case: https://github.com/loadimpact/k6/blob/master/cmd/run.go#L140
The only reason I can think of why the request level should not override all other possible option inputs is that you won't be able to override it from outside of the script (using CLI or Env vars). However, in reality that might not be an issue as one can argue that if you have specified a tag on the request level it's probably for a very good reason.
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.
Yeah, agree, and you can "override" tags you've specified at the request level from the CLI if you just use environment variables in the code tags 🙂
So here the for loop should check if Tags[k]
is present before saving the value, I think that should be enough.
core/engine_test.go
Outdated
}() | ||
|
||
for !c.IsRunning() { | ||
time.Sleep(time.Millisecond) |
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.
See the notes about the IsRunning()
method below, this should be refactored. Or possibly removed, I'm not sure if it's even needed and if we actually need to have a context, cancel it, Run()
the collector and check when it finishes... This is a test and we know it's the Dummy
collector anyway, so can't we skip all of that?
core/engine_test.go
Outdated
|
||
//wait for the collector to start running | ||
for !c.IsRunning() { | ||
time.Sleep(time.Millisecond) |
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 applies here as in the comment above
stats/dummy/collector.go
Outdated
|
||
// IsRunning returns the current status of the collector | ||
func (c *Collector) IsRunning() bool { | ||
return c.running |
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 will cause a race condition since it doesn't lock (see Run()
), but that's beside the point. Generally in Go it's not a very good idea to have methods like this, because the only way they can be used is with continuous polling, like you've done with the time.Sleep(time.Millisecond)
, and it's also easier to introduce race conditions. It's much, much better to use channels or something like sync.WaitGroup
(or even sync.Cond
for particularly tricky cases) for this type of synchronization.
opts := Options{}.Apply(Options{SummaryTrendStats: stats}) | ||
assert.Equal(t, stats, opts.SummaryTrendStats) | ||
}) | ||
t.Run("RunTags", func(t *testing.T) { |
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.
All of the other changes besides this one are out of the scope for this pull request. I don't mind very much, but ideally they should have been in a separate PR, which I would have reviewed and merged in a few minutes. Now they have to wait for the other more complicated things here to be fixed, and they clutter the code review and confuse the commit history a bit.
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, separate PR would have been better for other tests. I can remove them from this PR if necessary.
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 I said, I don't mind all that much and they're already part of the history anyway. At this point I think it's better to leave them as they are, since the alternatives are to either force push the branch or create a new pull request from a new branch (and loose the context and comments already here)
@@ -52,7 +52,9 @@ func TestCollectorCollect(t *testing.T) { | |||
ctx, cancel := context.WithCancel(context.Background()) | |||
defer cancel() | |||
go func() { c.Run(ctx) }() | |||
time.Sleep(1 * time.Millisecond) |
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, it's not good that there was a sleep here, I think that I will probably have to refactor the Dummy
collector a bit... The whole running
variable should probably go, it shouldn't be needed since we have the context
...
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 about the Dummy
collector, I have mentioned the issue here: #469 (comment)
Changing it would avoid all the "subpar" changes I made to the tests in order to get them to work.
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, I missed this comment before posting again in the general PR thread. OK, I'm convinced we should refactor the Dummy
collector. Not sure if my suggestion with using a channel instead of a Sample
slice is the best way to go about it, but I don't have any other ideas.
Maybe we can just remove the running
check with panic()
for this pull request and create a new issue and PR for the actual Dummy
collector refactoring... @robingustafsson?
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.
One idea is to change the Dummy
collector implementation by adding a buffered channel to signal the running start and use that instead of the polling solution in the tests. That should get rid of the nastiness in there and we can refactor the rest in a separate PR.
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 not sure we actually need to signal anything, the dummy collector is used just for tests, so we basically just have to have an easy way to read the collected samples. I think that we could just replace the current []stats.Sample
with a Samples
channel (buffered or not, both could be useful and the buffer size will be supplied when the dummy collector is created anyway) for stuffing the results in the collector and reading them outside with range
. When the context is closed, close the Samples
channel an that's that.
But that should probably be a part of another PR for #469 or for a new issue. Do you think that simply removing this check temporarily (before that other PR is created) will be enough so we don't need all of that nasty polling and sleep?
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 guess so. And I would have to change the stats/dummy/collector_test.go test file. That would fix the issue on #469 as well.
Looking at this a bit more closely, I'm not sure if you can easily get rid of all of the polling and sleep with how the dummy collector currently works. I think that maybe we should refactor the dummy collector to actually use an (optionally buffered) It's probably also worth it to investigate how the collectors are used in general and see if some refactoring of the |
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 now, I'll add a note to #469 about the fixes of the Dummy collector we discussed here
The code LGTM, well done @antekresic! The only issue I have is with the naming and CLI UX :) I think Another thing I started thinking about is consistency in the CLI. This option is implemented in plural form ( Singular:
Plural:
What are your thoughts on this? |
Always the hardest part, naming things :) Looking at all the options of the For instance, At the end of the day, for me, it all comes down to consistency. Pick a rule and stick to it :) |
Closes #461
I changed the option name to
--run-tags
to keep consistent with the new--system-tags
option.--tags
looked to general.