Module: Datadog::Tracing::Contrib::Rails::Runner

Defined in:
lib/datadog/tracing/contrib/rails/runner.rb

Overview

Instruments the ‘bin/rails runner` command. This command executes the provided code with the host Rails application loaded. The command can be either:

  • ‘-`: for code provided through the STDIN.

  • File path: for code provided through a local file.

  • ‘inline code`: for code provided directly as a command line argument.

The difficulty in instrumenting the Rails Runner is that the Rails application (and as a consequence the Datadog tracing library) is loaded very late in the runner execution. The Rails application is loaded inside the same method the method that directly executes the code the user wants the runner to execute:

“‘ruby def perform(code_or_file = nil, *command_argv)

boot_application! # Loads the Rails and Datadog

if code_or_file == "-"
  eval($stdin.read, TOPLEVEL_BINDING, "stdin") # Calls the user code for this Runner
# ...

“‘

This means that there’s no time to instrument the calling method, ‘perform`, which would be ideal. Instead, we resort to instrumenting `eval` and `load`, but only for calls from the `Rails::Command::RunnerCommand` class.

Defined Under Namespace

Modules: InstrumentedKernel

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.prepended(base) ⇒ Object



72
73
74
# File 'lib/datadog/tracing/contrib/rails/runner.rb', line 72

def self.prepended(base)
  base.const_set(:Kernel, InstrumentedKernel)
end

Instance Method Details

#eval(*args) ⇒ Object

Instruments the ‘Kernel.eval` method, but only for the `Rails::Command::RunnerCommand` class.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/datadog/tracing/contrib/rails/runner.rb', line 41

def eval(*args)
  source = args[0]

  if args[2] == 'stdin'
    name = Ext::SPAN_RUNNER_STDIN
    operation = Ext::TAG_OPERATION_STDIN
  else
    name = Ext::SPAN_RUNNER_INLINE
    operation = Ext::TAG_OPERATION_INLINE
  end

  Tracing.trace(
    name,
    service: Datadog.configuration.tracing[:rails][:service_name],
    tags: {
      Tracing::Metadata::Ext::TAG_COMPONENT => Ext::TAG_COMPONENT,
      Tracing::Metadata::Ext::TAG_OPERATION => operation,
    }
  ) do |span|
    if source
      span.set_tag(
        Ext::TAG_RUNNER_SOURCE,
        Core::Utils.truncate(source, MAX_TAG_VALUE_SIZE)
      )
    end
    Contrib::Analytics.set_rate!(span, Datadog.configuration.tracing[:rails])

    super
  end
end