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
@@ -14,11 +14,12 @@ module TingYun
14
14
 
15
15
  include HandleErrors
16
16
 
17
- # number of attempts we've made to contact the server
18
- attr_accessor :connect_attempts
17
+
19
18
 
20
19
  # Disconnect just sets connected to false, which prevents
21
20
  # the agent from trying to connect again
21
+ # @connect_state has three state {:disconnected,:pending,:connected}
22
+
22
23
  def disconnect
23
24
  @connect_state = :disconnected
24
25
  true
@@ -39,17 +40,6 @@ module TingYun
39
40
  force || (!connected? && !disconnected?)
40
41
  end
41
42
 
42
- # Retry period is a minute for each failed attempt that
43
- # we've made. This should probably do some sort of sane TCP
44
- # backoff to prevent hammering the server, but a minute for
45
- # each attempt seems to work reasonably well.
46
- def connect_retry_period
47
- [600, connect_attempts * 60].min
48
- end
49
-
50
- def note_connect_failure
51
- self.connect_attempts += 1
52
- end
53
43
 
54
44
  def generate_environment_report
55
45
  @environment_report = environment_for_connect
@@ -114,17 +104,15 @@ module TingYun
114
104
  # agent run and Ting Yun sees it as a separate instance (default is false).
115
105
  def catch_errors
116
106
  yield
117
-
118
- rescue TingYun::Support::Exception::ExpiredConfigurationException => e
107
+ rescue TingYun::Support::Exception::UnKnownServerException => e
119
108
  handle_force_restart(e)
120
109
  retry
121
- rescue TingYun::Support::Exception::InvalidDataTokenException => e
122
- handle_force_restart(e)
110
+ rescue TingYun::Support::Exception::ServerConnectionException => e
111
+ handle_delay_restart(e, 60)
123
112
  retry
124
- rescue TingYun::Support::Exception::InvalidDataException => e
125
- handle_server_error(e)
126
113
  rescue => e
127
- handle_other_error(e)
114
+ handle_delay_restart(e, 60)
115
+ retry
128
116
  end
129
117
 
130
118
  # Takes a hash of configuration data returned from the
@@ -14,7 +14,7 @@ module TingYun
14
14
  module ContainerDataManager
15
15
 
16
16
 
17
- attr_reader :stats_engine, :error_collector, :transaction_sampler, :sql_sampler, :middleware
17
+ attr_reader :stats_engine, :error_collector, :transaction_sampler, :sql_sampler
18
18
 
19
19
 
20
20
  def drop_buffered_data
@@ -34,7 +34,6 @@ module TingYun
34
34
  @error_collector = TingYun::Agent::Collector::ErrorCollector.new
35
35
  @transaction_sampler = TingYun::Agent::Collector::TransactionSampler.new
36
36
  @sql_sampler = TingYun::Agent::Collector::SqlSampler.new
37
- @middleware = TingYun::Agent::Collector::MiddleWareCollector.new(@events)
38
37
  end
39
38
 
40
39
  def container_for_endpoint(endpoint)
@@ -106,7 +105,7 @@ module TingYun
106
105
  def harvest_from_container(container, endpoint)
107
106
  items =[]
108
107
  begin
109
- if TingYun::Agent.config[:'nbs.agent_enabled']
108
+ if TingYun::Agent.config[:'enabled']
110
109
  items = container.harvest!
111
110
  else
112
111
  container.reset!
@@ -53,8 +53,13 @@ module TingYun
53
53
  drop_buffered_data
54
54
  @service.force_restart if @service
55
55
  @connect_state = :pending
56
- sleep 30
57
56
  end
57
+
58
+ def handle_delay_restart(error, sec)
59
+ handle_force_restart(error)
60
+ sleep sec
61
+ end
62
+
58
63
  def handle_force_disconnect(error)
59
64
  TingYun::Agent.logger.warn "Ting Yun forced this agent to disconnect (#{error.message})"
60
65
  disconnect
@@ -11,8 +11,11 @@ module TingYun
11
11
 
12
12
  # Check to see if the agent should start, returning +true+ if it should.
13
13
  # should hava the vaild app_name, unstart-state and able to start
