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
@@ -2,6 +2,7 @@
2
2
  # This file is distributed under Ting Yun's license terms.
3
3
 
4
4
  module TingYun
5
+ # the basic Logger
5
6
  module Logger
6
7
 
7
8
  end
@@ -1,25 +1,25 @@
1
1
  # encoding: utf-8
2
2
  # This file is distributed under Ting Yun's license terms.
3
-
4
3
  require 'thread'
5
4
  require 'logger'
6
5
  require 'ting_yun/logger/log_once'
7
6
  require 'ting_yun/logger/memory_logger'
8
7
  require 'ting_yun/support/hostname'
9
8
  require 'ting_yun/logger/null_logger'
10
-
9
+ require 'ting_yun/logger/create_logger_helper'
11
10
 
12
11
  module TingYun
13
12
  module Logger
14
13
  class AgentLogger
15
- include LogOnce
14
+ include ::TingYun::Logger::LogOnce
15
+ include ::TingYun::Logger::CreateLoggerHelper
16
16
 
17
17
  def initialize(root = "", override_logger=nil)
18
18
  @already_logged_lock = Mutex.new
19
19
  clear_already_logged
20
20
  create_log(root, override_logger)
21
- set_log_level!
22
- set_log_format!
21
+ set_log_level
22
+ set_log_format
23
23
 
24
24
  gather_startup_logs
25
25
  end
@@ -64,9 +64,6 @@ module TingYun
64
64
  end
65
65
  end
66
66
 
67
- def log_formatter=(formatter)
68
- @log.formatter = formatter
69
- end
70
67
 
71
68
  private
72
69
 
@@ -102,67 +99,14 @@ module TingYun
102
99
  nil
103
100
  end
104
101
 
105
- def check_log_file
106
- unless File.exist? @file_path
107
- begin
108
- @log = ::Logger.new(@file_path)
109
- set_log_format!
110
- rescue => e
111
- @log = ::Logger.new(STDOUT)
112
- warn("check_log_file: Failed creating logger for file #{@file_path}, using standard out for logging.", e)
113
- end
114
- end
115
- end
116
-
117
- def create_log(root, override_logger)
118
- if !override_logger.nil?
119
- @log = override_logger
120
- elsif ::TingYun::Agent.config[:'nbs.agent_enabled'] == false
121
- create_null_logger
122
- else
123
- if wants_stdout?
124
- @log = ::Logger.new(STDOUT)
125
- else
126
- create_log_to_file(root)
127
- end
128
- end
129
- end
130
-
131
- def create_log_to_file(root)
132
- path = find_or_create_file_path(::TingYun::Agent.config[:agent_log_file_path], root)
133
- if path.nil?
134
- @log = ::Logger.new(STDOUT)
135
- warn("Error creating log directory #{::TingYun::Agent.config[:agent_log_file_path]}, using standard out for logging.")
136
- else
137
- @file_path = "#{path}/#{::TingYun::Agent.config[:agent_log_file_name]}"
138
- begin
139
- @log = ::Logger.new(@file_path)
140
- rescue => e
141
- @log = ::Logger.new(STDOUT)
142
- warn("Failed creating logger for file #{@file_path}, using standard out for logging.", e)
143
- end
144
- end
145
- end
146
-
147
- def create_null_logger
148
- @log = ::TingYun::Logger::NullLogger.new
149
- end
150
102
 
151
103
  def wants_stdout?
152
104
  ::TingYun::Agent.config[:agent_log_file_name].upcase == "STDOUT"
153
105
  end
154
106
 
155
- def find_or_create_file_path(path_setting, root)
156
- for abs_path in [File.expand_path(path_setting),
157
- File.expand_path(File.join(root, path_setting))] do
158
- if File.directory?(abs_path) || (Dir.mkdir(abs_path) rescue nil)
159
- return abs_path[%r{^(.*?)/?$}]
160
- end
161
- end
162
- nil
163
- end
164
107
 
165
- def set_log_level!
108
+
109
+ def set_log_level
166
110
  @log.level = AgentLogger.log_level_for(::TingYun::Agent.config[:agent_log_level])
167
111
  end
168
112
 
