Skip to content
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

feat(datastore): Add query profiling #9200

Merged
merged 23 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
730d947
feat(datastore): Query profiling
bhshkh Dec 18, 2023
5825267
feat(datastore): remove comment
bhshkh Dec 18, 2023
bf802dc
Merge branch 'main' into feature/ds-query-profiling
bhshkh Dec 27, 2023
4d8a1f1
feat(datastore): Refactor test
bhshkh Dec 27, 2023
1f507c6
Merge branch 'main' into feature/ds-query-profiling
bhshkh Jan 10, 2024
4276f61
feat(datastore): Refactor integration test
bhshkh Jan 17, 2024
8420179
Merge branch 'main' into feature/ds-query-profiling
bhshkh Feb 13, 2024
21923dc
feat(datastore): Use ExplainOptions instead of QueryMode
bhshkh Feb 14, 2024
365c625
feat(datastore): Refactoring code
bhshkh Feb 14, 2024
5033f50
feat(datastore): Additional comments
bhshkh Feb 14, 2024
ac60830
feat(datastore): Resolving vet failures
bhshkh Feb 14, 2024
252f0e9
Merge branch 'googleapis:main' into feature/ds-query-profiling
bhshkh Mar 18, 2024
f0ba17f
feat(datastore): Updating to match latest protos
bhshkh Mar 18, 2024
edb28f2
Merge branch 'main' into feature/ds-query-profiling
bhshkh Apr 8, 2024
54e092d
feat(datastore): Add RunWithOptions
bhshkh Apr 9, 2024
1cfdc14
Merge branch 'main' into feature/ds-query-profiling
bhshkh Apr 17, 2024
6f9f76a
fix(datastore): Resolving vet failures
bhshkh Apr 18, 2024
cf4823b
Merge branch 'main' into feature/ds-query-profiling
bhshkh Apr 18, 2024
0ceff9f
Merge branch 'main' into feature/ds-query-profiling
bhshkh Apr 18, 2024
6d23653
doc(datastore): Adde comment for preview feature
bhshkh Apr 18, 2024
700e3a1
feat(datastore): Correcting the error message
bhshkh Apr 22, 2024
144e73e
Merge branch 'main' into feature/ds-query-profiling
bhshkh May 7, 2024
4730d3e
feat(datastore): Resolving test failures
bhshkh May 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
164 changes: 80 additions & 84 deletions datastore/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"cloud.google.com/go/internal/testutil"
"cloud.google.com/go/internal/uid"
"cloud.google.com/go/rpcreplay"
"github.com/google/go-cmp/cmp/cmpopts"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
pb "google.golang.org/genproto/googleapis/datastore/v1"
Expand Down Expand Up @@ -1005,6 +1006,7 @@
"i_avg": &pb.Value{ValueType: &pb.Value_DoubleValue{DoubleValue: 2}},
"count": &pb.Value{ValueType: &pb.Value_IntegerValue{IntegerValue: 3}},
}

