Skip to content

Commit

Permalink
Merge pull request #728 from DataDog/feature/change_analytics_to_tag
Browse files Browse the repository at this point in the history
Implement set_tag shortcut for Analytics
  • Loading branch information
delner authored Mar 26, 2019
2 parents 73e841b + 8f38713 commit 874544c
Show file tree
Hide file tree
Showing 8 changed files with 275 additions and 36 deletions.
58 changes: 58 additions & 0 deletions lib/ddtrace/analytics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
require 'ddtrace/ext/analytics'

module Datadog
# Defines analytics behavior
module Analytics
class << self
def set_sample_rate(span, sample_rate)
return if span.nil? || !sample_rate.is_a?(Numeric)
span.set_metric(Datadog::Ext::Analytics::TAG_SAMPLE_RATE, sample_rate)
end
end

# Extension for Datadog::Span
module Span
def self.included(base)
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
base.class_eval do
# Instance methods
include InstanceMethodsCompatibility
include InstanceMethods
end
else
base.send(:prepend, InstanceMethods)
end
end

# Compatibility shim for Rubies not supporting `.prepend`
module InstanceMethodsCompatibility
def self.included(base)
base.class_eval do
alias_method :set_tag_without_analytics, :set_tag
remove_method :set_tag
end
end

def set_tag(*args, &block)
set_tag_without_analytics(*args, &block)
end
end

# Instance methods
module InstanceMethods
def set_tag(key, value)
case key
when Ext::Analytics::TAG_ENABLED
# If true, set rate to 1.0, otherwise set 0.0.
value = value == true ? Ext::Analytics::DEFAULT_SAMPLE_RATE : 0.0
Analytics.set_sample_rate(self, value)
when Ext::Analytics::TAG_SAMPLE_RATE
Analytics.set_sample_rate(self, value)
else
super if defined?(super)
end
end
end
end
end
end
7 changes: 3 additions & 4 deletions lib/ddtrace/contrib/analytics.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require 'ddtrace/ext/analytics'
require 'ddtrace/analytics'

module Datadog
module Contrib
# Defines sampling behavior for integrations
# Defines analytics behavior for integrations
module Analytics
module_function

Expand All @@ -13,8 +13,7 @@ def enabled?(flag = nil)
end

def set_sample_rate(span, sample_rate)
return if span.nil? || sample_rate.nil?
span.set_metric(Datadog::Ext::Analytics::TAG_SAMPLE_RATE, sample_rate)
Datadog::Analytics.set_sample_rate(span, sample_rate)
end
end
end
Expand Down
57 changes: 27 additions & 30 deletions lib/ddtrace/contrib/extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Contrib
module Extensions
def self.extended(base)
Datadog.send(:extend, Helpers)
Datadog::Configuration::Settings.send(:include, Configuration)
Datadog::Configuration::Settings.send(:include, Configuration::Settings)
end

# Helper methods for Datadog module.
Expand All @@ -17,44 +17,41 @@ def registry
end
end

# Extensions for Datadog::Configuration::Settings
module Configuration
InvalidIntegrationError = Class.new(StandardError)

def self.included(base)
# Add the additional options to the global configuration settings
base.instance_eval do
option :registry, default: Registry.new
# Extensions for Datadog::Configuration::Settings
module Settings
InvalidIntegrationError = Class.new(StandardError)

def self.included(base)
# Add the additional options to the global configuration settings
base.instance_eval do
option :registry, default: Registry.new
end
end
end

def initialize(options = {})
super
set_option(:registry, options[:registry]) if options.key?(:registry)
end
def [](integration_name, configuration_name = :default)
integration = fetch_integration(integration_name)
integration.configuration(configuration_name) unless integration.nil?
end

def [](integration_name, configuration_name = :default)
integration = fetch_integration(integration_name)
integration.configuration(configuration_name) unless integration.nil?
end
def use(integration_name, options = {}, &block)
integration = fetch_integration(integration_name)

def use(integration_name, options = {}, &block)
integration = fetch_integration(integration_name)
unless integration.nil?
configuration_name = options[:describes] || :default
filtered_options = options.reject { |k, _v| k == :describes }
integration.configure(configuration_name, filtered_options, &block)
end

unless integration.nil?
configuration_name = options[:describes] || :default
filtered_options = options.reject { |k, _v| k == :describes }
integration.configure(configuration_name, filtered_options, &block)
integration.patch if integration.respond_to?(:patch)
end

integration.patch if integration.respond_to?(:patch)
end

private
private

def fetch_integration(name)
get_option(:registry)[name] ||
raise(InvalidIntegrationError, "'#{name}' is not a valid integration.")
def fetch_integration(name)
get_option(:registry)[name] ||
raise(InvalidIntegrationError, "'#{name}' is not a valid integration.")
end
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/ddtrace/ext/analytics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ module Datadog
module Ext
# Defines constants for trace analytics
module Analytics
DEFAULT_SAMPLE_RATE = 1.0
ENV_TRACE_ANALYTICS_ENABLED = 'DD_TRACE_ANALYTICS_ENABLED'.freeze
# Tag for sample rate; used by agent to determine whether analytics event is emitted.
TAG_ENABLED = 'analytics.enabled'.freeze
TAG_SAMPLE_RATE = '_dd1.sr.eausr'.freeze
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/ddtrace/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require 'ddtrace/utils'
require 'ddtrace/ext/errors'
require 'ddtrace/analytics'

