Module: InstrumentAllTheThings::Instrumentors

Defined in:
lib/instrument_all_the_things/instrumentors/tracing.rb,
lib/instrument_all_the_things/instrumentors/error_logging.rb,
lib/instrument_all_the_things/instrumentors/execution_count_and_timing.rb

Constant Summary collapse

DEFAULT_TRACE_OPTIONS =
{
  span_type: '',
  tags: {},
  span_name: 'method.execution',
}.freeze
TRACE_WRAPPER =
proc do |opts, context|
  opts = if opts == true
           DEFAULT_TRACE_OPTIONS.dup
         else
           DEFAULT_TRACE_OPTIONS.merge(opts)
         end

  span_name = opts.delete(:span_name)

  proc do |klass, next_blk, actual_code|
    passed_ops = opts.dup
    passed_ops[:resource] ||= context.trace_name(klass)
    passed_ops[:tags] ||= {}
    passed_ops[:type] = passed_ops.delete(:span_type)

    InstrumentAllTheThings.tracer.trace(span_name, **passed_ops) do
      next_blk.call(klass, actual_code)
    end
  end
end
DEFAULT_ERROR_LOGGING_OPTIONS =
{
  exclude_bundle_path: true,
  rescue_class: StandardError,
}.freeze
ERROR_LOGGER =
lambda do |exception, backtrace_cleaner|
end
ERROR_LOGGING_WRAPPER =
lambda do |opts, context|
  opts = if opts == true
           DEFAULT_ERROR_LOGGING_OPTIONS
         else
           DEFAULT_ERROR_LOGGING_OPTIONS.merge(opts)
         end

  backtrace_cleaner = if opts[:exclude_bundle_path] && defined?(Bundler)
                        bundle_path = Bundler.bundle_path.to_s
                        ->(trace) { trace.reject { |p| p.start_with?(bundle_path) } }
                      else
                        ->(trace) { trace }
                      end

  lambda do |klass, next_blk, actual_code|
    next_blk.call(klass, actual_code)
  rescue opts[:rescue_class] => e
    raise if e.instance_variable_get(:@_logged_by_iatt)

    e.instance_variable_set(:@_logged_by_iatt, true)

    InstrumentAllTheThings.logger&.error <<~ERROR
      An error occurred in #{context.trace_name(klass)}

      #{e.message}
      #{backtrace_cleaner.call(e.backtrace || []).join("\n")}
    ERROR

    raise
  end
end
DEFAULT_EXECUTION_COUNT_AND_TIMING_OPTIONS =
{}.freeze
EXECUTION_COUNT_AND_TIMING_WRAPPER =
proc do |_opts, context|
  proc do |klass, next_blk, actual_code|
    context.tags ||= []

    InstrumentAllTheThings.increment("#{context.stats_name(klass)}.executed", { tags: context.tags })
    InstrumentAllTheThings.time("#{context.stats_name(klass)}.duration", { tags: context.tags }) do
      next_blk.call(klass, actual_code)
    end
  rescue StandardError
    InstrumentAllTheThings.increment("#{context.stats_name(klass)}.errored", { tags: context.tags })
    raise
  end
end