Class: OpenTelemetry::Instrumentation::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/opentelemetry/instrumentation/base.rb

Overview

The Base class holds all metadata and configuration for an instrumentation. All instrumentation packages should include a subclass of +Instrumentation::Base+ that will register it with +OpenTelemetry.instrumentation_registry+ and make it available for discovery and installation by an SDK.

A typical subclass of Base will provide an install block, a present block, and possibly a compatible block. Below is an example:

module OpenTelemetry module Instrumentation module Sinatra class Instrumentation < OpenTelemetry::Instrumentation::Base install do |config| # install instrumentation, either by library hook or applying # a monkey patch end

    # determine if the target library is present
    present do
      defined?(::Sinatra)
    end

    # if the target library is present, is it compatible?
    compatible do
      Gem::Version.new(Sinatra::VERSION)) > MIN_VERSION
    end
  end
end

end end

The instrumentation name and version will be inferred from the namespace of the class. In this example, they'd be 'OpenTelemetry::Instrumentation::Sinatra' and OpenTelemetry::Instrumentation::Sinatra::VERSION, but can be explicitly set using the +instrumentation_name+ and +instrumetation_version+ methods if necessary.

All subclasses of OpenTelemetry::Instrumentation::Base are automatically registered with OpenTelemetry.instrumentation_registry which is used by SDKs for instrumentation discovery and installation.

Instrumentation libraries can use the instrumentation subclass to easily gain a reference to its named tracer. For example:

OpenTelemetry::Instrumentation::Sinatra.instance.tracer

The instrumention class establishes a convention for disabling an instrumentation by environment variable and local configuration. An instrumentation disabled by environment variable will take precedence over local config. The convention for environment variable name is the library name, upcased with '::' replaced by underscores, OPENTELEMETRY shortened to OTEL_LANG, and '_ENABLED' appended. For example: OTEL_RUBY_INSTRUMENTATION_SINATRA_ENABLED = false.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, version, install_blk, present_blk, compatible_blk, options) ⇒ Base

rubocop:disable Metrics/ParameterLists



197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/opentelemetry/instrumentation/base.rb', line 197

def initialize(name, version, install_blk, present_blk,
               compatible_blk, options)
  @name = name
  @version = version
  @install_blk = install_blk
  @present_blk = present_blk
  @compatible_blk = compatible_blk
  @config = {}
  @installed = false
  @options = options
  @tracer = OpenTelemetry::Trace::Tracer.new
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



192
193
194
# File 'lib/opentelemetry/instrumentation/base.rb', line 192

def config
  @config
end

#installedObject (readonly) Also known as: installed?

Returns the value of attribute installed.



192
193
194
# File 'lib/opentelemetry/instrumentation/base.rb', line 192

def installed
  @installed
end

#nameObject (readonly)

Returns the value of attribute name.



192
193
194
# File 'lib/opentelemetry/instrumentation/base.rb', line 192

def name
  @name
end

#tracerObject (readonly)

Returns the value of attribute tracer.



192
193
194
# File 'lib/opentelemetry/instrumentation/base.rb', line 192

def tracer
  @tracer
end

#versionObject (readonly)

Returns the value of attribute version.



192
193
194
# File 'lib/opentelemetry/instrumentation/base.rb', line 192

def version
  @version
end

Class Method Details

.compatible(&blk) ⇒ Object

The compatible block for this instrumentation. This check will be run if the target library is present to determine if it's compatible. It's not required, but a common use case will be to check to target library version for compatibility.

Parameters:

  • blk (Callable)

    The compatibility block for this instrumentation



136
137
138
# File 'lib/opentelemetry/instrumentation/base.rb', line 136

def compatible(&blk)
  @compatible_blk = blk
end

.inherited(subclass) ⇒ Object

rubocop:disable Lint/MissingSuper



77
78
79
# File 'lib/opentelemetry/instrumentation/base.rb', line 77

def inherited(subclass) # rubocop:disable Lint/MissingSuper
  OpenTelemetry::Instrumentation.registry.register(subclass)
end

.install(&blk) {|config| ... } ⇒ Object

The install block for this instrumentation. This will be where you install instrumentation, either by framework hook or applying a monkey patch.

Parameters:

  • blk (Callable)

    The install block for this instrumentation

Yield Parameters:

  • config (Hash)

    The instrumentation config will be yielded to the install block



116
117
118
# File 'lib/opentelemetry/instrumentation/base.rb', line 116

def install(&blk)
  @install_blk = blk
end

.instanceObject



165
166
167
168
# File 'lib/opentelemetry/instrumentation/base.rb', line 165

def instance
  @instance ||= new(instrumentation_name, instrumentation_version, install_blk,
                    present_blk, compatible_blk, options)
end

.instrumentation_name(instrumentation_name = nil) ⇒ Object

Optionally set the name of this instrumentation. If not explicitly set, the name will default to the namespace of the class, or the class name if it does not have a namespace. If there is not a namespace, or a class name, it will default to 'unknown'.