14
+ # The agent is disabled when it is not force enabled by the
15
+ # 'nbs.agent_enabled' option (e.g. in a manual start), or
16
+ # enabled normally through the configuration file
14
17
  def agent_should_start?
15
- return false if already_started? || disabled?
18
+ return false if already_started? || !TingYun::Agent.config[:'nbs.agent_enabled']
16
19
  unless app_name_configured?
17
20
  TingYun::Agent.logger.error "No application name configured.",
18
21
  "The Agent cannot start without at least one. Please check your ",
@@ -36,96 +39,30 @@ module TingYun
36
39
  end
37
40
  end
38
41
 
39
- # The agent is disabled when it is not force enabled by the
40
- # 'nbs.agent_enabled' option (e.g. in a manual start), or
41
- # enabled normally through the configuration file
42
- def disabled?
43
- !TingYun::Agent.config[:'nbs.agent_enabled']
44
- end
45
42
 
46
43
  def log_startup
47
- log_environment
48
- log_dispatcher
49
- log_app_name
50
- end
51
-
52
- def log_environment
53
- Agent.logger.info "Environment: #{::TingYun::Frameworks.framework.env}"
54
- end
55
-
56
- # Logs the dispatcher to the log file to assist with
57
- # debugging. When no debugger is present, logs this fact to
58
- # assist with proper dispatcher detection
59
- def log_dispatcher
44
+ Agent.logger.info "Environment: #{::TingYun::Frameworks.framework.env}" # log_environment
60
45
  dispatcher_name = TingYun::Agent.config[:dispatcher].to_s
61
-
62
46
  if dispatcher_name.empty?
63
47
  TingYun::Agent.logger.info 'No known dispatcher detected.'
64
48
  else
65
49
  TingYun::Agent.logger.info "Dispatcher: #{dispatcher_name}"
66
- end
67
- end
68
-
69
- def log_app_name
70
- TingYun::Agent.logger.info "Application: #{TingYun::Agent.config.app_names.join(", ")}"
71
- end
72
-
73
- def sinatra_app?
74
- (
75
- defined?(Sinatra::Application) &&
76
- Sinatra::Application.respond_to?(:run) &&
77
- Sinatra::Application.run?
78
- )
79
- end
80
-
81
- # Classy logging of the agent version and the current pid,
82
- # so we can disambiguate processes in the log file and make
83
- # sure they're running a reasonable version
84
- def log_version_and_pid
85
- TingYun::Agent.logger.debug "Ting Yun Ruby Agent #{TingYun::VERSION::STRING} Initialized: pid = #{$$}"
50
+ end # log_dispatcher
51
+ TingYun::Agent.logger.info "Application: #{TingYun::Agent.config.app_names.join(", ")}" # log_app_name
86
52
  end
87
53
 
88
- # Warn the user if they have configured their agent not to
89
- # send data, that way we can see this clearly in the log file
90
- def monitoring?
91
- if TingYun::Agent.config[:monitor_mode]
92
- true
93
- else
94
- TingYun::Agent.logger.warn('Agent configured not to send data in this environment.')
95
- false
96
- end
97
- end
98
54
 
99
- # Tell the user when the license key is missing so they can
100
- # fix it by adding it to the file
101
- def has_license_key?
55
+ # A correct license key exists and is of the proper length
56
+ def has_correct_license_key?
102
57
  if TingYun::Agent.config[:license_key] && TingYun::Agent.config[:license_key].length > 0
103
58
  true
104
59
  else
105
60
  TingYun::Agent.logger.warn("No license key found. " +
106
- "This often means your tingyun.yml file was not found, or it lacks a section for the running environment,'#{::TingYun::Frameworks.framework.env}'. You may also want to try linting your tingyun.yml to ensure it is valid YML.")
61
+ "This often means your tingyun.yml file was not found, or it lacks a section for the running environment,'#{::TingYun::Frameworks.framework.env}'. You may also want to try linting your tingyun.yml to ensure it is valid YML.")
107
62
  false
108
63
  end
109
64
  end
110
65
 
