Integrate with ActiveRecord::QueryLogs (old marginalia)
mrcasals opened this issue · 7 comments
Is your feature request related to a problem? Please describe.
ActiveRecord::QueryLogs
(the old marginalia
gem, now bundled in Rails 7) allow us to add comments on SQL queries to detect where is the query triggered from (what controller and action). But when using GraphQL, the comment becomes useless because it's always the same controller and action, so we become blind.
Describe the solution you'd like
ActiveRecord::QueryLogs allow for customization so we could add the current GraphQL query being resolved.
Describe alternatives you've considered
None.
Additional context
None.
Hey, thanks for the suggestion! I think that's a great idea. Here's how you could add that in your own app in the meantime:
# In your Application setup:
config.active_record.query_log_tags = [
# Rails default keys:
:application, :controller, :action, :job,
# Tell QueryLogs about this new key:
{ graphql_query: -> { Current.graphql_query_names } }
]
# Assuming `class Current < ActiveSupport::CurrentAttributes` as in https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html
# Substitute your own global state object as-needed
module ActiveRecordQueryLogsTrace
def execute_multiplex(multiplex:)
Current.graphql_query_names = multiplex.queries.map { |q| q.selected_operation&.name || "anonymous" }
end
end
I think that would tag ActiveRecord queries with the currently running operation(s). Is that what you had in mind?
A deeper integration is also possible, for example, tagging SQL with the currently-running Dataloader::Source or GraphQL field.
This looks good, I'm trying to adapt it to my code because I'm using an old version of the gem, v2.0.14 (sorry, forgot to mention it!). I'm guessing the ActiveRecordQueryLogsTrace
module would be used with trace_with(ActiveRecordQueryLogsTrace)
in the latest version, so I should use tracer(ActiveRecordQueryLogsTrace)
there and adapt it, I'll get back to you!
Thanks!
Here's an approach that would work in 2.0.x:
# Assuming `class Current < ActiveSupport::CurrentAttributes` as in https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html
# Substitute your own global state object as-needed
module ActiveRecordQueryLogsInstrumenter
def self.begin_multiplex(multiplex)
Current.graphql_query_names = multiplex.queries.map { |q| q.selected_operation&.name || "anonymous" }
end
def self.end_multiplex(_multiplex); end
end
# ...
class MySchema < GraphQL::Schema
instrument(:multiplex, ActiveRecordQueryLogsInstrumenter
end
(The instrument(...)
API was merged into trace_with
in recent versions.)
Awesome, it works! Thanks! I just had to change the method names, they should be before_multiplex
and after_multiplex
, but apart from that everything works fine! Thank you so much ❤️
I'll leave the issue open in case you want to track it to automatically add intergration with QueryLogs, but feel free to close it if needed!
Hello @rmosolgo, it seems that in your example (#4946 (comment)), super
needs to be called.
Like this:
# In your Application setup:
config.active_record.query_log_tags = [
# Rails default keys:
:application, :controller, :action, :job,
# Tell QueryLogs about this new key:
{ graphql_query: -> { Current.graphql_query_names } }
]
# Assuming `class Current < ActiveSupport::CurrentAttributes` as in https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html
# Substitute your own global state object as-needed
module ActiveRecordQueryLogsTrace
def execute_multiplex(multiplex:)
Current.graphql_query_names = multiplex.queries.map { |q| q.selected_operation&.name || "anonymous" }
super
end
end
v2.3.11 will include a new module, GraphQL::Current
with some helpers for this: https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/current.rb. Thanks again for the suggestion!
Awesome! this is gonna be very helpful for debugging, thank you ❤ Glad the suggestion was useful!