ddtrace 0.30.1 → 0.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +28 -0
  3. data/.circleci/images/primary/Dockerfile-2.7.0 +73 -0
  4. data/Appraisals +111 -2
  5. data/CHANGELOG.md +33 -1
  6. data/Rakefile +69 -1
  7. data/ddtrace.gemspec +1 -0
  8. data/docker-compose.yml +30 -0
  9. data/docs/GettingStarted.md +28 -3
  10. data/lib/ddtrace.rb +6 -0
  11. data/lib/ddtrace/buffer.rb +3 -3
  12. data/lib/ddtrace/configuration/base.rb +2 -1
  13. data/lib/ddtrace/configuration/settings.rb +15 -2
  14. data/lib/ddtrace/context.rb +62 -57
  15. data/lib/ddtrace/context_flush.rb +51 -114
  16. data/lib/ddtrace/context_provider.rb +45 -0
  17. data/lib/ddtrace/contrib/action_cable/configuration/settings.rb +25 -0
  18. data/lib/ddtrace/contrib/action_cable/event.rb +65 -0
  19. data/lib/ddtrace/contrib/action_cable/events.rb +33 -0
  20. data/lib/ddtrace/contrib/action_cable/events/broadcast.rb +49 -0
  21. data/lib/ddtrace/contrib/action_cable/events/perform_action.rb +52 -0
  22. data/lib/ddtrace/contrib/action_cable/events/transmit.rb +50 -0
  23. data/lib/ddtrace/contrib/action_cable/ext.rb +23 -0
  24. data/lib/ddtrace/contrib/action_cable/instrumentation.rb +31 -0
  25. data/lib/ddtrace/contrib/action_cable/integration.rb +36 -0
  26. data/lib/ddtrace/contrib/action_cable/patcher.rb +27 -0
  27. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +2 -2
  28. data/lib/ddtrace/contrib/action_view/events/render_partial.rb +5 -3
  29. data/lib/ddtrace/contrib/action_view/events/render_template.rb +5 -3
  30. data/lib/ddtrace/contrib/action_view/instrumentation/partial_renderer.rb +2 -1
  31. data/lib/ddtrace/contrib/action_view/instrumentation/template_renderer.rb +4 -2
  32. data/lib/ddtrace/contrib/action_view/patcher.rb +1 -1
  33. data/lib/ddtrace/contrib/active_record/events/instantiation.rb +1 -1
  34. data/lib/ddtrace/contrib/active_record/events/sql.rb +1 -1
  35. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +2 -2
  36. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +2 -2
  37. data/lib/ddtrace/contrib/dalli/patcher.rb +1 -1
  38. data/lib/ddtrace/contrib/dalli/quantize.rb +1 -1
  39. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -1
  40. data/lib/ddtrace/contrib/excon/middleware.rb +3 -3
  41. data/lib/ddtrace/contrib/faraday/connection.rb +18 -0
  42. data/lib/ddtrace/contrib/faraday/integration.rb +1 -1
  43. data/lib/ddtrace/contrib/faraday/patcher.rb +3 -3
  44. data/lib/ddtrace/contrib/grape/endpoint.rb +5 -5
  45. data/lib/ddtrace/contrib/grape/patcher.rb +1 -1
  46. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +1 -1
  47. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +2 -2
  48. data/lib/ddtrace/contrib/grpc/patcher.rb +1 -1
  49. data/lib/ddtrace/contrib/http/instrumentation.rb +1 -1
  50. data/lib/ddtrace/contrib/mongodb/subscribers.rb +2 -2
  51. data/lib/ddtrace/contrib/patchable.rb +1 -1
  52. data/lib/ddtrace/contrib/patcher.rb +1 -1
  53. data/lib/ddtrace/contrib/rack/middlewares.rb +2 -2
  54. data/lib/ddtrace/contrib/rack/patcher.rb +2 -2
  55. data/lib/ddtrace/contrib/rack/request_queue.rb +1 -1
  56. data/lib/ddtrace/contrib/rails/configuration/settings.rb +1 -0
  57. data/lib/ddtrace/contrib/rails/framework.rb +12 -0
  58. data/lib/ddtrace/contrib/rake/instrumentation.rb +2 -2
  59. data/lib/ddtrace/contrib/redis/quantize.rb +1 -1
  60. data/lib/ddtrace/contrib/sinatra/tracer.rb +1 -1
  61. data/lib/ddtrace/ext/forced_tracing.rb +1 -1
  62. data/lib/ddtrace/ext/sampling.rb +3 -0
  63. data/lib/ddtrace/logger.rb +42 -0
  64. data/lib/ddtrace/metrics.rb +5 -5
  65. data/lib/ddtrace/monkey.rb +1 -1
  66. data/lib/ddtrace/pin.rb +1 -1
  67. data/lib/ddtrace/pipeline.rb +1 -1
  68. data/lib/ddtrace/propagation/http_propagator.rb +2 -2
  69. data/lib/ddtrace/runtime/cgroup.rb +1 -1
  70. data/lib/ddtrace/runtime/container.rb +1 -1
  71. data/lib/ddtrace/runtime/metrics.rb +1 -1
  72. data/lib/ddtrace/sampler.rb +1 -1
  73. data/lib/ddtrace/sampling/rule.rb +1 -1
  74. data/lib/ddtrace/sampling/rule_sampler.rb +4 -4
  75. data/lib/ddtrace/span.rb +24 -6
  76. data/lib/ddtrace/sync_writer.rb +4 -3
  77. data/lib/ddtrace/tracer.rb +37 -77
  78. data/lib/ddtrace/transport/http/client.rb +2 -2
  79. data/lib/ddtrace/utils.rb +1 -1
  80. data/lib/ddtrace/version.rb +2 -2
  81. data/lib/ddtrace/workers.rb +3 -3
  82. data/lib/ddtrace/writer.rb +3 -2
  83. metadata +44 -6
  84. data/lib/ddtrace/contrib/faraday/rack_builder.rb +0 -18
  85. data/lib/ddtrace/provider.rb +0 -21
