-
Notifications
You must be signed in to change notification settings - Fork 231
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
Instrumentation Packaging and Installation #19
Comments
So currently the user needs to do:
I wonder if we could merge steps two and three. Maybe something like
which does both steps. We'd still need the underlying methods to support multiple tracers per app. I'm also curios how can we make it work with metrics API nicely. Lets say we have |
Is multiple tracers per app a requirement? The API doesn't appear to support this at present. |
Not entirely sure. I myself haven't needed it in a real app. It does have some benefits though. E.g. it makes testing easier. Here I have a simple script that creates two tracers and creates a quick trace. |
Likewise for the distributed context API, and logging once we get there. Ideally, we could find a suitable lifecycle hook that'd let us initialize all the components, so we'd have something like: OpenTelemetry.tracer = VendorATracer.new
OpenTelemetry.meter = VendorBMeter.new
OpenTelemetry.logger = VendorCLogger.new
OpenTelemetry.distributed_context_manager = VendorDContextManager.new
# implicit initialization hook Where we call The challenge is finding a well-defined point where all the instrumentation has been loaded and all the OT components have been registered. If that has to be done explicitly, we at least need to provide guidance for typical use cases (e.g. Rails apps). |
Interesting. In that case, the tracers aren't registered as the tracer, but I guess you still want them to install the instrumentation. Perhaps it makes more sense to have a global registry of instrumentation in the API, and a hook (or component-specific hooks) that can be called for non-global components (like your 2 tracer example above)? |
I like this idea a lot. We might find other things that need to happen at this point in the application that we can facilitate with this method as well.
We could possibly have a configure block that will setup the tracer, meter, logger, etc, and install instrumentation afterwards. It could yield them individually to the block, or the block could possibly just reference them off the OpenTelemetry module. Something like: OpenTelemetry.configure do |ot|
ot.tracer = TracerImplementation.new
ot.meter = MeterImplementation.new
ot.logger = LoggerImplementation.new
...
end |
In terms of multiple tracer support. I think having a configure block that will by default install instrumentation using the tracer that is being configured will solve the majority of use cases. For people who want a more fine-grained tracer approach, this will probably require some custom code on behalf of the user. Since we do effectively have an instrumentation registry with this design, we can expose methods that allow users to interact with the individual pieces of instrumentation. We could provide an |
Also one thing to consider is that not all instrumentations can be applied globally. This works fine for activerecord, but e.g. rack expects a middleware. With opentracing we did it like https://github.com/opentracing-contrib/ruby-rack-tracer . Faraday had something similar https://github.com/opentracing-contrib/ruby-faraday-tracer . In rack case it used the global tracer by default, but it was also possible to specify the tracer in the arguments. |
There might be a class of instrumentation that is not auto-installable. We can decide if it makes sense to have them subclass |
@mwear what would you think about encouraging instrumentation authors to not add the library they are instrumenting as a dependency? The benefit of doing that is you can have a tool that auto-instruments whatever libraries it detects are loadable and skip over other libraries. The alternatives are 1) having apps manually list out all of the instrumentation gems they want to use 2) auto instrumenting anyway but pulling in gems the app has no intention of actually using |
There are pros and cons to specifying the library version as a dependency. Except in rare cases, instrumentation is only going to be compatible certain versions of the instrumented library and a version check has to happen somewhere. By making the instrumented library a dependency, we can lean on Bundler to resolve them and report incompatibilities. One huge benefit, is that users will discover incompatibilities at build time, rather than at runtime with other approaches. While this does mean that a user would need to explicitly list instrumentation as a dependency, it doesn't mean this has to be a completely manual process. There could be a method of discovery to help find compatible instrumentation. A prerequisite would be an instrumentation registry of sorts. A way that I would envision this working would be a rake task that introspects your application, queries the registry, and lists compatible instrumentation. This presupposes that someday a registry will exist, and I don't know if that is the case or not. If the instrumented library isn't an explicit dependency, then a version check still has to happen somewhere. This logic could be part of the For now, I think all options are on the table and both of these are reasonable approaches. We do need a instrumentation discovery story and the shape of that story will likely inform choices such as this. |
Relevant: #67. open-telemetry/oteps#41 proposes to use https://github.com/DataDog/dd-trace-rb as the basis for auto-instrumentation. I have not 👀 at the code closely. |
Third Party Instrumentation Proposal for OpenTelemetry Ruby
Overview
There is an RFC for auto-instrumentation and this document describes a possible approach that we could use for managing instrumentation for the OpenTelemetry Ruby Project.
Packaging
Installation
Implementation
The implementation I am proposing is very similar to and inspired by
Rails::Railtie
.OpenTelemetry Ruby will ship with a common base class,
OpenTelemetry::Instrumentation
thatClass#inherited
callback)Example Instrumentation Package
A package should list its dependencies in its
gemspec
A package will ship with a class that subclasses
OpenTelemetry::Instrumentation
which will auto-register instrumentation, and provide hooks for installing and enabling it. The base class will automatically check for an environment variable derived off of theinstrumentation_name
field for overriding an enabled decision. The convention I'm proposing for an environment variable name isOPENTELEMETRY_{insrumentation_name}_ENABLED
, which in this example would beOPENTELEMETRY_OTEL_ACTIVE_RECORD_ENABLED
.Instrumentation installation API
The SDK should provide an API method to install instrumentation that can be called at the right time during application startup. This method should evaluate and install all instrumentation that subclasses
OpenTelemetry::Instrumentation
if it is enabled.OpenTelemetry::Instrumentation Implementation
Below is a rough-draft of what the OpenTelemetry::Instrumentation class would look like
Discussion
I've been thinking about how we can package instrumentation for OpenTelemetry Ruby and wanted to put these thoughts in writing as a starting point for a discussion about it. I'm open to any and all suggestions with the end goal of us having the best possible instrumentation distribution story, even if it doesn't end up being this one.
The text was updated successfully, but these errors were encountered: