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,194 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
require 'ting_yun/support/exception'
|
4
|
+
|
5
|
+
|
6
|
+
module TingYun
|
7
|
+
module Agent
|
8
|
+
module Event
|
9
|
+
class EventLoop
|
10
|
+
class Timer
|
11
|
+
attr_reader :next_fire_time, :event, :interval, :last_fired_at
|
12
|
+
|
13
|
+
def initialize(interval, event, repeat=false)
|
14
|
+
@interval = interval
|
15
|
+
@event = event
|
16
|
+
@repeat = repeat
|
17
|
+
@started_at = Time.now
|
18
|
+
@last_fired_at = nil
|
19
|
+
reschedule
|
20
|
+
end
|
21
|
+
|
22
|
+
def reschedule
|
23
|
+
@next_fire_time = calculate_next_fire_time
|
24
|
+
end
|
25
|
+
|
26
|
+
def advance(amount)
|
27
|
+
@next_fire_time -= amount
|
28
|
+
end
|
29
|
+
|
30
|
+
def last_interval_start
|
31
|
+
@last_fired_at || @started_at
|
32
|
+
end
|
33
|
+
|
34
|
+
def calculate_next_fire_time
|
35
|
+
now = Time.now
|
36
|
+
return now if @interval == 0
|
37
|
+
fire_time = @last_fired_at || now
|
38
|
+
while fire_time <= now
|
39
|
+
fire_time += @interval
|
40
|
+
end
|
41
|
+
fire_time
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_fired_time
|
45
|
+
@last_fired_at = Time.now
|
46
|
+
end
|
47
|
+
|
48
|
+
def due?(now=Time.now)
|
49
|
+
now >= @next_fire_time
|
50
|
+
end
|
51
|
+
|
52
|
+
def finished?
|
53
|
+
!@repeat && @last_fired_at
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@self_pipe_rd, @self_pipe_wr = IO.pipe
|
59
|
+
@event_queue = Queue.new
|
60
|
+
@stopped = false
|
61
|
+
@timers = {}
|
62
|
+
|
63
|
+
@subscriptions = Hash.new { |h,k| h[k] = [] }
|
64
|
+
@subscriptions[:__add_timer] << Proc.new { |t| set_timer(t) }
|
65
|
+
@subscriptions[:__add_event] << Proc.new { |e, blk| @subscriptions[e] << blk }
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_timer(timer)
|
69
|
+
existing_timer = @timers[timer.event]
|
70
|
+
|
71
|
+
if existing_timer
|
72
|
+
elapsed_interval = Time.now - existing_timer.last_interval_start
|
73
|
+
timer.advance(elapsed_interval)
|
74
|
+
end
|
75
|
+
|
76
|
+
@timers[timer.event] = timer
|
77
|
+
|
78
|
+
fire_timer(timer)
|
79
|
+
end
|
80
|
+
|
81
|
+
def next_timeout
|
82
|
+
return nil if @timers.empty?
|
83
|
+
timeout = @timers.values.map(&:next_fire_time).min - Time.now
|
84
|
+
timeout < 0 ? 0 : timeout
|
85
|
+
end
|
86
|
+
|
87
|
+
def stopped?
|
88
|
+
@stopped
|
89
|
+
end
|
90
|
+
|
91
|
+
def stop
|
92
|
+
@stopped = true
|
93
|
+
wakeup
|
94
|
+
end
|
95
|
+
|
96
|
+
def run
|
97
|
+
::TingYun::Agent.logger.debug "Running event loop"
|
98
|
+
while !stopped?
|
99
|
+
run_once
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_once(nonblock=false)
|
104
|
+
wait_to_run(nonblock)
|
105
|
+
|
106
|
+
prune_timers
|
107
|
+
fire_timers
|
108
|
+
|
109
|
+
until @event_queue.empty?
|
110
|
+
evt, args = @event_queue.pop
|
111
|
+
dispatch_event(evt, args)
|
112
|
+
reschedule_timer_for_event(evt)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def wait_to_run(nonblock)
|
117
|
+
timeout = nonblock ? 0 : next_timeout
|
118
|
+
ready = IO.select([@self_pipe_rd], nil, nil, timeout)
|
119
|
+
|
120
|
+
if ready && ready[0] && ready[0][0] && ready[0][0] == @self_pipe_rd
|
121
|
+
@self_pipe_rd.read(1)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def fire_timers
|
126
|
+
@timers.each do |event, timer|
|
127
|
+
fire_timer(timer)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def fire_timer(timer)
|
132
|
+
if timer.due?
|
133
|
+
@event_queue << [timer.event]
|
134
|
+
timer.set_fired_time
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def prune_timers
|
139
|
+
@timers.delete_if { |e, t| t.finished? }
|
140
|
+
end
|
141
|
+
|
142
|
+
def dispatch_event(event, args)
|
143
|
+
TingYun::Agent.logger.debug("EventLoop: Dispatching event '#{event}' with #{@subscriptions[event].size} callback(s).")
|
144
|
+
|
145
|
+
errors = []
|
146
|
+
@subscriptions[event].each do |s|
|
147
|
+
begin
|
148
|
+
s.call(*args)
|
149
|
+
rescue TingYun::Support::Exception::ExpiredConfigurationException, TingYun::Support::Exception::InvalidDataTokenException, TingYun::Support::Exception::InvalidDataException
|
150
|
+
raise
|
151
|
+
rescue => e
|
152
|
+
errors << e
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if !errors.empty?
|
157
|
+
::TingYun::Agent.logger.error "#{errors.size} error(s) running task for event '#{event}' in Agent Event Loop:", *errors
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def reschedule_timer_for_event(e)
|
162
|
+
@timers[e].reschedule if @timers[e]
|
163
|
+
end
|
164
|
+
|
165
|
+
def on(event, &blk)
|
166
|
+
fire(:__add_event, event, blk)
|
167
|
+
end
|
168
|
+
|
169
|
+
def fire(event, *args)
|
170
|
+
@event_queue << [event, args]
|
171
|
+
wakeup
|
172
|
+
end
|
173
|
+
|
174
|
+
def fire_every(interval, event)
|
175
|
+
::TingYun::Agent.logger.debug "Firing event #{event} every #{interval} seconds."
|
176
|
+
fire(:__add_timer, Timer.new(interval, event, true))
|
177
|
+
end
|
178
|
+
|
179
|
+
def fire_after(interval, event)
|
180
|
+
::TingYun::Agent.logger.debug "Firing event #{event} after #{interval} seconds."
|
181
|
+
fire(:__add_timer, Timer.new(interval, event, false))
|
182
|
+
end
|
183
|
+
|
184
|
+
def wakeup
|
185
|
+
begin
|
186
|
+
@self_pipe_wr.write_nonblock '.'
|
187
|
+
rescue Errno::EAGAIN
|
188
|
+
::TingYun::Agent.logger.debug "Failed to wakeup event loop"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
require 'ting_yun/support/exception'
|
4
|
+
require 'ting_yun/support/hostname'
|
5
|
+
require 'ting_yun/configuration/server_source'
|
6
|
+
require 'ting_yun/agent/instance_methods/handle_errors'
|
7
|
+
require 'ting_yun/environment_report'
|
8
|
+
|
9
|
+
|
10
|
+
module TingYun
|
11
|
+
module Agent
|
12
|
+
module InstanceMethods
|
13
|
+
module Connect
|
14
|
+
|
15
|
+
include HandleErrors
|
16
|
+
|
17
|
+
# number of attempts we've made to contact the server
|
18
|
+
attr_accessor :connect_attempts
|
19
|
+
|
20
|
+
# Disconnect just sets connected to false, which prevents
|
21
|
+
# the agent from trying to connect again
|
22
|
+
def disconnect
|
23
|
+
@connect_state = :disconnected
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def connected?
|
28
|
+
@connect_state == :connected
|
29
|
+
end
|
30
|
+
|
31
|
+
def disconnected?
|
32
|
+
@connect_state == :disconnected
|
33
|
+
end
|
34
|
+
|
35
|
+
# Don't connect if we're already connected, or if we tried to connect
|
36
|
+
# and were rejected with prejudice because of a license issue, unless
|
37
|
+
# we're forced to by force_reconnect.
|
38
|
+
def should_connect?(force=false)
|
39
|
+
force || (!connected? && !disconnected?)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Retry period is a minute for each failed attempt that
|
43
|
+
# we've made. This should probably do some sort of sane TCP
|
44
|
+
# backoff to prevent hammering the server, but a minute for
|
45
|
+
# each attempt seems to work reasonably well.
|
46
|
+
def connect_retry_period
|
47
|
+
[600, connect_attempts * 60].min
|
48
|
+
end
|
49
|
+
|
50
|
+
def note_connect_failure
|
51
|
+
self.connect_attempts += 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def generate_environment_report
|
55
|
+
@environment_report = environment_for_connect
|
56
|
+
end
|
57
|
+
|
58
|
+
# We've seen objects in the environment report (Rails.env in
|
59
|
+
# particular) that can't seralize to JSON. Cope with that here and
|
60
|
+
# clear out so downstream code doesn't have to check again.
|
61
|
+
def sanitize_environment_report
|
62
|
+
if !@service.valid_to_marshal?(@environment_report)
|
63
|
+
@environment_report = {}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# Checks whether we should send environment info, and if so,
|
69
|
+
# returns the snapshot from the local environment.
|
70
|
+
# Generating the EnvironmentReport has the potential to trigger
|
71
|
+
# require calls in Rails environments, so this method should only
|
72
|
+
# be called synchronously from on the main thread.
|
73
|
+
def environment_for_connect
|
74
|
+
::TingYun::Agent.config[:send_environment_info] ? TingYun::EnvironmentReport.new.data : {}
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# Initializes the hash of settings that we send to the
|
79
|
+
# server. Returns a literal hash containing the options
|
80
|
+
def connect_settings
|
81
|
+
sanitize_environment_report
|
82
|
+
settings = {
|
83
|
+
:pid => $$,
|
84
|
+
:port => ::TingYun::Agent.config[:port],
|
85
|
+
:host => local_host,
|
86
|
+
:appName => ::TingYun::Agent.config.app_names,
|
87
|
+
:language => 'Ruby',
|
88
|
+
:agentVersion => ::TingYun::VERSION::STRING,
|
89
|
+
:env => @environment_report,
|
90
|
+
:config => ::TingYun::Agent.config.to_collector_hash
|
91
|
+
}
|
92
|
+
settings
|
93
|
+
end
|
94
|
+
|
95
|
+
def local_host
|
96
|
+
TingYun::Support::Hostname.get
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns connect data passed back from the server
|
100
|
+
def connect_to_server
|
101
|
+
@service.connect(connect_settings)
|
102
|
+
end
|
103
|
+
|
104
|
+
#merge server config
|
105
|
+
def query_server_for_configuration
|
106
|
+
finish_setup(connect_to_server)
|
107
|
+
end
|
108
|
+
|
109
|
+
# * <tt>:keep_retrying => false</tt> to only try to connect once, and
|
110
|
+
# return with the connection set to nil. This ensures we may try again
|
111
|
+
# later (default true).
|
112
|
+
# * <tt>force_reconnect => true</tt> if you want to establish a new connection
|
113
|
+
# to the server before running the worker loop. This means you get a separate
|
114
|
+
# agent run and Ting Yun sees it as a separate instance (default is false).
|
115
|
+
def catch_errors
|
116
|
+
yield
|
117
|
+
|
118
|
+
rescue TingYun::Support::Exception::ExpiredConfigurationException => e
|
119
|
+
handle_force_restart(e)
|
120
|
+
retry
|
121
|
+
rescue TingYun::Support::Exception::InvalidDataTokenException => e
|
122
|
+
handle_force_restart(e)
|
123
|
+
retry
|
124
|
+
rescue TingYun::Support::Exception::InvalidDataException => e
|
125
|
+
handle_server_error(e)
|
126
|
+
rescue => e
|
127
|
+
handle_other_error(e)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Takes a hash of configuration data returned from the
|
131
|
+
# server and uses it to set local variables and to
|
132
|
+
# initialize various parts of the agent that are configured
|
133
|
+
# separately.
|
134
|
+
#
|
135
|
+
def finish_setup(config_data)
|
136
|
+
return if config_data == nil
|
137
|
+
|
138
|
+
if config_data['config']
|
139
|
+
::TingYun::Agent.logger.debug "Using config from server"
|
140
|
+
end
|
141
|
+
::TingYun::Agent.logger.debug "Server provided config: #{config_data.inspect}"
|
142
|
+
server_config = TingYun::Configuration::ServerSource.new(config_data)
|
143
|
+
::TingYun::Agent.config.replace_or_add_config(server_config)
|
144
|
+
#log_connection!(config_data)
|
145
|
+
end
|
146
|
+
|
147
|
+
def log_connection!(config_data)
|
148
|
+
::TingYun::Agent.logger.debug "Connected to TingYun Service at #{@service.collector.name}"
|
149
|
+
::TingYun::Agent.logger.debug "Application Run = #{@service.applicationId}."
|
150
|
+
::TingYun::Agent.logger.debug "Connection data = #{config_data.inspect}"
|
151
|
+
if config_data['messages'] && config_data['messages'].any?
|
152
|
+
log_collector_messages(config_data['messages'])
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def log_collector_messages(messages)
|
157
|
+
messages.each do |message|
|
158
|
+
::TingYun::Agent.logger.send(message['level'].downcase, message['message'])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ting_yun/support/exception'
|
3
|
+
require 'ting_yun/agent/collector/stats_engine'
|
4
|
+
require 'ting_yun/agent/collector/error_collector'
|
5
|
+
|
6
|
+
require 'ting_yun/agent/collector/transaction_sampler'
|
7
|
+
|
8
|
+
require 'ting_yun/agent/collector/sql_sampler'
|
9
|
+
|
10
|
+
|
11
|
+
module TingYun
|
12
|
+
module Agent
|
13
|
+
module InstanceMethods
|
14
|
+
module ContainerDataManager
|
15
|
+
|
16
|
+
|
17
|
+
attr_reader :stats_engine, :error_collector, :transaction_sampler, :sql_sampler, :middleware
|
18
|
+
|
19
|
+
|
20
|
+
def drop_buffered_data
|
21
|
+
@stats_engine.reset!
|
22
|
+
@transaction_sampler.reset!
|
23
|
+
@sql_sampler.reset!
|
24
|
+
@error_collector.reset!
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset_objects_with_locks
|
28
|
+
init_containers
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def init_containers
|
33
|
+
@stats_engine = TingYun::Agent::Collector::StatsEngine.new
|
34
|
+
@error_collector = TingYun::Agent::Collector::ErrorCollector.new
|
35
|
+
@transaction_sampler = TingYun::Agent::Collector::TransactionSampler.new
|
36
|
+
@sql_sampler = TingYun::Agent::Collector::SqlSampler.new
|
37
|
+
@middleware = TingYun::Agent::Collector::MiddleWareCollector.new(@events)
|
38
|
+
end
|
39
|
+
|
40
|
+
def container_for_endpoint(endpoint)
|
41
|
+
case endpoint
|
42
|
+
when :metric_data then
|
43
|
+
@stats_engine
|
44
|
+
# type code here
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def transmit_data
|
49
|
+
::TingYun::Agent.logger.debug('Sending data to Ting Yun Service')
|
50
|
+
|
51
|
+
@events.notify(:middleware_harvest)
|
52
|
+
@service.session do # use http keep-alive
|
53
|
+
harvest_and_send_errors
|
54
|
+
harvest_and_send_external_errors
|
55
|
+
harvest_and_send_timeslice_data
|
56
|
+
harvest_and_send_transaction_traces
|
57
|
+
harvest_and_send_slowest_sql
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def harvest_and_send_timeslice_data
|
62
|
+
harvest_and_send_from_container(@stats_engine, :metric_data)
|
63
|
+
end
|
64
|
+
|
65
|
+
def harvest_and_send_errors
|
66
|
+
harvest_and_send_from_container(@error_collector.error_trace_array, :error_data)
|
67
|
+
end
|
68
|
+
|
69
|
+
def harvest_and_send_external_errors
|
70
|
+
harvest_and_send_from_container(@error_collector.external_error_array, :external_error_data)
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def harvest_and_send_transaction_traces
|
75
|
+
harvest_and_send_from_container(@transaction_sampler, :action_trace_data)
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
def harvest_and_send_slowest_sql
|
80
|
+
harvest_and_send_from_container(@sql_sampler, :sql_trace)
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# Harvests data from the given container, sends it to the named endpoint
|
85
|
+
# on the service, and automatically merges back in upon a recoverable
|
86
|
+
# failure.
|
87
|
+
#
|
88
|
+
# The given container should respond to:
|
89
|
+
#
|
90
|
+
# #harvest!
|
91
|
+
# returns an enumerable collection of data items to be sent to the
|
92
|
+
# collector.
|
93
|
+
#
|
94
|
+
# #reset!
|
95
|
+
# drop any stored data and reset to a clean state.
|
96
|
+
#
|
97
|
+
# #merge!(items)
|
98
|
+
# merge the given items back into the internal buffer of the
|
99
|
+
# container, so that they may be harvested again later.
|
100
|
+
#
|
101
|
+
def harvest_and_send_from_container(container, endpoint)
|
102
|
+
items = harvest_from_container(container, endpoint)
|
103
|
+
send_data_to_endpoint(endpoint, items, container)
|
104
|
+
end
|
105
|
+
|
106
|
+
def harvest_from_container(container, endpoint)
|
107
|
+
items =[]
|
108
|
+
begin
|
109
|
+
if TingYun::Agent.config[:'nbs.agent_enabled']
|
110
|
+
items = container.harvest!
|
111
|
+
else
|
112
|
+
container.reset!
|
113
|
+
end
|
114
|
+
rescue => e
|
115
|
+
TingYun::Agent.logger.error("Failed to harvest #{endpoint} data, resetting. Error: ", e)
|
116
|
+
container.reset!
|
117
|
+
end
|
118
|
+
items
|
119
|
+
end
|
120
|
+
|
121
|
+
def send_data_to_endpoint(endpoint, items, container)
|
122
|
+
TingYun::Agent.logger.info("Sending #{items.size} items to #{endpoint}")
|
123
|
+
begin
|
124
|
+
@service.send(endpoint, items)
|
125
|
+
rescue => e
|
126
|
+
TingYun::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
|
127
|
+
container.merge!(items)
|
128
|
+
raise
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# This file is distributed under Ting Yun's license terms.
|
3
|
+
|
4
|
+
#
|
5
|
+
|
6
|
+
module TingYun
|
7
|
+
module Agent
|
8
|
+
module InstanceMethods
|
9
|
+
module HandleErrors
|
10
|
+
# When the server sends us an error with the license key, we
|
11
|
+
# want to tell the user that something went wrong, and let
|
12
|
+
# them know where to go to get a valid license key
|
13
|
+
#
|
14
|
+
# After this runs, it disconnects the agent so that it will
|
15
|
+
# no longer try to connect to the server, saving the
|
16
|
+
# application and the server load
|
17
|
+
def handle_license_error(error)
|
18
|
+
TingYun::Agent.logger.error(\
|
19
|
+
error.message, \
|
20
|
+
"You need to obtain a valid license key, or to upgrade your account.")
|
21
|
+
disconnect
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle_unrecoverable_agent_error(error)
|
25
|
+
TingYun::Agent.logger.error(error.message)
|
26
|
+
disconnect
|
27
|
+
shutdown
|
28
|
+
end
|
29
|
+
|
30
|
+
# When we have a problem connecting to the server, we need
|
31
|
+
# to tell the user what happened, since this is not an error
|
32
|
+
# we can handle gracefully.
|
33
|
+
def log_error(error)
|
34
|
+
TingYun::Agent.logger.error "Error establishing connection with Ting Yun Service at #{service.inspect}:", error
|
35
|
+
end
|
36
|
+
|
37
|
+
# Handles an unknown error in the worker thread by logging
|
38
|
+
# it and disconnecting the agent, since we are now in an
|
39
|
+
# unknown state.
|
40
|
+
def handle_other_error(error)
|
41
|
+
TingYun::Agent.logger.error "Unhandled error in worker thread, disconnecting this agent process:"
|
42
|
+
# These errors are fatal (that is, they will prevent the agent from
|
43
|
+
# reporting entirely), so we really want backtraces when they happen
|
44
|
+
TingYun::Agent.logger.log_exception(:error, error)
|
45
|
+
disconnect
|
46
|
+
end
|
47
|
+
|
48
|
+
# Handles the case where the server tells us to restart -
|
49
|
+
# this clears the data, clears connection attempts, and
|
50
|
+
# waits a while to reconnect.
|
51
|
+
def handle_force_restart(error)
|
52
|
+
TingYun::Agent.logger.debug error.message
|
53
|
+
drop_buffered_data
|
54
|
+
@service.force_restart if @service
|
55
|
+
@connect_state = :pending
|
56
|
+
sleep 30
|
57
|
+
end
|
58
|
+
def handle_force_disconnect(error)
|
59
|
+
TingYun::Agent.logger.warn "Ting Yun forced this agent to disconnect (#{error.message})"
|
60
|
+
disconnect
|
61
|
+
end
|
62
|
+
|
63
|
+
def handle_server_error(error)
|
64
|
+
TingYun::Agent.logger.error(error.message)
|
65
|
+
drop_buffered_data
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|