module Datadog
# Represents a logical unit of work in the system. Each trace consists of one or more spans.
Expand Down Expand Up @@ -252,3 +253,6 @@ def now_allocations
end
end
end

# Include extensions after Span (for Ruby 1.9 compatibility)
Datadog::Span.send(:include, Datadog::Analytics::Span)
146 changes: 146 additions & 0 deletions spec/ddtrace/analytics_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
require 'spec_helper'

require 'ddtrace/analytics'
require 'ddtrace/span'

RSpec.describe Datadog::Analytics do
describe '.set_sample_rate' do
subject(:set_sample_rate) { described_class.set_sample_rate(span, sample_rate) }
let(:span) { instance_double(Datadog::Span) }
let(:sample_rate) { 0.5 }

before do
allow(span).to receive(:set_metric) unless span.nil?
set_sample_rate
end

context 'given span that is' do
context 'nil' do
let(:span) { nil }
it { expect { set_sample_rate }.to_not raise_error }
end
end

context 'given sample rate that is' do
context 'nil' do
let(:sample_rate) { nil }
it { expect(span).to_not have_received(:set_metric) }
end

context 'a String' do
let(:sample_rate) { '1.0' }
it { expect(span).to_not have_received(:set_metric) }
end

context 'a Float' do
let(:sample_rate) { 1.0 }

it do
expect(span).to have_received(:set_metric)
.with(Datadog::Ext::Analytics::TAG_SAMPLE_RATE, sample_rate)
end
end
end
end
end

RSpec.describe Datadog::Analytics::Span do
subject(:test_object) { test_class.new }

describe '#set_tag' do
subject(:set_tag) { test_object.set_tag(key, value) }

before do
allow(Datadog::Analytics).to receive(:set_sample_rate)
set_tag
end

context 'when #set_tag is defined on the class' do
let(:test_class) do
Class.new do
# Define this method here to prove it doesn't
# override behavior in Datadog::Analytics::Span.
def set_tag(key, value)
[key, value]
end

# Include extensions at bottom (for Ruby 1.9 compatibility)
include Datadog::Analytics::Span
end
end

context 'and is given' do
context 'some kind of tag' do
let(:key) { 'my.tag' }
let(:value) { 'my.value' }

it 'calls the super #set_tag' do
is_expected.to eq([key, value])
end
end

context 'TAG_ENABLED with' do
let(:key) { Datadog::Ext::Analytics::TAG_ENABLED }

context 'true' do
let(:value) { true }

it do
expect(Datadog::Analytics).to have_received(:set_sample_rate)
.with(test_object, Datadog::Ext::Analytics::DEFAULT_SAMPLE_RATE)
end
end

context 'false' do
let(:value) { false }

it do
expect(Datadog::Analytics).to have_received(:set_sample_rate)
.with(test_object, 0.0)
end
end

context 'nil' do
let(:value) { nil }

it do
expect(Datadog::Analytics).to have_received(:set_sample_rate)
.with(test_object, 0.0)
end
end
end

context 'TAG_SAMPLE_RATE with' do
let(:key) { Datadog::Ext::Analytics::TAG_SAMPLE_RATE }

context 'a Float' do
let(:value) { 0.5 }

it do
expect(Datadog::Analytics).to have_received(:set_sample_rate)
.with(test_object, value)
end
end

context 'a String' do
let(:value) { '0.5' }

it do
expect(Datadog::Analytics).to have_received(:set_sample_rate)
.with(test_object, value)
end
end

context 'nil' do
let(:value) { nil }

it do
expect(Datadog::Analytics).to have_received(:set_sample_rate)
.with(test_object, value)
end
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion spec/ddtrace/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
context 'when the integration doesn\'t exist' do
it do
expect { configuration[:foobar] }.to raise_error(
Datadog::Contrib::Extensions::Configuration::InvalidIntegrationError
Datadog::Contrib::Extensions::Configuration::Settings::InvalidIntegrationError
)
end
end
Expand Down
34 changes: 34 additions & 0 deletions spec/ddtrace/span_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'spec_helper'

require 'ddtrace/span'

RSpec.describe Datadog::Span do
subject(:span) { described_class.new(tracer, name) }
let(:tracer) { get_test_tracer }
let(:name) { 'my.span' }

describe '#set_tag' do
subject(:set_tag) { span.set_tag(key, value) }
before { set_tag }

context 'given Datadog::Ext::Analytics::TAG_ENABLED' do
let(:key) { Datadog::Ext::Analytics::TAG_ENABLED }
let(:value) { true }

it 'sets the analytics sample rate' do
expect(span.get_metric(Datadog::Ext::Analytics::TAG_SAMPLE_RATE)).to eq(1.0)
expect(span.get_tag(Datadog::Ext::Analytics::TAG_SAMPLE_RATE)).to be nil
end
end

context 'given Datadog::Ext::Analytics::TAG_SAMPLE_RATE' do
let(:key) { Datadog::Ext::Analytics::TAG_SAMPLE_RATE }
let(:value) { 0.5 }

it 'sets the analytics sample rate' do
expect(span.get_metric(Datadog::Ext::Analytics::TAG_SAMPLE_RATE)).to eq(value)
expect(span.get_tag(Datadog::Ext::Analytics::TAG_SAMPLE_RATE)).to be nil
end
end
end
end

0 comments on commit 874544c

Please sign in to comment.