Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract ActionView from Rails #762

Merged
merged 4 commits into from
Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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/'` |
brettlangdon marked this conversation as resolved.
Show resolved Hide resolved

### 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
brettlangdon marked this conversation as resolved.
Show resolved Hide resolved
option :template_base_path, default: 'views/'
end
end
end
end
end
17 changes: 17 additions & 0 deletions lib/ddtrace/contrib/action_view/ext.rb
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
brettlangdon marked this conversation as resolved.
Show resolved Hide resolved
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
Loading