tingyun_rpm 1.4.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -0
  3. data/lib/ting_yun/agent.rb +7 -1
  4. data/lib/ting_yun/agent/collector/error_collector.rb +103 -25
  5. data/lib/ting_yun/agent/collector/error_collector/error_trace_array.rb +2 -0
  6. data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +20 -13
  7. data/lib/ting_yun/agent/collector/transaction_sampler.rb +4 -1
  8. data/lib/ting_yun/agent/collector/transaction_sampler/class_method.rb +4 -4
  9. data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +1 -3
  10. data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +6 -0
  11. data/lib/ting_yun/agent/method_tracer_helpers.rb +6 -4
  12. data/lib/ting_yun/agent/transaction.rb +15 -15
  13. data/lib/ting_yun/agent/transaction/apdex.rb +1 -1
  14. data/lib/ting_yun/agent/transaction/class_method.rb +14 -17
  15. data/lib/ting_yun/agent/transaction/exceptions.rb +19 -6
  16. data/lib/ting_yun/agent/transaction/instance_method.rb +8 -4
  17. data/lib/ting_yun/agent/transaction/trace.rb +23 -4
  18. data/lib/ting_yun/agent/transaction/trace_node.rb +26 -6
  19. data/lib/ting_yun/agent/transaction/traced_method_stack.rb +2 -2
  20. data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +17 -8
  21. data/lib/ting_yun/configuration/default_source.rb +22 -1
  22. data/lib/ting_yun/http/abstract_request.rb +23 -0
  23. data/lib/ting_yun/http/curb_wrappers.rb +76 -0
  24. data/lib/ting_yun/http/excon_wrappers.rb +81 -0
  25. data/lib/ting_yun/http/http_client_request.rb +2 -2
  26. data/lib/ting_yun/http/net_http_request.rb +2 -2
  27. data/lib/ting_yun/http/typhoeus_wrappers.rb +88 -0
  28. data/lib/ting_yun/instrumentation/bunny.rb +3 -3
  29. data/lib/ting_yun/instrumentation/curb.rb +191 -0
  30. data/lib/ting_yun/instrumentation/excon.rb +131 -0
  31. data/lib/ting_yun/instrumentation/grape.rb +4 -2
  32. data/lib/ting_yun/instrumentation/kafka.rb +3 -3
  33. data/lib/ting_yun/instrumentation/memcached.rb +1 -1
  34. data/lib/ting_yun/instrumentation/middleware_proxy.rb +17 -1
  35. data/lib/ting_yun/instrumentation/middleware_tracing.rb +1 -1
  36. data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +1 -0
  37. data/lib/ting_yun/instrumentation/net.rb +24 -24
  38. data/lib/ting_yun/instrumentation/rack.rb +10 -10
  39. data/lib/ting_yun/instrumentation/rails3/action_controller.rb +1 -1
  40. data/lib/ting_yun/instrumentation/rake.rb +8 -4
  41. data/lib/ting_yun/instrumentation/support/action_controller_subscriber.rb +1 -1
  42. data/lib/ting_yun/instrumentation/support/action_view_subscriber.rb +2 -2
  43. data/lib/ting_yun/instrumentation/support/active_record_subscriber.rb +2 -2
  44. data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +3 -3
  45. data/lib/ting_yun/instrumentation/support/external_error.rb +4 -4
  46. data/lib/ting_yun/instrumentation/support/external_helper.rb +6 -1
  47. data/lib/ting_yun/instrumentation/thrift.rb +1 -1
  48. data/lib/ting_yun/instrumentation/typhoeus.rb +75 -0
  49. data/lib/ting_yun/support/exception.rb +2 -0
  50. data/lib/ting_yun/support/http_clients/uri_util.rb +12 -7
  51. data/lib/ting_yun/ting_yun_service.rb +1 -1
  52. data/lib/ting_yun/ting_yun_service/upload_service.rb +15 -3
  53. data/lib/ting_yun/version.rb +2 -2
  54. metadata +9 -3
  55. data/lib/ting_yun/http/generic_request.rb +0 -8
