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

fix!: activerecord find_by_sql spans on Rails 7.0+ #1184

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

mrsimo
Copy link

@mrsimo mrsimo commented Sep 26, 2024

For #1183

From my tests, using _query_by_sql to instrument is compatible with 7.0, 7.1 and 7.2, and is mostly equivalent to find_by_sql, with that one calling _query_by_sql itself. I believe this would be enough to bring back the same behavior we had in 6.1.

I am a bit conflicted with the name of these spans, since find_by_sql isn't entirely true anymore. Should they be called _query_by_sql in that case instead? Feels weird using the name of a private method, though. Should we do a more generic read or query? Help on this would be appreciated 😸

Thank you!!

Copy link

linux-foundation-easycla bot commented Sep 26, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

@mrsimo
Copy link
Author

mrsimo commented Oct 1, 2024

Sorry about those tests, somehow pushed a last minute thing that broke the build!

@kaylareopelle
Copy link
Contributor

Sorry about those tests, somehow pushed a last minute thing that broke the build!

No problem, @mrsimo! Taking a look at this now. It looks like there's one Rubocop offense preventing the active_record suite from passing: https://github.com/open-telemetry/opentelemetry-ruby-contrib/actions/runs/11132211056/job/30938815177?pr=1184#step:6:418

super
if ::ActiveRecord.version >= Gem::Version.new('7.0.0')
def _query_by_sql(...)
tracer.in_span("#{self}.find_by_sql") do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get what you're saying about the naming! If we change the name of the span, we should consider marking this update as a breaking change since all 7.0 spans would now have a new name.

I like your suggestion of query for 7.0+ spans since they don't roll up to find_by_sql.

Unfortunately, instrumentation often has to resort to private methods to get the data users want, so _query_by_sql probably wouldn't be too much of a shock and perhaps easier for a user to connect the dots.

I'd love to hear other opinions!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like query (or similar) would be the most stable for the future. Since we're hooking onto internal AR methods, it's possible we might need to change methods, needing a breaking change every time.

The downside is that all other spans being generated have the name of the method we're hooking into, so it would be a bit inconsistent. We could make it configurable?

As a user of this instrumentation I'd lean towards something more generic and stable. I usually have the mysql2 or trilogy spans with details about the exact query that ran, and as a developer I'd need to open the rails code to know what _query_by_sql even is. Even the find_by_sql was a bit confusing, I didn't know all reads (used to) go through that method.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I'm leaning toward query now too!

I hesitate to make it configurable. We have some configuration around span naming for ActiveSupport::Notifications in some of our Rails-related instrumentation gems, but in this scenario, since the span is not related to ActiveSupport::Notifications, I think having a single, consistent name would be best.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a change to use query instead of find_by_sql. Spans are now called User query, Account query, etc. I'm liking it!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to hear! Would you mind updating the PR title to mark this as a breaking change? I think this'll help anyone who uses find_by_sql in their observability backends know to update things accordingly.

It can be marked as a breaking change by updating the title to start with fix!: instead of fix:

If you don't think this should be a breaking change, let me know and we can discuss it further.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Totally agree that it's a breaking change.

Copy link
Contributor

@xuan-cao-swi xuan-cao-swi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

You can ignore this suggestions since it's just a preference

method_name = ::ActiveRecord.version >= Gem::Version.new('7.0.0') ? :_query_by_sql : :find_by_sql

define_method(method_name) do |*args, **kwargs|
  tracer.in_span("#{self} query") do
    super(*args, **kwargs)
  end
end

p.s. just checked active_record 3,4,5 and 6, they all use find_by_sql, so only 7+ they made big change, hopefully they won't do it again in 8 😁

@mrsimo
Copy link
Author

mrsimo commented Oct 4, 2024

Hey @xuan-cao-swi! Thanks for the suggestion! An error happens with that version:

ArgumentError: wrong number of arguments (given 3, expected 1..2)
    /Users/albert/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/activerecord-6.1.7.8/lib/active_record/querying.rb:46:in `find_by_sql'
    lib/opentelemetry/instrumentation/active_record/patches/querying.rb:25:in `block (2 levels) in <module:ClassMethods>'

I'm not very familiar with define_method, but seems to have some limitations compared to defining the method explicitly, since we can use (...) and call super without any parameters.

@xuan-cao-swi
Copy link
Contributor

Sorry, I should test it before make a comment. It's missing the key-like arguments. I updated my comments (with **kwargs)

@mrsimo mrsimo changed the title fix: activerecord find_by_sql spans on Rails 7.0+ fix!: activerecord find_by_sql spans on Rails 7.0+ Oct 14, 2024
@mrsimo
Copy link
Author

mrsimo commented Oct 14, 2024

@xuan-cao-swi cool! Pushed that change!

Copy link
Contributor

@kaylareopelle kaylareopelle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants