Module: Datadog::Contrib::Rails::Patcher

Includes:
Patcher
Defined in:
lib/ddtrace/contrib/rails/patcher.rb

Overview

Patcher enables patching of 'rails' module.

Constant Summary collapse

BEFORE_INITIALIZE_ONLY_ONCE_PER_APP =
Hash.new { |h, key| h[key] = Datadog::Utils::OnlyOnce.new }
AFTER_INITIALIZE_ONLY_ONCE_PER_APP =
Hash.new { |h, key| h[key] = Datadog::Utils::OnlyOnce.new }

Class Method Summary collapse

Methods included from Patcher

included

Class Method Details

.add_logger(app) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 70

def add_logger(app)
  should_warn = true
  # check if lograge key exists
  # Note: Rails executes initializers sequentially based on alphabetical order,
  # and lograge config could occur after datadog config.
  # So checking for `app.config.lograge.enabled` may yield a false negative,
  # and adding custom options naively if `config.lograge` exists from the lograge Railtie,
  # is inconsistent since a lograge initializer would override it.
  # Instead, we patch Lograge `custom_options` internals directly
  # as part of Rails framework patching
  # and just flag off the warning log here.
  # SemanticLogger we similarly patch in the after_initiaize block, and should flag
  # off the warning log here if we know we'll patch this gem later.
  should_warn = false if app.config.respond_to?(:lograge) || defined?(::SemanticLogger)

  # if lograge isn't set, check if tagged logged is enabled.
  # if so, add proc that injects trace identifiers for tagged logging.
  if (logger = app.config.logger) &&
     defined?(::ActiveSupport::TaggedLogging) &&
     logger.is_a?(::ActiveSupport::TaggedLogging)

    Datadog::Contrib::Rails::LogInjection.add_as_tagged_logging_logger(app)
    should_warn = false
  end

  Datadog.logger.warn("Unable to enable Datadog Trace context, Logger #{logger} is not supported") if should_warn
end

.add_middleware(app) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 47

def add_middleware(app)
  # Add trace middleware at the top of the middleware stack,
  # to ensure we capture the complete execution time.
  app.middleware.insert_before(0, Datadog::Contrib::Rack::TraceMiddleware)

  # Some Rails middleware can swallow an application error, preventing
  # the error propagation to the encompassing Rack span.
  #
  # We insert our own middleware right before these Rails middleware
  # have a chance to swallow the error.
  #
  # Note: because the middleware stack is push/pop, "before" and "after" are reversed
  # for our use case: we insert ourselves with "after" a middleware to ensure we are
  # able to pop the request "before" it.
  if defined?(::ActionDispatch::DebugExceptions)
    # Rails >= 3.2
    app.middleware.insert_after(::ActionDispatch::DebugExceptions, Datadog::Contrib::Rails::ExceptionMiddleware)
  else
    # Rails < 3.2
    app.middleware.insert_after(::ActionDispatch::ShowExceptions, Datadog::Contrib::Rails::ExceptionMiddleware)
  end
end

.after_intialize(app) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 104

def after_intialize(app)
  AFTER_INITIALIZE_ONLY_ONCE_PER_APP[app].run do
    # Finish configuring the tracer after the application is initialized.
    # We need to wait for some things, like application name, middleware stack, etc.
    setup_tracer
  end
end

.before_intialize(app) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 37

def before_intialize(app)
  BEFORE_INITIALIZE_ONLY_ONCE_PER_APP[app].run do
    # Middleware must be added before the application is initialized.
    # Otherwise the middleware stack will be frozen.
    # Sometimes we don't want to activate middleware e.g. OpenTracing, etc.
    add_middleware(app) if Datadog.configuration[:rails][:middleware]
    add_logger(app) if Datadog.configuration[:rails][:log_injection]
  end
end

.patchObject



26
27
28
29
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 26

def patch
  patch_before_intialize
  patch_after_intialize
end

.patch_after_intializeObject



98
99
100
101
102
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 98

def patch_after_intialize
  ::ActiveSupport.on_load(:after_initialize) do
    Datadog::Contrib::Rails::Patcher.after_intialize(self)
  end
end

.patch_before_intializeObject



31
32
33
34
35
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 31

def patch_before_intialize
  ::ActiveSupport.on_load(:before_initialize) do
    Datadog::Contrib::Rails::Patcher.before_intialize(self)
  end
end

.setup_tracerObject

Configure Rails tracing with settings



113
114
115
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 113

def setup_tracer
  Datadog::Contrib::Rails::Framework.setup
end

.target_versionObject



22
23
24
# File 'lib/ddtrace/contrib/rails/patcher.rb', line 22

def target_version
  Integration.version
end