@@ -0,0 +1,131 @@
1
+ TingYun::Support::LibraryDetection.defer do
2
+ named :excon
3
+
4
+ EXCON_MIN_VERSION = Gem::Version.new("0.10.1")
5
+ EXCON_MIDDLEWARE_MIN_VERSION = Gem::Version.new("0.19.0")
6
+
7
+ depends_on do
8
+ defined?(::Excon) && defined?(::Excon::VERSION)
9
+ end
10
+
11
+ executes do
12
+ excon_version = Gem::Version.new(::Excon::VERSION)
13
+ if excon_version >= EXCON_MIN_VERSION
14
+ install_excon_instrumentation(excon_version)
15
+ else
16
+ ::TingYun::Agent.logger.warn("Excon instrumentation requires at least version #{EXCON_MIN_VERSION}")
17
+ end
18
+ end
19
+
20
+ def install_excon_instrumentation(excon_version)
21
+ require 'ting_yun/agent/cross_app/cross_app_tracing'
22
+ require 'ting_yun/http/excon_wrappers'
23
+
24
+ if excon_version >= EXCON_MIDDLEWARE_MIN_VERSION
25
+ install_middleware_excon_instrumentation
26
+ else
27
+ install_legacy_excon_instrumentation
28
+ end
29
+ end
30
+
31
+ def install_middleware_excon_instrumentation
32
+ ::TingYun::Agent.logger.info 'Installing middleware-based Excon instrumentation'
33
+ defaults = Excon.defaults
34
+
35
+ if defaults[:middlewares]
36
+ defaults[:middlewares] << ::Excon::Middleware::TingYunCrossAppTracing
37
+ else
38
+ ::TingYun::Agent.logger.warn("Did not find :middlewares key in Excon.defaults, skipping Excon instrumentation")
39
+ end
40
+ end
41
+
42
+ def install_legacy_excon_instrumentation
43
+ ::TingYun::Agent.logger.info 'Installing legacy Excon instrumentation'
44
+
45
+ ::Excon::Connection.install_tingyun_instrumentation
46
+ end
47
+
48
+
49
+ end
50
+
51
+ module ::Excon
52
+ class Connection
53
+ def tingyun_connection_params
54
+ (@connection || @data)
55
+ end
56
+
57
+ def tingyun_resolved_request_params(request_params)
58
+ resolved = tingyun_connection_params.merge(request_params)
59
+ resolved[:headers] = resolved[:headers].merge(request_params[:headers] || {})
60
+ resolved
61
+ end
62
+
63
+ def request_with_tingyun_trace(params, &block)
64
+ orig_response = nil
65
+ resolved_params = tingyun_resolved_request_params(params)
66
+ wrapped_request = ::TingYun::Http::ExconHTTPRequest.new(resolved_params)
67
+ ::TingYun::Agent::CrossAppTracing.trace_http_request(wrapped_request) do
68
+ orig_response = request_without_tingyun_trace(resolved_params, &block)
69
+ ::TingYun::Http::ExconHTTPResponse.new(orig_response)
70
+ end
71
+ orig_response
72
+ end
73
+
74
+ def self.install_tingyun_instrumentation
75
+ alias request_without_tingyun_trace request
76
+ alias request request_with_tingyun_trace
77
+ end
78
+ end
79
+
80
+ module Middleware
81
+ class TingYunCrossAppTracing
82
+ TRACE_DATA_IVAR = :@tingyun_trace_data
83
+
84
+ def initialize(stack)
85
+ @stack = stack
86
+ end
87
+
88
+ def request_call(datum)
89
+ begin
90
+ # Only instrument this request if we haven't already done so, because
91
+ # we can get request_call multiple times for requests marked as
92
+ # :idempotent in the options, but there will be only a single
93
+ # accompanying response_call/error_call.
94
+ if datum[:connection] && !datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
95
+ wrapped_request = ::TingYun::Http::ExconHTTPRequest.new(datum)
96
+ state = TingYun::Agent::TransactionState.tl_get
97
+ t0 = Time.now.to_f
98
+ node = TingYun::Agent::CrossAppTracing.start_trace(state, t0, wrapped_request)
99
+
100
+ datum[:connection].instance_variable_set(TRACE_DATA_IVAR, [t0, node, wrapped_request])
101
+ end
102
+ rescue => e
103
+ TingYun::Agent.logger.debug(e)
104
+ end
105
+ @stack.request_call(datum)
106
+ end
107
+
108
+ def response_call(datum)
109
+ finish_trace(datum)
110
+ @stack.response_call(datum)
111
+ end
112
+
113
+ def error_call(datum)
114
+ finish_trace(datum)
115
+ @stack.error_call(datum)
116
+ end
117
+
118
+ def finish_trace(datum)
119
+ trace_data = datum[:connection] && datum[:connection].instance_variable_get(TRACE_DATA_IVAR)
120
+ if trace_data
121
+ datum[:connection].instance_variable_set(TRACE_DATA_IVAR, nil)
122
+ t0, segment, wrapped_request = trace_data
123
+ if datum[:response]
124
+ wrapped_response = ::TingYun::Http::ExconHTTPResponse.new(datum[:response])
125
+ end
126
+ TingYun::Agent::CrossAppTracing.finish_trace(TingYun::Agent::TransactionState.tl_get,t0, segment, wrapped_request, wrapped_response )
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -21,13 +21,15 @@ TingYun::Support::LibraryDetection.defer do
21
21
  name = ["Grape",
22
22
  self.options[:method].first,
23
23
  self.options[:for].to_s,
24
- self.namespace.sub(%r{\A/}, ''), # removing leading slashes
25
- self.options[:path].first.sub(%r{\A/}, ''),
24
+ self.namespace.to_s.sub(%r{\A/}, ''), # removing leading slashes
25
+ self.options[:path].first.to_s.sub(%r{\A/}, ''),
26
26
  ].compact.select{ |n| n.to_s unless n.to_s.empty? }.join("/")