111
- # A license key is an arbitrary 40 character string,
112
- # usually looks something like a SHA1 hash
113
- def correct_license_length
114
- key = TingYun::Agent.config[:license_key]
115
-
116
- if key.length > 0
117
- true
118
- else
119
- TingYun::Agent.logger.error("Invalid license key: #{key}")
120
- false
121
- end
122
- end
123
-
124
- # A correct license key exists and is of the proper length
125
- def has_correct_license_key?
126
- has_license_key? && correct_license_length
127
- end
128
-
129
66
  # Logs the configured application names
130
67
  def app_name_configured?
131
68
  names = TingYun::Agent.config.app_names
@@ -149,7 +86,7 @@ module TingYun
149
86
  # setting up the worker thread and the exit handler to shut
150
87
  # down the agent
151
88
  def check_config_and_start_agent
152
- return unless monitoring? && has_correct_license_key?
89
+ return unless has_correct_license_key?
153
90
  return if is_using_forking_dispatcher?
154
91
  setup_and_start_agent
155
92
  end
@@ -163,7 +100,7 @@ module TingYun
163
100
  @dispatcher.mark_started
164
101
  generate_environment_report
165
102
  install_exit_handler
166
- cpu_and_memory
103
+ @middleware.load_samplers # cpu and memory load
167
104
 
168
105
  if TingYun::Agent.config[:sync_startup]
169
106
  connect_in_sync
@@ -199,9 +136,7 @@ module TingYun
199
136
  end
200
137
 
201
138
  return if !needs_restart ||
202
- !Agent.config[:'nbs.agent_enabled'] ||
203
- !Agent.config[:monitor_mode] ||
204
- disconnected?
139
+ !Agent.config[:'nbs.agent_enabled'] || disconnected?
205
140
 
206
141
  ::TingYun::Agent.logger.debug "Starting the worker thread in #{Process.pid} (parent #{Process.ppid}) after forking."
207
142
 
@@ -212,9 +147,6 @@ module TingYun
212
147
  setup_and_start_agent(options)
213
148
  end
214
149
 
215
- def cpu_and_memory
216
- @middleware.load_samplers
217
- end
218
150
 
219
151
  end
220
152
  end
@@ -6,14 +6,24 @@ require 'ting_yun/agent/method_tracer_helpers'
6
6
  require 'ting_yun/agent/transaction/transaction_metrics'
7
7
  require 'ting_yun/agent/transaction/request_attributes'
8
8
  require 'ting_yun/agent/transaction/attributes'
9
+ require 'ting_yun/agent/transaction/exceptions'
10
+ require 'ting_yun/agent/transaction/apdex'
11
+ require 'ting_yun/agent/transaction/class_method'
12
+ require 'ting_yun/agent/transaction/instance_method'
9
13
 
10
14
 
11
15
  module TingYun
12
16
  module Agent
17
+ # web transaction
13
18
  class Transaction
14
19
 
20
+ include TingYun::Agent::Transaction::InstanceMethod
21
+
22
+ extend TingYun::Agent::Transaction::ClassMethod
23
+
24
+
25
+
15
26
 
16
- APDEX_TXN_METRIC_PREFIX = 'Apdex/'.freeze
17
27
  SUBTRANSACTION_PREFIX = 'Nested/'.freeze
18
28
  CONTROLLER_PREFIX = 'WebAction/'.freeze
19
29
  RAKE_TRANSACTION_PREFIX = 'BackgroundAction/Rake'.freeze
@@ -23,7 +33,7 @@ module TingYun
23
33
  MIDDLEWARE_PREFIX = 'Middleware/Rack/'.freeze
24
34
  GRAPE_PREFIX = 'Grape/'.freeze
25
35
  RAKE_PREFIX = 'Rake'.freeze
26
- WEB_TRANSACTION_CATEGORIES = [:controller, :uri, :rack, :sinatra, :grape, :middleware, :thrift].freeze
36
+
27
37
  EMPTY_SUMMARY_METRICS = [].freeze
28
38
  MIDDLEWARE_SUMMARY_METRICS = ['Middleware/all'.freeze].freeze
29
39
 
@@ -32,43 +42,40 @@ module TingYun
32
42
  NESTED_TRACE_STOP_OPTIONS = {:metric => true}.freeze
33
43
 
34
44
 
