tingyun_rpm 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/lib/ting_yun/agent/agent.rb +8 -0
- data/lib/ting_yun/agent/collector/stats_engine/base_quantile_hash.rb +20 -0
- data/lib/ting_yun/agent/collector/stats_engine/metric_stats.rb +10 -0
- data/lib/ting_yun/agent/collector/stats_engine.rb +9 -0
- data/lib/ting_yun/agent/collector/transaction_sampler/class_method.rb +2 -2
- data/lib/ting_yun/agent/cross_app/cross_app_tracing.rb +16 -10
- data/lib/ting_yun/agent/datastore/metric_helper.rb +31 -7
- data/lib/ting_yun/agent/datastore.rb +6 -11
- data/lib/ting_yun/agent/dispatcher.rb +5 -1
- data/lib/ting_yun/agent/instance_methods/container_data_manager.rb +5 -1
- data/lib/ting_yun/agent/instance_methods/start_worker_thread.rb +5 -0
- data/lib/ting_yun/agent/method_tracer_helpers.rb +8 -4
- data/lib/ting_yun/agent/transaction/attributes.rb +6 -2
- data/lib/ting_yun/agent/transaction/class_method.rb +14 -5
- data/lib/ting_yun/agent/transaction/instance_method.rb +20 -4
- data/lib/ting_yun/agent/transaction/trace.rb +2 -1
- data/lib/ting_yun/agent/transaction/trace_node.rb +10 -2
- data/lib/ting_yun/agent/transaction/traced_method_stack.rb +2 -2
- data/lib/ting_yun/agent/transaction/transaction_sample_builder.rb +2 -1
- data/lib/ting_yun/agent/transaction/transaction_state.rb +22 -1
- data/lib/ting_yun/agent/transaction/transaction_timings.rb +1 -2
- data/lib/ting_yun/agent/transaction.rb +13 -7
- data/lib/ting_yun/configuration/default_source.rb +44 -7
- data/lib/ting_yun/configuration/yaml_source.rb +1 -0
- data/lib/ting_yun/frameworks/instrumentation.rb +6 -1
- data/lib/ting_yun/frameworks/rails5.rb +10 -0
- data/lib/ting_yun/frameworks.rb +1 -1
- data/lib/ting_yun/http/http_client_request.rb +39 -0
- data/lib/ting_yun/http/net_http_request.rb +4 -0
- data/lib/ting_yun/instrumentation/active_record.rb +11 -5
- data/lib/ting_yun/instrumentation/bunny.rb +142 -0
- data/lib/ting_yun/instrumentation/data_mapper.rb +167 -0
- data/lib/ting_yun/instrumentation/grape.rb +39 -0
- data/lib/ting_yun/instrumentation/http_client.rb +70 -0
- data/lib/ting_yun/instrumentation/kafka.rb +218 -0
- data/lib/ting_yun/instrumentation/memcached.rb +135 -0
- data/lib/ting_yun/instrumentation/middleware_proxy.rb +1 -4
- data/lib/ting_yun/instrumentation/middleware_tracing.rb +5 -1
- data/lib/ting_yun/instrumentation/mongo.rb +18 -6
- data/lib/ting_yun/instrumentation/mongo2.rb +5 -1
- data/lib/ting_yun/instrumentation/mongo_command_log_subscriber.rb +5 -5
- data/lib/ting_yun/instrumentation/moped.rb +4 -3
- data/lib/ting_yun/instrumentation/net.rb +3 -3
- data/lib/ting_yun/instrumentation/rails3/action_controller.rb +8 -4
- data/lib/ting_yun/instrumentation/rails3/action_view.rb +8 -4
- data/lib/ting_yun/instrumentation/rails4/action_controller.rb +29 -0
- data/lib/ting_yun/instrumentation/rails4/action_view.rb +29 -0
- data/lib/ting_yun/instrumentation/rails4/active_record.rb +30 -0
- data/lib/ting_yun/instrumentation/rails5/action_cable.rb +31 -0
- data/lib/ting_yun/instrumentation/rails5/action_controller.rb +29 -0
- data/lib/ting_yun/instrumentation/rails5/action_view.rb +28 -0
- data/lib/ting_yun/instrumentation/rails5/active_record.rb +30 -0
- data/lib/ting_yun/instrumentation/rake.rb +3 -2
- data/lib/ting_yun/instrumentation/redis.rb +6 -5
- data/lib/ting_yun/instrumentation/sidekiq.rb +61 -0
- data/lib/ting_yun/instrumentation/sinatra/action.rb +95 -0
- data/lib/ting_yun/instrumentation/sinatra/view.rb +67 -0
- data/lib/ting_yun/instrumentation/support/action_cable_subscriber.rb +83 -0
- data/lib/ting_yun/instrumentation/{rails4 → support}/action_controller_subscriber.rb +5 -29
- data/lib/ting_yun/instrumentation/{rails4 → support}/action_view_subscriber.rb +2 -24
- data/lib/ting_yun/instrumentation/support/active_record_helper.rb +23 -6
- data/lib/ting_yun/instrumentation/{rails4 → support}/active_record_subscriber.rb +13 -37
- data/lib/ting_yun/instrumentation/support/controller_instrumentation.rb +204 -1
- data/lib/ting_yun/instrumentation/support/database.rb +2 -1
- data/lib/ting_yun/instrumentation/support/external_error.rb +2 -2
- data/lib/ting_yun/instrumentation/support/external_helper.rb +30 -0
- data/lib/ting_yun/instrumentation/support/method_instrumentation.rb +228 -0
- data/lib/ting_yun/instrumentation/support/metric_translator.rb +4 -1
- data/lib/ting_yun/instrumentation/support/sinatra_helper.rb +20 -0
- data/lib/ting_yun/instrumentation/support/transaction_namer.rb +3 -1
- data/lib/ting_yun/instrumentation/thrift.rb +5 -6
- data/lib/ting_yun/logger/agent_logger.rb +1 -0
- data/lib/ting_yun/logger/create_logger_helper.rb +16 -2
- data/lib/ting_yun/metrics/metric_data.rb +8 -2
- data/lib/ting_yun/metrics/metric_spec.rb +2 -1
- data/lib/ting_yun/support/helper.rb +4 -0
- data/lib/ting_yun/support/quantile_p2.rb +204 -0
- data/lib/ting_yun/ting_yun_service/upload_service.rb +38 -12
- data/lib/ting_yun/ting_yun_service.rb +4 -7
- data/lib/ting_yun/version.rb +3 -1
- data/lib/tingyun_rpm.rb +0 -4
- data/tingyun_rpm.gemspec +3 -3
- metadata +35 -13
- data/CODE_OF_CONDUCT.md +0 -13
- data/lib/ting_yun/agent/method_tracer.rb +0 -256
@@ -0,0 +1,228 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/frameworks' unless defined?(TingYun::Frameworks::Framework)
|
3
|
+
require 'ting_yun/support/helper'
|
4
|
+
require 'ting_yun/agent/method_tracer_helpers'
|
5
|
+
require 'ting_yun/agent/transaction/transaction_state'
|
6
|
+
|
7
|
+
module TingYun
|
8
|
+
module Instrumentation
|
9
|
+
module Support
|
10
|
+
module MethodInstrumentation
|
11
|
+
|
12
|
+
# This module contains class methods added to support installing custom
|
13
|
+
# metric tracers and executing for individual metrics.
|
14
|
+
#
|
15
|
+
# == Examples
|
16
|
+
#
|
17
|
+
# When the agent initializes, it extends Module with these methods.
|
18
|
+
# However if you want to use the API in code that might get loaded
|
19
|
+
# before the agent is initialized you will need to require
|
20
|
+
# this file:
|
21
|
+
#
|
22
|
+
# require 'ting_yun/instrumentation/support/method_instrumentation'
|
23
|
+
# class A
|
24
|
+
# include TingYun::Instrumentation::Support::MethodInstrumentation
|
25
|
+
# def process
|
26
|
+
# ...
|
27
|
+
# end
|
28
|
+
# add_method_tracer :process
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# To instrument a class method:
|
32
|
+
#
|
33
|
+
# require 'ting_yun/instrumentation/support/method_instrumentation'
|
34
|
+
# class An
|
35
|
+
# def self.process
|
36
|
+
# ...
|
37
|
+
# end
|
38
|
+
# class << self
|
39
|
+
# include TingYun::Instrumentation::Support::MethodInstrumentation
|
40
|
+
# add_method_tracer :process
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# @api public
|
45
|
+
|
46
|
+
def self.included(klass)
|
47
|
+
klass.extend ClassMethods
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.extended(klass)
|
51
|
+
klass.extend ClassMethods
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
def method_exists?(method_name)
|
56
|
+
exists = method_defined?(method_name) || private_method_defined?(method_name)
|
57
|
+
::TingYun::Agent.logger.error("Did not trace #{self.name}##{method_name} because that method does not exist") unless exists
|
58
|
+
exists
|
59
|
+
end
|
60
|
+
|
61
|
+
# Example:
|
62
|
+
# Foo.default_metric_name('bar') #=> "tingyun/#{Foo.name}/bar"
|
63
|
+
def default_metric_name(method_name)
|
64
|
+
"tingyun/#{self.name}/#{method_name.to_s}"
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# Checks to see if we have already traced a method with a
|
69
|
+
# given metric by checking to see if the traced method
|
70
|
+
# exists. Warns the user if methods are being double-traced
|
71
|
+
# to help with debugging custom instrumentation.
|
72
|
+
def traced_method_exists?(method_name, metric_name)
|
73
|
+
exists = method_defined?(define_trace_method_name(method_name, metric_name))
|
74
|
+
::TingYun::Agent.logger.error("Attempt to trace a method twice with the same metric: Method = #{method_name}, Metric Name = #{metric_name}") if exists
|
75
|
+
exists
|
76
|
+
end
|
77
|
+
|
78
|
+
def tingyun_eval(method_name, metric_name, options)
|
79
|
+
options = validate_options(method_name, options)
|
80
|
+
if options[:scope]
|
81
|
+
define_method_with_scope(method_name, metric_name, options)
|
82
|
+
else
|
83
|
+
define_method_without_scope(method_name,metric_name, options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
DEFAULT_SETTINGS = {:scope => true, :metric => true, :before_code => "", :after_code => "" }.freeze
|
88
|
+
|
89
|
+
def validate_options(method_name, options)
|
90
|
+
unless options.is_a?(Hash)
|
91
|
+
raise TypeError.new("Error adding method tracer to #{method_name}: provided options must be a Hash")
|
92
|
+
end
|
93
|
+
options = DEFAULT_SETTINGS.merge(options)
|
94
|
+
unless options[:scope] || options[:metric]
|
95
|
+
raise "Can't add a tracer where push_scope is false and metric is false"
|
96
|
+
end
|
97
|
+
options
|
98
|
+
end
|
99
|
+
|
100
|
+
def define_method_with_scope(method_name,metric_name,options)
|
101
|
+
"def #{define_trace_method_name(method_name,metric_name)}(*args, &block)
|
102
|
+
#{options[:before_code]}
|
103
|
+
|
104
|
+
result = ::TingYun::Agent::MethodTracerHelpers.trace_execution_scoped(\"#{metric_name}\",
|
105
|
+
:metric => #{options[:metric]}) do
|
106
|
+
#{define_untrace_method_name(method_name, metric_name)}(*args, &block)
|
107
|
+
end
|
108
|
+
#{options[:after_code]}
|
109
|
+
result
|
110
|
+
end"
|
111
|
+
end
|
112
|
+
|
113
|
+
def define_method_without_scope(method_name,metric_name,options)
|
114
|
+
"def #{define_trace_method_name(method_name,metric_name)}(*args, &block)
|
115
|
+
return #{define_untrace_method_name(method_name, metric_name)}(*args, &block) unless TingYun::Agent::TransactionState.tl_get.execution_traced?\n
|
116
|
+
#{options[:before_code]}
|
117
|
+
t0 = Time.now
|
118
|
+
begin
|
119
|
+
#{define_untrace_method_name(method_name, metric_name)}(*args, &block)\n
|
120
|
+
ensure
|
121
|
+
duration = (Time.now - t0).to_f
|
122
|
+
::TingYun::Agent.record_metric(\"#{metric_name}\", duration)
|
123
|
+
#{options[:after_code]}
|
124
|
+
end
|
125
|
+
end"
|
126
|
+
end
|
127
|
+
|
128
|
+
# Add a method tracer to the specified method.
|
129
|
+
#
|
130
|
+
# By default, this will cause invocations of the traced method to be
|
131
|
+
# recorded in transaction traces, and in a metric named after the class
|
132
|
+
# and method. It will also make the method show up in transaction-level
|
133
|
+
# breakdown charts and tables.
|
134
|
+
#
|
135
|
+
# === Overriding the metric name
|
136
|
+
#
|
137
|
+
# +metric_name+ is a string that is eval'd to get the name of the
|
138
|
+
# metric associated with the call, so if you want to use interpolation
|
139
|
+
# evaluated at call time, then single quote the value like this:
|
140
|
+
#
|
141
|
+
# add_method_tracer :foo, 'tingyun/#{self.class.name}/foo'
|
142
|
+
#
|
143
|
+
# This would name the metric according to the class of the runtime
|
144
|
+
# intance, as opposed to the class where +foo+ is defined.
|
145
|
+
#
|
146
|
+
# If not provided, the metric name will be <tt>tingyun/ClassName/method_name</tt>.
|
147
|
+
#
|
148
|
+
# @param [Symbol] method_name the name of the method to trace
|
149
|
+
# @param [String] metric_name the metric name to record calls to
|
150
|
+
# the traced method under. This may be either a static string, or Ruby
|
151
|
+
# code to be evaluated at call-time in order to determine the metric
|
152
|
+
# name dynamically.
|
153
|
+
# @param [Hash] options additional options controlling how the method is
|
154
|
+
# traced.
|
155
|
+
# @option options [Boolean] :scope (true) If false, the traced method will
|
156
|
+
# not appear in transaction traces(the components) or breakdown charts, and it will
|
157
|
+
# only be visible in custom dashboards(the generals).
|
158
|
+
# @option options [Boolean] :metric (true) If false, the traced method will
|
159
|
+
# only appear in transaction traces, but no metrics will be recorded
|
160
|
+
# for it.
|
161
|
+
# @option options [String] :before_code ('') Ruby code to be inserted and run
|
162
|
+
# before the tracer begins timing.
|
163
|
+
# @option options [String] :after_code ('') Ruby code to be inserted and run
|
164
|
+
# after the tracer stops timing.
|
165
|
+
#
|
166
|
+
# @example
|
167
|
+
# add_method_tracer :foo
|
168
|
+
#
|
169
|
+
# # With a custom metric name
|
170
|
+
# add_method_tracer :foo, 'tingyun/#{self.class.name}/foo'
|
171
|
+
#
|
172
|
+
# # Instrument foo only for custom dashboards (not in transaction
|
173
|
+
# # traces or breakdown charts)
|
174
|
+
# add_method_tracer :foo, 'tingyun/foo', :scope => false
|
175
|
+
#
|
176
|
+
# # Instrument foo in transaction traces only
|
177
|
+
# add_method_tracer :foo, 'tingyun/foo', :metric => false
|
178
|
+
#
|
179
|
+
# @api public
|
180
|
+
#
|
181
|
+
|
182
|
+
|
183
|
+
def add_method_tracer(method_name, metric_name = nil, opt={})
|
184
|
+
return unless method_exists?(method_name)
|
185
|
+
metric_name ||= default_metric_name(method_name)
|
186
|
+
return if traced_method_exists?(method_name, metric_name)
|
187
|
+
|
188
|
+
traced_method = tingyun_eval(method_name, metric_name,opt)
|
189
|
+
|
190
|
+
visibility = TingYun::Helper.instance_method_visibility self, method_name
|
191
|
+
class_eval traced_method, __FILE__, __LINE__
|
192
|
+
|
193
|
+
alias_method define_untrace_method_name(method_name, metric_name), method_name
|
194
|
+
alias_method method_name, define_trace_method_name(method_name, metric_name)
|
195
|
+
send visibility, method_name
|
196
|
+
send visibility, define_trace_method_name(method_name, metric_name)
|
197
|
+
::TingYun::Agent.logger.debug("Traced method: class = #{self.name},"+
|
198
|
+
"method = #{method_name}, "+
|
199
|
+
"metric = '#{metric_name}'")
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
|
205
|
+
# given a method and a metric, this method returns the
|
206
|
+
# traced alias of the method name
|
207
|
+
def define_trace_method_name(method_name, metric_name)
|
208
|
+
"#{_sanitize_name(method_name)}_with_trace_#{_sanitize_name(metric_name)}"
|
209
|
+
end
|
210
|
+
# given a method and a metric, this method returns the
|
211
|
+
# untraced alias of the method name
|
212
|
+
def define_untrace_method_name(method_name, metric_name)
|
213
|
+
"#{_sanitize_name(method_name)}_without_trace_#{_sanitize_name(metric_name)}"
|
214
|
+
end
|
215
|
+
|
216
|
+
# makes sure that method names do not contain characters that
|
217
|
+
# might break the interpreter, for example ! or ? characters
|
218
|
+
# that are not allowed in the middle of method names
|
219
|
+
def _sanitize_name(name)
|
220
|
+
name.to_s.tr_s('^a-zA-Z0-9', '_')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
|
@@ -10,7 +10,7 @@ module TingYun
|
|
10
10
|
|
11
11
|
MONGODB = 'MongoDB'.freeze
|
12
12
|
|
13
|
-
def self.metrics_for(name, payload)
|
13
|
+
def self.metrics_for(name, payload, host_port)
|
14
14
|
payload ||= {}
|
15
15
|
|
16
16
|
return nil if collection_in_selector?(payload)
|
@@ -27,6 +27,9 @@ module TingYun
|
|
27
27
|
|
28
28
|
TingYun::Agent::Datastore::MetricHelper.metrics_for(MONGODB,
|
29
29
|
TingYun::Agent::Datastore::Mongo.transform_operation(name),
|
30
|
+
host_port[0],
|
31
|
+
host_port[1],
|
32
|
+
payload[:database],
|
30
33
|
collection)
|
31
34
|
rescue => e
|
32
35
|
TingYun::Agent.logger.debug("Failure during Mongo metric generation", e)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TingYun
|
4
|
+
module Instrumentation
|
5
|
+
module Support
|
6
|
+
module SinatraHelper
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
SINATRA_MIN_VERSION = '1.2.3'.freeze
|
11
|
+
SINATRA_MAX_VERSION = '1.4.8'.freeze
|
12
|
+
|
13
|
+
def version_supported?
|
14
|
+
TingYun::Support::VersionNumber.new(::Sinatra::VERSION) >= TingYun::Support::VersionNumber.new(SINATRA_MIN_VERSION)
|
15
|
+
TingYun::Support::VersionNumber.new(::Sinatra::VERSION) <= TingYun::Support::VersionNumber.new(SINATRA_MAX_VERSION)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -19,13 +19,15 @@ module TingYun
|
|
19
19
|
when :uri then
|
20
20
|
::TingYun::Agent::Transaction::CONTROLLER_PREFIX
|
21
21
|
when :sinatra then
|
22
|
-
::TingYun::Agent::Transaction::
|
22
|
+
::TingYun::Agent::Transaction::CONTROLLER_PREFIX
|
23
23
|
when :middleware then
|
24
24
|
::TingYun::Agent::Transaction::MIDDLEWARE_PREFIX
|
25
25
|
when :grape then
|
26
26
|
::TingYun::Agent::Transaction::GRAPE_PREFIX
|
27
27
|
when :rake then
|
28
28
|
::TingYun::Agent::Transaction::RAKE_PREFIX
|
29
|
+
when :action_cable then
|
30
|
+
::TingYun::Agent::Transaction::CABLE_PREFIX
|
29
31
|
else
|
30
32
|
"#{category.to_s}/" # for internal use only
|
31
33
|
end
|
@@ -13,6 +13,7 @@ TingYun::Support::LibraryDetection.defer do
|
|
13
13
|
executes do
|
14
14
|
TingYun::Agent.logger.info 'Installing Thrift Instrumentation'
|
15
15
|
require 'ting_yun/support/serialize/json_wrapper'
|
16
|
+
require 'ting_yun/instrumentation/support/external_helper'
|
16
17
|
end
|
17
18
|
|
18
19
|
executes do
|
@@ -40,19 +41,17 @@ TingYun::Support::LibraryDetection.defer do
|
|
40
41
|
require 'ting_yun/instrumentation/support/thrift_helper'
|
41
42
|
|
42
43
|
include TingYun::Instrumentation::ThriftHelper
|
43
|
-
|
44
|
+
include TingYun::Instrumentation::Support::ExternalHelper
|
44
45
|
|
45
46
|
def send_message_args_with_tingyun(args_class, args = {})
|
46
47
|
return send_message_args_without_tingyun(args_class, args) unless TingYun::Agent.config[:'nbs.transaction_tracer.thrift'] && TingYun::Agent.config[:'nbs.transaction_tracer.enabled']
|
47
48
|
begin
|
48
49
|
state = TingYun::Agent::TransactionState.tl_get
|
49
50
|
return unless state.execution_traced?
|
50
|
-
cross_app_id = TingYun::Agent.config[:tingyunIdSecret] or
|
51
|
-
raise TingYun::Agent::CrossAppTracing::Error, "no tingyunIdSecret configured"
|
52
|
-
tingyun_id = "#{cross_app_id};c=1;x=#{state.request_guid}"
|
53
51
|
|
54
|
-
data = TingYun::Support::Serialize::JSONWrapper.dump("TingyunID" =>
|
55
|
-
|
52
|
+
data = TingYun::Support::Serialize::JSONWrapper.dump("TingyunID" => create_tingyun_id("thrift"))
|
53
|
+
TingYun::Agent.logger.info("thift will send TingyunID : ", data)
|
54
|
+
@oprot.write_field_begin("TingyunField", 11, 40000)
|
56
55
|
@oprot.write_string(data)
|
57
56
|
@oprot.write_field_end
|
58
57
|
rescue => e
|
@@ -4,7 +4,7 @@ module TingYun
|
|
4
4
|
module Logger
|
5
5
|
module CreateLoggerHelper
|
6
6
|
|
7
|
-
|
7
|
+
module_function
|
8
8
|
|
9
9
|
def create_log(root, override_logger)
|
10
10
|
if !override_logger.nil?
|
@@ -26,6 +26,7 @@ module TingYun
|
|
26
26
|
begin
|
27
27
|
@log = ::Logger.new(@file_path)
|
28
28
|
set_log_format
|
29
|
+
set_log_level
|
29
30
|
rescue => e
|
30
31
|
@log = ::Logger.new(STDOUT)
|
31
32
|
warn("check_log_file: Failed creating logger for file #{@file_path}, using standard out for logging.", e)
|
@@ -33,7 +34,20 @@ module TingYun
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
+
def create_new_logfile
|
38
|
+
file_path = TingYun::Agent.logger.file_path
|
39
|
+
shift_age = TingYun::Agent.config[:agent_log_file_number]
|
40
|
+
if File.size(file_path) >= (TingYun::Agent.config[:agent_log_file_size])*1024*1024
|
41
|
+
(shift_age-3).downto(0) do |i|
|
42
|
+
index_file = file_path.gsub('.log', "_#{i}.log")
|
43
|
+
if FileTest.exist?(index_file)
|
44
|
+
File.rename(index_file, file_path.gsub('.log', "_#{i+1}.log"))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
TingYun::Agent.agent.untraced_graceful_disconnect
|
48
|
+
File.rename(file_path, file_path.gsub('.log', "_0.log"))
|
49
|
+
end
|
50
|
+
end
|
37
51
|
|
38
52
|
def create_log_to_file(root)
|
39
53
|
path = find_or_create_file_path(::TingYun::Agent.config[:agent_log_file_path], root)
|
@@ -13,11 +13,13 @@ module TingYun
|
|
13
13
|
attr_accessor :metric_id
|
14
14
|
# the actual statistics object
|
15
15
|
attr_accessor :stats
|
16
|
+
attr_reader :quantile
|
16
17
|
|
17
|
-
def initialize(metric_spec, stats, metric_id)
|
18
|
+
def initialize(metric_spec, stats, metric_id, quantile = [])
|
18
19
|
@metric_spec = metric_spec
|
19
20
|
@stats = stats
|
20
21
|
@metric_id = metric_id
|
22
|
+
@quantile = quantile
|
21
23
|
end
|
22
24
|
|
23
25
|
def eql?(o)
|
@@ -48,7 +50,11 @@ module TingYun
|
|
48
50
|
|
49
51
|
def to_collector_array(encoder=nil)
|
50
52
|
stat_key = metric_id || to_hash
|
51
|
-
|
53
|
+
if quantile.empty?
|
54
|
+
[stat_key, metrics(stat_key)]
|
55
|
+
else
|
56
|
+
[stat_key, metrics(stat_key), quantile]
|
57
|
+
end
|
52
58
|
end
|
53
59
|
|
54
60
|
def to_hash
|
@@ -8,7 +8,7 @@
|
|
8
8
|
module TingYun
|
9
9
|
module Metrics
|
10
10
|
class MetricSpec
|
11
|
-
attr_accessor :name, :scope, :calleeId, :calleeName
|
11
|
+
attr_accessor :name, :scope, :calleeId, :calleeName, :full_name
|
12
12
|
|
13
13
|
# the maximum length of a metric name or metric scope
|
14
14
|
MAX_LENGTH = 255
|
@@ -16,6 +16,7 @@ module TingYun
|
|
16
16
|
EMPTY_SCOPE = ''.freeze
|
17
17
|
|
18
18
|
def initialize(metric_name='', metric_scope=nil)
|
19
|
+
@full_name = metric_name.to_s
|
19
20
|
if metric_name.to_s.length > MAX_LENGTH
|
20
21
|
@name = metric_name.to_s[LENGTH_RANGE]
|
21
22
|
else
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module TingYun
|
5
|
+
module Support
|
6
|
+
class QuantileP2
|
7
|
+
|
8
|
+
def self.support?
|
9
|
+
return false if !TingYun::Agent.config[:'nbs.quantile']
|
10
|
+
quantile = TingYun::Agent.config[:'nbs.quantile']
|
11
|
+
quantile = JSON.parse(quantile) rescue false unless quantile.is_a?(Array)
|
12
|
+
return false if !quantile || quantile.empty? || (quantile.size > quantile.uniq.size) || quantile.any? { |i| i.to_i == 0 || !i.is_a?(Fixnum)}
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
attr_accessor :quartileList, :markers_y, :markers_x, :p2_n, :count
|
19
|
+
def initialize(quartileList)
|
20
|
+
@quartileList = quartileList.sort!
|
21
|
+
@markers_y = Array.new(@quartileList.length * 2 + 3){0.0}
|
22
|
+
@count = 0
|
23
|
+
initMarkers
|
24
|
+
end
|
25
|
+
|
26
|
+
def initMarkers
|
27
|
+
quartile_count = quartileList.length
|
28
|
+
marker_count = quartile_count * 2 + 3
|
29
|
+
@markers_x = Array.new(marker_count){0.0}
|
30
|
+
@markers_x[0] = 0.0
|
31
|
+
@p2_n = Array.new(markers_y.length){0}
|
32
|
+
(0..quartile_count-1).each do |i|
|
33
|
+
marker = quartileList[i]
|
34
|
+
markers_x[i * 2 + 1] = (marker + markers_x[i * 2]) / 2
|
35
|
+
markers_x[i * 2 + 2] = marker
|
36
|
+
end
|
37
|
+
markers_x[marker_count - 2] = (1 + quartileList[quartile_count - 1]) / 2
|
38
|
+
markers_x[marker_count - 1] = 1.0
|
39
|
+
(0..marker_count-1).each do |i|
|
40
|
+
p2_n[i] = i
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def markers
|
45
|
+
|
46
|
+
if (count < markers_y.length)
|
47
|
+
result = Array.new(count){0.0}
|
48
|
+
markers = Array.new(markers_y.length){0.0}
|
49
|
+
pw_q_copy = markers_y.clone()
|
50
|
+
pw_q_copy.sort!
|
51
|
+
j = 0
|
52
|
+
(pw_q_copy.length - count .. pw_q_copy.length - 1).each do |i|
|
53
|
+
result[j] = pw_q_copy[i]
|
54
|
+
j+=1
|
55
|
+
end
|
56
|
+
|
57
|
+
(0..pw_q_copy.length-1).each do |i|
|
58
|
+
markers[i] = result[((count - 1) * i * 1.0 / (pw_q_copy.length - 1)).round]
|
59
|
+
end
|
60
|
+
return markers;
|
61
|
+
end
|
62
|
+
|
63
|
+
return markers_y;
|
64
|
+
end
|
65
|
+
|
66
|
+
def binarySearch(arr, key)
|
67
|
+
low = 0
|
68
|
+
high = arr.length-1
|
69
|
+
|
70
|
+
while(low <=high) do
|
71
|
+
mid = (low + high) >> 1
|
72
|
+
midVal = arr[mid]
|
73
|
+
if (midVal < key)
|
74
|
+
low = mid + 1
|
75
|
+
elsif(midVal > key)
|
76
|
+
high = mid - 1
|
77
|
+
else
|
78
|
+
midBits = midVal.round 16
|
79
|
+
keyBits = key.round 16
|
80
|
+
if (midBits == keyBits)
|
81
|
+
return mid
|
82
|
+
elsif(midBits < keyBits)
|
83
|
+
low = mid + 1
|
84
|
+
else
|
85
|
+
high = mid - 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
return -(low + 1)
|
90
|
+
end
|
91
|
+
|
92
|
+
def quadPred(d, i)
|
93
|
+
qi = markers_y[i]
|
94
|
+
qip1 = markers_y[i + 1]
|
95
|
+
qim1 = markers_y[i - 1]
|
96
|
+
ni = p2_n[i]
|
97
|
+
nip1 = p2_n[i + 1]
|
98
|
+
nim1 = p2_n[i - 1]
|
99
|
+
|
100
|
+
a = (ni - nim1 + d) * (qip1 - qi) / (nip1 - ni)
|
101
|
+
b = (nip1 - ni - d) * (qi - qim1) / (ni - nim1)
|
102
|
+
return qi + (d * (a + b)) / (nip1 - nim1)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def linPred(d, i)
|
107
|
+
qi = markers_y[i]
|
108
|
+
qipd = markers_y[i + d]
|
109
|
+
ni = p2_n[i]
|
110
|
+
nipd = p2_n[i + d]
|
111
|
+
|
112
|
+
return qi + d * (qipd - qi) / (nipd - ni)
|
113
|
+
end
|
114
|
+
|
115
|
+
def add(v)
|
116
|
+
|
117
|
+
return unless v.is_a?(Numeric)
|
118
|
+
obsIdx = count
|
119
|
+
@count += 1
|
120
|
+
|
121
|
+
if (obsIdx < markers_y.length)
|
122
|
+
markers_y[obsIdx] = v
|
123
|
+
if (obsIdx == markers_y.length - 1)
|
124
|
+
markers_y.sort!
|
125
|
+
end
|
126
|
+
else
|
127
|
+
|
128
|
+
|
129
|
+
# k = markers_y.find_index {|i| i==v or i>v}
|
130
|
+
#
|
131
|
+
# if k ##in
|
132
|
+
# if v==markers_y[k] ##exist
|
133
|
+
# if k == 0##first
|
134
|
+
# markers_y[0] = v
|
135
|
+
# k = 1
|
136
|
+
# elsif k == markers_y.length-1 ##last
|
137
|
+
# k = markers_y.length - 1;
|
138
|
+
# markers_y[k] = v
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
# else
|
142
|
+
# k = markers_y.length -1
|
143
|
+
# end
|
144
|
+
k = binarySearch markers_y, v
|
145
|
+
|
146
|
+
if k< 0
|
147
|
+
k = -(k + 1)
|
148
|
+
end
|
149
|
+
if k==0
|
150
|
+
markers_y[0] = v
|
151
|
+
k = 1
|
152
|
+
elsif k == markers_y.length
|
153
|
+
k = markers_y.length - 1
|
154
|
+
markers_y[k] = v
|
155
|
+
end
|
156
|
+
|
157
|
+
(k..p2_n.length-1).each do |i|
|
158
|
+
p2_n[i] += 1
|
159
|
+
end
|
160
|
+
|
161
|
+
(1..markers_y.length - 2).each do |i|
|
162
|
+
|
163
|
+
n_ = markers_x[i] * obsIdx
|
164
|
+
di = n_ - p2_n[i]
|
165
|
+
if ((di-1.0 >=0.000001 && p2_n[i + 1] - p2_n[i] > 1) || ((di+1.0 <=0.000001 && p2_n[i - 1] - p2_n[i] < -1)))
|
166
|
+
d = di < 0 ? -1 : 1
|
167
|
+
qi_ = quadPred(d, i)
|
168
|
+
if (qi_ < markers_y[i - 1] || qi_ > markers_y[i + 1])
|
169
|
+
|
170
|
+
qi_ = linPred(d, i)
|
171
|
+
end
|
172
|
+
|
173
|
+
markers_y[i] = qi_
|
174
|
+
|
175
|
+
p2_n[i] += d
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
#
|
184
|
+
# testdata4 =[0.0, 3009.0, 3046.0, 3070.0, 3102.0, 3119.0, 3139.0, 3150.0, 3163.0, 3179.0, 3228.0]
|
185
|
+
# testdata3 =[2,1,6,6,4,9,5,6,2,7,2,4,9,7,8,4,1,8,8,8,3,5,4,1,9,5,5,6,2,0,8,5,3,6,1,4,8,0,0,1,1,3,9,9,6,7,1,5,8,7,6,9,3,1,2,4,8,2,3,4,7,2,9,2,3,9,8,7,6,1,8,5,0,8,3,2,8,0,1,7,4,9,9,3,6,2,3,0,1,4,9,3,0,9,6,1,9,7,1,9,3,4,4,0,9,6,2,6,1,4,9,9,2,2,3,0,2,0,4,4,1,9,2,7,8,9,6,5,6,5,1,4,3,6,4,7,6,6,5,6,2,2,5,4,8,6,3,4,7,2,4,8,7,0,0,0,9,6,5,2,8,3,2,1,9,2,4,0,3,2,3,6,6,6,4,8,1,0,7,7,2,8,5,1,3,0,5,3,3,3,3,8,8,7,9,1,3,3,1,1,0,5,2,2,4,9,3,3,5,7,4,0,7,4,2,6,3,2,5,4,9,0,8,8,0,6,7,0,2,3,3,4,7,9,9,7,8,5,1,4,5,0,8,5,8,7,0,7,3,9,5,0,7,1,2,6,8,3,3,6,0,6,0,0,4,5,6,3,6,8,6,3,2,8,9,1,9,3,8,6,3,5,9,0,3,6,2,9,1,1,0,6,4,1,0,9,3,2,9,5,6,3,7,8,3,4,1,0,8,1,3,0,3,3,9,9,7,2,1,3,5,6,6,9,5,1,9,8,8,7,0,7,3,9,3,1,6,1,7,3,3,3,9,9,8,4,3,8,1,2,0,1,9,6,3,2,2,5,5,7,3,4,2,2,7,5,4,7,0,6,4,3,6,4,2,9,3,4,8,7,8,2,1,6,6,7,0,7,8,4,8,0,1,6,9,9,5,5,7,5,6,7,4,8,7,6,7,1,1,1,1,9,2,2,0,3,4,0,6,9,9,1,8,5,0,5,5,4,7,6,5,6,2,1,2,5,0,6,3,7,3,6,1,3,1,0,5,3,9,2,9,9,8,0,9,5,3,9,6,8,0,0,2,5,3,1,3,4,2,9,4,3,0,8,1,7,0,5,3,9,5,3,4,4,1,7,5,5,8,9,8,0,1,0,1,9,7,8,2,3,4,7,5,3,8,7,8,4,1,3,6,6,0,8,8,1,3,5,2,6,0,1,2,1,5,3,5,0,7,0,2,3,9,8,2,5,8,4,8,9,8,7,2,7,7,1,2,3,7,9,7,4,5,2,6,2,3,8,8,8,0,8,4,7,9,2,6,7,5,1,3,0,4,1,3,8,2,8,1,0,5,6,3,5,6,7,9,2,4,5,9,2,9,5,0,6,1,1,0,3,9,2,8,6,6,8,6,3,9,0,0,7,1,9,9,6,4,7,3,0,1,8,1,6,5,7,3,9,7,0,3,7,3,3,6,0,6,3,3,4,7,4,1,3,9,3,2,2,5,0,5,2,5,1,2,3,9,0,9,8,7,9,2,0,9,8,9,0,5,4,4,4,4,3,2,9,0,2,5,8,0,9,4,6,5,0,2,1,8,1,4,8,4,2,0,2,9,7,7,7,1,2,1,3,3,5,1,9,2,3,2,7,6,5,6,9,5,0,7,9,8,3,4,5,1,6,4,6,9,4,5,0,0,0,6,8,3,4,0,7,8,6,9,8,8,9,8,7,8,0,6,5,8,5,4,6,3,5,4,1,0,9,7,2,4,1,7,9,3,4,1,5,7,9,5,8,9,4,6,1,3,5,8,4,0,4,1,4,2,4,3,0,0,8,9,5,2,7,8,2,6,1,9,8,9,9,0,7,9,6,8,8,8,7,4,7,4,3,3,2,5,9,5,3,3,2,3,1,0,5,7,7,2,5,9,3,7,4,1,3,1,5,4,0,5,6,9,1,5,2,4,5,8,5,3,0,1,3,3,4,0,1,0,8,8,0,7,9,1,1,0,5,2,1,2,8,2,6,6,8,2,7,9,5,5,1,2,0,0,5,9,8,8,1,5,7,2,1,2,3,5,5,3,9,4,0,5,2,2,5,0,0,2,5,3,3,5,2,8,9,8,8,6,7,7,9,6,7,0,6,0,6,4,8,7,8,7,4,4,1,0,4,1,9,3,2,1,7,3,1,1,2,3,2,9,5,9,1,8,4,6,6,1,0,9,9,3,4,9,9,0,5,7,0,5,8,2,1,3,4,7,6,0,3,0,7,3,0,1,3,0,1,0,5,2,3,3,4,3,2]
|
186
|
+
# testdata2 =[3028.0, 2211.0]
|
187
|
+
# testdata1 =[3110,3770,3990,3990,3000,3880,3330,3440,3440,3000,3550,3440,3220,3330,3220,3110,3770,3110,3880,3330,3440,3440,3000,3110,3220,3440,3000,3550,3880,3990,3990,3550,3110,3330,3330,3000,3880,3660,3110,3990,3110,3990,3440,3330,3660,3660,3000,3220,3220,3330,3660,3990,3440,3220,3220,3440,3440,3880,3990,3550,3440,3110,3330,3440,3110,3770,3330,3220,3440,3440,3440,3220,3660,3000,3440,3550,3220,3220,3110,3660,3110,3880,3550,3770,3220,3440,3220,3110,3220,3220,3110,3880,3550,3770,3770,3550,3990,3220,3880,3660,3110,3550,3990,3110,3550,3880,3110,3770,3770,3110,3440,3770,3000,3110,3990,3110,3550,3770,3990,3000,3990,3110,3550,3880,3110,3880,3550,3220,3550,3550,3770,3990,3550,3220,3330,3990,3770,3770,3550,3770,3880,3660,3330,3990,3990,3000,3110,3440,3220,3000,3550,3770,3110,3550,3330,3990,3110,3330,3550,3440,3220,3550,3220,3330,3000,3660,3110,3770,3110,3660,3550,3440,3990,3330,3990,3550,3990,3550,3330,3770,3550,3550,3000,3440,3000,3330,3440,3110,3880,3110,3550,3660,3990,3220,3330,3330,3000,3660,3660,3220]
|
188
|
+
# testdatas =[testdata1.map(&:to_f),testdata2,testdata3.map(&:to_f),testdata4]
|
189
|
+
# quartileList =[1.0/7*2,1.0/7*3,1.0/7*4,1.0/7*5 ]
|
190
|
+
#
|
191
|
+
# qm=::TingYun::Support::QuantileP2.new(quartileList)
|
192
|
+
# # testdatas.each do |testdata|
|
193
|
+
# # qp=::TingYun::Support::QuantileP2.new(quartileList)
|
194
|
+
# # testdata.each do |da|
|
195
|
+
# # qp.add(da)
|
196
|
+
# # p qp.markers
|
197
|
+
# # p "---------"
|
198
|
+
# # end
|
199
|
+
# # end
|
200
|
+
# testdata4.each do |da|
|
201
|
+
# qm.add(da.to_f)
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# p qm.markers
|