-
Notifications
You must be signed in to change notification settings - Fork 107
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: Query profiling feature #1221
feat: Query profiling feature #1221
Conversation
Copy paste over the files from the preview branch
Thread the query mode through the client library. Allow calls to get made using the query mode.
This code allows basic query profiling to work and creates a basic code snippet that can be used to make it work.
This will be useful for debugging grpc issues.
This mock server will be super useful for ensuring that the right data gets transmitted in private preview so that we can confirm the client library is working correctly.
We use the ts file instead.
See if Explain gets passed along to the mock server.
Protos.json is needed to pass the plan along.
Make sure changes don’t break the use of this callback by adding this test.
Define it with a more general data structure.
…into query-profiling-feature # Conflicts: # protos/google/datastore/v1/query_profile.proto # protos/protos.d.ts # protos/protos.js # protos/protos.json # src/v1/datastore_client.ts
The merge caused generated files to have a diff. The diff should not be in the PR.
only should not be used here
Data structures need to be added for the return values that contain stats.
Add stats to info if it is available. If there are no results then end the stream and send the info back. This way, stats will always be sent in info if they are available and the program won ’t break if there are no results.
Explain what happens when the result set is empty. Just send the stats back.
The mock server code was used for debugging and now we don’t need it since the service is working.
Calls to nightly don’t have a second database to work with. Regular calls work now so nightly calls are not necessary.
Bring the query profiling tests back.
This reverts commit 040d0a5.
Stats do not necessarily come from the server.
Each query profiling mode needs to be explored.
Stats returned needs to be parsed by a special library that will remove the complexities of the Struct object.
A library is needed for parsing the Struct values. Add the libraries and use them.
src/query.ts
Outdated
resultsReturned?: number; | ||
executionDuration?: google.protobuf.IDuration; | ||
readOperations?: number; | ||
debugStats?: JSONValue; |
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 Java we made this a Map. Is there a reason why we are using this specific type?
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 client library doesn't typically return Map
objects. It usually returns dictionaries when an object needs to be returned that maps keys to values. For example, an interface like { [key: string]: any };
.
The issue here is that the values coming from the server are of type google.protobuf.IStruct
and the serializer.toProto3JSON
function is used to decode these types returning a JSONValue
type which is stored in debugStats. The compiler only guarantees the value will be a JSONValue
, but in practice a { [key: string]: any };
type should always be returned.
We can change the return type to { [key: string]: any };
and the compiler won't complain because we are using Object.assign
so maybe we should do that. What do you think?
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 works, would like a NodeJS opinion however :)
} | ||
export interface ExecutionStats { | ||
resultsReturned?: number; | ||
executionDuration?: google.protobuf.IDuration; |
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.
similar here, could this just be a numeric value? Are there other already modeled fields that are similar? What are their return 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.
When a time is provided by the user then just a number representing milliseconds is provided and parsed here to match the proto. However, when commit returns a commitTime then it is passed back to the user as is. go/cfdb-ds-go-query-profiling returns a duration object like this according to the design doc so I think this should stay as is to match Golang and other return 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.
sg, would appreciate @sofisl's thoughts on this 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.
For both types, I think this is OK given that this is exactly what is returned from the service and what other languages are doing. However as I was mentioning to @danieljbruce, I think it's worth showing users how to transform these values in samples, which will be in a separate PR.
package.json
Outdated
@@ -48,6 +48,8 @@ | |||
"extend": "^3.0.2", | |||
"google-gax": "^4.0.5", | |||
"is": "^3.3.0", | |||
"proto3-json-serializer": "^2.0.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 are pretty big additions. We use protobufjs & proto3-json-serializer in google-gax, is it possible to just use it from there?
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. Great suggestion.
This PR implements Query Profiling in Node Datastore.
Changes:
Two dependencies are imported that are used for decoding structs contained in query profiling explain metrics into a flatter format that matches other clients.
A getInfoFromStats function is added that translates the explain metrics from the server into a format that the user will see. A query mode enum is added and offered to the user. Interfaces are added for explain metrics, the plan and the execution stats. runAggregationQuery and runQuery functions are modified to send info back to the user that contains explain metrics. System tests and unit tests are added as well.
Not included:
Note that this PR does not include query profiling samples. Samples must be included in a separate PR because the samples use
require('@google-cloud/datastore')
which fetches the latest released version of the client library. Therefore, we must release the query profiling feature first before query profiling samples will work in this PR because we are following the convention other samples follow where the latest release is used for samples.