27
27
  TingYun::Agent::Transaction.set_default_transaction_name(name, :controller)
28
28
  run_without_tingyun(*args)
29
29
  rescue => e
30
30
  TingYun::Agent.logger.info("Error getting Grape Endpoint Name. Error: #{e.message}. Options: #{self.options.inspect}")
31
+ TingYun::Agent.notice_error(e,:type=>:exception)
32
+ raise e
31
33
  end
32
34
 
33
35
  end
@@ -98,7 +98,7 @@ TingYun::Support::LibraryDetection.defer do
98
98
  TingYun::Agent.logger.error("Failed to kafka each_message in client : ", e)
99
99
  block.call(message)
100
100
  ensure
101
- TingYun::Agent::Transaction.stop(state, Time.now, summary_metrics)
101
+ TingYun::Agent::Transaction.stop(state, Time.now.to_f, summary_metrics)
102
102
  end
103
103
  end
104
104
  each_message_without_tingyun(*args, **options, &wrap_block)
@@ -127,7 +127,7 @@ TingYun::Support::LibraryDetection.defer do
127
127
  TingYun::Agent.logger.error("Failed to Bunny call_with_tingyun : ", e)
128
128
  block.call(message)
129
129
  ensure
130
- TingYun::Agent::Transaction.stop(state, Time.now, summary_metrics)
130
+ TingYun::Agent::Transaction.stop(state, Time.now.to_f, summary_metrics)
131
131
  end
132
132
  end
133
133
  if options.empty? && args.empty?
@@ -158,7 +158,7 @@ TingYun::Support::LibraryDetection.defer do
158
158
  TingYun::Agent.logger.error("Failed to Bunny call_with_tingyun : ", e)
159
159
  block.call(batch)
160
160
  ensure
161
- TingYun::Agent::Transaction.stop(state, Time.now, summary_metrics)
161
+ TingYun::Agent::Transaction.stop(state, Time.now.to_f, summary_metrics)
162
162
  end
163
163
  end
164
164
  if options.empty? && args.empty?
@@ -28,7 +28,7 @@ TingYun::Support::LibraryDetection.defer do
28
28
  named :memcached
29
29
 
30
30
  depends_on do
