Skip to content

Commit

Permalink
Merge pull request #762 from DataDog/refactor/extract_actionview_from…
Browse files Browse the repository at this point in the history
…_rails

Extract ActionView from Rails
  • Loading branch information
delner committed Sep 3, 2019
2 parents 33b476c + 322086b commit 33a662a
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 218 deletions.
3 changes: 3 additions & 0 deletions Appraisals
Expand Up @@ -306,6 +306,7 @@ elsif Gem::Version.new('2.2.0') <= Gem::Version.new(RUBY_VERSION) \
end

appraise 'contrib' do
gem 'actionview'
gem 'active_model_serializers', '>= 0.10.0'
gem 'activerecord', '< 5.1.5'
gem 'aws-sdk'
Expand Down Expand Up @@ -451,6 +452,7 @@ elsif Gem::Version.new('2.3.0') <= Gem::Version.new(RUBY_VERSION) \
end

appraise 'contrib' do
gem 'actionview'
gem 'active_model_serializers', '>= 0.10.0'
gem 'activerecord', '< 5.1.5'
gem 'aws-sdk'
Expand Down Expand Up @@ -484,6 +486,7 @@ elsif Gem::Version.new('2.3.0') <= Gem::Version.new(RUBY_VERSION) \
elsif Gem::Version.new('2.4.0') <= Gem::Version.new(RUBY_VERSION)
if RUBY_PLATFORM != 'java'
appraise 'contrib' do
gem 'actionview'
gem 'active_model_serializers', '>= 0.10.0'
gem 'activerecord', '< 5.1.5'
gem 'aws-sdk'
Expand Down
12 changes: 12 additions & 0 deletions Rakefile
Expand Up @@ -59,6 +59,7 @@ namespace :spec do
end

