tingyun_rpm 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +14 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +3 -0
- data/Guardfile +25 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/cert/cacert.pem +0 -0
- data/lib/ting_yun/agent/agent.rb +128 -0
- data/lib/ting_yun/agent/class_methods.rb +21 -0
- data/lib/ting_yun/agent/collector/base_sampler.rb +2 -0
- data/lib/ting_yun/agent/collector/error_collector/error_trace_array.rb +88 -0
- data/lib/ting_yun/agent/collector/error_collector/noticed_error.rb +129 -0
- data/lib/ting_yun/agent/collector/error_collector.rb +165 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/cpu_sampler.rb +68 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/memory_sampler.rb +139 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/middle_ware.rb +13 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector/sampler.rb +59 -0
- data/lib/ting_yun/agent/collector/middle_ware_collector.rb +80 -0
- data/lib/ting_yun/agent/collector/sql_sampler.rb +299 -0
- data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +170 -0
- data/lib/ting_yun/agent/collector/stats_engine/stats_hash.rb +172 -0
- data/lib/ting_yun/agent/collector/stats_engine.rb +28 -0
- data/lib/ting_yun/agent/collector/transaction_sampler/slowest_sample_buffer.rb +25 -0
- data/lib/ting_yun/agent/collector/transaction_sampler/transaction_sample_buffer_base.rb +96 -0
- data/lib/ting_yun/agent/collector/transaction_sampler.rb +226 -0
- data/lib/ting_yun/agent/container_data_manager.rb +94 -0
- data/lib/ting_yun/agent/cross_app/cross_app_monitor.rb +131 -0
- data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +202 -0
- data/lib/ting_yun/agent/cross_app/inbound_request_monitor.rb +22 -0
- data/lib/ting_yun/agent/database.rb +410 -0
- data/lib/ting_yun/agent/datastore/metric_helper.rb +82 -0
- data/lib/ting_yun/agent/datastore/mongo.rb +44 -0
- data/lib/ting_yun/agent/datastore.rb +33 -0
- data/lib/ting_yun/agent/dispatcher.rb +39 -0
- data/lib/ting_yun/agent/event/event_listener.rb +47 -0
- data/lib/ting_yun/agent/event/event_loop.rb +194 -0
- data/lib/ting_yun/agent/instance_methods/connect.rb +164 -0
- data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +137 -0
- data/lib/ting_yun/agent/instance_methods/handle_errors.rb +71 -0
- data/lib/ting_yun/agent/instance_methods/start.rb +219 -0
- data/lib/ting_yun/agent/instance_methods/start_worker_thread.rb +51 -0
- data/lib/ting_yun/agent/instance_methods.rb +39 -0
- data/lib/ting_yun/agent/method_tracer.rb +256 -0
- data/lib/ting_yun/agent/method_tracer_helpers.rb +85 -0
- data/lib/ting_yun/agent/threading/agent_thread.rb +49 -0
- data/lib/ting_yun/agent/transaction/attributes.rb +22 -0
- data/lib/ting_yun/agent/transaction/request_attributes.rb +126 -0
- data/lib/ting_yun/agent/transaction/trace.rb +125 -0
- data/lib/ting_yun/agent/transaction/trace_node.rb +110 -0
- data/lib/ting_yun/agent/transaction/traced_method_stack.rb +80 -0
- data/lib/ting_yun/agent/transaction/transaction_metrics.rb +51 -0
- data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +63 -0
- data/lib/ting_yun/agent/transaction/transaction_state.rb +112 -0
- data/lib/ting_yun/agent/transaction.rb +522 -0
- data/lib/ting_yun/agent.rb +207 -0
- data/lib/ting_yun/configuration/default_source.rb +638 -0
- data/lib/ting_yun/configuration/dotted_hash.rb +46 -0
- data/lib/ting_yun/configuration/environment_source.rb +116 -0
- data/lib/ting_yun/configuration/manager.rb +232 -0
- data/lib/ting_yun/configuration/manual_source.rb +14 -0
- data/lib/ting_yun/configuration/server_source.rb +88 -0
- data/lib/ting_yun/configuration/yaml_source.rb +136 -0
- data/lib/ting_yun/configuration.rb +9 -0
- data/lib/ting_yun/environment_report.rb +123 -0
- data/lib/ting_yun/frameworks/class_methods.rb +47 -0
- data/lib/ting_yun/frameworks/external.rb +15 -0
- data/lib/ting_yun/frameworks/instance_methods.rb +120 -0
- data/lib/ting_yun/frameworks/instrumentation.rb +67 -0
- data/lib/ting_yun/frameworks/rails.rb +63 -0
- data/lib/ting_yun/frameworks/rails3.rb +26 -0
- data/lib/ting_yun/frameworks/rails4.rb +14 -0
- data/lib/ting_yun/frameworks/ruby.rb +17 -0
- data/lib/ting_yun/frameworks/sinatra.rb +10 -0
- data/lib/ting_yun/frameworks.rb +34 -0
- data/lib/ting_yun/http/generic_request.rb +8 -0
- data/lib/ting_yun/http/net_http_request.rb +46 -0
- data/lib/ting_yun/instrumentation/active_record.rb +103 -0
- data/lib/ting_yun/instrumentation/middleware_proxy.rb +77 -0
- data/lib/ting_yun/instrumentation/middleware_tracing.rb +84 -0
- data/lib/ting_yun/instrumentation/mongo.rb +103 -0
- data/lib/ting_yun/instrumentation/mongo2.rb +37 -0
- data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +97 -0
- data/lib/ting_yun/instrumentation/moped.rb +95 -0
- data/lib/ting_yun/instrumentation/net.rb +59 -0
- data/lib/ting_yun/instrumentation/rack.rb +109 -0
- data/lib/ting_yun/instrumentation/rails3/action_controller.rb +63 -0
- data/lib/ting_yun/instrumentation/rails3/action_view.rb +115 -0
- data/lib/ting_yun/instrumentation/rails4/action_controller_subscriber.rb +124 -0
- data/lib/ting_yun/instrumentation/rails4/action_view_subscriber.rb +118 -0
- data/lib/ting_yun/instrumentation/rails4/active_record_subscriber.rb +124 -0
- data/lib/ting_yun/instrumentation/rails_middleware.rb +38 -0
- data/lib/ting_yun/instrumentation/redis.rb +70 -0
- data/lib/ting_yun/instrumentation/support/active_record_helper.rb +178 -0
- data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +54 -0
- data/lib/ting_yun/instrumentation/support/database.rb +38 -0
- data/lib/ting_yun/instrumentation/support/event_formatter.rb +19 -0
- data/lib/ting_yun/instrumentation/support/evented_subscriber.rb +97 -0
- data/lib/ting_yun/instrumentation/support/external_error.rb +52 -0
- data/lib/ting_yun/instrumentation/support/metric_translator.rb +84 -0
- data/lib/ting_yun/instrumentation/support/mongo_formatter.rb +49 -0
- data/lib/ting_yun/instrumentation/support/parameter_filtering.rb +21 -0
- data/lib/ting_yun/instrumentation/support/queue_time.rb +76 -0
- data/lib/ting_yun/instrumentation/support/transaction_namer.rb +68 -0
- data/lib/ting_yun/instrumentation/thrift.rb +329 -0
- data/lib/ting_yun/logger/agent_logger.rb +196 -0
- data/lib/ting_yun/logger/log_once.rb +38 -0
- data/lib/ting_yun/logger/memory_logger.rb +56 -0
- data/lib/ting_yun/logger/null_logger.rb +31 -0
- data/lib/ting_yun/logger/startup_logger.rb +13 -0
- data/lib/ting_yun/logger.rb +8 -0
- data/lib/ting_yun/metrics/metric_data.rb +86 -0
- data/lib/ting_yun/metrics/metric_spec.rb +89 -0
- data/lib/ting_yun/metrics/stats.rb +158 -0
- data/lib/ting_yun/metrics.rb +12 -0
- data/lib/ting_yun/support/coerce.rb +86 -0
- data/lib/ting_yun/support/collector.rb +29 -0
- data/lib/ting_yun/support/exception.rb +79 -0
- data/lib/ting_yun/support/hash_extensions.rb +25 -0
- data/lib/ting_yun/support/helper.rb +54 -0
- data/lib/ting_yun/support/hostname.rb +13 -0
- data/lib/ting_yun/support/http_clients/uri_util.rb +49 -0
- data/lib/ting_yun/support/language_support.rb +155 -0
- data/lib/ting_yun/support/library_detection.rb +129 -0
- data/lib/ting_yun/support/local_environment.rb +185 -0
- data/lib/ting_yun/support/path.rb +13 -0
- data/lib/ting_yun/support/serialize/encodes.rb +61 -0
- data/lib/ting_yun/support/serialize/encoding_normalizer.rb +84 -0
- data/lib/ting_yun/support/serialize/json_marshaller.rb +73 -0
- data/lib/ting_yun/support/serialize/json_wrapper.rb +78 -0
- data/lib/ting_yun/support/serialize/marshaller.rb +69 -0
- data/lib/ting_yun/support/serialize/ok_json.rb +651 -0
- data/lib/ting_yun/support/system_info.rb +206 -0
- data/lib/ting_yun/support/timer_lib.rb +29 -0
- data/lib/ting_yun/support/version_number.rb +70 -0
- data/lib/ting_yun/ting_yun_service/connection.rb +118 -0
- data/lib/ting_yun/ting_yun_service/http.rb +41 -0
- data/lib/ting_yun/ting_yun_service/request.rb +90 -0
- data/lib/ting_yun/ting_yun_service/ssl.rb +45 -0
- data/lib/ting_yun/ting_yun_service/upload_service.rb +149 -0
- data/lib/ting_yun/ting_yun_service.rb +124 -0
- data/lib/ting_yun/version.rb +17 -0
- data/lib/tingyun_rpm.rb +47 -0
- data/tingyun_rpm.gemspec +60 -0
- 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
|