35
- # A Time instance for the start time, never nil
36
- attr_accessor :start_time
37
-
38
45
 
39
46
  # A Time instance used for calculating the apdex score, which
40
47
  # might end up being @start, or it might be further upstream if
41
48
  # we can find a request header for the queue entry time
42
- attr_accessor :apdex_start,
43
- :category,
44
- :frame_stack,
45
- :exceptions,
46
- :default_name,
47
- :metrics,
48
- :http_response_code,
49
- :response_content_type,
50
- :error_recorded,
51
- :guid,
52
- :attributes,
53
- :request_attributes
54
-
55
-
56
- def initialize(category, options)
57
- @guid = options[:client_transaction_id] || generate_guid
49
+
50
+
51
+ attr_reader :apdex,
52
+ :exceptions,
53
+ :metrics,
54
+ :attributes,
55
+ :request_attributes,
56
+ :frame_stack,
57
+ :guid,
58
+ :category,
59
+ :default_name,
60
+ :start_time
61
+
62
+
63
+
64
+ def initialize(category, client_transaction_id, options)
65
+ @start_time = Time.now
66
+
67
+ @exceptions = TingYun::Agent::Transaction::Exceptions.new
68
+ @metrics = TingYun::Agent::TransactionMetrics.new
69
+ @attributes = TingYun::Agent::Transaction::Attributes.new
70
+ @apdex = TingYun::Agent::Transaction::Apdex.new(options[:apdex_start_time], @start_time)
71
+
58
72
  @has_children = false
59
73
  @category = category
60
- @exceptions = {}
61
- @start_time = Time.now
62
- @apdex_start = options[:apdex_start_time] || @start_time
74
+
75
+ @guid = client_transaction_id || generate_guid
63
76
  @frame_stack = []
64
77
  @frozen_name = nil
65
78
  @default_name = TingYun::Helper.correctly_encoded(options[:transaction_name])
66
- @metrics = TingYun::Agent::TransactionMetrics.new
67
-
68
- @error_recorded = false
69
-
70
- @attributes = TingYun::Agent::Transaction::Attributes.new
71
-
72
79
 
73
80
  if request = options[:request]
74
81
  @request_attributes = TingYun::Agent::Transaction::RequestAttributes.new request
@@ -77,7 +84,6 @@ module TingYun
77
84
  end
78
85
  end
79
86
 
80
-
81
87
  def request_path
82
88
  @request_attributes && @request_attributes.request_path
83
89
  end
@@ -86,116 +92,20 @@ module TingYun
86
92
  @request_attributes && @request_attributes.port
87
93
  end
88
94
 
89
- def self.wrap(state, name, category, options = {})
90
- Transaction.start(state, category, options.merge(:transaction_name => name))
91
-
92
- begin
93
- # We shouldn't raise from Transaction.start, but only wrap the yield
94
- # to be absolutely sure we don't report agent problems as app errors
95
- yield
96
- rescue => e
97
- Transaction.notice_error(e)
98
- raise e
99
- ensure
100
- Transaction.stop(state)
101
- end
102
- end
103
-
104
-
105
- def self.start(state, category, options)
106
- category ||= :controller
107
- txn = state.current_transaction
108
- options[:client_transaction_id] = state.client_transaction_id
109
- if txn
110
- txn.create_nested_frame(state, category, options)
111
- else
112
- txn = start_new_transaction(state, category, options)
113
- end
114
-
115
- # merge params every step into here
116
- txn.attributes.merge_request_parameters(options[:filtered_params])
117
-
118
- txn
119
- rescue => e
120
- TingYun::Agent.logger.error("Exception during Transaction.start", e)
121
- end
122
-
123
- def self.start_new_transaction(state, category, options)
124
- txn = Transaction.new(category, options)
125
- state.reset(txn)
126
- txn.start(state)
127
- txn
128
- end
129
95
 
130
96
  def start(state)
131
97
  return if !state.execution_traced?
98
+ ::TingYun::Agent.instance.events.notify(:start_transaction) # Dispatcher调用
99
+
100
+ ::TingYun::Agent::Collector::TransactionSampler.on_start_transaction(state, start_time)
101
+ ::TingYun::Agent::Collector::SqlSampler.on_start_transaction(state, request_path)
132
102
 
