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

add otel instrumentation #161

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

add otel instrumentation #161

wants to merge 4 commits into from

Conversation

bmansoob
Copy link
Contributor

We recently integrated profiling with tracing and the feedback we have gotten is quite encouraging.

The ability to see traces and profiles side by side is something internal users have asked for sometime now. To that end, It makes sense to integrate tracing and profiling here in the gem - to avoid repetitive rework in clients.

This PR adds a new otel_instrumentation_enabled as a new config option. It can only be enabled if OpenTelemetry::Instrumentation::Rack is loaded. app_profiler does not require this explicitly, it is optional.

All our apps use otel gems - so things should work out of the box for them.

@bmansoob bmansoob requested a review from gmcgibbon February 19, 2025 15:23
def otel_instrumentation_enabled=(value)
if value
raise ArgumentError,
"OpenTelemetry::Instrumentation::Rack not defined" unless defined?(OpenTelemetry::Instrumentation::Rack)

Choose a reason for hiding this comment

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

Just a comment for posterity. The OpenTelemetry::Instrumentation::Rack module allows us to reliably get a handle on the rack span.

@bmansoob bmansoob force-pushed the otel-instrumentation branch from f861989 to fb2cfef Compare February 20, 2025 15:25
@bmansoob
Copy link
Contributor Author

@gmcgibbon if you could please take a look from ruby/rails perspective. Much appreciated 🙏

@@ -50,5 +50,13 @@ class ConfigurationTest < TestCase
ensure
AppProfiler.profile_sampler_enabled = old_status
end

test "otel_instrumentation_enabled raises ArgumentError if opentelemetry is not installed" do
Copy link
Contributor Author

Choose a reason for hiding this comment

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

will update the description since we are no longer raising.

Copy link
Member

@gmcgibbon gmcgibbon Feb 20, 2025

Choose a reason for hiding this comment

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

Hmmmm... With the approach I'm suggesting, we can likely mock the gem call to raise Gem::MissingSpecError instead. Though, this is usually tested with multiple bundles and test suites for when we have X gem and when we don't. Considering this is a small feature, I think mocking is ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mocking does not work -- because gem is monkey patched here? https://github.com/rubygems/rubygems/blob/bundler-v2.5.9/bundler/lib/bundler/rubygems_integration.rb#L206.

I can remove the test altogether and just rescue Gem::MissingSpecError and Gem::LoadError in code and leave at that.

logger.warn("OpenTelemetry::Instrumentation::Rack not defined. Setting enabled to false.")
@otel_instrumentation_enabled = false
return
end
Copy link
Member

@gmcgibbon gmcgibbon Feb 20, 2025

Choose a reason for hiding this comment

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

This should raise when not available. We can implement a peer dependency with this:

gem "opentelemetry-instrumentation-rack", "VERSION_CONSTRAINT_HERE"
require "opentelemetry-instrumentation-rack"

In place of the defined? call. Rails does something similar with Active Record adapters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to explicitly add a dependency to otel stuff, thinking that might be the preference. This is okay with me too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

clarified privately -- I understand the suggestion now.

Copy link
Contributor Author

@bmansoob bmansoob Feb 21, 2025

Choose a reason for hiding this comment

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

Looking at this https://github.com/rubygems/rubygems/blob/master/lib/rubygems/core_ext/kernel_gem.rb#L11-L12. Since we do not need a version constraint, only require should suffice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -50,5 +50,13 @@ class ConfigurationTest < TestCase
ensure
AppProfiler.profile_sampler_enabled = old_status
end

test "otel_instrumentation_enabled raises ArgumentError if opentelemetry is not installed" do
Copy link
Member

@gmcgibbon gmcgibbon Feb 20, 2025

Choose a reason for hiding this comment

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

Hmmmm... With the approach I'm suggesting, we can likely mock the gem call to raise Gem::MissingSpecError instead. Though, this is usually tested with multiple bundles and test suites for when we have X gem and when we don't. Considering this is a small feature, I think mocking is ok.

@@ -7,6 +7,11 @@

module AppProfiler
class Middleware
OTEL_PROFILE_ID = "profile.id"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

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.

3 participants