Parameters:

  • instrumentation_name (String) (defaults to: nil)

    The full name of the instrumentation package



87
88
89
90
91
92
93
# File 'lib/opentelemetry/instrumentation/base.rb', line 87

def instrumentation_name(instrumentation_name = nil)
  if instrumentation_name
    @instrumentation_name = instrumentation_name
  else
    @instrumentation_name ||= infer_name || 'unknown'
  end
end

.instrumentation_version(instrumentation_version = nil) ⇒ Object

Optionally set the version of this instrumentation. If not explicitly set, the version will default to the VERSION constant under namespace of the class, or the VERSION constant under the class name if it does not have a namespace. If a VERSION constant cannot be found, it defaults to '0.0.0'.

Parameters:

  • instrumentation_version (String) (defaults to: nil)

    The version of the instrumentation package



102
103
104
105
106
107
108
# File 'lib/opentelemetry/instrumentation/base.rb', line 102

def instrumentation_version(instrumentation_version = nil)
  if instrumentation_version
    @instrumentation_version = instrumentation_version
  else
    @instrumentation_version ||= infer_version || '0.0.0'
  end
end

.option(name, default:, validate:) ⇒ Object

The option method is used to define default configuration options for the instrumentation library. It requires a name, default value, and a validation callable to be provided. a key in the VALIDATORS hash. The supported keys are, :array, :boolean, :callable, :integer, :string.

Parameters:

  • name (String)

    The name of the configuration option

  • default

    The default value to be used, or to used if validation fails

  • validate (Callable, Symbol)

    Accepts a callable or a symbol that matches

Raises:

  • (ArgumentError)


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/opentelemetry/instrumentation/base.rb', line 148

def option(name, default:, validate:)
  validator = VALIDATORS[validate] || validate
  raise ArgumentError, "validate must be #{VALIDATORS.keys.join(', ')}, or a callable" unless validator.respond_to?(:call) || validator.respond_to?(:include?)

  @options ||= []

  validation_type = if VALIDATORS[validate]
                      validate
                    elsif validate.respond_to?(:include?)
                      :enum
                    else
                      :callable
                    end

  @options << { name: name, default: default, validator: validator, validation_type: validation_type }
end

.present(&blk) ⇒ Object

The present block for this instrumentation. This block is used to detect if target library is present on the system. Typically this will involve checking to see if the target gem spec was loaded or if expected constants from the target library are present.

Parameters:

  • blk (Callable)

    The present block for this instrumentation



126
127
128
# File 'lib/opentelemetry/instrumentation/base.rb', line 126

def present(&blk)
  @present_blk = blk
end

Instance Method Details

#compatible?Boolean

Calls the compatible block of the Instrumentation subclasses, if no block is provided it's assumed to be compatible

Returns:

  • (Boolean)


246
247
248
249
250
# File 'lib/opentelemetry/instrumentation/base.rb', line 246

def compatible?
  return true unless @compatible_blk

  instance_exec(&@compatible_blk)
end

#enabled?(config = nil) ⇒ Boolean

Whether this instrumentation is enabled. It first checks to see if it's enabled by an environment variable and will proceed to check if it's enabled by local config, if given.

Parameters:

  • config (optional Hash) (defaults to: nil)

    The local config

Returns:

  • (Boolean)


257
258
259
260
261
262
# File 'lib/opentelemetry/instrumentation/base.rb', line 257

def enabled?(config = nil)
  return false unless enabled_by_env_var?
  return config[:enabled] if config&.key?(:enabled)

  true
end

#install(config = {}) ⇒ Object

Install instrumentation with the given config. The present? and compatible? will be run first, and install will return false if either fail. Will return true if install was completed successfully.

Parameters:

  • config (Hash) (defaults to: {})

    The config for this instrumentation



216
217
218
219
220
221
222
223
224
225
# File 'lib/opentelemetry/instrumentation/base.rb', line 216

def install(config = {})
  return true if installed?

  @config = config_options(config)
  return false unless installable?(config)

  instance_exec(@config, &@install_blk)
  @tracer = OpenTelemetry.tracer_provider.tracer(name, version)
  @installed = true
end

#installable?(config = {}) ⇒ Boolean

Whether or not this instrumentation is installable in the current process. Will be true when the instrumentation defines an install block, is not disabled by environment or config, and the target library present and compatible.

Parameters:

  • config (Hash) (defaults to: {})

    The config for this instrumentation

Returns:

  • (Boolean)


232
233
234
# File 'lib/opentelemetry/instrumentation/base.rb', line 232

def installable?(config = {})
  @install_blk && enabled?(config) && present? && compatible?
end

#present?Boolean

Calls the present block of the Instrumentation subclasses, if no block is provided it's assumed the instrumentation is not present

Returns:

  • (Boolean)


238
239
240
241
242
# File 'lib/opentelemetry/instrumentation/base.rb', line 238

def present?
  return false unless @present_blk

  instance_exec(&@present_blk)
end