@@ -30,7 +30,7 @@ module Datadog
30
30
  rescue StandardError => e
31
31
  # in case of an Exception we don't create a
32
32
  # `request.queuing` span
33
- Datadog::Tracer.log.debug("[rack] unable to parse request queue headers: #{e}")
33
+ Datadog::Logger.log.debug("[rack] unable to parse request queue headers: #{e}")
34
34
  nil
35
35
  end
36
36
  end
@@ -67,6 +67,7 @@ module Datadog
67
67
  option :tracer do |o|
68
68
  o.delegate_to { Datadog.tracer }
69
69
  o.on_set do |value|
70
+ Datadog.configuration[:action_cable][:tracer] = value
70
71
  Datadog.configuration[:active_record][:tracer] = value
71
72
  Datadog.configuration[:active_support][:tracer] = value
72
73
  Datadog.configuration[:action_pack][:tracer] = value
@@ -3,6 +3,7 @@ require 'ddtrace/ext/app_types'
3
3
 
4
4
  require 'ddtrace/contrib/active_record/integration'
5
5
  require 'ddtrace/contrib/active_support/integration'
6
+ require 'ddtrace/contrib/action_cable/integration'
6
7
  require 'ddtrace/contrib/action_pack/integration'
7
8
  require 'ddtrace/contrib/action_view/integration'
8
9
  require 'ddtrace/contrib/grape/endpoint'
@@ -23,6 +24,7 @@ module Datadog
23
24
  config = config_with_defaults
24
25
 
25
26
  activate_rack!(config)
27
+ activate_action_cable!(config)
26
28
  activate_active_support!(config)
27
29
  activate_action_pack!(config)
28
30
  activate_action_view!(config)
@@ -65,6 +67,16 @@ module Datadog
65
67
  )
66
68
  end
67
69
 
70
+ def self.activate_action_cable!(config)
71
+ return unless defined?(::ActionCable)
72
+
73
+ Datadog.configuration.use(
74
+ :action_cable,
75
+ service_name: "#{config[:service_name]}-#{Contrib::ActionCable::Ext::SERVICE_NAME}",
76
+ tracer: config[:tracer]
77
+ )
78
+ end
79
+
68
80
  def self.activate_action_pack!(config)
69
81
  return unless defined?(::ActionPack)
70
82
 
@@ -47,14 +47,14 @@ module Datadog
47
47
  span.set_tag(Ext::TAG_TASK_ARG_NAMES, arg_names)
48
48
  span.set_tag(Ext::TAG_INVOKE_ARGS, quantize_args(args)) unless args.nil?
49
49
  rescue StandardError => e
50
- Datadog::Tracer.log.debug("Error while tracing Rake invoke: #{e.message}")
50
+ Datadog::Logger.log.debug("Error while tracing Rake invoke: #{e.message}")
51
51
  end
52
52
 
53
53
  def annotate_execute!(span, args)
54
54
  span.resource = name
