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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3752c62ac9fc5fded9a78b273cf8d82254d07499
4
- data.tar.gz: 92668b61dc19882c8063fcbfe1f38a7019f4f574
3
+ metadata.gz: 1e1698a0cac85df291567637e7d8905c7dd5d30b
4
+ data.tar.gz: 504578a77dac8308f1f43d6cec9933da44778a57
5
5
  SHA512:
6
- metadata.gz: 3612d7ea6911dd1d38fb3e868f6fb9d753d3d0cd494c7fb770543c0263fa150fca4e09e2cb165f6ebc159274f92a25e8f27bc4dd46ebabc0f511e00da060b4a5
7
- data.tar.gz: f9bb466fabbb9be45e1353d751299a45476a64beb32343c5d5351ae5cda9a7e3c74c5d2efee753f8037e466527dddd505239fcf6a096727a1bcc09dc3a0c563c
6
+ metadata.gz: e067d0a87a03f9428e811cea75288256ad09cc992ead66d89337ca6966d7428acaa6c2a781a67bf91b77ef62a20057c1d65445dbe6640bc686f43b0ceb52c0ff
7
+ data.tar.gz: 9246032c6e6841630838a20713a86355a4f73b5085ff3ce1f066988646409dc4b688f2fde31b3fa4d2e4f0e72ea8f6cbb54bf8f070d42ab8f1feae63c33cece7
data/.gitignore CHANGED
@@ -11,4 +11,4 @@ log/
11
11
  .ruby-version
12
12
  .idea/
13
13
  todo
14
-
14
+ .DS_Store
data/Guardfile CHANGED
@@ -23,3 +23,13 @@ guard :minitest, :test_folders => ['test/ting_yun'], :all_after_pass => false do
23
23
  watch('test/agent_helper.rb') { "test/tingyun" }
24
24
 
25
25
  end
26
+
27
+ guard "rubycritic" do
28
+ watch(%r{^app/(.+)\.rb$})
29
+ watch(%r{^lib/(.+)\.rb$})
30
+ end
31
+
32
+ # A sample Guardfile
33
+ # More info at https://github.com/guard/guard#readme
34
+
35
+
@@ -46,6 +46,7 @@ module TingYun
46
46
  end
47
47
 
48
48
 
49
+
49
50
  # Record a value for the given metric name.
50
51
  #
51
52
  # This method should be used to record event-based metrics such as method
@@ -9,6 +9,7 @@ require 'ting_yun/agent/event/event_listener'
9
9
  require 'ting_yun/agent/dispatcher'
10
10
  require 'ting_yun/agent/collector/middle_ware_collector'
11
11
  require 'ting_yun/agent/cross_app/cross_app_monitor'
12
+ require 'ting_yun/agent/collector/transaction_sampler'
12
13
 
13
14
 
14
15
  # The Agent is a singleton that is instantiated when the plugin is
@@ -25,7 +26,7 @@ module TingYun
25
26
  end
26
27
 
27
28
  # service for communicating with collector
28
- attr_accessor :service, :cross_app_monitor
29
+ attr_accessor :service, :cross_app_monitor, :middleware
29
30
  attr_reader :events
30
31
 
31
32
  extend ClassMethods
@@ -37,11 +38,11 @@ module TingYun
37
38
  @environment_report = nil
38
39
  @service = TingYunService.new
39
40
  @connect_state = :pending #[:pending, :connected, :disconnected]
40
- @connect_attempts = 0
41
41
  @events = TingYun::Agent::Event::EventListener.new
42
42
  @after_fork_lock = Mutex.new
43
43
  @dispatcher = TingYun::Agent::Dispatcher.new(@events)
44
44
  @cross_app_monitor = TingYun::Agent::CrossAppMonitor.new(@events)
45
+ @middleware = TingYun::Agent::Collector::MiddleWareCollector.new(@events)
45
46
 
46
47
  init_containers
47
48
  end
@@ -51,7 +52,7 @@ module TingYun
51
52
  return unless agent_should_start?
52
53
  log_startup
53
54
  check_config_and_start_agent
54
- log_version_and_pid
55
+ TingYun::Agent.logger.debug "Ting Yun Ruby Agent #{TingYun::VERSION::STRING} Initialized: pid = #{$$}" # log_version_and_pid
55
56
  end
56
57
 
57
58
  # Attempt a graceful shutdown of the agent, flushing any remaining
