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

NH-85973 NH-89212 instrument function handler dependencies #144

Merged
merged 11 commits into from
Aug 27, 2024
4 changes: 2 additions & 2 deletions lambda/otel/layer/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ source 'https://rubygems.org'

source 'https://rubygems.pkg.github.com/solarwinds' do
gem 'opentelemetry-exporter-otlp', '0.26.1'
gem 'opentelemetry-metrics-api', '0.0.1'
gem 'opentelemetry-metrics-sdk', '0.0.1'
end

gem 'opentelemetry-metrics-api', '0.1.0'
gem 'opentelemetry-metrics-sdk', '0.1.0'
gem 'solarwinds_apm', '6.0.2'
47 changes: 47 additions & 0 deletions lambda/otel/layer/otel_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,53 @@
require 'opentelemetry-metrics-api'
require 'opentelemetry-metrics-sdk'
require 'opentelemetry-exporter-otlp'
# We need to load the function code's dependencies, and _before_ any dependencies might
# be initialized outside of the function handler, bootstrap instrumentation. This allows
# instrumentation targets to be present, and accommodates instrumentations like AWS SDK
# that add plugins on client initialization (vs. prepending methods).
Fixed Show fixed Hide fixed
def preload_libraries
cheempz marked this conversation as resolved.
Show resolved Hide resolved
default_task_location = '/var/task'

handler_file = ENV.values_at('ORIG_HANDLER', '_HANDLER').compact.first&.split('.')&.first

unless handler_file && File.exist?("#{default_task_location}/#{handler_file}.rb")
OpenTelemetry.logger.warn { 'Could not find the original handler file to preload libraries.' }
return
end

libraries = File.read("#{default_task_location}/#{handler_file}.rb")
.scan(/^\s*require\s+['"]([^'"]+)['"]/)
.flatten

libraries.each do |lib|
require lib
rescue StandardError => e
OpenTelemetry.logger.warn { "Could not load library #{lib}: #{e.message}" }
end
end

preload_libraries

cheempz marked this conversation as resolved.
Show resolved Hide resolved
require 'opentelemetry/instrumentation/aws_sdk/handler'
require 'opentelemetry/instrumentation/aws_sdk/services'

def loaded_constants
services = Aws.constants & OpenTelemetry::Instrumentation::AwsSdk::SERVICES.map(&:to_sym)

services.each_with_object([]) do |service, constants|
next if Aws.autoload?(service)

begin
constants << Aws.const_get(service, false).const_get(:Client, false)
rescue StandardError => e
OpenTelemetry.logger.warn { "Constant could not be loaded: #{e.message}" }
end
end
end

Seahorse::Client::Base.add_plugin(OpenTelemetry::Instrumentation::AwsSdk::Plugin) if defined?(Seahorse::Client::Base)
loaded_constants.each { |klass| klass.add_plugin(OpenTelemetry::Instrumentation::AwsSdk::Plugin) }

cheempz marked this conversation as resolved.
Show resolved Hide resolved
require 'solarwinds_apm'

def otel_wrapper(event:, context:)
Expand Down
2 changes: 1 addition & 1 deletion lib/solarwinds_apm/opentelemetry/otlp_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def initialize
# @param [Context] parent_context the
# started span.
def on_start(span, parent_context)
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] processor on_start span: #{span.inspect}" }
SolarWindsAPM.logger.debug { "[#{self.class}/#{__method__}] processor on_start span: #{span.to_span_data.inspect}" }

return if non_entry_span(parent_context: parent_context)

Expand Down