tingyun_rpm 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +14 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +3 -0
  7. data/Guardfile +25 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +41 -0
  10. data/cert/cacert.pem +0 -0
  11. data/lib/ting_yun/agent/agent.rb +128 -0
  12. data/lib/ting_yun/agent/class_methods.rb +21 -0
  13. data/lib/ting_yun/agent/collector/base_sampler.rb +2 -0
  14. data/lib/ting_yun/agent/collector/error_collector/error_trace_array.rb +88 -0
  15. data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +129 -0
  16. data/lib/ting_yun/agent/collector/error_collector.rb +165 -0
  17. data/lib/ting_yun/agent/collector/middle_ware_collector/cpu_sampler.rb +68 -0
  18. data/lib/ting_yun/agent/collector/middle_ware_collector/memory_sampler.rb +139 -0
  19. data/lib/ting_yun/agent/collector/middle_ware_collector/middle_ware.rb +13 -0
  20. data/lib/ting_yun/agent/collector/middle_ware_collector/sampler.rb +59 -0
  21. data/lib/ting_yun/agent/collector/middle_ware_collector.rb +80 -0
  22. data/lib/ting_yun/agent/collector/sql_sampler.rb +299 -0
  23. data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +170 -0
  24. data/lib/ting_yun/agent/collector/stats_engine/stats_hash.rb +172 -0
  25. data/lib/ting_yun/agent/collector/stats_engine.rb +28 -0
  26. data/lib/ting_yun/agent/collector/transaction_sampler/slowest_sample_buffer.rb +25 -0
  27. data/lib/ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base.rb +96 -0
  28. data/lib/ting_yun/agent/collector/transaction_sampler.rb +226 -0
  29. data/lib/ting_yun/agent/container_data_manager.rb +94 -0
  30. data/lib/ting_yun/agent/cross_app/cross_app_monitor.rb +131 -0
  31. data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +202 -0
  32. data/lib/ting_yun/agent/cross_app/inbound_request_monitor.rb +22 -0
  33. data/lib/ting_yun/agent/database.rb +410 -0
  34. data/lib/ting_yun/agent/datastore/metric_helper.rb +82 -0
  35. data/lib/ting_yun/agent/datastore/mongo.rb +44 -0
  36. data/lib/ting_yun/agent/datastore.rb +33 -0
  37. data/lib/ting_yun/agent/dispatcher.rb +39 -0
  38. data/lib/ting_yun/agent/event/event_listener.rb +47 -0
  39. data/lib/ting_yun/agent/event/event_loop.rb +194 -0
  40. data/lib/ting_yun/agent/instance_methods/connect.rb +164 -0
  41. data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +137 -0
  42. data/lib/ting_yun/agent/instance_methods/handle_errors.rb +71 -0
  43. data/lib/ting_yun/agent/instance_methods/start.rb +219 -0
  44. data/lib/ting_yun/agent/instance_methods/start_worker_thread.rb +51 -0
  45. data/lib/ting_yun/agent/instance_methods.rb +39 -0
  46. data/lib/ting_yun/agent/method_tracer.rb +256 -0
  47. data/lib/ting_yun/agent/method_tracer_helpers.rb +85 -0
  48. data/lib/ting_yun/agent/threading/agent_thread.rb +49 -0
  49. data/lib/ting_yun/agent/transaction/attributes.rb +22 -0
  50. data/lib/ting_yun/agent/transaction/request_attributes.rb +126 -0
  51. data/lib/ting_yun/agent/transaction/trace.rb +125 -0
  52. data/lib/ting_yun/agent/transaction/trace_node.rb +110 -0
  53. data/lib/ting_yun/agent/transaction/traced_method_stack.rb +80 -0
  54. data/lib/ting_yun/agent/transaction/transaction_metrics.rb +51 -0
  55. data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +63 -0
  56. data/lib/ting_yun/agent/transaction/transaction_state.rb +112 -0
  57. data/lib/ting_yun/agent/transaction.rb +522 -0
  58. data/lib/ting_yun/agent.rb +207 -0
  59. data/lib/ting_yun/configuration/default_source.rb +638 -0
  60. data/lib/ting_yun/configuration/dotted_hash.rb +46 -0
  61. data/lib/ting_yun/configuration/environment_source.rb +116 -0
  62. data/lib/ting_yun/configuration/manager.rb +232 -0
  63. data/lib/ting_yun/configuration/manual_source.rb +14 -0
  64. data/lib/ting_yun/configuration/server_source.rb +88 -0
  65. data/lib/ting_yun/configuration/yaml_source.rb +136 -0
  66. data/lib/ting_yun/configuration.rb +9 -0
  67. data/lib/ting_yun/environment_report.rb +123 -0
  68. data/lib/ting_yun/frameworks/class_methods.rb +47 -0
  69. data/lib/ting_yun/frameworks/external.rb +15 -0
  70. data/lib/ting_yun/frameworks/instance_methods.rb +120 -0
  71. data/lib/ting_yun/frameworks/instrumentation.rb +67 -0
  72. data/lib/ting_yun/frameworks/rails.rb +63 -0
  73. data/lib/ting_yun/frameworks/rails3.rb +26 -0
  74. data/lib/ting_yun/frameworks/rails4.rb +14 -0
  75. data/lib/ting_yun/frameworks/ruby.rb +17 -0
  76. data/lib/ting_yun/frameworks/sinatra.rb +10 -0
  77. data/lib/ting_yun/frameworks.rb +34 -0
  78. data/lib/ting_yun/http/generic_request.rb +8 -0
  79. data/lib/ting_yun/http/net_http_request.rb +46 -0
  80. data/lib/ting_yun/instrumentation/active_record.rb +103 -0
  81. data/lib/ting_yun/instrumentation/middleware_proxy.rb +77 -0
  82. data/lib/ting_yun/instrumentation/middleware_tracing.rb +84 -0
  83. data/lib/ting_yun/instrumentation/mongo.rb +103 -0
  84. data/lib/ting_yun/instrumentation/mongo2.rb +37 -0
  85. data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +97 -0
  86. data/lib/ting_yun/instrumentation/moped.rb +95 -0
  87. data/lib/ting_yun/instrumentation/net.rb +59 -0
  88. data/lib/ting_yun/instrumentation/rack.rb +109 -0
  89. data/lib/ting_yun/instrumentation/rails3/action_controller.rb +63 -0
  90. data/lib/ting_yun/instrumentation/rails3/action_view.rb +115 -0
  91. data/lib/ting_yun/instrumentation/rails4/action_controller_subscriber.rb +124 -0
  92. data/lib/ting_yun/instrumentation/rails4/action_view_subscriber.rb +118 -0
  93. data/lib/ting_yun/instrumentation/rails4/active_record_subscriber.rb +124 -0
  94. data/lib/ting_yun/instrumentation/rails_middleware.rb +38 -0
  95. data/lib/ting_yun/instrumentation/redis.rb +70 -0
  96. data/lib/ting_yun/instrumentation/support/active_record_helper.rb +178 -0
  97. data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +54 -0
  98. data/lib/ting_yun/instrumentation/support/database.rb +38 -0
  99. data/lib/ting_yun/instrumentation/support/event_formatter.rb +19 -0
  100. data/lib/ting_yun/instrumentation/support/evented_subscriber.rb +97 -0
  101. data/lib/ting_yun/instrumentation/support/external_error.rb +52 -0
  102. data/lib/ting_yun/instrumentation/support/metric_translator.rb +84 -0
  103. data/lib/ting_yun/instrumentation/support/mongo_formatter.rb +49 -0
  104. data/lib/ting_yun/instrumentation/support/parameter_filtering.rb +21 -0
  105. data/lib/ting_yun/instrumentation/support/queue_time.rb +76 -0
  106. data/lib/ting_yun/instrumentation/support/transaction_namer.rb +68 -0
  107. data/lib/ting_yun/instrumentation/thrift.rb +329 -0
  108. data/lib/ting_yun/logger/agent_logger.rb +196 -0
  109. data/lib/ting_yun/logger/log_once.rb +38 -0
  110. data/lib/ting_yun/logger/memory_logger.rb +56 -0
  111. data/lib/ting_yun/logger/null_logger.rb +31 -0
  112. data/lib/ting_yun/logger/startup_logger.rb +13 -0
  113. data/lib/ting_yun/logger.rb +8 -0
  114. data/lib/ting_yun/metrics/metric_data.rb +86 -0
  115. data/lib/ting_yun/metrics/metric_spec.rb +89 -0
  116. data/lib/ting_yun/metrics/stats.rb +158 -0
  117. data/lib/ting_yun/metrics.rb +12 -0
  118. data/lib/ting_yun/support/coerce.rb +86 -0
  119. data/lib/ting_yun/support/collector.rb +29 -0
  120. data/lib/ting_yun/support/exception.rb +79 -0
  121. data/lib/ting_yun/support/hash_extensions.rb +25 -0
  122. data/lib/ting_yun/support/helper.rb +54 -0
  123. data/lib/ting_yun/support/hostname.rb +13 -0
  124. data/lib/ting_yun/support/http_clients/uri_util.rb +49 -0
  125. data/lib/ting_yun/support/language_support.rb +155 -0
  126. data/lib/ting_yun/support/library_detection.rb +129 -0
  127. data/lib/ting_yun/support/local_environment.rb +185 -0
  128. data/lib/ting_yun/support/path.rb +13 -0
  129. data/lib/ting_yun/support/serialize/encodes.rb +61 -0
  130. data/lib/ting_yun/support/serialize/encoding_normalizer.rb +84 -0
  131. data/lib/ting_yun/support/serialize/json_marshaller.rb +73 -0
  132. data/lib/ting_yun/support/serialize/json_wrapper.rb +78 -0
  133. data/lib/ting_yun/support/serialize/marshaller.rb +69 -0
  134. data/lib/ting_yun/support/serialize/ok_json.rb +651 -0
  135. data/lib/ting_yun/support/system_info.rb +206 -0
  136. data/lib/ting_yun/support/timer_lib.rb +29 -0
  137. data/lib/ting_yun/support/version_number.rb +70 -0
  138. data/lib/ting_yun/ting_yun_service/connection.rb +118 -0
  139. data/lib/ting_yun/ting_yun_service/http.rb +41 -0
  140. data/lib/ting_yun/ting_yun_service/request.rb +90 -0
  141. data/lib/ting_yun/ting_yun_service/ssl.rb +45 -0
  142. data/lib/ting_yun/ting_yun_service/upload_service.rb +149 -0
  143. data/lib/ting_yun/ting_yun_service.rb +124 -0
  144. data/lib/ting_yun/version.rb +17 -0
  145. data/lib/tingyun_rpm.rb +47 -0
  146. data/tingyun_rpm.gemspec +60 -0
  147. metadata +415 -0