testCases := []struct {
desc string
wantFailure bool
Expand All @@ -1013,59 +1015,46 @@
opts []RunOption
}{
{
desc: "No mode",
desc: "No options",
wantRes: AggregationWithOptionsResult{
Result: wantAggResult,
},
},
{
desc: "Normal mode",
desc: "ExplainOptions.Analyze is false",
wantRes: AggregationWithOptionsResult{
Result: wantAggResult,
},
opts: []RunOption{QueryModeNormal},
},
{
desc: "Explain mode",
wantRes: AggregationWithOptionsResult{
Stats: &ResultSetStats{
QueryPlan: &QueryPlan{
PlanInfo: map[string]interface{}{
"indexes_used": []interface{}{
map[string]interface{}{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
Plan: &Plan{
IndexesUsed: []*map[string]interface{}{
{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
},
},
opts: []RunOption{QueryModeExplain},
opts: []RunOption{ExplainOptions{}},
},
{
desc: "ExplainAnalyze mode",
desc: "ExplainAnalyze.Analyze is true",
wantRes: AggregationWithOptionsResult{
Result: wantAggResult,
Stats: &ResultSetStats{
QueryPlan: &QueryPlan{
PlanInfo: map[string]interface{}{
"indexes_used": []interface{}{
map[string]interface{}{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
Plan: &Plan{
IndexesUsed: []*map[string]interface{}{
{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
QueryStats: map[string]interface{}{
},
ExecutionStats: &ExecutionStats{
ResultsReturned: 1,
DebugStats: &map[string]interface{}{
"documents_scanned": "0",
"index_entries_scanned": "3",
"results_returned": "1",
},
},
},
opts: []RunOption{QueryModeExplainAnalyze},
opts: []RunOption{ExplainOptions{Analyze: true}},
},
}

Expand All @@ -1081,7 +1070,11 @@
return
}

if err := isEqualResultSetStats(gotRes.Stats, testcase.wantRes.Stats); err != nil {
if !testutil.Equal(gotRes.Plan, testcase.wantRes.Plan) {
t.Errorf("%v Plan: got: %+v, want: %+v", testcase.desc, gotRes.Plan, testcase.wantRes.Plan)
}

if err := isEqualExecutionStats(gotRes.ExecutionStats, testcase.wantRes.ExecutionStats); err != nil {
r.Errorf("%q: Mismatch in stats %+v", testcase.desc, err)
}
})
Expand Down Expand Up @@ -1432,62 +1425,51 @@
}

type runWithOptionsTestcase struct {
desc string
wantKeys []*Key
wantStats *ResultSetStats
wantEntities []SQChild
opts []RunOption
desc string
wantKeys []*Key
wantExecutionStats *ExecutionStats
wantPlan *Plan
wantEntities []SQChild
opts []RunOption
}

func getRunWithOptionsTestcases(ctx context.Context, t *testing.T, client *Client, partialNameKey string, count int) ([]runWithOptionsTestcase, int64, *Key, func()) {
keys, entities, now, parent, cleanup := createTestEntities(ctx, t, client, partialNameKey, count)
return []runWithOptionsTestcase{
{
desc: "No mode",
desc: "No ExplainOptions",
wantKeys: keys,
wantEntities: entities,
},
{
desc: "Normal query mode",
opts: []RunOption{QueryModeNormal},
wantKeys: keys,
wantEntities: entities,
},
{
desc: "Explain query mode",
opts: []RunOption{QueryModeExplain},
wantStats: &ResultSetStats{
QueryPlan: &QueryPlan{
PlanInfo: map[string]interface{}{
"indexes_used": []interface{}{
map[string]interface{}{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
desc: "ExplainOptions.Analyze is false",
opts: []RunOption{ExplainOptions{}},
wantPlan: &Plan{
IndexesUsed: []*map[string]interface{}{
{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
},
},
{
desc: "ExplainAnalyze query mode",
opts: []RunOption{QueryModeExplainAnalyze},
desc: "ExplainAnalyze.Analyze is true",
opts: []RunOption{ExplainOptions{Analyze: true}},
wantKeys: keys,
wantStats: &ResultSetStats{
QueryPlan: &QueryPlan{
PlanInfo: map[string]interface{}{
"indexes_used": []interface{}{
map[string]interface{}{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
},
},
QueryStats: map[string]interface{}{
wantExecutionStats: &ExecutionStats{
bhshkh marked this conversation as resolved.
Show resolved Hide resolved
ResultsReturned: 1,
DebugStats: &map[string]interface{}{
"documents_scanned": "3",
"index_entries_scanned": "3",
"results_returned": "3",
},
},
wantPlan: &Plan{
IndexesUsed: []*map[string]interface{}{
{
"properties": "(T ASC, I ASC, __name__ ASC)",
"query_scope": "Includes Ancestors",
},
},
},
wantEntities: entities,
Expand All @@ -1514,7 +1496,10 @@
if !testutil.Equal(gotRes.Keys, testcase.wantKeys) {
t.Errorf("%v keys: got: %+v, want: %+v", testcase.desc, gotRes.Keys, testcase.wantKeys)
}
if err := isEqualResultSetStats(gotRes.Stats, testcase.wantStats); err != nil {
if !testutil.Equal(gotRes.Plan, testcase.wantPlan) {
t.Errorf("%v Plan: got: %+v, want: %+v", testcase.desc, gotRes.Plan, testcase.wantPlan)
}
if err := isEqualExecutionStats(gotRes.ExecutionStats, testcase.wantExecutionStats); err != nil {
t.Errorf("%v %+v", testcase.desc, err)
}
}
Expand Down Expand Up @@ -1544,28 +1529,39 @@
if !testutil.Equal(gotSQChildsFromRun, testcase.wantEntities) {
t.Errorf("%v entities: got: %+v, want: %+v", testcase.desc, gotSQChildsFromRun, testcase.wantEntities)
}
if err := isEqualResultSetStats(iter.Stats, testcase.wantStats); err != nil {
if !testutil.Equal(iter.Plan, testcase.wantPlan) {
t.Errorf("%v Plan: got: %+v, want: %+v", testcase.desc, iter.Plan, testcase.wantPlan)
}
if err := isEqualExecutionStats(iter.ExecutionStats, testcase.wantExecutionStats); err != nil {
t.Errorf("%v %+v", testcase.desc, err)
}
}
}

func isEqualResultSetStats(got *ResultSetStats, want *ResultSetStats) error {
func isEqualExecutionStats(got *ExecutionStats, want *ExecutionStats) error {
if (got != nil && want == nil) || (got == nil && want != nil) {
return fmt.Errorf("Stats: got: %+v, want: %+v", got, want)
return fmt.Errorf("ExecutionStats: got: %+v, want: %+v", got, want)
}
if got == nil {
return nil
}
if got != nil {
if !testutil.Equal(got.QueryPlan, want.QueryPlan) {
return fmt.Errorf("Stats.QueryPlan.PlanInfo: got: %+v, want: %+v", got.QueryPlan, want.QueryPlan)
}

for wantK, wantV := range want.QueryStats {
gotV, ok := got.QueryStats[wantK]
if !ok || !testutil.Equal(gotV, wantV) {
return fmt.Errorf("Stats.QueryPlan.QueryStats: got: %+v, want: %+v", got.QueryStats, want.QueryStats)
}
// Compare all fields except DebugStats
if !testutil.Equal(want, got, cmpopts.IgnoreFields(&ExecutionStats{}, "DebugStats")) {
return fmt.Errorf("ExecutionStats: mismatch (-want +got):\n%s:", testutil.Diff(want, got, cmpopts.IgnoreFields(&ExecutionStats{}, "DebugStats")))

Check failure on line 1551 in datastore/integration_test.go

View workflow job for this annotation

GitHub Actions / vet

error strings should not be capitalized or end with punctuation or a newline
}

// Compare DebugStats
gotDebugStats := *got.DebugStats
for wantK, wantV := range *want.DebugStats {
// ExecutionStats.Debugstats has some keys whose values cannot be predicted. So, those values have not been included in want
// Here, compare only those values included in want
gotV, ok := gotDebugStats[wantK]
if !ok || !testutil.Equal(gotV, wantV) {
return fmt.Errorf("ExecutionStats.DebugStats: wantKey: %v gotValue: %+v, wantValue: %+v", wantK, gotV, wantV)
}
}

return nil
}

Expand Down