-
Notifications
You must be signed in to change notification settings - Fork 375
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
Correctly set rails.cache.backend
span tag for multiple stores
#3060
Conversation
rails.cache.backend
for multiple storesrails.cache.backend
span tag for multiple stores
rails.cache.backend
span tag for multiple storesrails.cache.backend
span tag for multiple stores
# The name of the store is never saved anywhere. | ||
# ActiveSupport looks up stores by converting a symbol into a 'require' path: | ||
# https://github.com/rails/rails/blob/261975dbef77731d2c76f907f1076c5132ebc0e4/activesupport/lib/active_support/cache.rb#L139-L149 | ||
# | ||
# Given we are inside the store object itself, we can reverse engineer | ||
# the `require` path by converting the class name to snake case: | ||
# e.g. ActiveSupport::Cache::RedisStore -> active_support/cache/redis_store | ||
# | ||
# We only care about the last part of the path, but it's easier to convert | ||
# the whole class name then extract the last part. | ||
store: self.class.name.underscore.match(/active_support\/cache\/(.*)/)[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.
Nice, I think with sufficient repetitions, we should be confident to extract this.
Gemfile
Outdated
end | ||
end | ||
# This file was generated by Appraisal | ||
|
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.
Could you elaborate on why the need for this change? Should we extract this change into a separate PR?
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.
Sorry, @GustavoCaso, because it's a draft PR, I make a bunch of mess before getting it ready.
Mucking about with the Gemfile makes my testing easier locally.
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 also push my changes at the end of day in case my laptop explodes overnight.
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 also push my changes at the end of day in case my laptop explodes overnight.
Good call
# (only `RedisStore`, and not `ActiveSupport::Cache::RedisStore`) | ||
# the easiest way to retrieve the store symbol is to convert the fully qualified | ||
# name using Rails-provided methods, then extracting the last part. | ||
store: self.class.name.underscore.match(/active_support\/cache\/(.*)/)[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.
Would using regex for each command executed on the cache cause performance issues for the customer's application?
We could memoize the result on an instance variable
def store_name
return @store_name if defined?(@store_name)
@store_name = self.class.name.underscore.match(/active_support\/cache\/(.*)/)[1]
@store_name
end
Also, we always are getting the last portion of the match. Could we use split(''/'').last
rather than a regex?
def store_name
return @store_name if defined?(@store_name)
@store_name = self.class.name.underscore.split('/').last
@store_name
end
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.
Should we add a comment to explain that underscore
is from Rails::ActiveSupport
and that this codes works because is executed within the context of Rails
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.
Caching is great, I made those changes.
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.
Regarding "split+last" vs regex, I'm keeping the regex because it's the version that more closely mirrors ActiveSupport's logic (require "active_support/cache/#{store}"
).
And because we are only doing it once, as we are now caching, the performance impact will be almost nil.
I noticed that on the
Since we are changing related files, should we update it? Since that change is not related to the main purpose of the PR, fell free to ignore it |
This is because there's a conditional override for that method, depending if the gem https://github.com/redis-store/redis-activesupport is installed or not. It's still needed for such compatibility: dd-trace-rb/lib/datadog/tracing/contrib/active_support/cache/redis.rb Lines 31 to 37 in 94158db
|
Thanks for the context. It would be nice to note that rails 5.2.0+ has redis cache support. Maybe adding a comment that once we do not support old Rails version we can remove such code 😄 |
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.
LGTM
@GustavoCaso I documented this in code, good call! |
This fails for custom stores that are not in |
What does this PR do?
This PR fixes the span tag
rails.cache.backend
inrails.cache
spans to correctly represent the cache store object being instrumented.Motivation
Today, we always set
rails.cache.backend
toRails.configuration.cache_store
, which is a global application value.This works correctly for applications with a single cache store, but incorrectly reports this tag when multiple stores are used.
Additional Notes
How to test the change?
All changes are covered by testing.