133
- transaction_sampler.on_start_transaction(state, start_time)
134
- sql_sampler.on_start_transaction(state, request_path)
135
- TingYun::Agent.instance.events.notify(:start_transaction)
136
103
  frame_stack.push TingYun::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, Time.now.to_f)
137
104
  name_last_frame @default_name
138
105
  freeze_name_and_execute if @default_name.start_with?(RAKE_TRANSACTION_PREFIX)
139
106
  end
140
107
 
141
- def create_nested_frame(state, category, options)
142
- @has_children = true
143
- frame_stack.push TingYun::Agent::MethodTracerHelpers.trace_execution_scoped_header(state, Time.now.to_f)
144
- name_last_frame(options[:transaction_name])
145
108
 
146
- set_default_transaction_name(options[:transaction_name], category)
147
- end
148
-
149
-
150
- def set_default_transaction_name(name, category)
151
- return log_frozen_name(name) if name_frozen?
152
- if influences_transaction_name?(category)
153
- self.default_name = name
154
- @category = category if category
155
- end
156
- end
157
-
158
-
159
- def self.stop(state, end_time = Time.now)
160
-
161
- txn = state.current_transaction
162
-
163
- if txn.nil?
164
- TingYun::Agent.logger.error("Failed during Transaction.stop because there is no current transaction")
165
- return
166
- end
167
-
168
- nested_frame = txn.frame_stack.pop
169
-
170
- if txn.frame_stack.empty?
171
- txn.stop(state, end_time, nested_frame)
172
- state.reset
173
- else
174
- nested_name = nested_transaction_name(nested_frame.name)
175
-
176
- if nested_name.start_with?(MIDDLEWARE_PREFIX)
177
- summary_metrics = MIDDLEWARE_SUMMARY_METRICS
178
- else
179
- summary_metrics = EMPTY_SUMMARY_METRICS
180
- end
181
-
182
- TingYun::Agent::MethodTracerHelpers.trace_execution_scoped_footer(
183
- state,
184
- nested_frame.start_time.to_f,
185
- nested_name,
186
- summary_metrics,
187
- nested_frame,
188
- NESTED_TRACE_STOP_OPTIONS,
189
- end_time.to_f)
190
-
191
- end
192
-
193
- :transaction_stopped
194
- rescue => e
195
- state.reset
196
- TingYun::Agent.logger.error("Exception during Transaction.stop", e)
197
- nil
198
- end
199
109
 
200
110
 
201
111
  def stop(state, end_time, outermost_frame)
@@ -210,7 +120,7 @@ module TingYun
210
120
  trace_options = TRACE_OPTIONS_UNSCOPED
211
121
  end
212
122
 
213
- if needs_middleware_summary_metrics?(name)
123
+ if name.start_with?(MIDDLEWARE_PREFIX)
214
124
  summary_metrics_with_exclusive_time = MIDDLEWARE_SUMMARY_METRICS
215
125
  else
216
126
  summary_metrics_with_exclusive_time = EMPTY_SUMMARY_METRICS
@@ -226,280 +136,27 @@ module TingYun
226
136
  trace_options,
227
137
  end_time.to_f)
228
138
 
229
- commit!(state, end_time, name) unless ignore(best_name)
139
+ commit(state, end_time, name) unless ignore(best_name)
230
140
  end
231
141
 
232
- def self.nested_transaction_name(name)
233
- if name.start_with?(CONTROLLER_PREFIX) || name.start_with?(RAKE_TRANSACTION_PREFIX)
234
- "#{SUBTRANSACTION_PREFIX}#{name}"
235
- else
236
- name
237
- end
238
- end
239
142
 
240
- def commit!(state, end_time, outermost_node_name)
143
+ def commit(state, end_time, outermost_node_name)
241
144
 
242
145
  assign_agent_attributes
243
146
 
244
147
 
245
- transaction_sampler.on_finishing_transaction(state, self, end_time)
148
+ TingYun::Agent.instance.transaction_sampler.on_finishing_transaction(state, self, end_time)
246
149
 
