tingyun_rpm 1.1.4.2 → 1.2.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 +4 -4
  2. data/.gitignore +1 -1
  3. data/Guardfile +10 -0
  4. data/lib/ting_yun/agent.rb +1 -0
  5. data/lib/ting_yun/agent/agent.rb +16 -27
  6. data/lib/ting_yun/agent/collector/error_collector.rb +7 -18
  7. data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +26 -21
  8. data/lib/ting_yun/agent/collector/middle_ware_collector/cpu_sampler.rb +4 -9
  9. data/lib/ting_yun/agent/collector/sql_sampler.rb +32 -188
  10. data/lib/ting_yun/agent/collector/sql_sampler/slow_sql.rb +47 -0
  11. data/lib/ting_yun/agent/collector/sql_sampler/sql_trace.rb +73 -0
  12. data/lib/ting_yun/agent/collector/sql_sampler/transaction_sql_data.rb +26 -0
  13. data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +6 -5
  14. data/lib/ting_yun/agent/collector/stats_engine/stats_hash.rb +2 -2
  15. data/lib/ting_yun/agent/collector/transaction_sampler.rb +23 -159
  16. data/lib/ting_yun/agent/collector/transaction_sampler/class_method.rb +130 -0
  17. data/lib/ting_yun/agent/collector/transaction_sampler/slowest_sample_buffer.rb +1 -1
  18. data/lib/ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base.rb +1 -1
  19. data/lib/ting_yun/agent/cross_app/cross_app_monitor.rb +29 -79
  20. data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +36 -66
  21. data/lib/ting_yun/agent/database.rb +41 -349
  22. data/lib/ting_yun/agent/database/connection_manager.rb +44 -0
  23. data/lib/ting_yun/agent/database/explain_plan_helpers.rb +173 -0
  24. data/lib/ting_yun/agent/database/obfuscator.rb +151 -0
  25. data/lib/ting_yun/agent/database/statement.rb +70 -0
  26. data/lib/ting_yun/agent/event/event_loop.rb +1 -2
  27. data/lib/ting_yun/agent/instance_methods/connect.rb +8 -20
  28. data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +2 -3
  29. data/lib/ting_yun/agent/instance_methods/handle_errors.rb +6 -1
  30. data/lib/ting_yun/agent/instance_methods/start.rb +13 -81
  31. data/lib/ting_yun/agent/transaction.rb +48 -391
  32. data/lib/ting_yun/agent/transaction/apdex.rb +53 -0
  33. data/lib/ting_yun/agent/transaction/attributes.rb +2 -1
  34. data/lib/ting_yun/agent/transaction/class_method.rb +127 -0
  35. data/lib/ting_yun/agent/transaction/exceptions.rb +42 -0
  36. data/lib/ting_yun/agent/transaction/instance_method.rb +139 -0
  37. data/lib/ting_yun/agent/transaction/request_attributes.rb +9 -39
  38. data/lib/ting_yun/agent/transaction/trace.rb +7 -5
  39. data/lib/ting_yun/agent/transaction/trace_node.rb +1 -3
  40. data/lib/ting_yun/agent/transaction/traced_method_stack.rb +2 -3
  41. data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +6 -1
  42. data/lib/ting_yun/agent/transaction/transaction_state.rb +59 -17
  43. data/lib/ting_yun/agent/transaction/transaction_timings.rb +72 -0
  44. data/lib/ting_yun/configuration.rb +11 -0
  45. data/lib/ting_yun/configuration/default_source.rb +20 -17
  46. data/lib/ting_yun/configuration/manager.rb +50 -21
  47. data/lib/ting_yun/frameworks.rb +1 -0
  48. data/lib/ting_yun/frameworks/rails.rb +15 -0
  49. data/lib/ting_yun/instrumentation/active_record.rb +12 -18
  50. data/lib/ting_yun/instrumentation/middleware_tracing.rb +8 -14
  51. data/lib/ting_yun/instrumentation/mongo.rb +21 -27
  52. data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +7 -3
  53. data/lib/ting_yun/instrumentation/moped.rb +2 -2
  54. data/lib/ting_yun/instrumentation/net.rb +4 -5
  55. data/lib/ting_yun/instrumentation/rack.rb +1 -2
  56. data/lib/ting_yun/instrumentation/rails4/active_record_subscriber.rb +22 -20
  57. data/lib/ting_yun/instrumentation/redis.rb +2 -2
  58. data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +1 -1
  59. data/lib/ting_yun/instrumentation/support/external_error.rb +19 -16
  60. data/lib/ting_yun/instrumentation/support/javascript_instrumentor.rb +92 -0
  61. data/lib/ting_yun/instrumentation/support/thrift_helper.rb +73 -0
  62. data/lib/ting_yun/instrumentation/thrift.rb +19 -222
  63. data/lib/ting_yun/logger.rb +1 -0
  64. data/lib/ting_yun/logger/agent_logger.rb +11 -67
  65. data/lib/ting_yun/logger/create_logger_helper.rb +72 -0
  66. data/lib/ting_yun/metrics/metric_data.rb +9 -31
  67. data/lib/ting_yun/metrics/metric_spec.rb +11 -0
  68. data/lib/ting_yun/metrics/stats.rb +24 -1
  69. data/lib/ting_yun/middleware/agent_middleware.rb +28 -0
  70. data/lib/ting_yun/middleware/browser_monitoring.rb +111 -0
  71. data/lib/ting_yun/support/coerce.rb +1 -0
  72. data/lib/ting_yun/support/exception.rb +2 -33
  73. data/lib/ting_yun/support/local_environment.rb +7 -7
  74. data/lib/ting_yun/support/serialize/marshaller.rb +7 -25
  75. data/lib/ting_yun/ting_yun_service.rb +12 -9
  76. data/lib/ting_yun/ting_yun_service/connection.rb +3 -0
  77. data/lib/ting_yun/ting_yun_service/http.rb +4 -1
  78. data/lib/ting_yun/ting_yun_service/request.rb +5 -13
  79. data/lib/ting_yun/ting_yun_service/upload_service.rb +5 -7
  80. data/lib/ting_yun/version.rb +3 -5
  81. data/lib/tingyun_rpm.rb +12 -10
  82. data/tingyun_rpm.gemspec +3 -0
  83. metadata +49 -5
  84. data/.DS_Store +0 -0
  85. data/lib/ting_yun/agent/collector/base_sampler.rb +0 -2
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/support/helper'
3
+ module TingYun
4
+ module Agent
5
+
6
+ class Transaction
7
+ class Apdex
8
+ APDEX_TXN_METRIC_PREFIX = 'Apdex/'.freeze
9
+
10
+ attr_accessor :apdex_start, :transaction_start_time
11
+
12
+ def initialize(start, transaction_start)
13
+ @apdex_start = start || transaction_start
14
+ @transaction_start_time = transaction_start
15
+ end
16
+
17
+ def record_apdex(metric_name, end_time, failed)
18
+ total_duration = TingYun::Helper.time_to_millis(end_time - apdex_start)
19
+ if TingYun::Agent::Transaction.recording_web_transaction?
20
+ record_apdex_metrics(APDEX_TXN_METRIC_PREFIX, total_duration, TingYun::Agent.config[:apdex_t], metric_name, failed)
21
+ end
22
+ end
23
+
24
+ def record_apdex_metrics(transaction_prefix, total_duration, current_apdex_t, metric_name, failed)
25
+ return unless current_apdex_t
26
+ return unless metric_name.start_with?(CONTROLLER_PREFIX)
27
+
28
+ apdex_bucket_global = apdex_bucket(total_duration, failed, current_apdex_t)
29
+ txn_apdex_metric = metric_name.sub(/^[^\/]+\//, transaction_prefix)
30
+ ::TingYun::Agent::Transaction.metrics.record_unscoped(txn_apdex_metric, apdex_bucket_global, current_apdex_t)
31
+ end
32
+
33
+
34
+ def apdex_bucket(duration, failed, apdex_t)
35
+ case
36
+ when failed
37
+ :apdex_f
38
+ when duration <= apdex_t
39
+ :apdex_s
40
+ when duration <= 4 * apdex_t
41
+ :apdex_t
42
+ else
43
+ :apdex_f
44
+ end
45
+ end
46
+
47
+ def queue_time
48
+ @transaction_start_time - @apdex_start
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -11,14 +11,15 @@ module TingYun
11
11
  @request_params = {}
12
12
  end
13
13
 
14
+ # no longer to care about the value if nil or not
14
15
  def add_agent_attribute(key, value)
15
- return if value.nil?
16
16
  @agent_attributes[key] = value
17
17
  end
18
18
 
19
19
  def merge_request_parameters(hash)
20
20
  @request_params.merge!(hash) if hash
21
21
  end
22
+
22
23
  end
23
24
  end
24
25
  end
@@ -0,0 +1,127 @@
1
+ # encoding: utf-8
2
+
3
+ module TingYun
4
+ module Agent
5
+ class Transaction
6
+ # web transaction
7
+ module ClassMethod
8
+
9
+ def tl_current
10
+ TingYun::Agent::TransactionState.tl_get.current_transaction
11
+ end
12
+
13
+ def metrics
14
+ txn = tl_current
15
+ txn && txn.metrics
16
+ end
17
+
18
+
19
+ def recording_web_transaction? #THREAD_LOCAL_ACCESS
20
+ txn = tl_current
21
+ txn && txn.web_category?(txn.category)
22
+ end
23
+
24
+ # See TingYun::Agent.notice_error for options and commentary
25
+ def notice_error(e, options={})
26
+ state = TingYun::Agent::TransactionState.tl_get
27
+ txn = state.current_transaction
28
+ if txn
29
+ txn.exceptions.notice_error(e, options)
30
+ elsif TingYun::Agent.instance
31
+ TingYun::Agent.instance.error_collector.notice_error(e, options)
32
+ end
33
+ end
34
+
35
+
36
+ def stop(state, end_time = Time.now)
37
+
38
+ txn = state.current_transaction
39
+
40
+ unless txn
41
+ TingYun::Agent.logger.error("Failed during Transaction.stop because there is no current transaction")
42
+ return
43
+ end
44
+
45
+ nested_frame = txn.frame_stack.pop
46
+
47
+ if txn.frame_stack.empty?
48
+ txn.stop(state, end_time, nested_frame)
49
+ state.reset
50
+ else
51
+ nested_name = nested_transaction_name(nested_frame.name)
52
+
53
+ if nested_name.start_with?(MIDDLEWARE_PREFIX)
54
+ summary_metrics = MIDDLEWARE_SUMMARY_METRICS
55
+ else
56
+ summary_metrics = EMPTY_SUMMARY_METRICS
57
+ end
58
+
59
+ TingYun::Agent::MethodTracerHelpers.trace_execution_scoped_footer(
60
+ state,
61
+ nested_frame.start_time.to_f,
62
+ nested_name,
63
+ summary_metrics,
64
+ nested_frame,
65
+ NESTED_TRACE_STOP_OPTIONS,
66
+ end_time.to_f)
67
+
68
+ end
69
+
70
+ :transaction_stopped
71
+ rescue => e
72
+ state.reset
73
+ TingYun::Agent.logger.error("Exception during Transaction.stop", e)
74
+ nil
75
+ end
76
+
77
+ def wrap(state, name, category, options = {})
78
+ Transaction.start(state, category, options.merge(:transaction_name => name))
79
+
80
+ begin
81
+ # We shouldn't raise from Transaction.start, but only wrap the yield
82
+ # to be absolutely sure we don't report agent problems as app errors
83
+ yield
84
+ rescue => e
85
+ Transaction.notice_error(e)
86
+ raise e
87
+ ensure
88
+ Transaction.stop(state)
89
+ end
90
+ end
91
+
92
+
93
+ def start(state, category, options)
94
+ category ||= :controller
95
+ txn = state.current_transaction
96
+ if txn
97
+ txn.create_nested_frame(state, category, options)
98
+ else
99
+ txn = start_new_transaction(state, category, options)
100
+ end
101
+
102
+ # merge params every step into here
103
+ txn.attributes.merge_request_parameters(options[:filtered_params])
104
+
105
+ txn
106
+ rescue => e
107
+ TingYun::Agent.logger.error("Exception during Transaction.start", e)
108
+ end
109
+
110
+ def start_new_transaction(state, category, options)
111
+ txn = Transaction.new(category, state.client_transaction_id, options)
112
+ state.reset(txn)
113
+ txn.start(state)
114
+ txn
115
+ end
116
+
117
+ def nested_transaction_name(name)
118
+ if name.start_with?(CONTROLLER_PREFIX) || name.start_with?(RAKE_TRANSACTION_PREFIX)
119
+ "#{SUBTRANSACTION_PREFIX}#{name}"
120
+ else
121
+ name
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ module TingYun
4
+ module Agent
5
+ class Transaction
6
+ class Exceptions
7
+ attr_accessor :exceptions
8
+
9
+ def initialize
10
+ @exceptions = {}
11
+ end
12
+
13
+ def record_exceptions(attributes)
14
+ unless @exceptions.empty?
15
+ @exceptions.each do |exception, options|
16
+ options[:attributes] = attributes
17
+ ::TingYun::Agent.instance.error_collector.notice_error(exception, options)
18
+ end
19
+ end
20
+ end
21
+
22
+ # Do not call this. Invoke the class method instead.
23
+ def notice_error(error, options={}) # :nodoc:
24
+ if @exceptions[error]
25
+ @exceptions[error].merge! options
26
+ else
27
+ @exceptions[error] = options
28
+ end
29
+ end
30
+
31
+ #collector error
32
+ def had_error?
33
+ if @exceptions.empty?
34
+ return false
35
+ else
36
+ return true
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: utf-8
2
+
3
+ module TingYun
4
+ module Agent
5
+ class Transaction
6
+ module InstanceMethod
7
+
8
+ def create_nested_frame(state, category, options)
9
+ @has_children = true
10
+ frame_stack.push TingYun::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, Time.now.to_f)
11
+ name_last_frame(options[:transaction_name])
12
+
13
+ set_default_transaction_name(options[:transaction_name], category)
14
+ end
15
+
16
+
17
+ def set_default_transaction_name(name, category)
18
+ if @frozen_name
19
+ TingYun::Agent.logger.warn("Attempted to rename transaction to '#{name}' after transaction name was already frozen as '#{@frozen_name}'.")
20
+ return
21
+ end
22
+ if influences_transaction_name?(category)
23
+ @default_name = name
24
+ @category = category if category
25
+ end
26
+ end
27
+
28
+
29
+ def name_last_frame(name)
30
+ frame_stack.last.name = name
31
+ end
32
+
33
+
34
+ def best_name
35
+ @frozen_name || @default_name || ::TingYun::Agent::UNKNOWN_METRIC
36
+ end
37
+
38
+
39
+ def influences_transaction_name?(category)
40
+ !category || frame_stack.size == 1 || similar_category?(category)
41
+ end
42
+
43
+ WEB_TRANSACTION_CATEGORIES = [:controller, :uri, :rack, :sinatra, :grape, :middleware, :thrift].freeze
44
+
45
+ def web_category?(category)
46
+ WEB_TRANSACTION_CATEGORIES.include?(category)
47
+ end
48
+
49
+ def similar_category?(category)
50
+ web_category?(@category) == web_category?(category)
51
+ end
52
+
53
+
54
+ def needs_middleware_summary_metrics?(name)
55
+ name.start_with?(MIDDLEWARE_PREFIX)
56
+ end
57
+
58
+ alias_method :ignore, :needs_middleware_summary_metrics?
59
+
60
+ def record_summary_metrics(outermost_node_name,end_time)
61
+ unless @frozen_name == outermost_node_name
62
+ @metrics.record_unscoped(@frozen_name, TingYun::Helper.time_to_millis(end_time.to_f - start_time.to_f))
63
+ end
64
+ end
65
+
66
+ def assign_agent_attributes
67
+
68
+ @attributes.add_agent_attribute(:threadName, "pid-#{$$}");
69
+
70
+ if @request_attributes
71
+ @request_attributes.assign_agent_attributes @attributes
72
+ end
73
+
74
+ @attributes.add_agent_attribute(:tx_id, @guid);
75
+ @attributes.add_agent_attribute(:metric_name, best_name);
76
+
77
+ end
78
+
79
+
80
+ # This transaction-local hash may be used as temprory storage by
81
+ # instrumentation that needs to pass data from one instrumentation point
82
+ # to another.
83
+ #
84
+ # For example, if both A and B are instrumented, and A calls B
85
+ # but some piece of state needed by the instrumentation at B is only
86
+ # available at A, the instrumentation at A may write into the hash, call
87
+ # through, and then remove the key afterwards, allowing the
88
+ # instrumentation at B to read the value in between.
89
+ #
90
+ # Keys should be symbols, and care should be taken to not generate key
91
+ # names dynamically, and to ensure that keys are removed upon return from
92
+ # the method that creates them.
93
+ #
94
+ def instrumentation_state
95
+ @instrumentation_state ||= {}
96
+ end
97
+
98
+ def with_database_metric_name(model, method, product=nil)
99
+ previous = self.instrumentation_state[:datastore_override]
100
+ model_name = case model
101
+ when Class
102
+ model.name
103
+ when String
104
+ model
105
+ else
106
+ model.to_s
107
+ end
108
+ @instrumentation_state[:datastore_override] = [method, model_name, product]
109
+ yield
110
+ ensure
111
+ @instrumentation_state[:datastore_override] = previous
112
+ end
113
+
114
+ def freeze_name_and_execute
115
+ unless @frozen_name
116
+ @frozen_name = best_name
117
+ end
118
+
119
+ yield if block_given?
120
+ end
121
+
122
+
123
+
124
+ HEX_DIGITS = (0..15).map{|i| i.to_s(16)}
125
+ GUID_LENGTH = 16
126
+
127
+ # generate a random 64 bit uuid
128
+ private
129
+ def generate_guid
130
+ guid = ''
131
+ GUID_LENGTH.times do
132
+ guid << HEX_DIGITS[rand(16)]
133
+ end
134
+ guid
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -25,41 +25,15 @@ module TingYun
25
25
  @cookie = set_cookie(request)