31
- defined?(::Memcached) || (defined?(::Dalli) && defined?(::Dalli::Client)) && false
31
+ defined?(::Memcached) || (defined?(::Dalli) && defined?(::Dalli::Client))
32
32
  end
33
33
 
34
34
  depends_on do
@@ -8,15 +8,28 @@ module TingYun
8
8
  include TingYun::Instrumentation::MiddlewareTracing
9
9
 
10
10
 
11
+ class RackApp
12
+ def initialize(middleware_class)
13
+ @middleware = middleware_class
14
+ end
15
+
16
+ def new(app, *args, &block)
17
+ middleware_instance = @middleware.new(app, *args, &block)
18
+ MiddlewareProxy.wrap(middleware_instance)
19
+ end
20
+ end
11
21
 
12
22
  def self.is_sinatra_app?(target)
13
23
  defined?(::Sinatra::Base) && target.kind_of?(::Sinatra::Base)
14
24
  end
15
25
 
16
26
  def self.needs_wrapping?(target)
17
- !target.respond_to?(:_nr_has_middleware_tracing)
27
+ !target.respond_to?(:_nr_has_middleware_tracing) &&
28
+ !is_sinatra_app?(target)
18
29
  end
19
30
 
31
+
32
+
20
33
  def self.wrap(target, is_app=false)
21
34
  if needs_wrapping?(target)
22
35
  self.new(target, is_app)
@@ -25,6 +38,9 @@ module TingYun
25
38
  end
26
39
  end
27
40
 
41
+ def self.for_class(target_class)
42
+ RackApp.new(target_class)
43
+ end
28
44
 
29
45
  attr_reader :target, :category, :transaction_options
30
46
 
@@ -71,7 +71,7 @@ module TingYun
71
71
 
72
72
  result
73
73
  rescue Exception => e
74
- TingYun::Agent.notice_error(e)
74
+ TingYun::Agent.notice_error(e,:type=>:error)
75
75
  raise e
76
76
  ensure
77
77
  TingYun::Agent::Transaction.stop(state)
@@ -60,6 +60,7 @@ module TingYun
60
60
  def log_notification_error(event_type, error)
61
61
  TingYun::Agent.logger.error("Error during MongoDB #{event_type} event:")
62
62
  TingYun::Agent.logger.log_exception(:error, error)
63
+ TingYun::Agent.notice_error(error,:type=>:exception)
63
64
  end
64
65
 
65
66
 
@@ -31,30 +31,30 @@ TingYun::Support::LibraryDetection.defer do
31
31
  alias :request :request_with_tingyun_trace
32
32
 
33
33
 
34
- class << self
35
- def get_response_with_tingyun(uri_or_host, path = nil, port = nil, &block)
36
- begin
37
- get_response_without_tingyun(uri_or_host, path , port , &block)
38
- rescue => e
39
- ::TingYun::Instrumentation::Support::ExternalError.handle_error(e, "External/#{uri_or_host.to_s.gsub(/\/\z/,'').gsub('/','%2F')}/net%2Fhttp")
40
- raise e
41
- end
42
- end
43
- alias get_response_without_tingyun get_response
44
- alias get_response get_response_with_tingyun
45
-
46
- def start_with_tingyun(address, *arg, &block)
47
- begin
48
- start_without_tingyun(address, *arg, &block)
49
- rescue => e
50
- ::TingYun::Instrumentation::Support::ExternalError.handle_error(e, "External/#{address.to_s.gsub(/\/\z/,'').gsub('/','%2F')}/net%2Fhttp")
51
- raise e
52
- end
53
- end
54
- alias :start_without_tingyun :start
55
- alias :start :start_with_tingyun
56
-
57
- end
34
+ # class << self
35
+ # def get_response_with_tingyun(uri_or_host, path = nil, port = nil, &block)
36
+ # begin
37
+ # get_response_without_tingyun(uri_or_host, path , port , &block)
38
+ # rescue => e
39
+ # ::TingYun::Instrumentation::Support::ExternalError.handle_error(e, "External/#{uri_or_host.to_s.gsub(/\/\z/,'').gsub('/','%2F')}/net%2Fhttp")
40
+ # raise e
41
+ # end
42
+ # end
43
+ # alias get_response_without_tingyun get_response
44
+ # alias get_response get_response_with_tingyun
45
+ #
46
+ # def start_with_tingyun(address, *arg, &block)
47
+ # begin
48
+ # start_without_tingyun(address, *arg, &block)
49
+ # rescue => e
50
+ # # ::TingYun::Instrumentation::Support::ExternalError.handle_error(e, "External/#{address.to_s.gsub(/\/\z/,'').gsub('/','%2F')}/net%2Fhttp")
51
+ # raise e
52
+ # end
53
+ # end
54
+ # alias :start_without_tingyun :start
55
+ # alias :start :start_with_tingyun
56
+ #
57
+ # end
58
58
  end