@@ -77,39 +78,28 @@ module TingYun
77
78
 
78
79
  def connect!(option={})
79
80
  defaults = {
80
- :keep_retrying => ::TingYun::Agent.config[:keep_retrying],
81
- :force_reconnect => ::TingYun::Agent.config[:force_reconnect]
81
+ :force_reconnect => ::TingYun::Agent.config[:force_reconnect],
82
+ :keep_retrying => ::TingYun::Agent.config[:keep_retrying]
82
83
  }
83
84
  opts = defaults.merge(option)
84
85
  return unless should_connect?(opts[:force_reconnect])
85
86
  TingYun::Agent.logger.debug "Connecting Process to Ting Yun: #$0"
86
87
  query_server_for_configuration
87
- @connected_pid = $$
88
88
  @connect_state = :connected
89
- rescue TingYun::Support::Exception::LicenseException => e
90
- handle_license_error(e)
91
- rescue TingYun::Support::Exception::UnrecoverableAgentException => e
92
- handle_unrecoverable_agent_error(e)
93
- rescue StandardError, Timeout::Error, TingYun::Support::Exception::ServerConnectionException, TingYun::Support::Exception::AgentEnableException => e
94
- log_error(e)
95
- if TingYun::Agent.config[:keep_retrying]
96
- note_connect_failure
89
+ rescue Exception => error
90
+ ::TingYun::Agent.logger.error "Exception of unexpected type during Agent#connect! :", error
91
+ log_error(error)
92
+ if opts[:keep_retrying]
97
93
  ::TingYun::Agent.logger.info "Will re-attempt in 60 seconds"
98
- sleep 60
99
- retry
100
- else
101
- disconnect
94
+ raise
102
95
  end
103
- rescue Exception => e
104
- ::TingYun::Agent.logger.error "Exception of unexpected type during Agent#connect():", e
105
- raise
106
96
  end
107
97
 
108
98
 
109
99
  def install_exit_handler
110
100
  TingYun::Agent.logger.debug("Installing at_exit handler")
111
101
  at_exit do
112
- if need_exit_code_workaround?
102
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
113
103
  exit_status = $!.status if $!.is_a?(SystemExit)
114
104
  shutdown
115
105
  exit exit_status if exit_status
@@ -119,9 +109,6 @@ module TingYun
119
109
  end
120
110
  end
121
111
 
122
- def need_exit_code_workaround?
123
- defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
124
- end
125
112
 
126
113
  def untraced_graceful_disconnect
127
114
  begin
@@ -130,10 +117,12 @@ module TingYun
130
117
  transmit_data
131
118
  end
132
119
  end
133
- rescue => e
134
- ::TingYun::Agent.logger.error e
120
+ rescue => error
121
+ ::TingYun::Agent.logger.error error
135
122
  end
136
123
  end
124
+
125
+
137
126
  end
138
127
  end
139
128
  end
@@ -45,7 +45,7 @@ module TingYun
45
45
  metric_names = [ERRORS_ALL]
46
46
  return metric_names unless txn
47
47
 
48
- if txn.recording_web_transaction?
48
+ if TingYun::Agent::Transaction.recording_web_transaction?
49
49
  metric_names << ERRORS_ALL_WEB
50
50
  else
51
51
  metric_names << ERRORS_ALL_BACK_GROUND
@@ -72,7 +72,7 @@ module TingYun
72
72
  def notice_error(exception, options={})
73
73
  tag_exception(exception)
74
74
  state = ::TingYun::Agent::TransactionState.tl_get
75
- increment_error_count!(state, exception, options)
75
+ increment_error_count(state)
76
76
  noticed_error = create_noticed_error(exception, options)
77
77
  if noticed_error.is_external_error
78
78
  external_error_array.add_to_error_queue(noticed_error)
@@ -85,7 +85,7 @@ module TingYun
85
85
  end
86
86
 
87
87
  # Increments a statistic that tracks total error rate
88
- def increment_error_count!(state, exception, options={})
88
+ def increment_error_count(state)
89
89
  txn = state.current_transaction
90
90
 
91
91
  metric_names = aggregated_metric_names(txn)
@@ -102,26 +102,15 @@ module TingYun
102
102
  EMPTY_STRING = ''.freeze
103
103
 
104
104
  def create_noticed_error(exception, options)
