module Datadog::Tracing::Contrib::Sinatra::Framework
def self.activate_rack!(datadog_config, sinatra_config)
def self.activate_rack!(datadog_config, sinatra_config) datadog_config.tracing.instrument( :rack, service_name: sinatra_config[:service_name], distributed_tracing: sinatra_config[:distributed_tracing], ) end
def self.add_middleware(middleware, builder, *args, &block)
def self.add_middleware(middleware, builder, *args, &block) insert_middleware(builder, middleware, args, block) do |proc_, use| use.insert(0, proc_) end end
def self.add_middleware_after(after, middleware, builder, *args, &block)
def self.add_middleware_after(after, middleware, builder, *args, &block) index = middlewares(builder).index(after) raise "middleware #{after} not found" unless index insert_middleware(builder, middleware, args, block) do |proc_, use| use.insert(index + 1, proc_) end end
def self.add_middleware_before(before, middleware, builder, *args, &block)
def self.add_middleware_before(before, middleware, builder, *args, &block) index = middlewares(builder).index(before) raise "middleware #{before} not found" unless index insert_middleware(builder, middleware, args, block) do |proc_, use| use.insert(index, proc_) end end
def self.append_middleware(middleware, builder, *args, &block)
def self.append_middleware(middleware, builder, *args, &block) insert_middleware(builder, middleware, args, block) do |proc_, use| use.append(proc_) end end
def self.config_with_defaults(datadog_config)
def self.config_with_defaults(datadog_config) datadog_config.tracing[:sinatra] end
def self.include_middleware?(middleware, builder)
def self.include_middleware?(middleware, builder) middlewares(builder).include?(middleware) end
def self.insert_middleware(builder, middleware, args, block)
The block gets passed prepared arguments for the caller to decide
Insert a middleware class in the builder as it expects it internally.
def self.insert_middleware(builder, middleware, args, block) use = builder.instance_variable_get('@use') wrapped = wrap_middleware(middleware, *args, &block) # Makes the insert idempotent # The block can also throw :skip with its own logic catch(:skip) do throw(:skip) if middlewares(builder).include?(middleware) yield(wrapped, use) end end
def self.inspect_middlewares(builder)
def self.inspect_middlewares(builder) Datadog.logger.debug { 'Sinatra middlewares: ' << middlewares(builder).map(&:inspect).inspect } end
def self.middlewares(builder)
def self.middlewares(builder) builder.instance_variable_get(:@use).map do |proc_| next :unknown unless proc_.respond_to?(:binding) && proc_.binding.local_variable_defined?(:middleware) proc_.binding.local_variable_get(:middleware) end end
def self.setup
def self.setup Datadog.configure do |datadog_config| sinatra_config = config_with_defaults(datadog_config) activate_rack!(datadog_config, sinatra_config) end end
def self.wrap_middleware(middleware, *args, &block)
The `middleware` local variable name in the proc is important for introspection
Wrap the middleware class instantiation in a proc, like Sinatra does internally
def self.wrap_middleware(middleware, *args, &block) proc { |app| middleware.new(app, *args, &block) } end