59
59
  end
60
60
  end
@@ -39,14 +39,14 @@ module TingYun
39
39
  end
40
40
 
41
41
 
42
- # def use_with_tingyun(middleware_class, *args, &blk)
43
- # if ::TingYun::Instrumentation::RackHelpers.middleware_instrumentation_enabled?
44
- # wrapped_middleware_class = ::TingYun::Instrumentation::MiddlewareProxy.for_class(middleware_class)
45
- # use_without_tingyun(wrapped_middleware_class, *args, &blk)
46
- # else
47
- # use_without_tingyun(middleware_class, *args, &blk)
48
- # end
49
- # end
42
+ def use_with_tingyun(middleware_class, *args, &blk)
43
+ if ::TingYun::Instrumentation::RackHelpers.middleware_instrumentation_enabled?
44
+ wrapped_middleware_class = ::TingYun::Instrumentation::MiddlewareProxy.for_class(middleware_class)
45
+ use_without_tingyun(wrapped_middleware_class, *args, &blk)
46
+ else
47
+ use_without_tingyun(middleware_class, *args, &blk)
48
+ end
49
+ end
50
50
 
51
51
  # We patch this method for a reason that actually has nothing to do with
52
52
  # instrumenting rack itself. It happens to be a convenient and
@@ -99,8 +99,8 @@ TingYun::Support::LibraryDetection.defer do
99
99
  alias_method :run_without_tingyun, :run
100
100
  alias_method :run, :run_with_tingyun
101
101
  #
102
- # alias_method :use_without_tingyun, :use
103
- # alias_method :use, :use_with_tingyun
102
+ alias_method :use_without_tingyun, :use
103
+ alias_method :use, :use_with_tingyun
104
104
  end
105
105
 
106
106
  end
@@ -14,7 +14,7 @@ module TingYun
14
14
 
15
15
 
16
16
  def tingyun_metric_path(action_name_override = nil)
17
- if find_rule(request.request_method.upcase, request.path, request.env, request.filtered_parameters)
17
+ if TingYun::Agent.config[:'naming.rules_enabled'] && find_rule(request.request_method.upcase, request.path, request.env, request.filtered_parameters)
18
18
  return "Rails/#{namespace}/#{name(request.path.slice(1..-1), request.env, request.filtered_parameters, request.cookies)}"
19
19
  else
20
20
  return "URL/#{self.env["PATH_INFO"][1..-1].gsub(/\//,'%2F')}" unless TingYun::Agent.config[:'nbs.auto_action_naming']
@@ -7,7 +7,7 @@ TingYun::Support::LibraryDetection.defer do
7
7
  depends_on do
8
8
  defined?(::Rake)&&
9
9
  !::TingYun::Agent.config[:'disable_rake'] &&
10
- ::TingYun::Agent.config[:'rake.tasks'].any? &&
10
+ ::TingYun::Agent::Instrumentation::RakeInstrumentation.supported_instrument? &&
11
11
  ::TingYun::Agent::Instrumentation::RakeInstrumentation.supported_version?
12
12
  end
13
13
 
@@ -59,9 +59,9 @@ module TingYun
59
59
  end
60
60
 
61
61
  def self.should_trace? name