@@ -0,0 +1,109 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ting_yun/instrumentation/middleware_proxy'
4
+ require 'ting_yun/support/version_number'
5
+
6
+
7
+
8
+ module TingYun
9
+ module Instrumentation
10
+
11
+ module RackHelpers
12
+ extend self
13
+
14
+ def middleware_instrumentation_enabled?
15
+ version_supported? && !::TingYun::Agent.config[:disable_middleware_instrumentation]
16
+ end
17
+
18
+ def version_supported?
19
+ rack_version_supported?
20
+ end
21
+
22
+ def rack_version_supported?
23
+ return false unless defined? ::Rack
24
+
25
+ version = ::TingYun::Support::VersionNumber.new(::Rack.release)
26
+ min_version = ::TingYun::Support::VersionNumber.new('1.1.0')
27
+ version >= min_version
28
+ end
29
+ end
30
+
31
+ module RackBuilder
32
+ def run_with_tingyun(app, *args)
33
+ if ::TingYun::Instrumentation::RackHelpers.middleware_instrumentation_enabled?
34
+ wrapped_app = ::TingYun::Instrumentation::MiddlewareProxy.wrap(app, true)
35
+ run_without_tingyun(wrapped_app, *args)
36
+ else
37
+ run_without_tingyun(app, *args)
38
+ end
39
+ end
40
+
41
+
42
+ # def use_with_tingyun(middleware_class, *args, &blk)
43
+ # if ::TingYun::Instrumentation::RackHelpers.middleware_instrumentation_enabled?
44
+ # wrapped_middleware_class = ::TingYun::Instrumentation::MiddlewareProxy.for_class(middleware_class)
45
+ # use_without_tingyun(wrapped_middleware_class, *args, &blk)
46
+ # else
47
+ # use_without_tingyun(middleware_class, *args, &blk)
48
+ # end
49
+ # end
50
+
51
+ # We patch this method for a reason that actually has nothing to do with
52
+ # instrumenting rack itself. It happens to be a convenient and
53
+ # easy-to-hook point that happens late in the startup sequence of almost
54
+ # every application, making it a good place to do a final call to
55
+ # LibraryDetection.detect!, since all libraries are likely loaded at
56
+ # this point.
57
+ def to_app_with_tingyun_deferred_dependency_detection
58
+ unless ::Rack::Builder._nr_deferred_detection_ran
59
+ TingYun::Agent.logger.info "Doing deferred library-detection before Rack startup"
60
+ TingYun::Support::LibraryDetection.detect!
61
+ ::Rack::Builder._nr_deferred_detection_ran = true
62
+ end
63
+
64
+ result = to_app_without_tingyun
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+
72
+
73
+
74
+ TingYun::Support::LibraryDetection.defer do
75
+
76
+ named :rack
77
+
78
+ depends_on do
79
+ defined?(::Rack) && defined?(::Rack::Builder)
80
+ end
81
+
82
+ executes do
83
+ ::TingYun::Agent.logger.info 'Installing deferred Rack instrumentation'
84
+
85
+ class ::Rack::Builder
86
+ class << self
87
+ attr_accessor :_nr_deferred_detection_ran
88
+ end
89
+
90
+ self._nr_deferred_detection_ran = false
91
+
92
+ include ::TingYun::Instrumentation::RackBuilder
93
+
94
+ alias_method :to_app_without_tingyun, :to_app
95
+ alias_method :to_app, :to_app_with_tingyun_deferred_dependency_detection
96
+
97
+ unless TingYun::Agent.config[:disable_middleware_instrumentation]
98
+ ::TingYun::Agent.logger.info 'Installing Rack::Builder middleware instrumentation'
99
+
100
+ alias_method :run_without_tingyun, :run
101
+ alias_method :run, :run_with_tingyun
102
+ #
103
+ # alias_method :use_without_tingyun, :use
104
+ # alias_method :use, :use_with_tingyun
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/agent'
3
+ require 'ting_yun/instrumentation/support/controller_instrumentation'
4
+ require 'ting_yun/instrumentation/support/parameter_filtering'
5
+
6
+ module TingYun
7
+ module Instrumentation
8
+ module Rails3
9
+ module ActionController
10
+
11
+ def tingyun_metric_path(action_name_override = nil)
12
+
13
+ return self.env["PATH_INFO"] unless TingYun::Agent.config[:'nbs.auto_action_naming']
14
+
15
+ action = action_name_override || action_name
16
+ if action_name_override || self.class.action_methods.include?(action)
17
+ "Rails3/#{self.class.controller_path}%2F#{action}"
18
+ else
19
+ "Rails3/#{self.class.controller_path}%2F(other)"
20
+ end
21
+ end
22
+
23
+
24
+
25
+ def process_action(*args)
26
+ params = TingYun::Instrumentation::Support::ParameterFiltering.filter_rails_request_parameters(request.filtered_parameters)
27
+ perform_action_with_tingyun_trace(:category => :controller,
28
+ :name => self.action_name,
29
+ :path => tingyun_metric_path,
30
+ :params => params,
31
+ :class_name => self.class.name) do
32
+ super
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+ TingYun::Support::LibraryDetection.defer do
42
+ @name = :rails3_controller
43
+
44
+ depends_on do
45
+ defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3
46
+ end
47
+
48
+ depends_on do
49
+ defined?(ActionController) && defined?(ActionController::Base)
50
+ end
51
+
52
+ executes do
53
+ ::TingYun::Agent.logger.info 'Installing Rails 3 Controller instrumentation'
54
+ end
55
+
56
+ executes do
57
+ class ActionController::Base
58
+ include TingYun::Instrumentation::Support::ControllerInstrumentation
59
+ include TingYun::Instrumentation::Rails3::ActionController
60
+ end
61
+ end
62
+ end
63
+
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ting_yun/agent'
4
+ require 'ting_yun/agent/method_tracer'
5
+
6
+ module TingYun
7
+ module Instrumentation
8
+ module Rails3
9
+ module ActionView
10
+ extend self
11
+
12
+ def template_metric(identifier, options = {})
13
+ if options[:file]
14
+ "file"
15
+ elsif identifier.nil?
16
+ ::TingYun::Agent::UNKNOWN_METRIC
17
+ elsif identifier.include? '/' # this is a filepath
18
+ identifier.split('/')[-2..-1].join('/')
19
+ else
20
+ identifier
21
+ end
22
+ end
23
+ def render_type(file_path)
24
+ file = File.basename(file_path)
25
+ if file.starts_with?('_')
26
+ return 'Partial'
27
+ else
28
+ return 'Rendering'
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ TingYun::Support::LibraryDetection.defer do
38
+ @name = :rails31_view
39
+
40
+ # We can't be sure that this will work with future versions of Rails 3.
41
+ # Currently enabled for Rails 3.1 and 3.2
42
+ depends_on do
43
+ defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3 && ([1,2].member?(::Rails::VERSION::MINOR.to_i))
44
+ end
45
+
46
+ executes do
47
+ ::TingYun::Agent.logger.info 'Installing Rails 3.1/3.2 view instrumentation'
48
+ end
49
+
50
+ executes do
51
+ ActionView::TemplateRenderer.class_eval do
52
+ # namespaced helper methods
53
+
54
+ def render_with_tingyun(context, options)
55
+ # This is needed for rails 3.2 compatibility
56
+ @details = extract_details(options) if respond_to? :extract_details, true
57
+ identifier = determine_template(options) ? determine_template(options).identifier : nil
58
+ scope_name = "View/#{TingYun::Instrumentation::Rails3::ActionView.template_metric(identifier, options)}/Rendering"
59
+ TingYun::Agent::MethodTracer.trace_execution_scoped scope_name do
60
+ render_without_tingyun(context, options)
61
+ end
62
+ end
63
+
64
+ alias_method :render_without_tingyun, :render
65
+ alias_method :render, :render_with_tingyun
66
+ end
67
+
68
+ ActionView::PartialRenderer.class_eval do
69
+
70
+ def instrument_with_tingyun(name, payload = {}, &block)
71
+ identifier = payload[:identifier]
72
+ scope_name = "View/#{TingYun::Instrumentation::Rails3::ActionView.template_metric(identifier)}/Partial"
73
+ TingYun::Agent::MethodTracer.trace_execution_scoped(scope_name) do
74
+ instrument_without_tingyun(name, payload, &block)
75
+ end
76
+ end
77
+
78
+ alias_method :instrument_without_tingyun, :instrument
79
+ alias_method :instrument, :instrument_with_tingyun
80
+ end
81
+ end
82
+ end
83
+
84
+
85
+ TingYun::Support::LibraryDetection.defer do
86
+ @name = :rails30_view
87
+
88
+ depends_on do
89
+ defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3 && ::Rails::VERSION::MINOR.to_i == 0
90
+ end
91
+
92
+ executes do
93
+ ::TingYun::Agent.logger.info 'Installing Rails 3.0 view instrumentation'
94
+ end
95
+
96
+ executes do
97
+ ActionView::Template.class_eval do
98
+ def render_with_tingyun(*args, &block)
99
+ options = if @virtual_path && @virtual_path.starts_with?('/') # file render
100
+ {:file => true }
101
+ else
102
+ {}
103
+ end
104
+ str = "View/#{TingYun::Instrumentation::Rails3::ActionView.template_metric(@identifier, options)}/#{TingYun::Agent::Instrumentation::Rails3::ActionView.render_type(@identifier)}"
105
+ TingYun::Agent::MethodTracer.trace_execution_scoped str do
106
+ render_without_tingyun(*args, &block)
107
+ end
108
+ end
109
+
110
+ alias_method :render_without_tingyun, :render
111
+ alias_method :render, :render_with_tingyun
112
+
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,124 @@
1
+ # encoding: utf-8
2
+
3
+ require 'ting_yun/instrumentation/support/queue_time'
4
+ require 'ting_yun/agent/transaction/transaction_state'
5
+ require 'ting_yun/instrumentation/support/evented_subscriber'
6
+ require 'ting_yun/agent/transaction'
7
+
8
+ module TingYun
9
+ module Instrumentation
10
+ module Rails4
11
+ class ActionControllerSubscriber < TingYun::Instrumentation::Support::EventedSubscriber
12
+ def start(name, id, payload) #THREAD_LOCAL_ACCES
13
+ state = TingYun::Agent::TransactionState.tl_get
14
+ request = state.request
15
+ event = ControllerEvent.new(name, Time.now, nil, id, payload, request)
16
+ push_event(event)
17
+ # if state.execution_traced?
18
+ start_transaction(state, event)
19
+ # end
20
+ rescue => e
21
+ log_notification_error(e, name, 'start')
22
+ end
23
+
24
+ def finish(name, id, payload) #THREAD_LOCAL_ACCESS
25
+
26
+ event = pop_event(id)
27
+ event.payload.merge!(payload)
28
+
29
+ state = TingYun::Agent::TransactionState.tl_get
30
+
31
+
32
+ stop_transaction(state)
33
+ rescue => e
34
+ log_notification_error(e, name, 'finish')
35
+ end
36
+
37
+ def start_transaction(state, event)
38
+ TingYun::Agent::Transaction.start(state, :controller,
39
+ :request => event.request,
40
+ :filtered_params => event.payload[:params],
41
+ :apdex_start_time => event.queue_start,
42
+ :transaction_name => event.metric_name)
43
+ end
44
+
45
+ def stop_transaction(state)
46
+ # txn = state.current_transaction
47
+ TingYun::Agent::Transaction.stop(state)
48
+ end
49
+
50
+
51
+ end
52
+
53
+ class ControllerEvent < TingYun::Instrumentation::Support::Event
54
+ attr_accessor :parent
55
+ attr_reader :queue_start, :request
56
+
57
+ def initialize(name, start, ending, transaction_id, payload, request)
58
+ # We have a different initialize parameter list, so be explicit
59
+ super(name, start, ending, transaction_id, payload, nil)
60
+
61
+ @request = request
62
+ @controller_class = payload[:controller].split('::') \
63
+ .inject(Object) { |m, o| m.const_get(o) }
64
+
65
+ if request && request.respond_to?(:env)
66
+ @queue_start = TingYun::Instrumentation::Support::QueueTime.parse_frontend_timestamp(request.env, self.time)
67
+ end
68
+ end
69
+
70
+ def metric_name
71
+ if TingYun::Agent.config[:'nbs.auto_action_naming']
72
+ @metric_name ||= "WebAction/Rails/#{metric_path}%2F#{metric_action}"
73
+ else
74
+ path
75
+ end
76
+ end
77
+
78
+ def metric_path
79
+ @controller_class.controller_path
80
+ end
81
+
82
+ def metric_class
83
+ payload[:controller]
84
+ end
85
+
86
+ def metric_action
87
+ payload[:action]
88
+ end
89
+
90
+ def path
91
+ payload[:path]
92
+ end
93
+
94
+ def to_s
95
+ "#<TingYun::Instrumentation::ControllerEvent:#{object_id} name: \"#{name}\" id: #{transaction_id} payload: #{payload}}>"
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+
103
+ TingYun::Support::LibraryDetection.defer do
104
+ @name = :rails4_controller
105
+
106
+ depends_on do
107
+ defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 4
108
+ end
109
+
110
+ depends_on do
111
+ defined?(ActionController) && defined?(ActionController::Base)
112
+ end
113
+
114
+ executes do
115
+ ::TingYun::Agent.logger.info 'Installing Rails 4 Controller instrumentation'
116
+ end
117
+
118
+ executes do
119
+ ::TingYun::Instrumentation::Rails4::ActionControllerSubscriber \
120
+ .subscribe(/^process_action.action_controller$/)
121
+ end
122
+ end
123
+
124
+
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ require 'ting_yun/instrumentation/support/evented_subscriber'
5
+ require 'ting_yun/agent/transaction/transaction_state'
6
+ require 'ting_yun/agent'
7
+
8
+ module TingYun
9
+ module Instrumentation
10
+ module Rails4
11
+ class ActionViewSubscriber < TingYun::Instrumentation::Support::EventedSubscriber
12
+
13
+ def start(name, id, payload) #THREAD_LOCAL_ACCESS
14
+ event = RenderEvent.new(name, Time.now, nil, id, payload)
15
+ push_event(event)
16
+
17
+ state = TingYun::Agent::TransactionState.tl_get
18
+
19
+ if event.recordable?
20
+ stack = state.traced_method_stack
21
+ event.frame = stack.push_frame(state, :action_view, event.time)
22
+ end
23
+ rescue => e
24
+ log_notification_error(e, name, 'start')
25
+ end
26
+
27
+ def finish(name, id, payload) #THREAD_LOCAL_ACCESS
28
+ event = pop_event(id)
29
+
30
+ state = TingYun::Agent::TransactionState.tl_get
31
+
32
+ if event.recordable?
33
+ stack = state.traced_method_stack
34
+ frame = stack.pop_frame(state, event.frame, event.metric_name, event.end)
35
+ record_metrics(event, frame)
36
+ end
37
+ rescue => e
38
+ log_notification_error(e, name, 'finish')
39
+ end
40
+
41
+ def record_metrics(event, frame)
42
+ exclusive = event.duration - frame.children_time
43
+ TingYun::Agent.instance.stats_engine.tl_record_scoped_and_unscoped_metrics(
44
+ event.metric_name, nil, event.duration, exclusive)
45
+ end
46
+ end
47
+
48
+ class RenderEvent < TingYun::Instrumentation::Support::Event
49
+
50
+ def recordable?
51
+ name[0] == '!' ||
52
+ metric_name == 'View/text template/Rendering' ||
53
+ metric_name == "View/#{::TingYun::Agent::UNKNOWN_METRIC}/Partial"
54
+ end
55
+
56
+ def metric_name
57
+ if parent && (payload[:virtual_path] ||
58
+ (parent.payload[:identifier] =~ /template$/))
59
+ return parent.metric_name
60
+ elsif payload.key?(:virtual_path)
61
+ identifier = payload[:virtual_path]
62
+ else
63
+ identifier = payload[:identifier]
64
+ end
65
+
66
+ # memoize
67
+ @metric_name ||= "View/#{metric_path(identifier)}/#{metric_action(name)}"
68
+ @metric_name
69
+ end
70
+
71
+ def metric_path(identifier)
72
+ if identifier == nil
73
+ 'file'
74
+ elsif identifier =~ /template$/
75
+ identifier
76
+ elsif (parts = identifier.split('/')).size > 1
77
+ parts[-2..-1].join('/')
78
+ else
79
+ ::TingYun::Agent::UNKNOWN_METRIC
80
+ end
81
+ end
82
+
83
+ def metric_action(name)
84
+ case name
85
+ when /render_template.action_view$/ then
86
+ 'Rendering'
87
+ when 'render_partial.action_view' then
88
+ 'Partial'
89
+ when 'render_collection.action_view' then
90
+ 'Partial'
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ TingYun::Support::LibraryDetection.defer do
99
+ @name = :rails4_view
100
+
101
+ depends_on do
102
+ defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 4
103
+ end
104
+
105
+ depends_on do
106
+ !TingYun::Agent.config[:disable_view_instrumentation] &&
107
+ !TingYun::Instrumentation::Rails4::ActionViewSubscriber.subscribed?
108
+ end
109
+
110
+ executes do
111
+ TingYun::Agent.logger.info 'Installing Rails 4 view instrumentation'
112
+ end
113
+
114
+ executes do
115
+ TingYun::Instrumentation::Rails4::ActionViewSubscriber.subscribe(/render_.+\.action_view$/)
116
+ end
117
+ end
118
+ #
@@ -0,0 +1,124 @@
1
+ # encoding: utf-8
2
+ require 'ting_yun/instrumentation/support/evented_subscriber'
3
+ require 'ting_yun/agent/transaction/transaction_state'
4
+ require 'ting_yun/instrumentation/support/active_record_helper'
5
+ require 'ting_yun/support/helper'
6
+
7
+
8
+ module TingYun
9
+ module Instrumentation
10
+ module Rails4
11
+ class ActiveRecordSubscriber < TingYun::Instrumentation::Support::EventedSubscriber
12
+ CACHED_QUERY_NAME = 'CACHE'.freeze unless defined? CACHED_QUERY_NAME
13
+
14
+ def initialize
15
+ # We cache this in an instance variable to avoid re-calling method
16
+ # on each query.
17
+ @explainer = method(:get_explain_plan)
18
+ super
19
+ end
20
+
21
+ def start(name, id, payload) #THREAD_LOCAL_ACCESS
22
+
23
+ return if payload[:name] == CACHED_QUERY_NAME
24
+ super
25
+ rescue => e
26
+ log_notification_error(e, name, 'start')
27
+ end
28
+
29
+ def finish(name, id, payload) #THREAD_LOCAL_ACCESS
30
+ return if payload[:name] == CACHED_QUERY_NAME
31
+ state = TingYun::Agent::TransactionState.tl_get
32
+ event = pop_event(id)
33
+ config = active_record_config_for_event(event)
34
+ base_metric = record_metrics(event, config)
35
+ notice_sql(state, event, config, base_metric)
36
+ rescue => e
37
+ log_notification_error(e, name, 'finish')
38
+ end
39
+
40
+ def get_explain_plan( config, query )
41
+ connection = TingYun::Agent::Database.get_connection(config) do
42
+ ::ActiveRecord::Base.send("#{config[:adapter]}_connection",
43
+ config)
44
+ end
45
+ if connection && connection.respond_to?(:execute)
46
+ return connection.execute("EXPLAIN #{query}")
47
+ end
48
+ end
49
+
50
+ def notice_sql(state, event, config, metric)
51
+ stack = state.traced_method_stack
52
+ state.sql_duration = event.duration
53
+ # enter transaction trace node
54
+ frame = stack.push_frame(state, :active_record, event.time)
55
+
56
+ TingYun::Agent.instance.sql_sampler \
57
+ .notice_sql(event.payload[:sql], metric, config,
58
+ TingYun::Helper.milliseconds_to_seconds(event.duration),
59
+ state, @explainer)
60
+
61
+ TingYun::Agent.instance.transaction_sampler \
62
+ .notice_sql(event.payload[:sql], config,
63
+ event.duration,
64
+ state, @explainer)
65
+ # exit transaction trace node
66
+ stack.pop_frame(state, frame, metric, event.end)
67
+ end
68
+
69
+ def record_metrics(event, config)
70
+ base, *other_metrics = TingYun::Instrumentation::Support::ActiveRecordHelper.metrics_for(event.payload[:name],
71
+ TingYun::Helper.correctly_encoded(event.payload[:sql]),
72
+ config && config[:adapter])
73
+
74
+ TingYun::Agent.agent.stats_engine.tl_record_scoped_and_unscoped_metrics(base, other_metrics, event.duration)
75
+
76
+ base
77
+ end
78
+
79
+
80
+ def active_record_config_for_event(event)
81
+ return unless event.payload[:connection_id]
82
+
83
+ connection = nil
84
+ connection_id = event.payload[:connection_id]
85
+
86
+ ::ActiveRecord::Base.connection_handler.connection_pool_list.each do |handler|
87
+ connection = handler.connections.detect do |conn|
88
+ conn.object_id == connection_id
89
+ end
90
+
91
+ break if connection
92
+ end
93
+
94
+ connection.instance_variable_get(:@config) if connection
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ TingYun::Support::LibraryDetection.defer do
102
+ named :active_record_4
103
+
104
+
105
+ depends_on do
106
+ defined?(::ActiveRecord) && defined?(::ActiveRecord::Base) &&
107
+ defined?(::ActiveRecord::VERSION) &&
108
+ ::ActiveRecord::VERSION::MAJOR.to_i >= 4
109
+ end
110
+
111
+ depends_on do
112
+ !TingYun::Instrumentation::Rails4::ActiveRecordSubscriber.subscribed?
113
+ end
114
+
115
+ executes do
116
+ ::TingYun::Agent.logger.info 'Installing ActiveRecord 4 instrumentation'
117
+ end
118
+
119
+ executes do
120
+ ActiveSupport::Notifications.subscribe('sql.active_record',
121
+ TingYun::Instrumentation::Rails4::ActiveRecordSubscriber.new)
122
+ ::TingYun::Instrumentation::Support::ActiveRecordHelper.instrument_additional_methods
123
+ end
124
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ require 'ting_yun/instrumentation/middleware_proxy'
5
+
6
+ TingYun::Support::LibraryDetection.defer do
7
+ named :rails_middleware
8
+
9
+ depends_on do
10
+ defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i >= 3
11
+ end
12
+
13
+ depends_on do
14
+ !::TingYun::Agent.config[:disable_middleware_instrumentation]
15
+ end
16
+
17
+ executes do
18
+ ::TingYun::Agent.logger.info("Installing Rails 3+ middleware instrumentation")
19
+ module ActionDispatch
20
+ class MiddlewareStack
21
+ class Middleware
22
+ def build_with_ting_yun(app)
23
+ # MiddlewareProxy.wrap guards against double-wrapping here.
24
+ # We need to instrument the innermost app (usually a RouteSet),
25
+ # which will never itself be the return value from #build, but will
26
+ # instead be the initial value of the app argument.
27
+ wrapped_app = ::TingYun::Instrumentation::MiddlewareProxy.wrap(app)
28
+ result = build_without_ting_yun(wrapped_app)
29
+ ::TingYun::Instrumentation::MiddlewareProxy.wrap(result)
30
+ end
31
+
32
+ alias_method :build_without_ting_yun, :build
33
+ alias_method :build, :build_with_ting_yun
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end