105
- error_metric = options.delete(:metric_name) || EMPTY_STRING
106
-
105
+ attributes = options[:attributes]
106
+ error_metric = attributes.agent_attributes[:metric_name] || EMPTY_STRING
107
107
  noticed_error = TingYun::Agent::Collector::NoticedError.new(error_metric, exception)
108
- noticed_error.request_uri = options.delete(:uri) || EMPTY_STRING
109
- noticed_error.request_port = options.delete(:port)
110
- noticed_error.attributes = options.delete(:attributes)
111
-
112
- noticed_error.file_name = sense_method(exception, :file_name)
113
- noticed_error.line_number = sense_method(exception, :line_number)
108
+ noticed_error.attributes = attributes
114
109
  noticed_error.stack_trace = extract_stack_trace(exception)
115
-
116
- noticed_error.attributes_from_notice_error = options.delete(:custom_params) || {}
117
-
118
- # Any options that are passed to notice_error which aren't known keys
119
- # get treated as custom attributes, so merge them into that hash.
120
- noticed_error.attributes_from_notice_error.merge!(options)
121
-
122
110
  noticed_error
123
111
  end
124
112
 
113
+
125
114
  def skip_notice_error?(exception)
126
115
  exception_tagged?(exception)
127
116
  end
@@ -12,26 +12,28 @@ module TingYun
12
12
  module Collector
13
13
  class NoticedError
14
14
 
15
+
16
+
15
17
  attr_accessor :metric_name, :timestamp, :message, :exception_class_name,
16
- :request_uri, :request_port, :file_name, :line_number,
17
18
  :stack_trace, :attributes_from_notice_error, :attributes,
18
- :count_error, :thread_name, :is_external_error, :external_metric_name, :code, :trace
19
-
19
+ :count_error, :is_external_error, :external_metric_name, :code, :trace
20
20
 
21
21
  attr_reader :exception_id, :is_internal
22
22
 
23
23
 
24
24
  def initialize(metric_name, exception, timestamp = Time.now)
25
+ @metric_name = metric_name
26
+ @timestamp = timestamp
25
27
  @stack_trace = []
26
28
  @count_error = 1
27
29
  @exception_id = exception.object_id
28
- @metric_name = metric_name
29
- @timestamp = timestamp
30
30
  @exception_class_name = exception.is_a?(Exception) ? exception.class.name : 'Error'
31
- @external_metric_name = exception.instance_variable_get :@tingyun_klass
32
- @is_external_error = exception.instance_variable_get :@tingyun_external
33
- @code = exception.instance_variable_get :@tingyun_code
34
- @trace = exception.instance_variable_get :@tingyun_trace
31
+ @is_external_error = exception.respond_to?(:tingyun_external)? exception.tingyun_external : false
32
+ if @is_external_error
33
+ @external_metric_name = exception.tingyun_klass
34
+ @code = exception.tingyun_code
35
+ @trace = exception.tingyun_trace
36
+ end
35
37
  # It's critical that we not hold onto the exception class constant in this
36
38
  # class. These objects get serialized for Resque to a process that might
37
39
  # not have the original exception class loaded, so do all processing now
@@ -62,10 +64,13 @@ module TingYun
62
64
 
63
65
 
64
66
  def ==(other)
65
- if other.respond_to?(:exception_id)
66
- exception_id == other.exception_id
67
+ return true if other.respond_to?(:exception_id) && exception_id == other.exception_id
68
+
69
+ if metric_name == other.metric_name && message == other.message
70
+ @count_error = count_error + 1
71
+ return true
67
72
  else
68
- false
73
+ return false
69
74
  end
70
75
  end
71
76
 
@@ -88,23 +93,23 @@ module TingYun
88
93
  string(exception_class_name),
89
94
  string(message),
90
95
  count_error,
91
- string(request_uri),
96
+ string(attributes.agent_attributes[:request_path]||metric_name),
92
97
  encoder.encode(error_params)
93
98
  ]
94
99
  end
95
100
  end
96
101
 
97
102
  def error_params