@@ -178,11 +122,11 @@ module TingYun
178
122
  LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
179
123
  end
180
124
 
181
- def set_log_format!
182
- @hostname = TingYun::Support::Hostname.get
183
- @prefix = wants_stdout? ? '** [TingYun]' : ''
125
+ def set_log_format
126
+ hostname = TingYun::Support::Hostname.get
127
+ prefix = wants_stdout? ? '** [TingYun]' : ''
184
128
  @log.formatter = Proc.new do |severity, timestamp, progname, msg|
185
- "#{@prefix}[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{@hostname} (#{$$})] #{severity} : #{msg}\n"
129
+ "#{prefix}[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{hostname} (#{$$})] #{severity} : #{msg}\n"
186
130
  end
187
131
  end
188
132
 
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ module TingYun
4
+ module Logger
5
+ module CreateLoggerHelper
6
+
7
+
8
+
9
+ def create_log(root, override_logger)
10
+ if !override_logger.nil?
11
+ @log = override_logger
12
+ elsif ::TingYun::Agent.config[:'nbs.agent_enabled'] == false
13
+ create_null_logger
14
+ else
15
+ if wants_stdout?
16
+ @log = ::Logger.new(STDOUT)
17
+ else
18
+ create_log_to_file(root)
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ def check_log_file
25
+ unless File.exist? @file_path
26
+ begin
27
+ @log = ::Logger.new(@file_path)
28
+ set_log_format
29
+ rescue => e
30
+ @log = ::Logger.new(STDOUT)
31
+ warn("check_log_file: Failed creating logger for file #{@file_path}, using standard out for logging.", e)
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+
38
+ def create_log_to_file(root)
39
+ path = find_or_create_file_path(::TingYun::Agent.config[:agent_log_file_path], root)
40
+ unless path
41
+ @log = ::Logger.new(STDOUT)
42
+ warn("Error creating log directory #{::TingYun::Agent.config[:agent_log_file_path]}, using standard out for logging.")
43
+ else
44
+ @file_path = "#{path}/#{::TingYun::Agent.config[:agent_log_file_name]}"
45
+ begin
46
+ @log = ::Logger.new(@file_path)
47
+ rescue => e
48
+ @log = ::Logger.new(STDOUT)
49
+ warn("Failed creating logger for file #{@file_path}, using standard out for logging.", e)
50
+ end
51
+ end
52
+ end
53
+
54
+ def create_null_logger
55
+ @log = ::TingYun::Logger::NullLogger.new
56
+ end
57
+
58
+
59
+ def find_or_create_file_path(path_setting, root)
60
+ for abs_path in [File.expand_path(path_setting),
61
+ File.expand_path(File.join(root, path_setting))] do
62
+ if File.directory?(abs_path) || (FileUtils.mkdir_p(abs_path) rescue nil)
63
+ return abs_path[%r{^(.*?)/?$}]
64
+ end
65
+ end
66
+ nil
67
+ end
68
+
69
+
70
+ end
71
+ end
72
+ end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  # This file is distributed under Ting Yun's license terms.
3
3
 
4
- require 'ting_yun/support/coerce'
4
+
5
5
 
6
6
  module TingYun
7
7
  module Metrics
@@ -16,8 +16,8 @@ module TingYun
16
16
 
17
17
  def initialize(metric_spec, stats, metric_id)
18
18
  @metric_spec = metric_spec
19
- self.stats = stats
20
- self.metric_id = metric_id
19
+ @stats = stats
20
+ @metric_id = metric_id
21
21
  end
22
22
 
23
23
  def eql?(o)
@@ -45,42 +45,20 @@ module TingYun
45
45
  "#<MetricData metric_spec:#{metric_spec.inspect}, stats:#{stats.inspect}, metric_id:#{metric_id.inspect}>"
46
46
  end
47
47
 
48
- include TingYun::Support::Coerce
49
48
 
50
49
  def to_collector_array(encoder=nil)
51
- stat_key = metric_id || stats_has_parent?
52
- [ stat_key,metrics(stat_key)]
50
+ stat_key = metric_id || to_hash
51
+ [stat_key, metrics(stat_key)]
53
52
  end