62
- TingYun::Agent.config[:'rake.tasks'].any? do |task|
63
- task == name
64
- end
62
+ return ::TingYun::Agent.config[:'rake.tasks'].include?(name) if ::TingYun::Agent.config[:'rake.tasks'].any?
63
+ return !TingYun::Agent.config[:'rake.black.tasks'].include?(name) if ::TingYun::Agent.config[:'rake.black.tasks'].any?
64
+ return false
65
65
  end
66
66
 
67
67
  def self.ensure_at_exit
@@ -106,6 +106,10 @@ module TingYun
106
106
  end
107
107
  end
108
108
  end
109
+
110
+ def self.supported_instrument?
111
+ ::TingYun::Agent.config[:'rake.tasks'].any? or ::TingYun::Agent.config[:'rake.black.tasks'].any?
112
+ end
109
113
  end
110
114
  end
111
115
  end
@@ -74,7 +74,7 @@ module TingYun
74
74
  end
75
75
 
76
76
  def metric_name
77
- if find_rule(method, uri, request.header, params)
77
+ if TingYun::Agent.config[:'naming.rules_enabled'] && find_rule(method, uri, request.header, params)
78
78
  @metric_name = "WebAction/Rails/#{namespace}/#{name(uri, request.header, params, request.cookie)}"
79
79
  else
80
80
  if TingYun::Agent.config[:'nbs.auto_action_naming']
@@ -18,7 +18,7 @@ module TingYun
18
18
 
19
19
  if event.recordable?
20
20
  stack = state.traced_method_stack
21
- event.frame = stack.push_frame(state, :action_view, event.time)
21
+ event.frame = stack.push_frame(state, :action_view, event.time.to_f)
22
22
  end
23
23
  rescue => e
24
24
  log_notification_error(e, name, 'start')
@@ -31,7 +31,7 @@ module TingYun
31
31
 
32
32
  if event.recordable?
33
33
  stack = state.traced_method_stack
34
- frame = stack.pop_frame(state, event.frame, event.metric_name, event.end)
34
+ frame = stack.pop_frame(state, event.frame, event.metric_name, event.end.to_f)
35
35
  record_metrics(event, frame)
36
36
  end
37
37
  rescue => e
@@ -49,7 +49,7 @@ module TingYun
49
49
  stack = state.traced_method_stack
50
50
  state.timings.sql_duration = state.timings.sql_duration + event.duration
51
51
  # enter transaction trace node
52
- frame = stack.push_frame(state, :active_record, event.time)
52
+ frame = stack.push_frame(state, :active_record, event.time.to_f)
53
53
 
54
54
  sql_sampler.notice_sql(event.payload[:sql], base, config,
55
55
  TingYun::Helper.milliseconds_to_seconds(event.duration),
@@ -58,7 +58,7 @@ module TingYun
58
58
  transaction_sampler.notice_sql(event.payload[:sql], config, event.duration,
59
59
  state, @explainer, event.payload[:binds], event.payload[:name])
60
60
  # exit transaction trace node
61
- stack.pop_frame(state, frame, base, event.end, true, metric)
61
+ stack.pop_frame(state, frame, base, event.end.to_f, true, metric)
62
62
  end
63
63
 
64
64
  def record_metrics(event, config)
@@ -228,8 +228,8 @@ module TingYun
228
228
  begin
229
229
  yield
230
230
  rescue => e
231
- ::TingYun::Agent.notice_error(e)
232
- raise
231
+ ::TingYun::Agent.notice_error(e,:type=> :exception)
232
+ raise e
233
233
  end
234
234
  ensure
235
235
  TingYun::Agent::Transaction.stop(state)
@@ -245,7 +245,7 @@ module TingYun
245
245
  txn_options[:request] ||= trace_options[:request] if trace_options[:request]
246
246
  txn_options[:filtered_params] = trace_options[:params]
247
247
  txn_options[:transaction_name] = TingYun::Instrumentation::Support::TransactionNamer.name_for(nil, self, category, trace_options)
248
- txn_options[:apdex_start_time] = Time.now
248
+ txn_options[:apdex_start_time] = Time.now.to_f
249
249
 
250
250
  txn_options
251
251
  end