98
- hash = {
103
+ hash = {
99
104
  :params => custom_params
100
105
  }
101
- if is_external_error
102
- hash[:stacktrace] = trace
103
- else
104
- hash[:stacktrace] = stack_trace
105
- hash[:requestParams] = request_params
106
- end
107
- hash
106
+ if is_external_error
107
+ hash[:stacktrace] = trace
108
+ else
109
+ hash[:stacktrace] = stack_trace
110
+ hash[:requestParams] = request_params
111
+ end
112
+ hash
108
113
  end
109
114
 
110
115
  def custom_params
@@ -46,16 +46,11 @@ module TingYun
46
46
  return if elapsed < 1 # Causing some kind of math underflow
47
47
 
48
48
  usertime = t.utime - @last_utime
49
- # systemtime = t.stime - @last_stime
50
49
 
51
- # record_systemtime(systemtime) if systemtime >= 0
52
- record_usertime(usertime) if usertime >= 0
53
-
54
- # Calculate the true utilization by taking cpu times and dividing by
55
- # elapsed time X processor_count.
56
-
57
- record_user_util((usertime * 100) / (elapsed * @processor_count))
58
- # record_system_util(systemtime / (elapsed * @processor_count))
50
+ if usertime >= 0
51
+ record_usertime(usertime)
52
+ record_user_util((usertime * 100) / (elapsed * @processor_count))
53
+ end
59
54
  end
60
55
  @last_utime = t.utime
61
56
  @last_stime = t.stime
@@ -2,9 +2,11 @@
2
2
 
3
3
  require 'ting_yun/agent/database'
4
4
  require 'ting_yun/agent/transaction/transaction_state'
5
- require 'ting_yun/support/coerce'
6
- require 'ting_yun/metrics/stats'
7
- require 'ting_yun/support/helper'
5
+
6
+
7
+ require 'ting_yun/agent/collector/sql_sampler/transaction_sql_data'
8
+ require 'ting_yun/agent/collector/sql_sampler/slow_sql'
9
+ require 'ting_yun/agent/collector/sql_sampler/sql_trace'
8
10
  module TingYun
9
11
  module Agent
10
12
  module Collector
@@ -21,7 +23,7 @@ module TingYun
21
23
  # Each slow SQL trace keeps track of the number of times the same normalized
22
24
  # query was seen, the min, max, and total time spent executing those
23
25
  # queries, and an example backtrace from one of the aggregated queries.
24
- #
26
+
25
27
  class SqlSampler
26
28
 
27
29
  MAX_SAMPLES = 10
@@ -33,47 +35,32 @@ module TingYun
33
35
  @samples_lock = Mutex.new
34
36
  end
35
37
 
36
- def enabled?
37
- Agent.config[:'nbs.action_tracer.enabled'] &&
38
- Agent.config[:'nbs.action_tracer.slow_sql'] &&
39
- TingYun::Agent::Database.should_record_sql?('nbs.action_tracer.record_sql')
40
- end
41
-
42
- def on_start_transaction(state, uri=nil)
43
- return unless enabled?
44
-
45
- state.sql_sampler_transaction_data = TransactionSqlData.new
38
+ def self.on_start_transaction(state, uri)
39
+ return unless TingYun::Agent::Database.sql_sampler_enabled?
46
40
 
47
- if Agent.config[:'nbs.action_tracer.slow_sql'] && state.sql_sampler_transaction_data
48
- state.sql_sampler_transaction_data.set_transaction_info(uri)
49
- end
41
+ state.init_sql_transaction(::TingYun::Agent::Collector::TransactionSqlData.new(uri))
50
42
  end
51
43
 
52
44
  # duration{:type => sec}
53
- def notice_sql(sql, metric_name, config, duration, state=nil, explainer=nil) #THREAD_LOCAL_ACCESS sometimes
45
+ def self.notice_sql(sql, metric_name, config, duration, state=nil, explainer=nil, binds=[], name="SQL") #THREAD_LOCAL_ACCESS sometimes
54
46
  start_time = Time.now.to_f
55
47
  state ||= TingYun::Agent::TransactionState.tl_get
56
48
  data = state.sql_sampler_transaction_data
57
49
  return unless data
58
-
59
- if state.sql_recorded? && !metric_name.nil?
60
- if duration*1000 > TingYun::Agent.config[:'nbs.action_tracer.slow_sql_threshold']
61
- if duration*1000 > TingYun::Agent.config[:'nbs.action_tracer.stack_trace_threshold']
62
- backtrace = (caller.reject! { |t| t.include?('tingyun_rpm') })
63
- backtrace = backtrace.first(40) if backtrace.length > 40
64
- backtrace = backtrace.join("\n")
65
- else
66
- backtrace = ''
67
- end
68
- statement = TingYun::Agent::Database::Statement.new(sql, config, explainer)
69
- data.sql_data << SlowSql.new(statement, metric_name, duration, start_time, backtrace)
50
+ threshold = duration*1000
51
+ if threshold > TingYun::Agent.config[:'nbs.action_tracer.slow_sql_threshold'] && state.sql_recorded?
52
+ backtrace = ''
53
+ if threshold > TingYun::Agent.config[:'nbs.action_tracer.stack_trace_threshold']
54
+ backtrace = caller.reject! { |t| t.include?('tingyun_rpm') }
55
+ backtrace = backtrace.first(20).join("\n")
70
56
  end
57
+ statement = TingYun::Agent::Database::Statement.new(sql, config, explainer, binds, name)
58
+ data.sql_data << ::TingYun::Agent::Collector::SlowSql.new(statement, metric_name, duration, start_time, backtrace)
71
59
  end
72
60
  end
73
61
 
74
-
75
62
  def on_finishing_transaction(state, name)
76
- return unless enabled?
63
+ return unless TingYun::Agent::Database.sql_sampler_enabled?
77
64
 
78
65
  transaction_sql_data = state.sql_sampler_transaction_data
79
66
  return unless transaction_sql_data
@@ -84,16 +71,17 @@ module TingYun
84
71
  end
85
72
 
86
73
  def save_slow_sql(data)
87
- if data.sql_data.size > 0
74
+ size = data.sql_data.size
75
+ if size > 0
88
76
  @samples_lock.synchronize do
89
- ::TingYun::Agent.logger.debug "Examining #{data.sql_data.size} slow transaction sql statement(s)"
77
+ ::TingYun::Agent.logger.debug "Examining #{size} slow transaction sql statement(s)"
90
78
  save data
91
79
  end
92
80
  end
93
81
  end
94
82
 
95
83
  def save (transaction_sql_data)
96
- action_metric_name = transaction_sql_data.action_metric_name
84
+ action_metric_name = transaction_sql_data.metric_name
97
85
  uri = transaction_sql_data.uri
98
86
 
99
87
  transaction_sql_data.sql_data.each do |sql_item|
@@ -103,16 +91,14 @@ module TingYun
103
91
  sql_trace.aggregate(sql_item, action_metric_name, uri)
104
92
  else
105
93
  if has_room?
106
- sql_trace = SqlTrace.new(normalized_sql, sql_item, action_metric_name, uri)
107
- elsif should_add_trace?(sql_item)
108
- remove_shortest_trace
109
- sql_trace = SqlTrace.new(normalized_sql, sql_item, action_metric_name, uri)
110
- end
111
-
112
- if sql_trace
113
- @sql_traces[normalized_sql] = sql_trace
94
+ @sql_traces[normalized_sql] = ::TingYun::Agent::Collector::SqlTrace.new(normalized_sql, sql_item, action_metric_name, uri)
95
+ else
96
+ min, max = @sql_traces.minmax_by { |(_, trace)| trace.max_call_time }
97
+ if max.last.max_call_time < sql_item.duration
98
+ @sql_traces.delete(min.first)
99
+ @sql_traces[normalized_sql] = ::TingYun::Agent::Collector::SqlTrace.new(normalized_sql, sql_item, action_metric_name, uri)
100
+ end
114
101
  end
115
-
116
102
  end
117
103
  end
118
104
  end
@@ -122,23 +108,9 @@ module TingYun
122
108
  @sql_traces.size < MAX_SAMPLES
123
109
  end
124
110
 
125
- # this should always be called under the @samples_lock
126
- def should_add_trace?(sql_item)
127
- @sql_traces.any? do |(_, existing_trace)|
128
- existing_trace.max_call_time < sql_item.duration
129
- end
130
- end
131
-
132
- # this should always be called under the @samples_lock
133
- def remove_shortest_trace
134
- shortest_key, _ = @sql_traces.min_by { |(_, trace)| trace.max_call_time }
135
- @sql_traces.delete(shortest_key)
136
- end
137
-
138
111
 
139
112
  def harvest!
140
- return [] unless enabled?
141
-
113
+ return [] unless TingYun::Agent::Database.sql_sampler_enabled?
142
114
  slowest = []
143
115
  @samples_lock.synchronize do
144
116
  slowest = @sql_traces.values
@@ -159,143 +131,15 @@ module TingYun
159
131
  sql_traces.each do |trace|
160
132
  existing_trace = @sql_traces[trace.sql]
161
133
  if existing_trace
162
- existing_trace.aggregate_trace(trace)
134
+ existing_trace.aggregate(trace.slow_sql, trace.path, trace.url)
163
135
  else
164
136
  @sql_traces[trace.sql] = trace
165
137
  end
166
138
  end
167
139
  end
168
140
  end
169
-
170
-
171
- end
172
-
173
- class TransactionSqlData
174
- attr_reader :action_metric_name
175
- attr_reader :uri
176
- attr_reader :sql_data
177
-
178
- def initialize
179
- @sql_data = []
180
- end
181
-
182
- def set_transaction_info(uri)
183
- @uri = uri
184
- end
185
-
186
- def set_transaction_name(name)
187
- @action_metric_name = name
188
- end
189
- end
190
-
191
- class SlowSql
192
- attr_reader :statement
193
- attr_reader :metric_name
194
- attr_reader :duration
195
- attr_reader :backtrace
196
- attr_reader :start_time
197
-
198
-
199
- def initialize(statement, metric_name, duration, t0, backtrace=nil)
200
- @start_time = t0
201
- @statement = statement
202
- @metric_name = metric_name
203
- @duration = duration
204
- @backtrace = backtrace
205
- end
206
-
207
- def sql
208
- statement.sql
209
- end
210
-
211
- def obfuscate
212
- TingYun::Agent::Database.obfuscate_sql(statement)
213
- end
214
-
215
-
216
- def normalize
217
- TingYun::Agent::Database::Obfuscator.instance.default_sql_obfuscator(statement)
218
- end
219
-
220
- def explain
221
- if statement.config && statement.explainer
222
- TingYun::Agent::Database.explain_sql(statement.sql, statement.config, statement.explainer)
223
- end
224
- end
225
-
226
- # We can't serialize the explainer, so clear it before we transmit
227
- def prepare_to_send
228
- statement.explainer = nil
229
- end
230
141
  end
231
142
 
232
-
233
-
234
- class SqlTrace < TingYun::Metrics::Stats
235
-
236
- attr_reader :action_metric_name
237
- attr_reader :uri
238
- attr_reader :sql
239
- attr_reader :slow_sql
240
- attr_reader :params
241
-
242
- def initialize(normalized_query, slow_sql, action_name, uri)
243
- super()
244
- @params = {}
245
-
246
- @action_metric_name = action_name
247
- @slow_sql = slow_sql
248
- @sql = normalized_query
249
- @uri = uri
250
- @params[:stacktrace] = slow_sql.backtrace
251
- record_data_point(float(slow_sql.duration))
252
- end
253
-
254
- def aggregate(slow_sql, action_name, uri)
255
- if slow_sql.duration > max_call_time
256
- @action_metric_name = action_name
257
- @slow_sql = slow_sql
258
- @uri = uri
259
- @params[:stacktrace] = slow_sql.backtrace
260
- end
261
- record_data_point(float(slow_sql.duration))
262
- end
263
-
264
- def aggregate_trace(trace)
265
- aggregate(trace.slow_sql, trace.path, trace.url)
266
- end
267
-
268
- def prepare_to_send
269
- @sql = @slow_sql.sql unless need_to_obfuscate?
270
- @params[:explainPlan] = @slow_sql.explain if need_to_explain?
271
- end
272
-
273
- def need_to_obfuscate?
274
- Agent.config[:'nbs.action_tracer.record_sql'].to_s == 'obfuscated'
275
- end
276
-
277
- def need_to_explain?
278
- Agent.config[:'nbs.action_tracer.explain_enabled'] && @slow_sql.duration * 1000 > TingYun::Agent.config[:'nbs.action_tracer.explain_threshold']
279
- end
280
-
281
-
282
- include TingYun::Support::Coerce
283
-
284
- def to_collector_array(encoder)
285
- [
286
- @slow_sql.start_time,
287
- string(@action_metric_name),
288
- string(@slow_sql.metric_name),
289
- string(@uri||@action_metric_name),
290
- string(@sql),
291
- int(@call_count),
292
- TingYun::Helper.time_to_millis(@total_call_time),
293
- TingYun::Helper.time_to_millis(@max_call_time),
294
- TingYun::Helper.time_to_millis(@min_call_time),
295
- encoder.encode(@params)
296
- ]
297
- end
298
- end
299
143
  end
300
144
  end
301
145
  end