54
53
 
55
- def stats_has_parent?
56
- hash = { 'name' => metric_spec.name }
57
- hash['calleeId'] = metric_spec.calleeId unless metric_spec.calleeId.nil?
58
- hash['calleeName'] = metric_spec.calleeName unless metric_spec.calleeName.nil?
59
- unless metric_spec.scope.empty?
60
- hash['parent'] = metric_spec.scope
61
- end
62
-
63
- return hash
54
+ def to_hash
55
+ metric_spec.to_hash
64
56
  end
65
57
 
66
58
  def metrics(stat_key)
67
-
68
- metrics = []
69
-
70
- metrics << int(stats.call_count, stat_key)
71
- if stats.max_call_time != 0.0 #apedx
72
- metrics << float(stats.total_call_time, stat_key)
73
- metrics << float(stats.total_exclusive_time, stat_key)
74
- metrics << float(stats.max_call_time, stat_key)
75
- end
76
-
77
- if stats.min_call_time !=0.0 #
78
- metrics << float(stats.min_call_time, stat_key)
79
- metrics << float(stats.sum_of_squares, stat_key)
80
- end
81
-
82
- metrics
59
+ stats.metrics(stat_key)
83
60
  end
61
+
84
62
  end
85
63
  end
86
64
  end
@@ -82,6 +82,17 @@ module TingYun
82
82
  return (self.scope || '') <=> (o.scope || '')
83
83
  end
84
84
 
85
+ def to_hash
86
+ hash = { 'name' => name }
87
+ hash['calleeId'] = calleeId if calleeId
88
+ hash['calleeName'] = calleeName if calleeName
89
+ unless scope.empty?
90
+ hash['parent'] = scope
91
+ end
92
+
93
+ return hash
94
+ end
95
+
85
96
 
86
97
 
87
98
  end
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # This file is distributed under Ting Yun's license terms.
3
+ require 'ting_yun/support/coerce'
3
4
 
4
5
  module TingYun
5
6
  module Metrics
@@ -78,6 +79,10 @@ module TingYun
78
79
  }.to_json(*_)
79
80
  end
80
81
 
82
+
83
+
84
+
85
+
81
86
  def record(value=nil, aux=nil, &blk)
82
87
  if blk
83
88
  yield self
@@ -108,7 +113,6 @@ module TingYun
108
113
  end
109
114
 
110
115
 
111
-
112
116
  # record a single data point into the statistical gatherer. The gatherer
113
117
  # will aggregate all data points collected over a specified period and upload
114
118
  # its data to the TingYun server
@@ -142,6 +146,25 @@ module TingYun
142
146
  )
143
147
  end
144
148
 
149
+ include TingYun::Support::Coerce
150
+
151
+ def metrics(stat_key)
152
+ metrics = []
153
+
154
+ metrics << int(call_count, stat_key)
155
+ if max_call_time != 0.0 #apedx
156
+ metrics << float(total_call_time, stat_key)
157
+ metrics << float(total_exclusive_time, stat_key)
158
+ metrics << float(max_call_time, stat_key)
159
+ end
160
+
161
+ if min_call_time !=0.0 #
162
+ metrics << float(min_call_time, stat_key)
163
+ metrics << float(sum_of_squares, stat_key)
164
+ end
165
+
166
+ metrics
167
+ end
145
168
 
146
169
  protected