55
55
  span.set_tag(Ext::TAG_EXECUTE_ARGS, quantize_args(args.to_hash)) unless args.nil?
56
56
  rescue StandardError => e
57
- Datadog::Tracer.log.debug("Error while tracing Rake execute: #{e.message}")
57
+ Datadog::Logger.log.debug("Error while tracing Rake execute: #{e.message}")
58
58
  end
59
59
 
60
60
  def quantize_args(args)
@@ -15,7 +15,7 @@ module Datadog
15
15
  str = Utils.utf8_encode(str, binary: true, placeholder: PLACEHOLDER)
16
16
  Utils.truncate(str, VALUE_MAX_LEN, TOO_LONG_MARK)
17
17
  rescue => e
18
- Datadog::Tracer.log.debug("non formattable Redis arg #{str}: #{e}")
18
+ Datadog::Logger.log.debug("non formattable Redis arg #{str}: #{e}")
19
19
  PLACEHOLDER
20
20
  end
21
21
 
@@ -68,7 +68,7 @@ module Datadog
68
68
  span = Sinatra::Env.datadog_span(env)
69
69
 
70
70
  unless span
71
- Datadog::Tracer.log.error('missing request span in :after hook')
71
+ Datadog::Logger.log.error('missing request span in :after hook')
72
72
  return
73
73
  end
74
74
 
@@ -12,7 +12,7 @@ module Datadog
12
12
 
13
13
  # Only log each deprecation warning once (safeguard against log spam)
14
14
  unless @deprecation_warning_shown