26
26
  end
27
27
 
28
- def assign_agent_attributes(txn)
29
-
30
- if request_path
31
- txn.add_agent_attribute :request_path, request_path
32
- end
33
-
34
- if referer
35
- txn.add_agent_attribute :referer, referer
36
- end
37
-
38
- if accept
39
- txn.add_agent_attribute :accept, accept
40
- end
41
-
42
- if content_length
43
- txn.add_agent_attribute :contentLength, content_length
44
- end
45
-
46
- if host
47
- txn.add_agent_attribute :host, host
48
- end
49
-
50
- if port
51
- txn.add_agent_attribute :port, port
52
- end
53
-
54
- if user_agent
55
- txn.add_agent_attribute :userAgent, user_agent
56
- end
57
-
58
- if request_method
59
- txn.add_agent_attribute :method, request_method
60
- end
61
-
62
-
28
+ def assign_agent_attributes(attributes)
29
+ attributes.add_agent_attribute :request_path, request_path
30
+ attributes.add_agent_attribute :referer, referer
31
+ attributes.add_agent_attribute :accept, accept
32
+ attributes.add_agent_attribute :contentLength, content_length
33
+ attributes.add_agent_attribute :host, host
34
+ attributes.add_agent_attribute :port, port
35
+ attributes.add_agent_attribute :userAgent, user_agent
36
+ attributes.add_agent_attribute :method, request_method
63
37
  end
64
38
 
65
39
 
@@ -68,16 +42,12 @@ module TingYun
68
42
  # Make a safe attempt to get the referer from a request object, generally successful when
69
43
  # it's a Rack request.
70
44
 
71
-
72
-
73
45
  def referer_from_request request
74
46
  if referer = attribute_from_request(request, :referer)
75
47
  TingYun::Agent::HTTPClients::URIUtil.strip_query_string referer.to_s
76
48
  end
77
49
  end
78
50
 
79
-
80
-
81
51
  ROOT_PATH = "/".freeze
82
52
 
83
53
  def path_from_request request