147
170
 
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/instrumentation/middleware_proxy'
3
+
4
+ module TingYun
5
+ class AgentMiddleware
6
+
7
+ include TingYun::Instrumentation::MiddlewareTracing
8
+
9
+ attr_reader :transaction_options, :category, :target
10
+
11
+ def initialize(app)
12
+ @app = app
13
+ @category = :middleware
14
+ @target = self
15
+ @transaction_options = {
16
+ :transaction_name => build_transaction_name
17
+ }
18
+ end
19
+
20
+ def build_transaction_name
21
+ prefix = ::TingYun::Instrumentation::Support::TransactionNamer.prefix_for_category(nil, @category)
22
+ "#{prefix}#{self.class.name}/call"
23
+ end
24
+
25
+
26
+
27
+ end
28
+ end
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/middleware/agent_middleware'
3
+ require 'ting_yun/instrumentation/support/javascript_instrumentor'
4
+
5
+
6
+ module TingYun
7
+ class BrowserMonitoring < AgentMiddleware
8
+
9
+ CONTENT_TYPE = 'Content-Type'.freeze
10
+ TEXT_HTML = 'text/html'.freeze
11
+ CONTENT_DISPOSITION = 'Content-Disposition'.freeze
12
+ ATTACHMENT = 'attachment'.freeze
13
+
14
+ SCAN_LIMIT = 64_000
15
+
16
+ TITLE_END = '</title>'.freeze
17
+ TITLE_END_CAPITAL = '</TITLE>'.freeze
18
+ HEAD_END = '<head>'.freeze
19
+ HEAD_END_CAPITAL = '<HEAD>'.freeze
20
+
21
+ GT = '>'.freeze
22
+
23
+
24
+
25
+
26
+ def traced_call(env)
27
+ result = @app.call(env) # [status, headers, response]
28
+
29
+ js_to_inject = TingYun::Instrumentation::Support::JavascriptInstrument.browser_timing_header
30
+
31
+ if (js_to_inject != '') && should_instrument?(env, result[0], result[1])
32
+ response_string = auto_instrument_source(result[2], js_to_inject)
33
+
34
+ env[ALREADY_INSTRUMENTED_KEY] = true
35
+ if response_string
36
+ response = Rack::Response.new(response_string, result[0], result[1])
37
+ response.finish
38
+ else
39
+ result
40
+ end
41
+ else
42
+ result
43
+ end
44
+ end
45
+
46
+ ALREADY_INSTRUMENTED_KEY = "tingyun.browser_monitoring_already_instrumented"
47
+
48
+ def should_instrument?(env, status, headers)
49
+ status == 200 &&
50
+ is_ajax?(env) &&
51
+ !env[ALREADY_INSTRUMENTED_KEY] &&
52
+ is_html?(headers) &&
53
+ !is_attachment?(headers)
54
+ end
55
+
56
+ def is_html?(headers)
57
+ headers[CONTENT_TYPE] && headers[CONTENT_TYPE].include?(TEXT_HTML)
58
+ end
59
+
60
+ def is_ajax?(env)
61
+ env["HTTP_X_REQUESTED_WITH"].nil?
62
+ end
63
+
64
+ def is_attachment?(headers)
65
+ headers[CONTENT_DISPOSITION] && headers[CONTENT_DISPOSITION].include?(ATTACHMENT)
66
+ end
67
+
68
+ def auto_instrument_source(response, js_to_inject)
69
+ source = gather_source(response)
70
+ close_old_response(response)
71
+ return nil unless source
72
+
73
+ beginning_of_source = source[0..SCAN_LIMIT]
74
+ insertion_index = find_tag_end(beginning_of_source)
75
+
76
+ if insertion_index
77
+ source = source[0...insertion_index] <<
78
+ js_to_inject <<
79
+ source[insertion_index..-1]
80
+ else
81
+ TingYun::Agent.logger.debug "Skipping RUM instrumentation. Could not properly determine location to inject script."
82
+ end
83
+
84
+ source
85
+ rescue => e
86
+ TingYun::Agent.logger.debug "Skipping RUM instrumentation on exception.", e
87
+ nil
88
+ end
89
+
90
+ def gather_source(response)
91
+ source = nil
92
+ response.each {|fragment| source ? (source << fragment.to_s) : (source = fragment.to_s)}
93
+ source
94
+ end
95
+
96
+ def close_old_response(response)
97
+ if response.respond_to?(:close)
98
+ response.close
99
+ end
100
+ end
101
+
102
+ def find_tag_end(beginning_of_source)
103
+ tag_end = beginning_of_source.index(TITLE_END) ||
104
+ beginning_of_source.index(HEAD_END) ||
105
+ beginning_of_source.index(TITLE_END_CAPITAL) ||
106
+ beginning_of_source.index(HEAD_END_CAPITAL)
107
+
108
+ beginning_of_source.index(GT, tag_end) + 1 if tag_end
109
+ end
110
+ end
111
+ end