[
:action_view,
:active_model_serializers,
:active_record,
:active_support,
Expand Down Expand Up @@ -234,6 +235,10 @@ task :ci do
sh 'bundle exec appraisal rails30-postgres rake spec:rails'
sh 'bundle exec appraisal rails32-mysql2 rake spec:rails'
sh 'bundle exec appraisal rails32-postgres rake spec:rails'
# Rails suite specs
sh 'bundle exec appraisal rails32-postgres rake spec:action_view'
sh 'bundle exec appraisal rails32-mysql2 rake spec:active_record'
sh 'bundle exec appraisal rails32-postgres rake spec:active_support'
end
elsif Gem::Version.new('2.1.0') <= Gem::Version.new(RUBY_VERSION) \
&& Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.0')
Expand Down Expand Up @@ -288,6 +293,10 @@ task :ci do
sh 'bundle exec appraisal rails32-postgres rake spec:rails'
sh 'bundle exec appraisal rails4-mysql2 rake spec:rails'
sh 'bundle exec appraisal rails4-postgres rake spec:rails'
# Rails suite specs
sh 'bundle exec appraisal rails32-postgres rake spec:action_view'
sh 'bundle exec appraisal rails32-mysql2 rake spec:active_record'
sh 'bundle exec appraisal rails32-postgres rake spec:active_support'
end
elsif Gem::Version.new('2.2.0') <= Gem::Version.new(RUBY_VERSION)\
&& Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3.0')
Expand All @@ -303,6 +312,7 @@ task :ci do
sh 'bundle exec appraisal contrib rake test:sidekiq'
sh 'bundle exec appraisal contrib rake test:sucker_punch'
# Contrib specs
sh 'bundle exec appraisal contrib rake spec:action_view'
sh 'bundle exec appraisal contrib rake spec:active_model_serializers'
sh 'bundle exec appraisal contrib rake spec:active_record'
sh 'bundle exec appraisal contrib rake spec:active_support'
Expand Down Expand Up @@ -370,6 +380,7 @@ task :ci do
sh 'bundle exec appraisal contrib rake test:sidekiq'
sh 'bundle exec appraisal contrib rake test:sucker_punch'
# Contrib specs
sh 'bundle exec appraisal contrib rake spec:action_view'
sh 'bundle exec appraisal contrib rake spec:active_model_serializers'
sh 'bundle exec appraisal contrib rake spec:active_record'
sh 'bundle exec appraisal contrib rake spec:active_support'
Expand Down Expand Up @@ -436,6 +447,7 @@ task :ci do
sh 'bundle exec appraisal contrib rake test:sidekiq'
sh 'bundle exec appraisal contrib rake test:sucker_punch'
# Contrib specs
sh 'bundle exec appraisal contrib rake spec:action_view'
sh 'bundle exec appraisal contrib rake spec:active_model_serializers'
sh 'bundle exec appraisal contrib rake spec:active_record'
sh 'bundle exec appraisal contrib rake spec:active_support'
Expand Down
28 changes: 26 additions & 2 deletions docs/GettingStarted.md
Expand Up @@ -26,6 +26,7 @@ To contribute, check out the [contribution guidelines][contribution docs] and [d
- [Quickstart for OpenTracing](#quickstart-for-opentracing)
- [Manual instrumentation](#manual-instrumentation)
- [Integration instrumentation](#integration-instrumentation)
- [Action View](#action-view)
- [Active Model Serializers](#active-model-serializers)
- [Active Record](#active-record)
- [Active Support](#active-support)
Expand Down Expand Up @@ -321,6 +322,7 @@ For a list of available integrations, and their configuration options, please re

| Name | Key | Versions Supported | How to configure | Gem source |
| ------------------------ | -------------------------- | ------------------------ | ----------------------------------- | ------------------------------------------------------------------------------ |
| Action View | `action_view` | `>= 3.2, < 6.0` | *[Link](#action-view)* | *[Link](https://github.com/rails/rails/tree/master/actionview)* |
| Active Model Serializers | `active_model_serializers` | `>= 0.9` | *[Link](#active-model-serializers)* | *[Link](https://github.com/rails-api/active_model_serializers)* |
| Active Record | `active_record` | `>= 3.2, < 6.0` | *[Link](#active-record)* | *[Link](https://github.com/rails/rails/tree/master/activerecord)* |
| Active Support | `active_support` | `>= 3.2, < 6.0` | *[Link](#active-support)* | *[Link](https://github.com/rails/rails/tree/master/activesupport)* |
Expand All @@ -345,11 +347,33 @@ For a list of available integrations, and their configuration options, please re
| Resque | `resque` | `>= 1.0, < 2.0` | *[Link](#resque)* | *[Link](https://github.com/resque/resque)* |
| Rest Client | `rest-client` | `>= 1.8` | *[Link](#rest-client)* | *[Link](https://github.com/rest-client/rest-client)* |
| Sequel | `sequel` | `>= 3.41` | *[Link](#sequel)* | *[Link](https://github.com/jeremyevans/sequel)* |
| Shoryuken | `shoryuken` | `>= 4.0.2` | *[Link](#shoryuken)* | *[Link](https://github.com/phstc/shoryuken)*
| Shoryuken | `shoryuken` | `>= 4.0.2` | *[Link](#shoryuken)* | *[Link](https://github.com/phstc/shoryuken)* |
| Sidekiq | `sidekiq` | `>= 3.5.4` | *[Link](#sidekiq)* | *[Link](https://github.com/mperham/sidekiq)* |
| Sinatra | `sinatra` | `>= 1.4.5` | *[Link](#sinatra)* | *[Link](https://github.com/sinatra/sinatra)* |
| Sucker Punch | `sucker_punch` | `>= 2.0` | *[Link](#sucker-punch)* | *[Link](https://github.com/brandonhilkert/sucker_punch)* |

### Action View

Most of the time, Active Support is set up as part of Rails, but it can be activated separately:

```ruby
require 'actionview'
require 'ddtrace'

Datadog.configure do |c|
c.use :action_view, options
end
```

Where `options` is an optional `Hash` that accepts the following parameters:

| Key | Description | Default |
| ---| --- | --- |
| `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
| `service_name` | Service name used for rendering instrumentation. | `action_view` |
| `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |
| `template_base_path` | Used when the template name is parsed. If you don't store your templates in the `views/` folder, you may need to change this value | `'views/'` |

### Active Model Serializers

The Active Model Serializers integration traces the `serialize` event for version 0.9+ and the `render` event for version 0.10+.
Expand Down Expand Up @@ -461,7 +485,7 @@ Where `options` is an optional `Hash` that accepts the following parameters:
| Key | Description | Default |
| ---| --- | --- |
| `analytics_enabled` | Enable analytics for spans produced by this integration. `true` for on, `nil` to defer to global setting, `false` for off. | `false` |
| `cache_service` | Service name used for caching with `active_support` instrumentation. | `'active_support-cache'` |
| `cache_service` | Service name used for caching with `active_support` instrumentation. | `active_support-cache` |
| `tracer` | `Datadog::Tracer` used to perform instrumentation. Usually you don't need to set this. | `Datadog.tracer` |

### AWS
Expand Down
1 change: 1 addition & 0 deletions lib/ddtrace.rb
Expand Up @@ -21,6 +21,7 @@ module Datadog
extend Contrib::Extensions
end

require 'ddtrace/contrib/action_view/integration'
require 'ddtrace/contrib/active_model_serializers/integration'
require 'ddtrace/contrib/active_record/integration'
require 'ddtrace/contrib/active_support/integration'
Expand Down
24 changes: 24 additions & 0 deletions lib/ddtrace/contrib/action_view/configuration/settings.rb
@@ -0,0 +1,24 @@
require 'ddtrace/contrib/configuration/settings'
require 'ddtrace/contrib/action_view/ext'

module Datadog
module Contrib
module ActionView
module Configuration
# Custom settings for the ActionView integration
class Settings < Contrib::Configuration::Settings
option :analytics_enabled,
default: -> { env_to_bool(Ext::ENV_ANALYTICS_ENABLED, false) },
lazy: true

option :analytics_sample_rate,
default: -> { env_to_float(Ext::ENV_ANALYTICS_SAMPLE_RATE, 1.0) },
lazy: true

option :service_name, default: Ext::SERVICE_NAME
option :template_base_path, default: 'views/'
end
end
end
end
end
17 changes: 17 additions & 0 deletions lib/ddtrace/contrib/action_view/ext.rb
@@ -0,0 +1,17 @@
module Datadog
module Contrib
module ActionView
# ActionView integration constants
module Ext
APP = 'action_view'.freeze
ENV_ANALYTICS_ENABLED = 'DD_ACTION_VIEW_ANALYTICS_ENABLED'.freeze
ENV_ANALYTICS_SAMPLE_RATE = 'DD_ACTION_VIEW_ANALYTICS_SAMPLE_RATE'.freeze
SERVICE_NAME = 'action_view'.freeze
SPAN_RENDER_PARTIAL = 'rails.render_partial'.freeze
SPAN_RENDER_TEMPLATE = 'rails.render_template'.freeze
TAG_LAYOUT = 'rails.layout'.freeze
TAG_TEMPLATE_NAME = 'rails.template_name'.freeze
end
end
end
end
192 changes: 192 additions & 0 deletions lib/ddtrace/contrib/action_view/instrumentation.rb
@@ -0,0 +1,192 @@
require 'ddtrace/contrib/action_view/ext'

module Datadog
module Contrib
module ActionView
# Defines instrumentation for ActionView
module Instrumentation
# Instrumentation for template rendering
module TemplateRenderer
# Rails < 3.1 template rendering
module Rails30
# rubocop:disable Metrics/MethodLength
def self.prepended(base)
# rubocop:disable Metrics/BlockLength
base.class_eval do
def render_with_datadog(*args, &block)
# NOTE: This check exists purely for Rails 3.0 compatibility.
# The 'if' part can be removed when support for Rails 3.0 is removed.
if active_datadog_span
render_without_datadog(*args, &block)
else
datadog_tracer.trace(
Ext::SPAN_RENDER_TEMPLATE,
span_type: Datadog::Ext::HTTP::TEMPLATE
) do |span|
with_datadog_span(span) { render_without_datadog(*args, &block) }
end
end
end

def render_template_with_datadog(*args)
begin
template = args[0]
layout_name = args[1]

# update the tracing context with computed values before the rendering
template_name = template.try('identifier')
template_name = Utils.normalize_template_name(template_name)

if template_name
active_datadog_span.set_tag(
Ext::TAG_TEMPLATE_NAME,
template_name
)
end

if layout_name
active_datadog_span.set_tag(
Ext::TAG_LAYOUT,
layout_name
)
end
rescue StandardError => e
Datadog::Tracer.log.debug(e.message)
end

# execute the original function anyway
render_template_without_datadog(*args)
end

private

attr_accessor :active_datadog_span

def datadog_tracer
Datadog.configuration[:action_view][:tracer]
end

def with_datadog_span(span)
self.active_datadog_span = span
yield
ensure
self.active_datadog_span = nil
end

# method aliasing to patch the class
alias_method :render_without_datadog, :render
alias_method :render, :render_with_datadog

alias_method :render_template_without_datadog, :_render_template
alias_method :_render_template, :render_template_with_datadog
end
end
end

# Rails >= 3.1 template rendering
module Rails31Plus
def render(*args, &block)
datadog_tracer.trace(
Ext::SPAN_RENDER_TEMPLATE,
span_type: Datadog::Ext::HTTP::TEMPLATE
) do |span|
with_datadog_span(span) { super(*args, &block) }
end
end

def render_template(*args)
begin
# arguments based on render_template signature (stable since Rails 3.2)
template = args[0]
layout_name = args[1]

# update the tracing context with computed values before the rendering
template_name = template.try('identifier')
template_name = Utils.normalize_template_name(template_name)
layout = layout_name.try(:[], 'virtual_path')

if template_name
active_datadog_span.set_tag(
Ext::TAG_TEMPLATE_NAME,
template_name
)
end

if layout
active_datadog_span.set_tag(
Ext::TAG_LAYOUT,
layout
)
end
rescue StandardError => e
Datadog::Tracer.log.debug(e.message)
end

# execute the original function anyway
super(*args)
end

private

attr_accessor :active_datadog_span

def datadog_tracer
Datadog.configuration[:action_view][:tracer]
end

def with_datadog_span(span)
self.active_datadog_span = span
yield
ensure
self.active_datadog_span = nil
end
end
end

# Instrumentation for partial rendering
module PartialRenderer
def render(*args, &block)
datadog_tracer.trace(
Ext::SPAN_RENDER_PARTIAL,
span_type: Datadog::Ext::HTTP::TEMPLATE
) do |span|
with_datadog_span(span) { super(*args) }
end
end

def render_partial(*args)
begin
template_name = Utils.normalize_template_name(@template.try('identifier'))
if template_name
active_datadog_span.set_tag(
Ext::TAG_TEMPLATE_NAME,
template_name
)
end
rescue StandardError => e
Datadog::Tracer.log.debug(e.message)
end

# execute the original function anyway
super(*args)
end

private

attr_accessor :active_datadog_span

def datadog_tracer
Datadog.configuration[:action_view][:tracer]
end

def with_datadog_span(span)
self.active_datadog_span = span
yield
ensure
self.active_datadog_span = nil
end
end
end
end
end
end

0 comments on commit 33a662a

Please sign in to comment.