15
- Datadog::Tracer.log.warn(
15
+ Datadog::Logger.log.warn(
16
16
  'forced tracing: Datadog::Ext::ForcedTracing has been renamed to Datadog::Ext::ManualTracing'
17
17
  )
18
18
  @deprecation_warning_shown = true
@@ -1,6 +1,9 @@
1
1
  module Datadog
2
2
  module Ext
3
3
  module Sampling
4
+ ENV_SAMPLE_RATE = 'DD_TRACE_SAMPLE_RATE'.freeze
5
+ ENV_RATE_LIMIT = 'DD_TRACE_RATE_LIMIT'.freeze
6
+
4
7
  # If rule sampling is applied to a span, set this metric the sample rate configured for that rule.
5
8
  # This should be done regardless of sampling outcome.
6
9
  RULE_SAMPLE_RATE = '_dd.rule_psr'.freeze
@@ -7,6 +7,48 @@ module Datadog
7
7
  # - progname defaults to ddtrace to clearly identify Datadog dd-trace-rb related messages
8
8
  # - adds last caller stack-trace info to know where the message comes from
9
9
  class Logger < ::Logger
10
+ # Global, memoized, lazy initialized instance of a logger that is used within the the Datadog
11
+ # namespace. This logger outputs to +STDOUT+ by default, and is considered thread-safe.
12
+ class << self
13
+ def log
14
+ unless defined? @logger
15
+ @logger = Datadog::Logger.new(STDOUT)
16
+ @logger.level = Logger::WARN
17
+ end
18
+ @logger
19
+ end
20
+
21
+ # Override the default logger with a custom one.
22
+ def log=(logger)
23
+ return unless logger
24
+ return unless logger.respond_to? :methods
25
+ return unless logger.respond_to? :error
26
+ if logger.respond_to? :methods
27
+ unimplemented = new(STDOUT).methods - logger.methods
28
+ unless unimplemented.empty?
29
+ logger.error("logger #{logger} does not implement #{unimplemented}")
30
+ return
31
+ end
32
+ end
33
+ @logger = logger
34
+ end
35
+
36
+ # Activate the debug mode providing more information related to tracer usage
37
+ # Default to Warn level unless using custom logger
38
+ def debug_logging=(value)
39
+ if value
40
+ log.level = Logger::DEBUG
41
+ elsif log.is_a?(Datadog::Logger)
42
+ log.level = Logger::WARN
43
+ end
44
+ end
45
+
46
+ # Return if the debug mode is activated or not
47
+ def debug_logging
48
+ log.level == Logger::DEBUG
49
+ end
50
+ end
51
+
10
52
  def initialize(*args, &block)
11
53
  super
12
54
  self.progname = LOG_PREFIX
@@ -62,7 +62,7 @@ module Datadog
62
62
 
63
63
  statsd.count(stat, value, metric_options(options))
64
64
  rescue StandardError => e
65
- Datadog::Tracer.log.error("Failed to send count stat. Cause: #{e.message} Source: #{e.backtrace.first}")
65
+ Datadog::Logger.log.error("Failed to send count stat. Cause: #{e.message} Source: #{e.backtrace.first}")
66
66
  end
67
67
 
68
68
  def distribution(stat, value = nil, options = nil, &block)
@@ -72,7 +72,7 @@ module Datadog
72
72
 
73
73
  statsd.distribution(stat, value, metric_options(options))
74
74
  rescue StandardError => e
75
- Datadog::Tracer.log.error("Failed to send distribution stat. Cause: #{e.message} Source: #{e.backtrace.first}")
75
+ Datadog::Logger.log.error("Failed to send distribution stat. Cause: #{e.message} Source: #{e.backtrace.first}")
76
76
  end
77
77
 
78
78
  def increment(stat, options = nil)
@@ -81,7 +81,7 @@ module Datadog
81
81
 
82
82
  statsd.increment(stat, metric_options(options))
83
83
  rescue StandardError => e
84
- Datadog::Tracer.log.error("Failed to send increment stat. Cause: #{e.message} Source: #{e.backtrace.first}")
84
+ Datadog::Logger.log.error("Failed to send increment stat. Cause: #{e.message} Source: #{e.backtrace.first}")
85
85
  end
86
86
 
87
87
  def gauge(stat, value = nil, options = nil, &block)
@@ -91,7 +91,7 @@ module Datadog
91
91
 
92
92
  statsd.gauge(stat, value, metric_options(options))
93
93
  rescue StandardError => e
94
- Datadog::Tracer.log.error("Failed to send gauge stat. Cause: #{e.message} Source: #{e.backtrace.first}")
94
+ Datadog::Logger.log.error("Failed to send gauge stat. Cause: #{e.message} Source: #{e.backtrace.first}")
95
95
  end
96
96
 
97
97
  def time(stat, options = nil)
@@ -107,7 +107,7 @@ module Datadog
107
107
  distribution(stat, ((finished - start) * 1000), options)
108
108
  end
109
109
  rescue StandardError => e
110
- Datadog::Tracer.log.error("Failed to send time stat. Cause: #{e.message} Source: #{e.backtrace.first}")
110
+ Datadog::Logger.log.error("Failed to send time stat. Cause: #{e.message} Source: #{e.backtrace.first}")
111
111
  end
112
112
  end
113
113
 
@@ -48,7 +48,7 @@ module Datadog
48
48
  end
49
49
 
50
50
  def log_deprecation_warning(method)
51
- Datadog::Tracer.log.warn("#{method}:#{DEPRECATION_WARNING}")
51
+ Datadog::Logger.log.warn("#{method}:#{DEPRECATION_WARNING}")
52
52
  end
53
53
 
54
54
  class << self
@@ -107,7 +107,7 @@ module Datadog
107
107
  def log_deprecation_warning(method_name)
108
108
  # Only log each deprecation warning once (safeguard against log spam)
109
109
  do_once(method_name) do
110
- Datadog::Tracer.log.warn("#{method_name}:#{DEPRECATION_WARNING}")
110
+ Datadog::Logger.log.warn("#{method_name}:#{DEPRECATION_WARNING}")
111
111
  end
112
112
  end
113
113
  end
@@ -34,7 +34,7 @@ module Datadog
34
34
 
35
35
  result || []
36
36
  rescue => e
37
- Datadog::Tracer.log.debug(
37
+ Datadog::Logger.log.debug(
38
38
  "trace dropped entirely due to `Pipeline.before_flush` error: #{e}"
39
39
  )
40
40
 
@@ -19,7 +19,7 @@ module Datadog
19
19
  def self.inject!(context, env)
20
20
  # Prevent propagation from being attempted if context provided is nil.
21
21
  if context.nil?
22
- ::Datadog::Tracer.log.debug('Cannot inject context into env to propagate over HTTP: context is nil.'.freeze)
22
+ ::Datadog::Logger.log.debug('Cannot inject context into env to propagate over HTTP: context is nil.'.freeze)
23
23
  return
24
24
  end
25
25
 
@@ -58,7 +58,7 @@ module Datadog
58
58
  # Return an empty/new context if we have a mismatch in values extracted
59
59
  msg = "#{context.trace_id} != #{extracted_context.trace_id} && " \
60
60
  "#{context.span_id} != #{extracted_context.span_id}"
61
- ::Datadog::Tracer.log.debug("Cannot extract context from HTTP: extracted contexts differ, #{msg}".freeze)
61
+ ::Datadog::Logger.log.debug("Cannot extract context from HTTP: extracted contexts differ, #{msg}".freeze)
62
62
  # DEV: This will return from `self.extract` not this `each` block
63
63
  return ::Datadog::Context.new
64
64
  end
@@ -27,7 +27,7 @@ module Datadog
27
27
  end
28
28
  end
29
29
  rescue StandardError => e
30
- Datadog::Tracer.log.error("Error while parsing cgroup. Cause: #{e.message} Location: #{e.backtrace.first}")
30
+ Datadog::Logger.log.error("Error while parsing cgroup. Cause: #{e.message} Location: #{e.backtrace.first}")
31
31
  end
32
32
  end
33
33
  end
@@ -61,7 +61,7 @@ module Datadog
61
61
  break
62
62
  end
63
63
  rescue StandardError => e
64
- Datadog::Tracer.log.error(
64
+ Datadog::Logger.log.error(
65
65
  "Error while parsing container info. Cause: #{e.message} Location: #{e.backtrace.first}"
66
66
  )
67
67
  end
@@ -63,7 +63,7 @@ module Datadog
63
63
  def try_flush
64
64
  yield
65
65
  rescue StandardError => e
66
- Datadog::Tracer.log.error("Error while sending runtime metric. Cause: #{e.message}")
66
+ Datadog::Logger.log.error("Error while sending runtime metric. Cause: #{e.message}")
67
67
  end
68
68
 
69
69
  def default_metric_options
@@ -48,7 +48,7 @@ module Datadog
48
48
  # sampled.
49
49
  def initialize(sample_rate = 1.0)
50
50
  unless sample_rate > 0.0 && sample_rate <= 1.0
51
- Datadog::Tracer.log.error('sample rate is not between 0 and 1, disabling the sampler')
51
+ Datadog::Logger.log.error('sample rate is not between 0 and 1, disabling the sampler')
52
52
  sample_rate = 1.0
53
53
  end
54
54
 
@@ -28,7 +28,7 @@ module Datadog
28
28
  def match?(span)
29
29
  @matcher.match?(span)
30
30
  rescue => e
31
- Datadog::Tracer.log.error("Matcher failed. Cause: #{e.message} Source: #{e.backtrace.first}")
31
+ Datadog::Logger.log.error("Matcher failed. Cause: #{e.message} Source: #{e.backtrace.first}")
32
32
  nil
33
33
  end
34
34
 
@@ -19,15 +19,15 @@ module Datadog
19
19
  attr_reader :rules, :rate_limiter, :default_sampler
20
20
 
21
21
  # @param rules [Array<Rule>] ordered list of rules to be applied to a span
22
- # @param rate_limit [Float] number of traces per second, defaults to 100
22
+ # @param rate_limit [Float] number of traces per second, defaults to +100+
23
23
  # @param rate_limiter [RateLimiter] limiter applied after rule matching
24
24
  # @param default_sample_rate [Float] fallback sample rate when no rules apply to a span,
25
25
  # between +[0,1]+, defaults to +1+
26
26
  # @param default_sampler [Sample] fallback strategy when no rules apply to a span
27
27
  def initialize(rules = [],
28
- rate_limit: nil,
28
+ rate_limit: Datadog.configuration.sampling.rate_limit,
29
29
  rate_limiter: nil,
30
- default_sample_rate: nil,
30
+ default_sample_rate: Datadog.configuration.sampling.default_rate,
31
31
  default_sampler: nil)
32
32
 
33
33
  @rules = rules
@@ -95,7 +95,7 @@ module Datadog
95
95
  set_limiter_metrics(span, rate_limiter.effective_rate)
96
96
  end
97
97
  rescue StandardError => e
98
- Datadog::Tracer.log.error("Rule sampling failed. Cause: #{e.message} Source: #{e.backtrace.first}")
98
+ Datadog::Logger.log.error("Rule sampling failed. Cause: #{e.message} Source: #{e.backtrace.first}")
99
99
  yield(span)
100
100
  end
101
101
 
@@ -31,6 +31,9 @@ module Datadog
31
31
  # parsing 64-bit integers for distributed tracing since an upstream system may generate one
32
32
  EXTERNAL_MAX_ID = 2**64
33
33
 
34
+ # This limit is for numeric tags because uint64 could end up rounded.
35
+ NUMERIC_TAG_SIZE_RANGE = (-2**53..2**53)
36
+
34
37
  attr_accessor :name, :service, :resource, :span_type,
35
38
  :start_time, :end_time,
36
39
  :span_id, :trace_id, :parent_id,
@@ -80,9 +83,21 @@ module Datadog
80
83
  #
81
84
  # span.set_tag('http.method', request.method)
82
85
  def set_tag(key, value = nil)
83
- @meta[key] = value.to_s
86
+ # Keys must be unique between tags and metrics
87
+ @metrics.delete(key)
88
+
89
+ # NOTE: Adding numeric tags as metrics is stop-gap support
90
+ # for numeric typed tags. Eventually they will become
91
+ # tags again.
92
+ # Any numeric that is not an integer greater than max size is logged as a metric.
93
+ # Everything else gets logged as a tag.
94
+ if value.is_a?(Numeric) && !(value.is_a?(Integer) && !NUMERIC_TAG_SIZE_RANGE.cover?(value))
95
+ set_metric(key, value)
96
+ else
97
+ @meta[key] = value.to_s
98
+ end
84
99
  rescue StandardError => e
85
- Datadog::Tracer.log.debug("Unable to set the tag #{key}, ignoring it. Caused by: #{e}")
100
+ Datadog::Logger.log.debug("Unable to set the tag #{key}, ignoring it. Caused by: #{e}")
86
101
  end
87
102
 
88
103
  # This method removes a tag for the given key.
@@ -92,17 +107,20 @@ module Datadog
92
107
 
93
108
  # Return the tag with the given key, nil if it doesn't exist.
94
109
  def get_tag(key)
95
- @meta[key]
110
+ @meta[key] || @metrics[key]
96
111
  end
97
112
 
98
113
  # This method sets a tag with a floating point value for the given key. It acts
99
114
  # like `set_tag()` and it simply add a tag without further processing.
100
115
  def set_metric(key, value)
116
+ # Keys must be unique between tags and metrics
117
+ @meta.delete(key)
118
+
101
119
  # enforce that the value is a floating point number
102
120
  value = Float(value)
103
121
  @metrics[key] = value
104
122
  rescue StandardError => e
105
- Datadog::Tracer.log.debug("Unable to set the metric #{key}, ignoring it. Caused by: #{e}")
123
+ Datadog::Logger.log.debug("Unable to set the metric #{key}, ignoring it. Caused by: #{e}")
106
124
  end
107
125
 
108
126
  # This method removes a metric for the given key. It acts like {#remove_tag}.
@@ -112,7 +130,7 @@ module Datadog
112
130
 
113
131
  # Return the metric with the given key, nil if it doesn't exist.
114
132
  def get_metric(key)
115
- @metrics[key]
133
+ @metrics[key] || @meta[key]
116
134
  end
117
135
 
118
136
  # Mark the span with the given error.
@@ -154,7 +172,7 @@ module Datadog
154
172
  @context.close_span(self)
155
173
  @tracer.record(self)
156
174
  rescue StandardError => e
157
- Datadog::Tracer.log.debug("error recording finished trace: #{e}")
175
+ Datadog::Logger.log.debug("error recording finished trace: #{e}")
158
176
  Diagnostics::Health.metrics.error_span_finish(1, tags: ["error:#{e.class.name}"])
159
177
  end
160
178
  self
@@ -27,7 +27,7 @@ module Datadog
27
27
  def write(trace, services = nil)
28
28
  unless services.nil?
29
29
  Datadog::Patcher.do_once('SyncWriter#write') do
30
- Datadog::Tracer.log.warn(%(
30
+ Datadog::Logger.log.warn(%(
31
31
  write: Writing services has been deprecated and no longer need to be provided.
32
32
  write(traces, services) can be updted to write(traces)
33
33
  ))
@@ -38,7 +38,7 @@ module Datadog
38
38
  proc { flush_trace(trace) }
39
39
  )
40
40
  rescue => e
41
- Tracer.log.debug(e)
41
+ Logger.log.debug(e)
42
42
  end
43
43
 
44
44
  private
@@ -49,8 +49,9 @@ module Datadog
49
49
 
50
50
  def flush_trace(trace)
51
51
  processed_traces = Pipeline.process!([trace])
52
+ return if processed_traces.empty?
52
53
  inject_hostname!(processed_traces.first) if Datadog.configuration.report_hostname
53
- transport.send(:traces, processed_traces)
54
+ transport.send_traces(processed_traces)
54
55
  end
55
56
 
56
57
  def inject_hostname!(trace)
@@ -5,8 +5,6 @@ require 'pathname'
5
5
 
6
6
  require 'ddtrace/span'
7
7
  require 'ddtrace/context'
8
- require 'ddtrace/context_flush'
9
- require 'ddtrace/provider'
10
8
  require 'ddtrace/logger'
11
9
  require 'ddtrace/writer'
12
10
  require 'ddtrace/sampler'
@@ -21,57 +19,17 @@ module Datadog
21
19
  # of these function calls and sub-requests would be encapsulated within a single trace.
22
20
  # rubocop:disable Metrics/ClassLength
23
21
  class Tracer
24
- attr_reader :sampler, :tags, :provider
22
+ attr_reader :sampler, :tags, :provider, :context_flush
25
23
  attr_accessor :enabled, :writer
26
24
  attr_writer :default_service
27
25
 
28
26
  ALLOWED_SPAN_OPTIONS = [:service, :resource, :span_type].freeze
29
27
  DEFAULT_ON_ERROR = proc { |span, error| span.set_error(error) unless span.nil? }
30
28
 
31
- # Global, memoized, lazy initialized instance of a logger that is used within the the Datadog
32
- # namespace. This logger outputs to +STDOUT+ by default, and is considered thread-safe.
33
- def self.log
34
- unless defined? @logger
35
- @logger = Datadog::Logger.new(STDOUT)
36
- @logger.level = Logger::WARN
37
- end
38
- @logger
39
- end
40
-
41
- # Override the default logger with a custom one.
42
- def self.log=(logger)
43
- return unless logger
44
- return unless logger.respond_to? :methods
45
- return unless logger.respond_to? :error
46
- if logger.respond_to? :methods
47
- unimplemented = Logger.new(STDOUT).methods - logger.methods
48
- unless unimplemented.empty?
49
- logger.error("logger #{logger} does not implement #{unimplemented}")
50
- return
51
- end
52
- end
53
- @logger = logger
54
- end
55
-
56
- # Activate the debug mode providing more information related to tracer usage
57
- # Default to Warn level unless using custom logger
58
- def self.debug_logging=(value)
59
- if value
60
- log.level = Logger::DEBUG
61
- elsif log.is_a?(Datadog::Logger)
62
- log.level = Logger::WARN
63
- end
64
- end
65
-
66
- # Return if the debug mode is activated or not
67
- def self.debug_logging
68
- log.level == Logger::DEBUG
69
- end
70
-
71
29
  def services
72
30
  # Only log each deprecation warning once (safeguard against log spam)
73
31
  Datadog::Patcher.do_once('Tracer#set_service_info') do
74
- Datadog::Tracer.log.warn('services: Usage of Tracer.services has been deprecated')
32
+ Datadog::Logger.log.warn('services: Usage of Tracer.services has been deprecated')
75
33
  end
76
34
 
77
35
  {}
@@ -90,8 +48,9 @@ module Datadog
90
48
  # tracer.shutdown!
91
49
  #
92
50
  def shutdown!
93
- return if !@enabled || @writer.worker.nil?
94
- @writer.worker.stop
51
+ return unless @enabled
52
+
53
+ @writer.stop unless @writer.nil?
95
54
  end
96
55
 
97
56
  # Return the current active \Context for this traced execution. This method is
@@ -117,7 +76,11 @@ module Datadog
117
76
  @provider = options.fetch(:context_provider, Datadog::DefaultContextProvider.new)
118
77
  @provider ||= Datadog::DefaultContextProvider.new # @provider should never be nil
119
78
 
120
- @context_flush = options[:partial_flush] ? Datadog::ContextFlush.new(options) : nil
79
+ @context_flush = if options[:partial_flush]
80
+ Datadog::ContextFlush::Partial.new(options)
81
+ else
82
+ Datadog::ContextFlush::Finished.new
83
+ end
121
84
 
122
85
  @mutex = Mutex.new
123
86
  @tags = {}
@@ -132,6 +95,7 @@ module Datadog
132
95
  # * +enabled+: set if the tracer submits or not spans to the trace agent
133
96
  # * +hostname+: change the location of the trace agent
134
97
  # * +port+: change the port of the trace agent
98
+ # * +partial_flush+: enable partial trace flushing
135
99
  #
136
100
  # For instance, if the trace agent runs in a different location, just:
137
101
  #
@@ -142,18 +106,17 @@ module Datadog
142
106
 
143
107
  # Those are rare "power-user" options.
144
108
  sampler = options.fetch(:sampler, nil)
145
- max_spans_before_partial_flush = options.fetch(:max_spans_before_partial_flush, nil)
146
- min_spans_before_partial_flush = options.fetch(:min_spans_before_partial_flush, nil)
147
- partial_flush_timeout = options.fetch(:partial_flush_timeout, nil)
148
109
 
149
110
  @enabled = enabled unless enabled.nil?
150
111
  @sampler = sampler unless sampler.nil?
151
112
 
152
113
  configure_writer(options)
153
114
 
154
- @context_flush = Datadog::ContextFlush.new(options) unless min_spans_before_partial_flush.nil? &&
155
- max_spans_before_partial_flush.nil? &&
156
- partial_flush_timeout.nil?
115
+ @context_flush = if options[:partial_flush]
116
+ Datadog::ContextFlush::Partial.new(options)
117
+ else
118
+ Datadog::ContextFlush::Finished.new
119
+ end
157
120
  end
158
121
 
159
122
  # Set the information about the given service. A valid example is:
@@ -164,7 +127,7 @@ module Datadog
164
127
  def set_service_info(service, app, app_type)
165
128
  # Only log each deprecation warning once (safeguard against log spam)
166
129
  Datadog::Patcher.do_once('Tracer#set_service_info') do
167
- Datadog::Tracer.log.warn(%(
130
+ Datadog::Logger.log.warn(%(
168
131
  set_service_info: Usage of set_service_info has been deprecated,
169
132
  service information no longer needs to be reported to the trace agent.
170
133
  ))
@@ -179,7 +142,7 @@ module Datadog
179
142
  begin
180
143
  @default_service = File.basename($PROGRAM_NAME, '.*')
181
144
  rescue StandardError => e
182
- Datadog::Tracer.log.error("unable to guess default service: #{e}")
145
+ Datadog::Logger.log.error("unable to guess default service: #{e}")
183
146
  @default_service = 'ruby'.freeze
184
147
  end
185
148
  @default_service
@@ -302,7 +265,7 @@ module Datadog
302
265
  span = start_span(name, options)
303
266
  # rubocop:disable Lint/UselessAssignment
304
267
  rescue StandardError => e
305
- Datadog::Tracer.log.debug('Failed to start span: #{e}')
268
+ Datadog::Logger.log.debug('Failed to start span: #{e}')
306
269
  ensure
307
270
  return_value = yield(span)
308
271
  end
@@ -332,24 +295,20 @@ module Datadog
332
295
  def record(context)
333
296
  context = context.context if context.is_a?(Datadog::Span)
334
297
  return if context.nil?
335
- trace, sampled = context.get
336
-
337
- # If context flushing is configured...
338
- if @context_flush
339
- if sampled
340
- if trace.nil? || trace.empty?
341
- @context_flush.each_partial_trace(context) do |t|
342
- write(t)
343
- end
344
- else
345
- write(trace)
346
- end
347
- end
348
- # Default behavior
349
- else
350
- ready = !trace.nil? && !trace.empty? && sampled
351
- write(trace) if ready
352
- end
298
+
299
+ record_context(context)
300
+ end
301
+
302
+ # Consume trace from +context+, according to +@context_flush+
303
+ # criteria.
304
+ #
305
+ # \ContextFlush#consume! can return nil or an empty list if the
306
+ # trace is not available to flush or if the trace has not been
307
+ # chosen to be sampled.
308
+ def record_context(context)
309
+ trace = @context_flush.consume!(context)
310
+
311
+ write(trace) if trace && !trace.empty?
353
312
  end
354
313
 
355
314
  # Return the current active span or +nil+.
@@ -372,11 +331,11 @@ module Datadog
372
331
  def write(trace)
373
332
  return if @writer.nil? || !@enabled
374
333
 
375
- if Datadog::Tracer.debug_logging
376
- Datadog::Tracer.log.debug("Writing #{trace.length} spans (enabled: #{@enabled})")
334
+ if Datadog::Logger.debug_logging
335
+ Datadog::Logger.log.debug("Writing #{trace.length} spans (enabled: #{@enabled})")
377
336
  str = String.new('')
378
337
  PP.pp(trace, str)
379
- Datadog::Tracer.log.debug(str)
338
+ Datadog::Logger.log.debug(str)
380
339
  end
381
340
 
382
341
  @writer.write(trace)
@@ -461,6 +420,7 @@ module Datadog
461
420
  :configure_writer,
462
421
  :deactivate_priority_sampling!,
463
422
  :guess_context_and_parent,
423
+ :record_context,
464
424
  :write
465
425
  end
466
426
  end