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
EVG-5410 Add functions to query execution statistics #1744
Conversation
} | ||
|
||
// Returns the sort order specification (1, -1) for the date field corresponding to the Sort value. | ||
func sortDateOrder(sort Sort) int { |
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 it make sense to make this a method on Sort?
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 this is database specific, I have a preference for leaving it 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'm not sure what "database specific" means?
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 value returned, 1 or -1, is destined specifically to be the value of the "date" field in the aggregation pipeline's $sort stage.
model/stats/query.go
Outdated
) | ||
|
||
type GroupBy string | ||
type Sort 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.
should we use iotas here? are we using the string form 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.
The string values are not used. We could use iotas as well.
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 need to be exported? Do you have a validation method on these types to ensure that they have valid values?
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.
Yes, the types are part of the API. The validation is currently done in the validate() method of the StatsFilter but we might want to move it to method directly on these types.
model/stats/query.go
Outdated
if len(f.Tasks) == 0 { | ||
catcher.Add(errors.New("Missing Tasks values")) | ||
} | ||
} |
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't we avoid needing to pass a bool to the validate function but just inferring from the state of the filter?
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 bool indicates what the intended use is, I don't think we'd want to infer it from the filter itself. We could include the bool in the filter but we'd have to check that its value matches its usage anyway.
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 very much in favor of moving the bool out of the function arguments, in whatever way makes the most 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.
I replaced the bool with two validate methods, one for use with tests stats, one for use with task stats.
fields = []string{"_id.date", "_id.variant", "_id.task_name", "_id.test_file", "_id.distro"} | ||
operators = []string{dateOperator, "$gt", "$gt", "$gt", "$gt"} | ||
values = []interface{}{filter.StartAt.Date, filter.StartAt.BuildVariant, filter.StartAt.Task, filter.StartAt.Test, filter.StartAt.Distro} | ||
} |
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.
Is there anything that validates that we've specified the right number of arguments to each. It seems really easy to make a change here and get very different semantics. Seems like the operators are "whatever the date operator is plus $gt until the 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 created a struct to combine the field, operator and value, and now pass a array of the struct.
fields = []string{"_id.date", "_id.variant", "_id.task_name", "_id.distro"} | ||
operators = []string{dateOperator, "$gt", "$gt", "$gt"} | ||
values = []interface{}{filter.StartAt.Date, filter.StartAt.BuildVariant, filter.StartAt.Task, filter.StartAt.Distro} | ||
} |
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 above comment.
suite.Suite | ||
} | ||
|
||
func TestStatsQuerySuite(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.
I think this suite is probably a little too large: the test cases are very large, and it might be better to have some state on the suite object and then reset it in a setupTest fixture to make it easier to test, and more importantly debug fixtures if they 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.
Done.
model/stats/query.go
Outdated
NumTestFailed int `bson:"num_test_failed" json:"num_test_failed"` | ||
NumSystemFailed int `bson:"num_system_failed" json:"num_system_failed"` | ||
NumSetupFailed int `bson:"num_setup_failed" json:"num_setup_failed"` | ||
AvgDurationSuccess float32 `bson:"avg_duration_success" json:"avg_duration_success"` |
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.
mongodb doesn't have 32 bit floats, so lets keep this as float64 just to avoid weirdness.
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.
model/stats/db.go
Outdated
"date": 1, | ||
"requester": 1, | ||
{"$sort": bson.D{ | ||
{Name: "project", Value: 1}, |
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.
These should use ProjectKey
, etc., as should the rest of this 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.
Done.
model/stats/db.go
Outdated
// Queries on the precomputed statistics // | ||
/////////////////////////////////////////// | ||
|
||
// Creates an aggregation pipeline to query test statistics. |
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.
Comments on should be of the form <functionName> ...
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.
model/stats/db.go
Outdated
return id | ||
} | ||
|
||
// Edits a match expression to include that the 'fieldName' field must have its value in 'values'. |
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.
Delete?
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.
Yes. Done.
// } | ||
//} | ||
|
||
func buildMatchArrayExpression(values []string) interface{} { |
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.
Should this return a bson.M
?
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 can also return a string.
model/stats/db.go
Outdated
return buildPaginationOrBranches(fields) | ||
} | ||
|
||
// Creates an aggregation pipeline to query task statistics. |
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.
Nit: Comment style for this function and below.
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.
model/stats/query.go
Outdated
return catcher.Resolve() | ||
} | ||
|
||
// Represents search and aggregation parameters when querying the test or task statistics. |
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.
Comment style is especially important for public types.
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.
model/stats/query.go
Outdated
BeforeDate: before, | ||
Tests: tests, | ||
Tasks: tasks, | ||
BuildVariants: 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.
No need to explicitly set fields that are the zero value.
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 function has been removed.
|
||
// Queries the precomputed task statistics using a filter. | ||
func GetTaskStats(filter *StatsFilter) ([]TaskStats, error) { | ||
err := filter.validateForTasks() |
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.
nil check?
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 in the validation method.
@@ -147,9 +147,13 @@ db.notifications.ensureIndex({ "sent_at": 1 }) | |||
|
|||
//======hourly_test_stats======// | |||
db.hourly_test_stats.createIndex({ "_id.date": 1 }, { expireAfterSeconds: 26 * 7 * 24 * 3600 }) // 26 weeks TTL | |||
db.hourly_test_stats.createIndex({ "_id.project": 1 }, { "_id.requester": 1}, {"_id.task_name": 1}, {"_id.date": 1}) |
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.
Is there a ticket open for these indexes?
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.
Yes, they are in the existing ticket.
model/stats/query.go
Outdated
|
||
type GroupBy string | ||
|
||
func (gb *GroupBy) validate() 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 think it's not correct that these are pointer-recievers. Given that they're strings, I think we just remove some *
characteers and this all gets better.
model/stats/query.go
Outdated
case GroupByTask: | ||
case GroupByTest: | ||
default: | ||
return errors.Errorf("Invalid GroupBy value: %v", *gb) |
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 %s
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.
model/stats/query.go
Outdated
func GetTaskStats(filter *StatsFilter) ([]TaskStats, error) { | ||
err := filter.validateForTasks() | ||
if err != nil { | ||
return nil, err |
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 not wrap this 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.
Done.
Rebase on top of master (fa5b44e). Split tests into smaller units. Use struct for pagination fields. Update validation methods. Avoid mutable parameter in match stage construction.
Remove NewDefaultStatsFilter constructor Use float64 instead of float32 Remove json tags Remove unused code Update comments to match conventions Check nil in validateCommon methods
No description provided.