Add GraphQL::Tracing #917
Add GraphQL::Tracing #917
Conversation
…ects fix(FieldsWillMerge) handle input objects properly
feat(GraphQL.parse_file) add filename-aware parsing
Check if ActiveRecord::Relation is defined
…st satisfies [T!]
…list fix(VariableUsagesAreAllowed) a required variable inside a literal list satisfies [T!]
Sequel, contrarily to ActiveRecord, does not support `limit(0)` queries and raises a `Sequel::Error` instead. To fix this, we need to deal with this differently by using `where(false)` instead when we are attempting to perform a query for zero rows in Sequel.
Fix Sequel::Error when limit is 0
Use argument node instead of parent in ArgumentsAreDefined errors
Do not allow double non-null constraints
Validate enum names
Add a Travis build without Rails installed
without this, I was seeing: ``` TypeError: no implicit conversion of nil into String ```
Awesome! The amount of instrumentation is really nice and should help debug any performance issues easily. As discussed on the hackday yesterday there’s an issue with the way activesupport notifications are emitted that it’s difficult to see exactly what part of the query is causing the performance issues. This is because the graph tree is resolved breadth first. This means that the instrumentation does not follow the tree branches. If we have the following (multiplexed) queries: query {
viewer {
id
username
email
}
}
query userPageQuery($username: String!) {
user(username: $username) {
id
name
isViewer
username
trips {
id
title
subtitle
viewerCanEdit
header {
ratio
id
url
}
}
}
} It looks something like this in a performance monitoring tool. As you can see it’s very difficult to see what part of the query took the most time and looks very much like the second graph in @emilebosch ’s comment on issue #896 (comment) In order to create a better visualisation this we can re-order our instrumentation back into a tree-like structure. With the This example middleware below will build a hash that should represent the query structure above, based on the path in the notification context. class BetterInstrumentationMiddleware
def initialize(app, options = {})
@app = app
@options = options
@instrumentation = []
ActiveSupport::Notifications.subscribe(/.*/) do |*args|
@instrumentation << ActiveSupport::Notifications::Event.new(*args)
end
end
def call(env)
rack_result = @app.call(env)
nested_instrumentation = {}
current_path = []
# Loop over the instrumentation and check if there's a path array
# if there is one we can add it to our nested hash
# if there isn't we can assume this event happened in the current path
@instrumentation.each do |event|
current_path = event.payload[:context].try(:path) || current_path
# Set current branch to base
current_branch = nested_instrumentation
# Loop the paths and navigate to branch in our result hash
# if the branch is new, create a new hash for that branch
current_branch.each do |part|
current_branch = current_branch[part] ||= {}
end
current_branch['events'] ||= []
current_branch['events'].push(event)
end
@instrumentation = []
# Send it off to 3rd party monitoring
send_instrumentation(nested_instrumentation)
return rack_result
end
end The resulting hash would look something like this: {
"viewer" => {
"events" => [(events that happened when viewer was computed)],
"username" => {"events" => [(events that happened when viewer name was computed)]},
"id" => {"events" => [(events that happened when viewer id was computed)],
"email" => {"events" => [(events that happened when viewer email was computed)],
},
"user" => {
"events" => [(events that happened when user was computed)],
"id" => {"events" => [(events that happened when user id was computed)],
"name" => {"events" => [(events that happened when user name was computed)],
# and so on
}
} Adding this middleware, sending the I’m not entirely sure if/how we should handle this in the gem. I don’t think it’s possible to create something that re-emits the instrumentation in the right order, as other tools might be subscribed and would get all events twice. I think documenting these findings would be a good start, so anyone that wants to implement their own visualisation of the gem performance has an understanding of how to reproduce the tree. Another option could be that we create a helper that emits the query with all nested instrumentation, something that @emilebosch has done with his rails engine https://github.com/emilebosch/graphql-metrics. What do you think @rmosolgo |
@rmosolgo @matsimitsu Awesome work. I'd love to incorporate this tracing in the dashboard. This looks very nice @matsimitsu. Now its a bunched of hacked stuff together, but with this i think i can get quite far and make it look super pretty. Maybe its also cool to think about what we actually want to see:
I'm also thinking about the graphs that you might want to see. What's the low hanging fruit? |
update limits guide to include the context parameter
@matsimitsu @rmosolgo Cant we emit a query end notification, that has a method to get the query back in the right order? |
else | ||
@value = new_value | ||
end | ||
end |
rmosolgo
Aug 26, 2017
Author
Owner
Oops, this diff was added by mistake! I'll remove it.
Oops, this diff was added by mistake! I'll remove it.
Yes, let me take a look at these events and make a few changes:
|
Add default mutation field
…S::Notification conventions
I added |
@rmosolgo do you think it would be possible in the trace to highlight fields with a deprecation warning? Would be pretty useful IMO. |
Great! So all i need to do now is order them? Couldnt be easier!
…Sent from my iPhone
On 28 Aug 2017, at 21:58, Robert Mosolgo ***@***.***> wrote:
I added execute_multiplex which is the umbrella event for a call to Schema#execute or Schema#multiplex. When it finishes, you know everything is done!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@bdubaut I think you can use http://www.rubydoc.info/gems/graphql/GraphQL/Analysis/FieldUsage for that! |
GraphQL::Tracing
wraps gem internals so that subscribers can receive the metadata.TODO
.
in the active support key