247
- sql_sampler.on_finishing_transaction(state, @frozen_name)
150
+ TingYun::Agent.instance.sql_sampler.on_finishing_transaction(state, @frozen_name)
248
151
 
249
152
  record_summary_metrics(outermost_node_name, end_time)
250
- record_apdex(state, end_time)
251
- record_exceptions
252
- merge_metrics
253
- end
254
-
255
-
256
- def record_summary_metrics(outermost_node_name,end_time)
257
- unless @frozen_name == outermost_node_name
258
- @metrics.record_unscoped(@frozen_name, TingYun::Helper.time_to_millis(end_time.to_f - start_time.to_f))
259
- end
260
- end
261
-
262
- def assign_agent_attributes
263
-
264
- add_agent_attribute(:threadName, "pid-#{$$}");
265
-
266
- if http_response_code
267
- add_agent_attribute(:httpStatus, http_response_code.to_s)
268
- end
269
-
270
- if response_content_type
271
- add_agent_attribute(:contentType, response_content_type)
272
- end
273
-
274
-
275
- if @request_attributes
276
- @request_attributes.assign_agent_attributes self
277
- end
278
-
279
- end
280
-
281
- def add_agent_attribute(key, value)
282
- @attributes.add_agent_attribute(key, value)
283
- end
284
-
285
- #collector error
286
- def had_error?
287
- if @exceptions.empty?
288
- return false
289
- else
290
- return true
291
- end
292
- end
293
-
294
- def record_exceptions
295
- unless @exceptions.empty?
296
- @exceptions.each do |exception, options|
297
-
298
- options[:uri] ||= request_path if request_path
299
- options[:port] = request_port if request_port
300
- options[:metric_name] = best_name
301
- options[:attributes] = @attributes
302
-
303
- @error_recorded = !!::TingYun::Agent.instance.error_collector.notice_error(exception, options) || @error_recorded
304
- end
305
- end
306
- end
307
-
308
- def record_apdex(state, end_time=Time.now)
309
- total_duration = (end_time - apdex_start)*1000
310
- if recording_web_transaction?
311
- record_apdex_metrics(APDEX_TXN_METRIC_PREFIX, total_duration, apdex_t)
312
- end
313
- end
314
-
315
-
316
- def record_apdex_metrics(transaction_prefix, total_duration, current_apdex_t)
317
- return unless current_apdex_t
318
- return unless @frozen_name.start_with?(CONTROLLER_PREFIX)
319
-
320
- apdex_bucket_global = apdex_bucket(total_duration, current_apdex_t)
321
- txn_apdex_metric = @frozen_name.sub(/^[^\/]+\//, transaction_prefix)
322
- @metrics.record_unscoped(txn_apdex_metric, apdex_bucket_global, current_apdex_t)
323
- end
324
-
325
-
326
- def apdex_bucket(duration, current_apdex_t)
327
- self.class.apdex_bucket(duration, had_error?, current_apdex_t)
328
- end
329
-
330
- def self.apdex_bucket(duration, failed, apdex_t)
331
- case
332
- when failed
333
- :apdex_f
334
- when duration <= apdex_t
335
- :apdex_s
336
- when duration <= 4 * apdex_t
337
- :apdex_t
338
- else
339
- :apdex_f
340
- end
341
- end
342
-
343
- def apdex_t
344
- TingYun::Agent.config[:apdex_t]
345
- end
346
-
347
-
348
- # See TingYun::Agent.notice_error for options and commentary
349
- def self.notice_error(e, options={})
350
- state = TingYun::Agent::TransactionState.tl_get
351
- txn = state.current_transaction
352
- if txn
353
- txn.notice_error(e, options)
354
- elsif TingYun::Agent.instance
355
- TingYun::Agent.instance.error_collector.notice_error(e, options)
356
- end
357
- end
358
-
359
- # Do not call this. Invoke the class method instead.
360
- def notice_error(error, options={}) # :nodoc:
361
- if @exceptions[error]
362
- @exceptions[error].merge! options
363
- else
364
- @exceptions[error] = options
365
- end
366
- end
367
-
153
+ @apdex.record_apdex(@frozen_name, end_time, @exceptions.had_error?)
154
+ @exceptions.record_exceptions(@attributes)
368
155
 
369
- # This transaction-local hash may be used as temprory storage by
370
- # instrumentation that needs to pass data from one instrumentation point
371
- # to another.
372
- #
373
- # For example, if both A and B are instrumented, and A calls B
374
- # but some piece of state needed by the instrumentation at B is only
375
- # available at A, the instrumentation at A may write into the hash, call
376
- # through, and then remove the key afterwards, allowing the
377
- # instrumentation at B to read the value in between.
378
- #
379
- # Keys should be symbols, and care should be taken to not generate key
380
- # names dynamically, and to ensure that keys are removed upon return from
381
- # the method that creates them.
382
- #
383
- def instrumentation_state
384
- @instrumentation_state ||= {}
385
- end
386
-
387
- def with_database_metric_name(model, method, product=nil)
388
- previous = self.instrumentation_state[:datastore_override]
389
- model_name = case model
390
- when Class
391
- model.name
392
- when String
393
- model
394
- else
395
- model.to_s
396
- end
397
- self.instrumentation_state[:datastore_override] = [method, model_name, product]
398
- yield
399
- ensure
400
- self.instrumentation_state[:datastore_override] = previous
401
- end
402
-
403
- def freeze_name_and_execute
404
- if !name_frozen?
405
- @name_frozen = true
406
- @frozen_name = best_name
407
- end
408
156
 
409
- yield if block_given?
410
- end
411
-
412
- def promoted_transaction_name(name)
413
- if name.start_with?(MIDDLEWARE_PREFIX)
414
- "#{CONTROLLER_PREFIX}#{name}"
415
- else
416
- name
417
- end
418
- end
419
-
420
- def merge_metrics
421
157
  TingYun::Agent.instance.stats_engine.merge_transaction_metrics!(@metrics, best_name)
422
158
  end
423
159
 
424
- def name_last_frame(name)
425
- frame_stack.last.name = name
426
- end
427
-
428
- def name_frozen?
429
- @frozen_name ? true : false
430
- end
431
-
432
- def log_frozen_name(name)
433
- TingYun::Agent.logger.warn("Attempted to rename transaction to '#{name}' after transaction name was already frozen as '#{@frozen_name}'.")
434
- nil
435
- end
436
-
437
- def influences_transaction_name?(category)
438
- !category || frame_stack.size == 1 || similar_category?(category)
439
- end
440
-
441
- def web_category?(category)
442
- WEB_TRANSACTION_CATEGORIES.include?(category)
443
- end
444
-
445
- def similar_category?(category)
446
- web_category?(@category) == web_category?(category)
447
- end
448
-
449
- def recording_web_transaction?
450
- web_category?(@category)
451
- end
452
-
453
- def self.recording_web_transaction? #THREAD_LOCAL_ACCESS
454
- txn = tl_current
455
- txn && txn.recording_web_transaction?
456
- end
457
-
458
- def self.tl_current
459
- TingYun::Agent::TransactionState.tl_get.current_transaction
460
- end
461
-
462
- def needs_middleware_summary_metrics?(name)
463
- name.start_with?(MIDDLEWARE_PREFIX)
464
- end
465
-
466
- alias_method :ignore, :needs_middleware_summary_metrics?
467
-
468
- def best_name
469
- @frozen_name || @default_name || ::TingYun::Agent::UNKNOWN_METRIC
470
- end
471
-
472
- def queue_time
473
- @apdex_start ? @start_time - @apdex_start : 0
474
- end
475
-
476
-
477
- def agent
478
- TingYun::Agent.instance
479
- end
480
-
481
- def sql_sampler
482
- agent.sql_sampler
483
- end
484
-
485
-
486
- def transaction_sampler
487
- TingYun::Agent.instance.transaction_sampler
488
- end
489
-
490
- HEX_DIGITS = (0..15).map{|i| i.to_s(16)}
491
- GUID_LENGTH = 16
492
-
493
- # generate a random 64 bit uuid
494
- private
495
- def generate_guid
496
- guid = ''
497
- GUID_LENGTH.times do
498
- guid << HEX_DIGITS[rand(16)]
499
- end
500
- guid
501
- end
502
-
503
160
  end
504
161
  end
505
162
  end