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,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
|
4
|
+
module TingYun
|
5
|
+
module Agent
|
6
|
+
module Threading
|
7
|
+
class AgentThread
|
8
|
+
|
9
|
+
def self.create(label, &blk)
|
10
|
+
TingYun::Agent.logger.debug("Creating Ting Yun thread: #{label}")
|
11
|
+
wrapped_blk = Proc.new do
|
12
|
+
begin
|
13
|
+
blk.call
|
14
|
+
rescue => e
|
15
|
+
TingYun::Agent.logger.error("Thread #{label} exited with error", e)
|
16
|
+
rescue Exception => e
|
17
|
+
TingYun::Agent.logger.error("Thread #{label} exited with exception. Re-raising in case of interupt.", e)
|
18
|
+
raise
|
19
|
+
ensure
|
20
|
+
TingYun::Agent.logger.debug("Exiting TingYun thread: #{label}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
thread = backing_thread_class.new(&wrapped_blk)
|
25
|
+
thread[:TingYun_label] = label
|
26
|
+
thread
|
27
|
+
end
|
28
|
+
|
29
|
+
# Simplifies testing if we don't directly use ::Thread.list, so keep
|
30
|
+
# the accessor for it here on AgentThread to use and stub.
|
31
|
+
def self.list
|
32
|
+
backing_thread_class.list
|
33
|
+
end
|
34
|
+
|
35
|
+
# To allow tests to swap out Thread for a synchronous alternative,
|
36
|
+
# surface the backing class we'll use from the class level.
|
37
|
+
@backing_thread_class = ::Thread
|
38
|
+
|
39
|
+
def self.backing_thread_class
|
40
|
+
@backing_thread_class
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.backing_thread_class=(clazz)
|
44
|
+
@backing_thread_class = clazz
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TingYun
|
4
|
+
module Agent
|
5
|
+
class Transaction
|
6
|
+
class Attributes
|
7
|
+
|
8
|
+
attr_accessor :agent_attributes
|
9
|
+
def initialize
|
10
|
+
@agent_attributes = {}
|
11
|
+
@custom_attributes = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_agent_attribute(key, value)
|
15
|
+
return if value.nil?
|
16
|
+
@agent_attributes[key] = value
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ting_yun/support/http_clients/uri_util'
|
4
|
+
|
5
|
+
module TingYun
|
6
|
+
module Agent
|
7
|
+
class Transaction
|
8
|
+
class RequestAttributes
|
9
|
+
|
10
|
+
attr_reader :request_path, :referer, :accept, :content_length, :host,
|
11
|
+
:port, :user_agent, :request_method, :query_string
|
12
|
+
|
13
|
+
HTTP_ACCEPT_HEADER_KEY = 'HTTP_ACCEPT'.freeze
|
14
|
+
|
15
|
+
def initialize request
|
16
|
+
@request_path = path_from_request request
|
17
|
+
@referer = referer_from_request request
|
18
|
+
@accept = attribute_from_env request, HTTP_ACCEPT_HEADER_KEY
|
19
|
+
@content_length = content_length_from_request request
|
20
|
+
@host = attribute_from_request request, :host
|
21
|
+
@port = port_from_request request
|
22
|
+
@user_agent = attribute_from_request request, :user_agent
|
23
|
+
@request_method = attribute_from_request request, :request_method
|
24
|
+
@query_string = attribute_from_request request, :query_string
|
25
|
+
end
|
26
|
+
|
27
|
+
def assign_agent_attributes(txn)
|
28
|
+
|
29
|
+
if request_path
|
30
|
+
txn.add_agent_attribute :request_path, request_path
|
31
|
+
end
|
32
|
+
|
33
|
+
if referer
|
34
|
+
txn.add_agent_attribute :referer, referer
|
35
|
+
end
|
36
|
+
|
37
|
+
if accept
|
38
|
+
txn.add_agent_attribute :accept, accept
|
39
|
+
end
|
40
|
+
|
41
|
+
if content_length
|
42
|
+
txn.add_agent_attribute :contentLength, content_length
|
43
|
+
end
|
44
|
+
|
45
|
+
if host
|
46
|
+
txn.add_agent_attribute :host, host
|
47
|
+
end
|
48
|
+
|
49
|
+
if port
|
50
|
+
txn.add_agent_attribute :port, port
|
51
|
+
end
|
52
|
+
|
53
|
+
if user_agent
|
54
|
+
txn.add_agent_attribute :userAgent, user_agent
|
55
|
+
end
|
56
|
+
|
57
|
+
if request_method
|
58
|
+
txn.add_agent_attribute :method, request_method
|
59
|
+
end
|
60
|
+
|
61
|
+
if query_string
|
62
|
+
txn.add_agent_attribute :request_params, request_params
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Make a safe attempt to get the referer from a request object, generally successful when
|
70
|
+
# it's a Rack request.
|
71
|
+
|
72
|
+
def request_params
|
73
|
+
hash = {}
|
74
|
+
return hash if @query_string.empty?
|
75
|
+
query_string.split('&').each do |param|
|
76
|
+
_k,_v = param.strip.split('=')
|
77
|
+
hash[_k] = _v unless _v.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
|
83
|
+
def referer_from_request request
|
84
|
+
if referer = attribute_from_request(request, :referer)
|
85
|
+
TingYun::Agent::HTTPClients::URIUtil.strip_query_string referer.to_s
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
ROOT_PATH = "/".freeze
|
92
|
+
|
93
|
+
def path_from_request request
|
94
|
+
path = attribute_from_request(request, :path) || ''
|
95
|
+
path = TingYun::Agent::HTTPClients::URIUtil.strip_query_string(path)
|
96
|
+
path.empty? ? ROOT_PATH : path
|
97
|
+
end
|
98
|
+
|
99
|
+
def content_length_from_request request
|
100
|
+
if content_length = attribute_from_request(request, :content_length)
|
101
|
+
content_length.to_i
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def port_from_request request
|
106
|
+
if port = attribute_from_request(request, :port)
|
107
|
+
port.to_i
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def attribute_from_request request, attribute_method
|
112
|
+
if request.respond_to? attribute_method
|
113
|
+
request.send(attribute_method)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def attribute_from_env request, key
|
118
|
+
if env = attribute_from_request(request, :env)
|
119
|
+
env[key]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/agent/transaction/trace_node'
|
3
|
+
require 'ting_yun/support/helper'
|
4
|
+
require 'ting_yun/support/coerce'
|
5
|
+
require 'ting_yun/agent/database'
|
6
|
+
module TingYun
|
7
|
+
module Agent
|
8
|
+
class Transaction
|
9
|
+
class Trace
|
10
|
+
|
11
|
+
attr_accessor :node_count, :threshold, :metric_name, :uri, :guid, :attributes, :start_time, :finished, :tx_id
|
12
|
+
|
13
|
+
attr_reader :root_node
|
14
|
+
|
15
|
+
def initialize(start_time)
|
16
|
+
@start_time = start_time
|
17
|
+
@node_count = 0
|
18
|
+
@root_node = TingYun::Agent::Transaction::TraceNode.new(0.0, 'ROOT')
|
19
|
+
@prepared = false
|
20
|
+
@guid = generate_guid
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_node(time_since_start, metric_name = nil)
|
24
|
+
@node_count += 1
|
25
|
+
TingYun::Agent::Transaction::TraceNode.new(time_since_start, metric_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def duration
|
29
|
+
@root_node.duration
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
include TingYun::Support::Coerce
|
35
|
+
|
36
|
+
def trace_tree
|
37
|
+
[
|
38
|
+
duration,
|
39
|
+
request_params,
|
40
|
+
custom_params,
|
41
|
+
@root_node.to_array
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_collector_array(encoder)
|
46
|
+
[
|
47
|
+
@start_time.round,
|
48
|
+
duration,
|
49
|
+
TingYun::Helper.correctly_encoded(metric_name),
|
50
|
+
TingYun::Helper.correctly_encoded(uri),
|
51
|
+
encoder.encode(trace_tree),
|
52
|
+
tx_id || '',
|
53
|
+
guid
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
def prepare_to_send!
|
58
|
+
return self if @prepared
|
59
|
+
|
60
|
+
if TingYun::Agent::Database.should_record_sql?('nbs.action_tracer.record_sql')
|
61
|
+
collect_explain_plans!
|
62
|
+
prepare_sql_for_transmission!
|
63
|
+
else
|
64
|
+
@root_node.each_call do |node|
|
65
|
+
node.params.delete(:sql)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@prepared = true
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def collect_explain_plans!
|
73
|
+
return unless TingYun::Agent::Database.should_action_collect_explain_plans?
|
74
|
+
threshold = TingYun::Agent.config[:'nbs.action_tracer.action_threshold']
|
75
|
+
@root_node.each_call do |node|
|
76
|
+
if node[:sql] && node.duration > threshold
|
77
|
+
node[:explainPlan] = node.explain_sql
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def prepare_sql_for_transmission!(&block)
|
83
|
+
strategy = TingYun::Agent::Database.record_sql_method('nbs.action_tracer.record_sql')
|
84
|
+
@root_node.each_call do |node|
|
85
|
+
next unless node[:sql]
|
86
|
+
|
87
|
+
case strategy
|
88
|
+
when :obfuscated
|
89
|
+
node[:sql] = TingYun::Agent::Database.obfuscate_sql(node[:sql])
|
90
|
+
when :raw
|
91
|
+
node[:sql] = node[:sql].sql.to_s
|
92
|
+
else
|
93
|
+
node[:sql] = nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def custom_params
|
99
|
+
{
|
100
|
+
:threadName => string(attributes.agent_attributes[:threadName]),
|
101
|
+
:httpStatus => int(attributes.agent_attributes[:httpStatus]),
|
102
|
+
:referer => string(attributes.agent_attributes[:referer]) || ''
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def request_params
|
107
|
+
attributes.agent_attributes[:request_params]
|
108
|
+
end
|
109
|
+
|
110
|
+
HEX_DIGITS = (0..15).map{|i| i.to_s(16)}
|
111
|
+
GUID_LENGTH = 16
|
112
|
+
|
113
|
+
# generate a random 64 bit uuid
|
114
|
+
private
|
115
|
+
def generate_guid
|
116
|
+
guid = ''
|
117
|
+
GUID_LENGTH.times do
|
118
|
+
guid << HEX_DIGITS[rand(16)]
|
119
|
+
end
|
120
|
+
guid
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/support/helper'
|
3
|
+
require 'ting_yun/support/coerce'
|
4
|
+
require 'ting_yun/agent/database'
|
5
|
+
|
6
|
+
|
7
|
+
module TingYun
|
8
|
+
module Agent
|
9
|
+
class Transaction
|
10
|
+
class TraceNode
|
11
|
+
|
12
|
+
attr_reader :entry_timestamp, :parent_node, :called_nodes
|
13
|
+
attr_accessor :metric_name, :exit_timestamp, :uri, :count, :klass, :method
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
UNKNOWN_NODE_NAME = '<unknown>'.freeze
|
18
|
+
|
19
|
+
|
20
|
+
def initialize(timestamp, metric_name)
|
21
|
+
@entry_timestamp = timestamp
|
22
|
+
@metric_name = metric_name || UNKNOWN_NODE_NAME
|
23
|
+
@called_nodes = nil
|
24
|
+
@count = 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_called_node(s)
|
28
|
+
@called_nodes ||= []
|
29
|
+
@called_nodes << s
|
30
|
+
s.parent_node = self
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_trace(timestamp)
|
34
|
+
@exit_timestamp = timestamp
|
35
|
+
end
|
36
|
+
|
37
|
+
# return the total duration of this node
|
38
|
+
def duration
|
39
|
+
TingYun::Helper.time_to_millis(@exit_timestamp - @entry_timestamp)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def to_array
|
44
|
+
[TingYun::Helper.time_to_millis(entry_timestamp),
|
45
|
+
TingYun::Helper.time_to_millis(exit_timestamp),
|
46
|
+
TingYun::Support::Coerce.string(metric_name),
|
47
|
+
TingYun::Support::Coerce.string(uri)||'',
|
48
|
+
TingYun::Support::Coerce.int(count),
|
49
|
+
TingYun::Support::Coerce.string(klass)||TingYun::Support::Coerce.string(metric_name),
|
50
|
+
TingYun::Support::Coerce.string(method)||'',
|
51
|
+
params] +
|
52
|
+
[(@called_nodes ? @called_nodes.map{|s| s.to_array} : [])]
|
53
|
+
end
|
54
|
+
|
55
|
+
def custom_params
|
56
|
+
{}
|
57
|
+
end
|
58
|
+
|
59
|
+
def request_params
|
60
|
+
{}
|
61
|
+
end
|
62
|
+
|
63
|
+
def []=(key, value)
|
64
|
+
# only create a parameters field if a parameter is set; this will save
|
65
|
+
# bandwidth etc as most nodes have no parameters
|
66
|
+
params[key] = value
|
67
|
+
end
|
68
|
+
|
69
|
+
def [](key)
|
70
|
+
params[key]
|
71
|
+
end
|
72
|
+
|
73
|
+
def params
|
74
|
+
@params ||= {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def params=(p)
|
78
|
+
@params = p
|
79
|
+
end
|
80
|
+
|
81
|
+
def each_call(&blk)
|
82
|
+
blk.call self
|
83
|
+
|
84
|
+
if @called_nodes
|
85
|
+
@called_nodes.each do |node|
|
86
|
+
node.each_call(&blk)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def explain_sql
|
92
|
+
return params[:explainPlan] if params.key?(:explainPlan)
|
93
|
+
|
94
|
+
statement = params[:sql]
|
95
|
+
return nil unless statement.respond_to?(:config) &&
|
96
|
+
statement.respond_to?(:explainer)
|
97
|
+
|
98
|
+
TingYun::Agent::Database.explain_sql(statement.sql,
|
99
|
+
statement.config,
|
100
|
+
statement.explainer)
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
def parent_node=(s)
|
105
|
+
@parent_node = s
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TingYun
|
4
|
+
module Agent
|
5
|
+
class TracedMethodFrame
|
6
|
+
attr_reader :tag
|
7
|
+
attr_accessor :name, :start_time, :children_time
|
8
|
+
def initialize(tag, start_time)
|
9
|
+
@tag = tag
|
10
|
+
@start_time = start_time
|
11
|
+
@children_time = 0
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TracedMethodStack
|
16
|
+
def initialize
|
17
|
+
@stack = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def push_frame(state, tag, time = Time.now.to_f)
|
21
|
+
transaction_sampler.notice_push_frame(state, time) if sampler_enabled?
|
22
|
+
frame = TracedMethodFrame.new(tag, time)
|
23
|
+
@stack.push frame
|
24
|
+
frame
|
25
|
+
end
|
26
|
+
|
27
|
+
def pop_frame(state, expected_frame, name, time, deduct_call_time_from_parent=true)
|
28
|
+
frame = fetch_matching_frame(expected_frame)
|
29
|
+
note_children_time(frame, time, deduct_call_time_from_parent)
|
30
|
+
transaction_sampler.notice_pop_frame(state, name, time) if sampler_enabled?
|
31
|
+
frame.name = name
|
32
|
+
frame
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch_matching_frame(expected_frame)
|
36
|
+
while frame = @stack.pop
|
37
|
+
if frame == expected_frame
|
38
|
+
return frame
|
39
|
+
else
|
40
|
+
TingYun::Agent.logger.info("Unexpected frame in traced method stack: #{frame.inspect} expected to be #{expected_frame.inspect}")
|
41
|
+
TingYun::Agent.logger.debug do
|
42
|
+
["Backtrace for unexpected frame: ", caller.join("\n")]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
raise "Frame not found in blame stack: #{expected_frame.inspect}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def note_children_time(frame, time, deduct_call_time_from_parent)
|
51
|
+
if !@stack.empty?
|
52
|
+
if deduct_call_time_from_parent
|
53
|
+
@stack.last.children_time += (time - frame.start_time)*1000
|
54
|
+
else
|
55
|
+
@stack.last.children_time += frame.children_time
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def sampler_enabled?
|
62
|
+
TingYun::Agent.config[:'nbs.action_tracer.enabled']
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
def transaction_sampler
|
68
|
+
TingYun::Agent.instance.transaction_sampler
|
69
|
+
end
|
70
|
+
|
71
|
+
def clear
|
72
|
+
@stack.clear
|
73
|
+
end
|
74
|
+
|
75
|
+
def empty?
|
76
|
+
@stack.empty?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/metrics/stats'
|
3
|
+
|
4
|
+
module TingYun
|
5
|
+
module Agent
|
6
|
+
class TransactionMetrics
|
7
|
+
DEFAULT_PROC = Proc.new { |hash, name| hash[name] = TingYun::Metrics::Stats.new }
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@unscoped = Hash.new(&DEFAULT_PROC)
|
11
|
+
@scoped = Hash.new(&DEFAULT_PROC)
|
12
|
+
end
|
13
|
+
|
14
|
+
def record_scoped(names, value=nil, aux=nil, &blk)
|
15
|
+
_record_metrics(names, value, aux, @scoped, &blk)
|
16
|
+
end
|
17
|
+
|
18
|
+
def record_unscoped(names, value=nil, aux=nil, &blk)
|
19
|
+
_record_metrics(names, value, aux, @unscoped, &blk)
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_key?(key)
|
23
|
+
@unscoped.has_key?(key)
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
@unscoped[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
def each_unscoped
|
31
|
+
@unscoped.each { |name, stats| yield name, stats }
|
32
|
+
end
|
33
|
+
|
34
|
+
def each_scoped
|
35
|
+
@scoped.each { |name, stats| yield name, stats }
|
36
|
+
end
|
37
|
+
|
38
|
+
def _record_metrics(names, value, aux, target, &blk)
|
39
|
+
# This looks dumb, but we're avoiding an extra Array allocation.
|
40
|
+
case names
|
41
|
+
when Array
|
42
|
+
names.each do |name|
|
43
|
+
target[name].record(value, aux, &blk)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
target[names].record(value, aux, &blk)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ting_yun/agent/transaction/trace'
|
4
|
+
|
5
|
+
|
6
|
+
module TingYun
|
7
|
+
module Agent
|
8
|
+
class TransactionSampleBuilder
|
9
|
+
attr_reader :current_node, :trace
|
10
|
+
|
11
|
+
def initialize(time=Time.now)
|
12
|
+
@trace = TingYun::Agent::Transaction::Trace.new(time.to_f)
|
13
|
+
@trace_start = time.to_f
|
14
|
+
@current_node = @trace.root_node
|
15
|
+
end
|
16
|
+
|
17
|
+
def trace_entry(time)
|
18
|
+
if @trace.node_count < node_limit
|
19
|
+
node = @trace.create_node(time.to_f - @trace_start)
|
20
|
+
@current_node.add_called_node(node)
|
21
|
+
@current_node = node
|
22
|
+
|
23
|
+
if @trace.node_count == node_limit
|
24
|
+
::TingYun::Agent.logger.debug("Node limit of #{node_limit} reached, ceasing collection.")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@current_node
|
28
|
+
end
|
29
|
+
|
30
|
+
def trace_exit(metric_name, time)
|
31
|
+
@current_node.metric_name = metric_name
|
32
|
+
@current_node.end_trace(time.to_f - @trace_start)
|
33
|
+
@current_node = @current_node.parent_node
|
34
|
+
end
|
35
|
+
|
36
|
+
def finish_trace(time=Time.now.to_f)
|
37
|
+
|
38
|
+
if @trace.finished
|
39
|
+
::TingYun::Agent.logger.error "Unexpected double-finish_trace of Transaction Trace Object: \n#{@trace.to_s}"
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
@trace.root_node.end_trace(time - @trace_start)
|
44
|
+
|
45
|
+
@trace.threshold = transaction_trace_threshold
|
46
|
+
@trace.finished = true
|
47
|
+
@current_node = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def transaction_trace_threshold
|
52
|
+
Agent.config[:'nbs.action_tracer.action_threshold']
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
def node_limit
|
59
|
+
Agent.config[:'transaction_tracer.limit_segments']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|