apminsight 1.0.1 → 1.8.6
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/apm-agent.gemspec +64 -0
- data/conf/apminsight.conf +15 -24
- data/lib/agent/am_objectholder.rb +25 -19
- data/lib/agent/api/custom_tracker.rb +79 -0
- data/lib/agent/configuration/am_configuration.rb +284 -41
- data/lib/agent/handler/custom_api_handler.rb +40 -0
- data/lib/agent/handler/sequence_book.rb +125 -0
- data/lib/agent/handler/tracker_handler.rb +58 -0
- data/lib/agent/logging/am_logger.rb +20 -11
- data/lib/agent/metrics/am_metricsformatter.rb +117 -59
- data/lib/agent/metrics/am_metricsparser.rb +195 -468
- data/lib/agent/metrics/am_metricstore.rb +7 -6
- data/lib/agent/metrics/exception_record.rb +24 -0
- data/lib/agent/server/am_agent.rb +46 -17
- data/lib/agent/server/am_connector.rb +65 -21
- data/lib/agent/server/instrument/action_view.rb +64 -0
- data/lib/agent/server/instrument/active_record.rb +52 -0
- data/lib/agent/server/instrument/am_apm.rb +107 -97
- data/lib/agent/server/instrument/am_instrumenter.rb +54 -42
- data/lib/agent/server/instrument/environment.rb +42 -0
- data/lib/agent/server/instrument/rails.rb +56 -0
- data/lib/agent/server/instrument/sinatra.rb +97 -0
- data/lib/agent/server/worker/am_worker.rb +93 -49
- data/lib/agent/trackers/database_tracker.rb +107 -0
- data/lib/agent/trackers/default_tracker.rb +62 -0
- data/lib/agent/trackers/root_tracker.rb +43 -0
- data/lib/agent/util/am_constants.rb +53 -8
- data/lib/agent/util/am_util.rb +64 -1
- data/lib/agent/util/transaction_util.rb +35 -0
- data/lib/agent/version.rb +13 -0
- data/lib/apminsight.rb +4 -1
- metadata +114 -76
@@ -1,43 +1,55 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class APMInstrumenter
|
5
|
-
@t =nil;
|
6
|
-
def initialize
|
7
|
-
@obj=ManageEngine::APMObjectHolder.instance
|
8
|
-
end
|
1
|
+
##
|
2
|
+
## This is Rails framework specific tracking mechanism, they are moved to multiple files for separate tracking
|
3
|
+
##
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
5
|
+
#require 'agent/am_objectholder'
|
6
|
+
#require 'socket'
|
7
|
+
#module ManageEngine
|
8
|
+
# class APMInstrumenter
|
9
|
+
# @t =nil;
|
10
|
+
# def initialize
|
11
|
+
# @obj=ManageEngine::APMObjectHolder.instance
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def doSubscribe
|
15
|
+
# @obj=ManageEngine::APMObjectHolder.instance
|
16
|
+
# @obj.log.debug "[ instrumenter ] [ Subscriber for Agent ]"
|
17
|
+
# @subscriber = ActiveSupport::Notifications.subscribe do |name, start, finish, id, payload|
|
18
|
+
# if(ManageEngine::APMObjectHolder.instance.config.agent_enabled)
|
19
|
+
# #rt = (finish-start).to_i
|
20
|
+
# ManageEngine::APMWorker.getInstance.start
|
21
|
+
# ManageEngine::APMObjectHolder.instance.log.debug "[ Notifications for Agent ] #{Thread.current} #{id} #{name} - #{payload[:path]}"
|
22
|
+
# #trace= caller;
|
23
|
+
# #puts ">>> Threadlocal var : #{Thread.current[:apminsight]}"
|
24
|
+
# if name=="sql.active_record"
|
25
|
+
# #Thread.current[:apminsight] = "#{Thread.current[:apminsight]} + #{payload[:sql]}"
|
26
|
+
# if payload[:name] != "SCHEMA"
|
27
|
+
# @obj.log.debug ">>>>>>>> SQL: #{payload[:sql]}"
|
28
|
+
# end
|
29
|
+
# @obj.log.debug "~~~~~ SQL Payload: #{payload}"
|
30
|
+
# end
|
31
|
+
# id = "#{Thread.current}"
|
32
|
+
# stats = Hash.new
|
33
|
+
# stats["name"] = name;
|
34
|
+
# stats["start"] = start.to_f * 1000;
|
35
|
+
# stats["end"] = finish.to_f * 1000;
|
36
|
+
# stats["id"] = id;
|
37
|
+
# stats["payload"] = payload;
|
38
|
+
# if (name=="sql.active_record" && (finish.to_f - start.to_f)>=(ManageEngine::APMObjectHolder.instance.config.sql_trace_t).to_f)
|
39
|
+
# stats["trace"] = caller(20); # Taking stacktrace of depth 20
|
40
|
+
# end
|
41
|
+
# stats["ctime"] =ManageEngine::APMObjectHolder.instance.util.currenttimemillis;
|
42
|
+
# ManageEngine::APMObjectHolder.instance.collector.updateTransaction(id,stats);
|
43
|
+
# else
|
44
|
+
# ActiveSupport::Notifications.unsubscribe @subscriber
|
45
|
+
# @obj.log.info "[ instrumenter ] [ RETURNING NO METRICS] "
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def doUnSubscribe
|
51
|
+
# ActiveSupport::Notifications.unsubscribe @subscriber
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
#end #class
|
55
|
+
#end#module
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'agent/server/instrument/rails'
|
2
|
+
require 'agent/server/instrument/sinatra'
|
3
|
+
require 'agent/server/instrument/active_record'
|
4
|
+
require 'agent/server/instrument/action_view'
|
5
|
+
|
6
|
+
module ManageEngine
|
7
|
+
class Environment
|
8
|
+
|
9
|
+
SUPPORTED_FRAMEWORKS = [
|
10
|
+
ManageEngine::Instrumentation::RailsFramework.new,
|
11
|
+
ManageEngine::Instrumentation::SinatraFramework.new
|
12
|
+
]
|
13
|
+
|
14
|
+
DATABASE_INTERCEPTORS = [
|
15
|
+
ManageEngine::Instrumentation::ActiveRecordSQL.new
|
16
|
+
]
|
17
|
+
|
18
|
+
OTHER_INTERCEPTORS = [
|
19
|
+
ManageEngine::Instrumentation::ActionView.new
|
20
|
+
]
|
21
|
+
|
22
|
+
def detect_and_instrument
|
23
|
+
@framework ||= SUPPORTED_FRAMEWORKS.detect{ |framework| framework.present? }
|
24
|
+
if (@framework != nil)
|
25
|
+
@framework.instrument
|
26
|
+
end
|
27
|
+
|
28
|
+
DATABASE_INTERCEPTORS.each do |interceptor|
|
29
|
+
if (interceptor.present?)
|
30
|
+
interceptor.instrument
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
OTHER_INTERCEPTORS.each do |interceptor|
|
35
|
+
if (interceptor.present?)
|
36
|
+
interceptor.instrument
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'agent/handler/tracker_handler'
|
2
|
+
|
3
|
+
module ManageEngine
|
4
|
+
module Instrumentation
|
5
|
+
class RailsFramework
|
6
|
+
|
7
|
+
def present?
|
8
|
+
defined?(::Rails) && defined?(::ActionController)
|
9
|
+
end
|
10
|
+
|
11
|
+
def version
|
12
|
+
Rails::VERSION::STRING
|
13
|
+
end
|
14
|
+
|
15
|
+
def env
|
16
|
+
if Rails::VERSION::MAJOR >= 3
|
17
|
+
::Rails.env
|
18
|
+
else
|
19
|
+
RAILS_ENV.dup
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
'Rails'
|
25
|
+
end
|
26
|
+
|
27
|
+
def instrument
|
28
|
+
@obj = ManageEngine::APMObjectHolder.instance
|
29
|
+
@obj.log.info "Instrumenting ActionController.. Rails Version: #{version}"
|
30
|
+
@railsTracker = nil
|
31
|
+
|
32
|
+
ActiveSupport::Notifications.subscribe('start_processing.action_controller') do |name, start, finish, id, payload|
|
33
|
+
path = payload[:path].partition("?")[0]
|
34
|
+
@railsTracker = ManageEngine::Tracker::RootTracker.new("#{payload[:controller]}.#{payload[:action]}", start.to_f * 1000)
|
35
|
+
@railsTracker.url=(path)
|
36
|
+
@railsTracker = ManageEngine::Agent::TrackerHandler.invokeTracker(@railsTracker)
|
37
|
+
end # subscribe
|
38
|
+
|
39
|
+
|
40
|
+
ActiveSupport::Notifications.subscribe('process_action.action_controller') do |name, start, finish, id, payload|
|
41
|
+
if @railsTracker != nil
|
42
|
+
@railsTracker.finish(finish.to_f * 1000)
|
43
|
+
exception = payload[:exception_object]
|
44
|
+
if exception != nil
|
45
|
+
@railsTracker.setError(exception)
|
46
|
+
@railsTracker.setStatus(500) # By default, set 500 as status for error txns
|
47
|
+
end
|
48
|
+
ManageEngine::Agent::TrackerHandler.exitTracker(@railsTracker)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end # def instrument
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'agent/am_objectholder'
|
2
|
+
require 'agent/trackers/root_tracker'
|
3
|
+
|
4
|
+
module ManageEngine
|
5
|
+
module Instrumentation
|
6
|
+
class SinatraFramework
|
7
|
+
|
8
|
+
def present?
|
9
|
+
defined?(::Sinatra) && defined?(::Sinatra::Base)
|
10
|
+
end
|
11
|
+
|
12
|
+
def version
|
13
|
+
::Sinatra::VERSION
|
14
|
+
end
|
15
|
+
|
16
|
+
def env
|
17
|
+
ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
'Sinatra'
|
22
|
+
end
|
23
|
+
|
24
|
+
def instrument
|
25
|
+
ManageEngine::APMObjectHolder.instance.log.info "Instrumenting Sinatra framework. Version: #{version}"
|
26
|
+
::Sinatra::Base.class_eval do
|
27
|
+
include ManageEngine::Instrumentation::APMInsightSinatra
|
28
|
+
|
29
|
+
alias original_route_eval route_eval
|
30
|
+
alias route_eval apminsight_route_eval
|
31
|
+
|
32
|
+
# alias sinatra_exception_handler! handle_exception!
|
33
|
+
# alias handle_exception! apminsight_exception_handler!
|
34
|
+
|
35
|
+
end # class_eval
|
36
|
+
end # def instrument
|
37
|
+
|
38
|
+
end # class Sinatra
|
39
|
+
|
40
|
+
module APMInsightSinatra
|
41
|
+
|
42
|
+
def apminsight_route_eval(*args, &block)
|
43
|
+
|
44
|
+
# http://www.rubydoc.info/github/rack/rack/master/Rack/Request
|
45
|
+
url = (env.has_key?('sinatra.route') ? env['sinatra.route'] : @request.path).dup
|
46
|
+
@obj = ManageEngine::APMObjectHolder.instance
|
47
|
+
|
48
|
+
sinatraTracker = ManageEngine::Tracker::RootTracker.new(url)
|
49
|
+
sinatraTracker.url=(url)
|
50
|
+
sinatraTracker = ManageEngine::Agent::TrackerHandler.invokeTracker(sinatraTracker)
|
51
|
+
|
52
|
+
# TODO: capture all additional details @request.query_string @request.params
|
53
|
+
|
54
|
+
begin
|
55
|
+
original_route_eval(*args, &block)
|
56
|
+
|
57
|
+
rescue Exception => e # On application error, above method throws exception
|
58
|
+
if (sinatraTracker != nil)
|
59
|
+
sinatraTracker.setError(e)
|
60
|
+
sinatraTracker.setStatus(500) # By default, set 500 as status for error txns
|
61
|
+
end
|
62
|
+
raise e
|
63
|
+
|
64
|
+
ensure
|
65
|
+
if sinatraTracker != nil
|
66
|
+
sinatraTracker.finish
|
67
|
+
end
|
68
|
+
ManageEngine::Agent::TrackerHandler.exitTracker(sinatraTracker)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# def apminsight_exception_handler!(*args, &block)
|
74
|
+
# begin
|
75
|
+
# sinatra_exception_handler!(*args, &block)
|
76
|
+
# ensure
|
77
|
+
# tracker = Thread.current[:apminsight]
|
78
|
+
# puts "tracker is #{(tracker == nil)}"
|
79
|
+
# if tracker != nil
|
80
|
+
# tracker.error(args[0]) # Other way, env[sinatra.error]
|
81
|
+
# tracker.status(@response.status)
|
82
|
+
# finishTracker tracker
|
83
|
+
# end #if
|
84
|
+
# end#begin
|
85
|
+
# end#def
|
86
|
+
#
|
87
|
+
# def finishTracker(tracker)
|
88
|
+
# tracker.finish
|
89
|
+
# #ManageEngine::APMObjectHolder.instance.collector.updateTransaction(id,stats)
|
90
|
+
# puts tracker.to_s
|
91
|
+
# Thread.current[:apminsight] = nil
|
92
|
+
# end
|
93
|
+
|
94
|
+
end # module SinatraFramework
|
95
|
+
|
96
|
+
end # module Instrumentation
|
97
|
+
end
|
@@ -7,46 +7,63 @@ class APMWorker
|
|
7
7
|
@status = 'not_init'
|
8
8
|
@id = 0
|
9
9
|
attr_accessor :id
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def start
|
16
|
-
@obj = ManageEngine::APMObjectHolder.instance
|
17
|
-
|
18
|
-
if @status=="working"
|
19
|
-
@obj.log.debug "woker thread already started"
|
20
|
-
elsif @status == "initialized"
|
21
|
-
@obj.log.info "start worker thread for - #{Process.pid} :: #{@status} "
|
22
|
-
#@obj.log.info "Starting APMWorker Thread #{Process.pid} "
|
23
|
-
@apm = Thread.new do
|
24
|
-
@status = 'working'
|
25
|
-
while !@obj.shutdown do
|
26
|
-
checkforagentstatus
|
27
|
-
updateConfig
|
28
|
-
dc
|
29
|
-
sleep (@obj.config.connect_interval).to_i
|
30
|
-
end#w
|
31
|
-
@status= "end"
|
32
|
-
@obj.log.debug "Worker thread ends"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
10
|
+
def initialize
|
11
|
+
@status = "initialized"
|
12
|
+
@id = Process.pid
|
13
|
+
end
|
36
14
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
15
|
+
def start
|
16
|
+
@obj = ManageEngine::APMObjectHolder.instance
|
17
|
+
|
18
|
+
if @status=="working"
|
19
|
+
@obj.log.debug "worker thread already started"
|
20
|
+
elsif @status == "initialized"
|
21
|
+
@obj.log.info "start worker thread for - #{Process.pid} :: #{@status} "
|
22
|
+
#@obj.log.info "Starting APMWorker Thread #{Process.pid} "
|
23
|
+
@apm = Thread.new do
|
24
|
+
@status = 'working'
|
25
|
+
while !@obj.shutdown do
|
26
|
+
checkforagentstatus
|
27
|
+
updateConfig
|
28
|
+
dc
|
29
|
+
sleep (@obj.config.connect_interval).to_i
|
30
|
+
end#w
|
31
|
+
@status= "end"
|
32
|
+
@obj.log.debug "Worker thread ends"
|
42
33
|
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.getInstance
|
38
|
+
if(@work==nil || @work.id!=Process.pid)
|
39
|
+
@work = ManageEngine::APMWorker.new
|
40
|
+
end
|
41
|
+
return @work
|
42
|
+
end
|
43
43
|
|
44
44
|
def updateConfig
|
45
45
|
if(@obj.config.lastupdatedtime!=File.mtime(@obj.constants.apm_conf).to_i)
|
46
|
-
|
46
|
+
@obj.log.info "Configuration File Changed... So Updating Configuration."
|
47
|
+
agent_config_data = @obj.config.getAgentConfigData
|
47
48
|
@obj.config.lastupdatedtime=File.mtime(@obj.constants.apm_conf).to_i
|
48
49
|
@obj.config.configureFile
|
49
50
|
@obj.config.assignConfig
|
51
|
+
new_agent_config_data = @obj.config.getAgentConfigData
|
52
|
+
sendUpdate = "false"
|
53
|
+
agent_config_data.each do|key,value|
|
54
|
+
if key != "last.modified.time"
|
55
|
+
newValue = new_agent_config_data[key]
|
56
|
+
if value != newValue
|
57
|
+
sendUpdate = "true"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if sendUpdate == "true"
|
62
|
+
@obj.log.info "sending update to server #{new_agent_config_data}"
|
63
|
+
data1 = Hash.new
|
64
|
+
data1["custom_config_info"]=new_agent_config_data
|
65
|
+
resp = @obj.connector.post @obj.constants.connect_config_update_uri+@obj.config.instance_id,data1
|
66
|
+
end
|
50
67
|
end
|
51
68
|
end
|
52
69
|
|
@@ -57,12 +74,12 @@ class APMWorker
|
|
57
74
|
@obj.log.info "Agent in Disabled State."
|
58
75
|
if prevState
|
59
76
|
@obj.log.info "Agent in Disabled State. Going to unsubscribe"
|
60
|
-
@obj.instrumenter.doUnSubscribe
|
77
|
+
# @obj.instrumenter.doUnSubscribe
|
61
78
|
end
|
62
79
|
else
|
63
80
|
if !prevState
|
64
81
|
@obj.log.info "Agent in Active State."
|
65
|
-
@obj.instrumenter.doSubscribe
|
82
|
+
# @obj.instrumenter.doSubscribe
|
66
83
|
end
|
67
84
|
end
|
68
85
|
end
|
@@ -126,14 +143,18 @@ class APMWorker
|
|
126
143
|
tdata.concat(val[0])
|
127
144
|
when 2
|
128
145
|
tdata.concat(val[0])
|
129
|
-
trdata.
|
146
|
+
if (trdata.size < @obj.config.trace_overflow_t)
|
147
|
+
trdata.concat(val[1])
|
148
|
+
end
|
130
149
|
end
|
131
150
|
end
|
132
151
|
result.push(merge(tdata))
|
133
152
|
resp = @obj.connector.post @obj.constants.connect_data_uri+@obj.config.instance_id,result
|
153
|
+
@obj.log.info "#{tdata.size} metric(s) dispatched."
|
134
154
|
if trdata.size>0
|
135
155
|
result[2]=trdata;
|
136
156
|
resp = @obj.connector.post @obj.constants.connect_trace_uri+@obj.config.instance_id,result
|
157
|
+
@obj.log.info "#{trdata.size} trace(s) dispatched."
|
137
158
|
end
|
138
159
|
end
|
139
160
|
|
@@ -149,7 +170,7 @@ class APMWorker
|
|
149
170
|
def send_save data
|
150
171
|
begin
|
151
172
|
if FileTest.exist?(@obj.constants.agent_lock)
|
152
|
-
if Time.now.to_i - File.mtime(@obj.constants.agent_lock).to_i
|
173
|
+
if Time.now.to_i - File.mtime(@obj.constants.agent_lock).to_i >= (@obj.config.connect_interval).to_i
|
153
174
|
@obj.log.debug "worker send signal"
|
154
175
|
senddata data
|
155
176
|
else
|
@@ -172,7 +193,11 @@ class APMWorker
|
|
172
193
|
f.flock(File::LOCK_EX)
|
173
194
|
begin
|
174
195
|
f.each_line do |line|
|
175
|
-
|
196
|
+
begin
|
197
|
+
data.push(JSON.parse(line))
|
198
|
+
rescue Exception=>ex
|
199
|
+
@obj.log.logException "Error Parsing data, Skipping line #{line}", ex
|
200
|
+
end
|
176
201
|
end
|
177
202
|
f.truncate 0
|
178
203
|
rescue Exception=>e
|
@@ -223,18 +248,36 @@ class APMWorker
|
|
223
248
|
|
224
249
|
|
225
250
|
def mapdx res,dat
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
251
|
+
begin
|
252
|
+
rtData = res[0];
|
253
|
+
rtData[0] = rtData[0]+dat[0][0];
|
254
|
+
if dat[0][1]<rtData[1]
|
255
|
+
rtData[1]=dat[0][1]
|
256
|
+
end
|
257
|
+
if dat[0][2]>rtData[2]
|
258
|
+
rtData[2]=dat[0][2]
|
259
|
+
end
|
260
|
+
rtData[3] = rtData[3]+dat[0][3]
|
261
|
+
rtData[5] = rtData[5]+dat[0][5]
|
262
|
+
rtData[6] = rtData[6]+dat[0][6]
|
263
|
+
rtData[7] = rtData[7]+dat[0][7]
|
264
|
+
rtData[4] = rtData[3] != 0 ? (rtData[5].to_f + (rtData[6].to_f/2).to_f).to_f/rtData[3].to_f : 0
|
265
|
+
res[0] = rtData
|
266
|
+
|
267
|
+
resExcepData = res[1][@obj.constants.mf_logmetric]
|
268
|
+
excepData = dat[1][@obj.constants.mf_logmetric]
|
269
|
+
if (resExcepData == nil)
|
270
|
+
resExcepData = excepData
|
271
|
+
else
|
272
|
+
if (excepData != nil)
|
273
|
+
resExcepData = resExcepData.merge(excepData){|key, oldval, newval| newval + oldval}
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
res[1][@obj.constants.mf_logmetric] = resExcepData != nil ? resExcepData : Hash.new
|
278
|
+
rescue Exception=>e
|
279
|
+
@obj.log.logException "Exception while merging data",e
|
280
|
+
end
|
238
281
|
res
|
239
282
|
end
|
240
283
|
|
@@ -247,6 +290,7 @@ class APMWorker
|
|
247
290
|
res[2]=dat[2]
|
248
291
|
end
|
249
292
|
res[3] = res[3]+dat[3]
|
293
|
+
res[4] = res[4]+dat[4]
|
250
294
|
res
|
251
295
|
end
|
252
296
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module ManageEngine
|
2
|
+
module Tracker
|
3
|
+
class DatabaseTracker < DefaultTracker
|
4
|
+
|
5
|
+
def sql(query)
|
6
|
+
@query = format(query.dup)
|
7
|
+
end
|
8
|
+
|
9
|
+
def params(binds = [])
|
10
|
+
@binds = binds
|
11
|
+
end
|
12
|
+
|
13
|
+
def sqlBacktrace(backtrace)
|
14
|
+
@backtrace = backtrace
|
15
|
+
end
|
16
|
+
|
17
|
+
def getRawQuery
|
18
|
+
@query
|
19
|
+
end
|
20
|
+
|
21
|
+
def getObfuscatedQuery
|
22
|
+
ManageEngine::APMObjectHolder.instance.util.parametrizeQuery @query
|
23
|
+
end
|
24
|
+
|
25
|
+
def getCompleteQuery
|
26
|
+
begin
|
27
|
+
query = @query # Maintaining the original query
|
28
|
+
if query != nil && @binds != nil && @binds.length > 0
|
29
|
+
@binds.each do |ar|
|
30
|
+
if query.index("?") != nil
|
31
|
+
query["?"]=ar.value.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
return query
|
35
|
+
end
|
36
|
+
rescue Exception=>exe
|
37
|
+
@logger.logException "Not severe -#{exe.message}",exe
|
38
|
+
end
|
39
|
+
@query
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns array [db_operation, tablename]
|
43
|
+
def getQueryInfo
|
44
|
+
sql = @query
|
45
|
+
sql.strip!
|
46
|
+
sql.downcase!
|
47
|
+
sqlArr = sql.split(" ")
|
48
|
+
|
49
|
+
begin
|
50
|
+
tableName = case sqlArr[0]
|
51
|
+
when "select" then sqlArr[sqlArr.index("from")+1]
|
52
|
+
when "insert" then sqlArr[sqlArr.index("into")+1]
|
53
|
+
when "update" then sqlArr[1]
|
54
|
+
when "delete" then sqlArr[sqlArr.index("from")+1]
|
55
|
+
when "create" then sqlArr[1] + sqlArr[2]
|
56
|
+
when "alter" then sqlArr[1] + sqlArr[2]
|
57
|
+
when "drop" then sqlArr[1] + sqlArr[2]
|
58
|
+
when "show" then sqlArr[1]
|
59
|
+
when "describe" then sqlArr[1]
|
60
|
+
else "-"
|
61
|
+
end
|
62
|
+
|
63
|
+
return [sqlArr[0], tableName]
|
64
|
+
|
65
|
+
rescue Exception=>e
|
66
|
+
@logger.logException "#{e.message}",e
|
67
|
+
return [sqlArr[0], '-']
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def format s
|
72
|
+
s.gsub!("\"", '')
|
73
|
+
s.gsub!("\n", '')
|
74
|
+
s
|
75
|
+
end
|
76
|
+
|
77
|
+
def getAdditionalInfo
|
78
|
+
info = super
|
79
|
+
begin
|
80
|
+
if (@query != nil)
|
81
|
+
if (info == nil)
|
82
|
+
info = Hash.new
|
83
|
+
end
|
84
|
+
|
85
|
+
obj = ManageEngine::APMObjectHolder.instance
|
86
|
+
|
87
|
+
info["query"] = !obj.config.sql_capture_params ? getCompleteQuery : getObfuscatedQuery
|
88
|
+
# send only one backtrace, Exception backtrace have more priority
|
89
|
+
if (@backtrace != nil && @error == nil)
|
90
|
+
info["stacktrace"] = obj.util.formatStacktrace(@backtrace)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
rescue Exception => e
|
94
|
+
@logger.logException("Error updating additionalInfo in dbTracker.", e)
|
95
|
+
end
|
96
|
+
|
97
|
+
info
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
"#{@name} - #{@query}"
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ManageEngine
|
2
|
+
module Tracker
|
3
|
+
|
4
|
+
class DefaultTracker
|
5
|
+
|
6
|
+
attr_accessor :name, :error, :endtime, :starttime, :child, :sibling
|
7
|
+
|
8
|
+
def initialize(name = "unknonwn", time = ManageEngine::APMObjectHolder.instance.util.currenttimemillis)
|
9
|
+
@starttime = time.to_i
|
10
|
+
@name = name
|
11
|
+
@logger = ManageEngine::APMObjectHolder.instance.log
|
12
|
+
end
|
13
|
+
|
14
|
+
def finish(time = ManageEngine::APMObjectHolder.instance.util.currenttimemillis)
|
15
|
+
@endtime = time.to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
def error?
|
19
|
+
@error != nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def setError(exception)
|
23
|
+
@error = exception
|
24
|
+
end
|
25
|
+
|
26
|
+
def setName(context)
|
27
|
+
@name = context
|
28
|
+
end
|
29
|
+
|
30
|
+
def duration
|
31
|
+
begin
|
32
|
+
(@endtime - @starttime).to_i
|
33
|
+
rescue Exception=>e
|
34
|
+
@logger.warn "Name: #{name} Starttime: #{starttime} Endtime: #{endtime}"
|
35
|
+
raise e
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(obj)
|
40
|
+
return obj != nil && @name == obj.name
|
41
|
+
end
|
42
|
+
|
43
|
+
def hash
|
44
|
+
return @name.hash
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
@name
|
49
|
+
end
|
50
|
+
|
51
|
+
def getAdditionalInfo
|
52
|
+
if error?
|
53
|
+
{ManageEngine::APMObjectHolder.instance.constants.mf_exception_st => ManageEngine::APMObjectHolder.instance.util.formatStacktrace(@error.backtrace)}
|
54
|
+
else
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|