apminsight 0.0.3 → 1.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. data/Rakefile +4 -4
  2. data/VERSION +1 -1
  3. data/apm-agent.gemspec +64 -0
  4. data/conf/apminsight.conf +15 -24
  5. data/lib/agent/am_objectholder.rb +25 -19
  6. data/lib/agent/api/custom_tracker.rb +79 -0
  7. data/lib/agent/configuration/am_configuration.rb +306 -43
  8. data/lib/agent/handler/custom_api_handler.rb +40 -0
  9. data/lib/agent/handler/sequence_book.rb +125 -0
  10. data/lib/agent/handler/tracker_handler.rb +58 -0
  11. data/lib/agent/logging/am_logger.rb +21 -12
  12. data/lib/agent/metrics/am_metricsformatter.rb +117 -59
  13. data/lib/agent/metrics/am_metricsparser.rb +195 -468
  14. data/lib/agent/metrics/am_metricstore.rb +7 -6
  15. data/lib/agent/metrics/exception_record.rb +24 -0
  16. data/lib/agent/server/am_agent.rb +59 -21
  17. data/lib/agent/server/am_connector.rb +66 -22
  18. data/lib/agent/server/instrument/action_view.rb +64 -0
  19. data/lib/agent/server/instrument/active_record.rb +52 -0
  20. data/lib/agent/server/instrument/am_apm.rb +107 -97
  21. data/lib/agent/server/instrument/am_instrumenter.rb +54 -42
  22. data/lib/agent/server/instrument/environment.rb +42 -0
  23. data/lib/agent/server/instrument/rails.rb +56 -0
  24. data/lib/agent/server/instrument/sinatra.rb +97 -0
  25. data/lib/agent/server/worker/am_worker.rb +93 -49
  26. data/lib/agent/trackers/database_tracker.rb +107 -0
  27. data/lib/agent/trackers/default_tracker.rb +62 -0
  28. data/lib/agent/trackers/root_tracker.rb +43 -0
  29. data/lib/agent/util/am_constants.rb +57 -8
  30. data/lib/agent/util/am_util.rb +76 -14
  31. data/lib/agent/util/transaction_util.rb +35 -0
  32. data/lib/agent/version.rb +13 -0
  33. data/lib/apminsight.rb +4 -1
  34. metadata +115 -79
@@ -1,14 +1,15 @@
1
1
  require 'rubygems'
2
2
  require 'json'
3
3
  require 'socket'
4
- require 'rails'
4
+ require 'net/http'
5
5
  require 'agent/am_objectholder'
6
+ require 'agent/version'
6
7
 
7
8
  module ManageEngine
8
9
  class APMConfig
9
- attr_reader :agenthost,:agentport,:instance_id,:alreadyconnected,:apmhost,:apmport
10
- attr_reader :appname,:proxyneeded, :apdex_t, :trans_trace, :trans_trace_t, :sql_capture, :sql_capture_params, :sql_trace_t,:proxy_user,:proxy_pass
11
- attr_reader :proxy_host,:proxy_port ,:is_secured, :logs_dir ,:connection_retry,:agent_enabled,:connect_interval,:db_operations,:include_packages
10
+ attr_reader :agenthost,:agentport,:instance_id,:alreadyconnected,:apmhost,:apmport,:license_key,:site24x7, :site24x7url, :hostType,:delayedStart
11
+ attr_reader :appname,:proxyneeded, :apdex_t, :trans_trace, :trans_trace_t, :sql_capture, :sql_capture_params, :sql_trace_t,:proxy_user,:proxy_pass, :metric_overflow_t, :trace_overflow_t, :dbmetric_overflow_t
12
+ attr_reader :proxy_host,:proxy_port ,:is_secured, :logs_dir ,:connection_retry,:agent_enabled,:connect_interval,:db_operations,:txn_skip_listen, :url_merge_pattern
12
13
  attr_accessor :app_db,:app_dispatcher,:lastupdatedtime
13
14
  def initialize
14
15
  @obj = ManageEngine::APMObjectHolder.instance
@@ -21,19 +22,41 @@ module ManageEngine
21
22
  @instance_id = 0
22
23
  @agent_enabled = false
23
24
  @alreadyconnected = checkAgentInfo
25
+ @site24x7 = checkLicenseFile
26
+ if (@site24x7)
27
+ @site24x7url = @license_key.start_with?('eu_') ? @obj.constants.site24x7EUurl :
28
+ @license_key.start_with?('cn_') ? @obj.constants.site24x7CNurl :
29
+ @license_key.start_with?('au_') ? @obj.constants.site24x7AUurl :
30
+ @license_key.start_with?('in_') ? @obj.constants.site24x7INurl :
31
+ @license_key.start_with?('gd_') ? @obj.constants.site24x7GDurl :
32
+ @license_key.start_with?('jp_') ? @obj.constants.site24x7JPurl :
33
+ @license_key.start_with?('gd_') ? @obj.constants.site24x7GDurl :
34
+ @license_key.start_with?('ca_') ? @obj.constants.site24x7CAurl :
35
+ @license_key.start_with?('sa_') ? @obj.constants.site24x7SAurl :
36
+ @license_key.start_with?('uk_') ? @obj.constants.site24x7UKurl :
37
+ @license_key.start_with?('in_hd_') ? @obj.constants.site24x7HDFCurl : @obj.constants.site24x7USurl
38
+ end
24
39
  @db_operations =["select","insert","update","delete"]
25
- @obj.log.debug "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
26
- @obj.log.debug "APP HOME #{File.absolute_path(".")} "
27
- @obj.log.debug "APP HOME #{Dir.pwd} "
28
- @obj.log.debug "Configuration : "
29
- @obj.log.debug "Agent Name : #{@agenthost}"
30
- @obj.log.debug "Agent Already Connected : #{@alreadyconnected}"
31
- @obj.log.debug "Agent Enabled : #{@agent_enabled}"
32
- @obj.log.debug "Allowed DB Operations : #{@db_operations}"
33
- @config.each do|key,val|
34
- @obj.log.info "#{key} => #{val}"
35
- end
36
- @obj.log.debug "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
40
+ urlMergePattern
41
+ @hostType = getHostType
42
+ @obj.log.info "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
43
+ @obj.log.info "APP HOME #{File.absolute_path(".")} "
44
+ @obj.log.info "APP HOME #{Dir.pwd} "
45
+ @obj.log.info "Agent Version : #{ManageEngine::APMInsight::VERSION}"
46
+ #@obj.log.info "Configuration : "
47
+ #@obj.log.info "Hostname : #{@agenthost}"
48
+ @obj.log.info "Host Type: #{@hostType}"
49
+ @obj.log.info "Agent Already Connected : #{@alreadyconnected}"
50
+ @obj.log.info "Agent Enabled : #{@agent_enabled}"
51
+ @obj.log.info "Allowed DB Operations : #{@db_operations}"
52
+ # @config.each do|key,val|
53
+ # @obj.log.info "#{key} => #{val}"
54
+ # end
55
+ @obj.log.info "URL Merge Patterns"
56
+ @url_merge_pattern.each do |key, val|
57
+ @obj.log.info "#{key} => #{val}"
58
+ end
59
+ @obj.log.info "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
37
60
  @app_db="dummydb"
38
61
  @app_dispatcher = getDispatcher
39
62
  @lastupdatedtime=File.mtime(@obj.constants.apm_conf).to_i
@@ -41,27 +64,33 @@ module ManageEngine
41
64
 
42
65
  def configureFile
43
66
  begin
44
- gem_conf = Gem.loaded_specs[@obj.constants.apm_gem].full_gem_path
45
- #gem_conf = File.join(gem_conf, 'lib')
46
- gem_conf = File.join(gem_conf, 'conf')
47
- gem_conf = File.join(gem_conf, 'apminsight.conf')
48
- if(FileTest.exists?(@obj.constants.apm_conf))
67
+ if(FileTest.exist?(@obj.constants.apm_conf))
49
68
  #conf file exists in APPlication Home
50
- @obj.log.debug "Config File Read from #{@obj.constants.apm_conf}"
69
+ @obj.log.debug "Config File Exists. It is read from #{@obj.constants.apm_conf}"
51
70
  @config = @obj.util.readProperties(@obj.constants.apm_conf)
71
+ secureConfFile "#{@obj.constants.apm_conf}"
52
72
  else
73
+ gemSpecs = Gem.loaded_specs[@obj.constants.s247_apm_gem]
74
+ if (gemSpecs == nil)
75
+ gemSpecs = Gem.loaded_specs[@obj.constants.apm_gem]
76
+ end
77
+ gem_conf = gemSpecs.full_gem_path
78
+ #gem_conf = File.join(gem_conf, 'lib')
79
+ gem_conf = File.join(gem_conf, 'conf')
80
+ gem_conf = File.join(gem_conf, 'apminsight.conf')
53
81
  #conf file not exists in APPlications Home. So 1. copy it for gem locations
54
82
  if @obj.util.copyFiles gem_conf,@obj.constants.apm_conf
55
83
  #copied sucessfully
56
- @obj.log.debug "Config File Read from #{@obj.constants.apm_conf}"
84
+ @obj.log.info "Config File copied to application home directory. It is read from #{@obj.constants.apm_conf}"
57
85
  @config = @obj.util.readProperties(@obj.constants.apm_conf)
86
+ secureConfFile "#{@obj.constants.apm_conf}"
58
87
  else
59
88
  #Problem in copying, so reading props from Conf file in Gem Location
60
- @obj.log.debug "Config File Read from #{gem_conf}"
89
+ @obj.log.warn "Config File not copied. It is read from #{gem_conf}"
61
90
  @config = @obj.util.readProperties(gem_conf)
91
+ secureConfFile gem_conf
62
92
  end
63
93
  end
64
-
65
94
  rescue Exception=>e
66
95
  @obj.log.info "[Exception] Problem in Reading Configuration File : \n File : #{@obj.constants.apm_conf}"
67
96
  @obj.log.logException "#{e.message}",e
@@ -70,11 +99,29 @@ module ManageEngine
70
99
  end
71
100
  end
72
101
 
102
+ def secureConfFile(file)
103
+ begin
104
+ File.chmod(0600, file)
105
+ rescue Exception => e
106
+ @obj.log.warn "Unable to secure the conf file #{file}"
107
+ end
108
+ end
109
+
73
110
  def checkAgentInfo
74
- if FileTest.exists?(@obj.constants.agent_conf)
111
+ if FileTest.exist?(@obj.constants.agent_conf)
75
112
  @obj.log.debug "Status : Agent Already Connected"
76
113
  props = @obj.util.readProperties(@obj.constants.agent_conf)
77
- @instance_id = props["agent.id"]
114
+ instance_id = props["agent.id"]
115
+
116
+ if (instance_id == nil || instance_id == "")
117
+ # If instance id is not found or empty, it means the apminsight.info is being modified by user
118
+ # Ignore all its entry
119
+ @obj.log.warn "File: #{@obj.constants.agent_conf} is corrupted. Agent will continue ignoring these values."
120
+ return false
121
+ else
122
+ @instance_id = instance_id
123
+ end
124
+
78
125
  @agent_enabled= @obj.util.getBooleanValue props["agent.enabled"]
79
126
  true
80
127
  else
@@ -83,10 +130,35 @@ module ManageEngine
83
130
  end
84
131
  end
85
132
 
133
+ def checkLicenseFile
134
+ @obj.constants.setLicenseKey @license_key
135
+ if(@license_key.start_with?('APMI_'))
136
+ @obj.log.info "Connecting to App Manager"
137
+ false
138
+ else
139
+ @obj.log.info "Connecting to Site24x7"
140
+ true
141
+ end
142
+ end
143
+
144
+ def urlMergePattern
145
+ @url_merge_pattern = Hash.new
146
+ begin
147
+ if (FileTest.exist?(@obj.constants.mergepattern_conf))
148
+ @url_merge_pattern=@obj.util.readProperties(@obj.constants.mergepattern_conf)
149
+ end
150
+ rescue Exception => e
151
+ @obj.log.info "[Exception] Problem in Reading Configuration File : \n File : #{@obj.constants.mergepattern_conf}"
152
+ @obj.log.logException "#{e.message}",e
153
+ end
154
+ end
155
+
86
156
  def updateAgentInfoFile(props)
87
157
  @instance_id = props["agent.id"]
88
158
  @agent_enabled= @obj.util.getBooleanValue props["agent.enabled"]
89
159
  @obj.util.writeProperties(@obj.constants.agent_conf,props)
160
+
161
+ secureConfFile(@obj.constants.agent_conf)
90
162
  end
91
163
 
92
164
  def initValues
@@ -102,18 +174,31 @@ module ManageEngine
102
174
  @connection_retry = 0
103
175
  @connect_interval = 60
104
176
  @apdex_t=0.5
105
- @include_packages=Array.new
177
+ @txn_skip_listen=Array.new
106
178
  @trans_trace_t=2
107
179
  @sql_trace_t=3
180
+ @metric_overflow_t=250
181
+ @dbmetric_overflow_t=500
182
+ @trace_overflow_t=30
183
+ @site24x7url = @obj.constants.site24x7USurl #default agent communication URL
184
+ @delayedStart = false
108
185
  end
109
186
 
110
187
  def assignConfig
111
188
  initValues
112
189
  @config.each do |key,value|
190
+ value = checkAndGetEnvValue(value)
113
191
  case key
114
192
  when "application.name" then @appname=value
193
+ if (ENV.has_key?('APM_APPLICATION_NAME'))
194
+ @appname = ENV['APM_APPLICATION_NAME']
195
+ end
115
196
  when "apm.host" then @apmhost=value
116
197
  when "apm.port" then @apmport=isInteger(@apmport,value)
198
+ when "license.key" then @license_key=value
199
+ if (@license_key.empty? && ENV.has_key?('S247_LICENSE_KEY'))
200
+ @license_key = ENV['S247_LICENSE_KEY']
201
+ end
117
202
  when "behind.proxy" then @proxyneeded=@obj.util.getBooleanValue value
118
203
  when "agent.server.port" then @agentport=isInteger(@agentport,value)
119
204
  when "apdex.threshold" then @apdex_t=isFloat(@apdex_t,value)
@@ -123,46 +208,184 @@ module ManageEngine
123
208
  when "transaction.trace.sql.parametrize" then @sql_capture_params=@obj.util.getBooleanValue value
124
209
  when "transaction.trace.sql.stacktrace.threshold" then @sql_trace_t=isFloat(@sql_trace_t,value)
125
210
  when "proxy.server.host" then @proxy_host=value
126
- when "proxy.server.port" then @proxy_port=value
211
+ when "proxy.server.port" then @proxy_port=isInteger(@proxy_port,value)
127
212
  when "proxy.auth.username" then @proxy_user=value
128
- when "proxy.auth.password" then @proxy_pass=value
129
- when "apminsight.secure" then @is_secured=@obj.util.getBooleanValue value
213
+ when "proxy.auth.password" then @proxy_pass=@obj.util.decrypt value, @license_key
214
+ if (@proxy_pass == nil)
215
+ @proxy_pass = value
216
+ end
217
+ when "apm.protocol.https" then @is_secured=@obj.util.getBooleanValue value
130
218
  when "apminsight.log.dir" then @logs_dir=value
219
+ when "apminsight.log.level" then @obj.log.setLevel value
131
220
  when "agent.connection.retry" then @connection_retry=value #Not in Conf - yet to come
132
- when "agent.connection.interval" then @connect_interval=value#Not in Conf - yet to come
133
- when "include.packages" then @include_packages=@obj.util.getArray value,","
221
+ when "agent.polling.interval" then @connect_interval=isInteger(@connect_interval, value)#Not in Conf - yet to come
222
+ when "transaction.skip.listening" then @txn_skip_listen=@obj.util.getArray value.gsub("\s", ""),","
223
+ when "metricstore.metric.bucket.size" then @metric_overflow_t = isInteger(@metric_overflow_t, value)
224
+ when "metricstore.dbmetric.bucket.size" then @dbmetric_overflow_t = isInteger(@dbmetric_overflow_t, value)
225
+ when "transaction.tracestore.size" then @trace_overflow_t = isInteger(@trace_overflow_t, value)
226
+ when "agent.delay.start" then @delayedStart=@obj.util.getBooleanValue value
134
227
  end
135
228
  end
229
+ store_encrypted_data(@config)
230
+ end
231
+
232
+ #Checks whether the given value is Environment Variable
233
+ def checkAndGetEnvValue(data)
234
+ begin
235
+ value = "#{data}"[/\{(.*)\}/,1]
236
+ if (value != nil && ENV.has_key?(value))
237
+ return data.gsub(/\{.*\}/, ENV[value])
238
+ end
239
+ rescue Exception=>e
240
+ end
241
+ return data
136
242
  end
137
243
 
244
+ def store_encrypted_data config
245
+ data = config["proxy.auth.password"]
246
+ if (data != nil && @obj.util.decrypt(data, @license_key) == nil) # checking whether data is already encrypted
247
+ begin
248
+ file_contents = ""
249
+ conf_file = File.open(@obj.constants.apm_conf, 'r')
250
+ conf_file.read.each_line do |line|
251
+ if line.start_with?("proxy.auth.password")
252
+ file_contents += "proxy.auth.password=" + @obj.util.encrypt(config["proxy.auth.password"], @license_key)
253
+ else
254
+ file_contents += line
255
+ end
256
+ #file_contents += "\n"
257
+ end #end of do read loop
258
+ conf_file.close
259
+ conf_file = File.open(@obj.constants.apm_conf, "w+")
260
+ conf_file.puts file_contents
261
+ conf_file.close
262
+ file_contents = nil # clearing memory
263
+ rescue Exception=>e
264
+ @obj.log.logException "Error while encrypting file", e
265
+ end
266
+ end # if already encrypted
267
+ end
268
+
269
+ def getHostType
270
+ begin
271
+ # Check for AWS environment
272
+ url = URI.parse('http://169.254.169.254/latest/meta-data/') # AWS metadata url
273
+ request = Net::HTTP::Get.new(url.path)
274
+ response = Net::HTTP.start(url.host, url.port, :read_timeout => 2) {|http| http.request(request)}
275
+ if (response.kind_of? Net::HTTPOK)
276
+ @hostType = "AWS"
277
+ return @hostType
278
+ end
279
+ rescue Exception => e
280
+ end
281
+
282
+ begin
283
+ #Check for Azure environment
284
+ url = URI.parse('http://169.254.169.254/metadata/v1/maintenance') # Azure metadata url
285
+ request = Net::HTTP::Get.new(url.path)
286
+ response = Net::HTTP.start(url.host, url.port, :read_timeout => 2) {|http| http.request(request)}
287
+ if (response.kind_of? Net::HTTPOK)
288
+ @hostType = "AZURE"
289
+ return @hostType
290
+ end
291
+ rescue Exception => e
292
+ end
293
+
294
+ begin
295
+ # Check for Heroku env. In the backgroud it is using AWS EC2, hence sending as AWS
296
+ if (ENV.has_key?('DYNO') || ENV.has_key?('STACK'))
297
+ @hostType = "AWS"
298
+ return @hostType
299
+ end
300
+ rescue Exception => e
301
+ end
302
+
303
+ @hostType = nil
304
+ end
305
+
138
306
  def getAgentInfo
139
307
  data = Hash.new
140
308
  agentdata = Hash.new
141
- agentdata = {"application.type"=>"RUBY","application.name"=>@appname,"hostname"=>@agenthost,"port"=>@agentport,"agent.version"=>"1.0"}
309
+ agentdata = {"application.type"=>"RUBY","application.name"=>@appname,"hostname"=>@agenthost,"port"=>@agentport,"agent.version"=>ManageEngine::APMInsight::MAJOR_VERSION}
310
+ if (@hostType != nil)
311
+ agentdata["host.type"]=@hostType
312
+ end
313
+ begin
314
+ fqdn = Addrinfo.getaddrinfo(Socket.gethostname, nil).first.getnameinfo.first
315
+ if (fqdn != nil)
316
+ agentdata["fqdn"] = fqdn
317
+ end
318
+ rescue Exception=>e
319
+ @obj.log.warn("Unable to get fqdn value #{e.message}")
320
+ end
142
321
  data["agent_info"]=agentdata
143
322
  data["environment"]=getEnvData
323
+ data["custom_config_info"]=getAgentConfigData
144
324
  data
145
325
  end
146
326
 
147
327
  def getEnvData
148
328
  env = Hash.new
149
329
  begin
150
- ENV.to_hash.each do |key, value|
151
- env[key] = value
152
- end
153
- env["Application Path"]="#{Rails.root}"
330
+ env["OS"] = Gem::Platform.local.os
331
+ env["OS Version"] = Gem::Platform.local.version
332
+ env["OS Arch"] = Gem::Platform.local.cpu
333
+ env["Ruby Version"] = "#{RUBY_VERSION}"
334
+ gemSpecs = Gem.loaded_specs[@obj.constants.s247_apm_gem]
335
+ if (gemSpecs == nil)
336
+ gemSpecs = Gem.loaded_specs[@obj.constants.apm_gem]
337
+ end
338
+ if (gemSpecs != nil)
339
+ env["Agent Installed Path"] = gemSpecs.full_gem_path
340
+ end
341
+
342
+ # ENV.to_hash.each do |key, value|
343
+ # env[key] = value
344
+ # end
345
+ env["Application Path"] = "#{Dir.pwd}"
154
346
  rescue Exception=>e
347
+ @obj.log.warn "Error in capturing env data. #{e.message}"
155
348
  end
156
349
  env
157
350
  end
158
351
 
352
+ def getAgentConfigData
353
+ agentconfig = Hash.new
354
+ agentconfig["last.modified.time"]=@lastupdatedtime*1000
355
+ agentconfig["apdex.threshold"]=@apdex_t
356
+ agentconfig["sql.capture.enabled"]=0
357
+ if @sql_capture
358
+ agentconfig["sql.capture.enabled"]=1
359
+ end
360
+ agentconfig["transaction.trace.enabled"]=0
361
+ if @trans_trace
362
+ agentconfig["transaction.trace.enabled"]=1
363
+ end
364
+ agentconfig["transaction.trace.threshold"]=@trans_trace_t
365
+ agentconfig["transaction.trace.sql.parametrize"]=0
366
+ if @sql_capture_params
367
+ agentconfig["transaction.trace.sql.parametrize"]=1
368
+ end
369
+ agentconfig["transaction.trace.sql.stacktrace.threshold"]=@sql_trace_t
370
+ agentconfig["transaction.tracking.request.interval"]=1
371
+ agentconfig
372
+ end
159
373
 
160
374
  def getDispatcher
161
- dispatcher = "unknown"
162
- if defined?(PhusionPassenger) then
163
- dispatcher = "passenger"
164
- end
165
- dispatcher
375
+
376
+ @obj.log.info "Server: #{ENV['SERVER_SOFTWARE']}"
377
+
378
+ dispatcher = "unknown"
379
+ if defined?(PhusionPassenger) then
380
+ dispatcher = "passenger"
381
+ end
382
+ if defined?(Unicorn) then
383
+ dispatcher = "unicorn"
384
+ end
385
+ if defined?(Rainbows) then
386
+ dispatcher = "rainbows"
387
+ end
388
+ dispatcher
166
389
  end
167
390
 
168
391
  def isInteger default,value
@@ -184,6 +407,46 @@ module ManageEngine
184
407
  end
185
408
  end
186
409
 
410
+ def update_config configInfo
411
+ filepath = @obj.constants.apm_conf
412
+ f = "apminsight.conf.new"
413
+ begin
414
+ propsFile=File.open(filepath, 'r')
415
+ file = File.new(f,"w+")
416
+ propsFile.read.each_line do |line|
417
+ line.strip!
418
+ if (line[0] != ?# and line[0] != ?=)
419
+ i = line.index('=')
420
+ if (i)
421
+ key1 = line[0..i - 1].strip
422
+ if configInfo.has_key?(key1)
423
+ file.puts "#{key1}=#{configInfo[key1]}\n"
424
+ else
425
+ file.puts "#{line}\n"
426
+ end
427
+ else
428
+ file.puts "#{line}\n"
429
+ end
430
+ else
431
+ file.puts "#{line}\n"
432
+ end
433
+ end
434
+ rescue Exception=>e
435
+ @obj.log.info "Problem in Reading / Writing Property File : #{e.message} "
436
+ @obj.log.error "#{e.backtrace}"
437
+ ensure
438
+ propsFile.close
439
+ file.close
440
+ end
441
+ res = @obj.util.copyFiles f, filepath
442
+ if res
443
+ @obj.log.info "copyFiles result = #{res}"
444
+ #delete apminsight.conf.new has to be done
445
+ end
446
+ configureFile
447
+ assignConfig
448
+ end
449
+
187
450
 
188
451
  end#c
189
452
  end#m
@@ -0,0 +1,40 @@
1
+ require 'agent/handler/sequence_book'
2
+
3
+ module APMInsight
4
+ module API
5
+ class CustomAPIHandler
6
+
7
+ ## Create tracker for custom instrumented methods and send them to tracker handler
8
+ def self.invokeTracker name
9
+ begin
10
+ # @obj = ManageEngine::APMObjectHolder.instance
11
+
12
+ if Thread.current[:apminsight] != nil
13
+ tracker = ManageEngine::Tracker::DefaultTracker.new(name)
14
+ tracker = ManageEngine::Agent::TrackerHandler.invokeTracker(tracker)
15
+ return tracker
16
+ end
17
+
18
+ return nil
19
+ rescue Exception=>e
20
+ return nil
21
+ end
22
+ end
23
+
24
+ def self.exitTracker tracker
25
+ if tracker != nil
26
+ tracker.finish
27
+ ManageEngine::Agent::TrackerHandler.exitTracker(tracker)
28
+ end
29
+ end
30
+
31
+ def self.track_exception exception
32
+ seqBook = Thread.current[:apminsight]
33
+ if seqBook != nil
34
+ seqBook.addExceptionInfo exception
35
+ end
36
+ end
37
+
38
+ end #class CustomAPIhandler
39
+ end #module API
40
+ end
@@ -0,0 +1,125 @@
1
+ require 'agent/metrics/exception_record'
2
+
3
+ module APMInsight
4
+ module Agent
5
+ class SequenceBook
6
+ attr_reader :openTracker, :closedTracker, :rootTracker, :trackerCount, :closedTrackerCount, :exceptionBag, :listenFlag
7
+
8
+ def initialize
9
+ @rootTracker = createDummyTracker()
10
+ @closedTracker = @rootTracker
11
+ @openTracker = nil
12
+
13
+ @trackerCount = 0
14
+ @closedTrackerCount = 0
15
+ @listenFlag = -1
16
+ # @exceptionBag = Array.new
17
+ end
18
+
19
+ def attachTracker tracker
20
+ if tracker == nil
21
+ return nil
22
+ end
23
+
24
+ # If RootTracker is not set, check type and set
25
+ if @rootTracker == @closedTracker
26
+ if !tracker.is_a?(ManageEngine::Tracker::RootTracker)
27
+ closeSequence()
28
+ return nil
29
+ end
30
+ @rootTracker = tracker
31
+
32
+ updateListenFlag()
33
+ end
34
+
35
+
36
+ # Attach tracker as Sibling or Child and set nominee
37
+ if @closedTracker != nil
38
+ tracker.sibling = @closedTracker
39
+ @closedTracker.sibling = tracker # Nominee - if dropped/corrupted, defaults to this tracker
40
+ @openTracker = tracker
41
+ @closedTracker = nil
42
+ else
43
+ if tracker.equal?(@openTracker)
44
+ return nil
45
+ end
46
+
47
+ @openTracker.child = tracker
48
+ tracker.sibling = @openTracker
49
+ @openTracker = tracker
50
+ end
51
+
52
+ checkAndArrestSequence()
53
+
54
+ return tracker
55
+ end
56
+
57
+ def closeTracker tracker
58
+ @closedTrackerCount += 1
59
+ @closedTracker = tracker
60
+ tracker.sibling = nil
61
+ @openTracker = nil
62
+
63
+ # Marks end of transaction
64
+ if @rootTracker == tracker
65
+ if @listenFlag < 1 || (@listenFlag >= 1 && @trackerCount > 1)
66
+ # if some trackers are not closed, while processing the metrics, it may go into infinite loop
67
+ if (@closedTrackerCount - @trackerCount) == 0
68
+ sequenceBag = Hash.new
69
+ sequenceBag["roottracker"] = @rootTracker
70
+ sequenceBag["exceptions"] = @exceptionBag
71
+
72
+ ManageEngine::APMObjectHolder.instance.collector.updateTransaction(@rootTracker.url, sequenceBag)
73
+ else
74
+ ManageEngine::APMObjectHolder.instance.log.warn "Some trackers are not closed, dropping the metrics for #{@rootTracker.url}"
75
+ end
76
+ end
77
+ closeSequence()
78
+ end
79
+ end
80
+
81
+ def closeSequence
82
+ @rootTracker = nil
83
+ @openTracker = @closedTracker = nil
84
+ @trackerCount = 0
85
+ @closedTrackerCount = 0
86
+ Thread.current[:apminsight] = nil
87
+ end
88
+
89
+ def addExceptionInfo(exception)
90
+ begin
91
+ if @exceptionBag == nil
92
+ @exceptionBag = Set.new
93
+ end
94
+ if (@exceptionBag.size() < 10)
95
+ exceptionRecord = ::APMInsight::Errors::ExceptionRecord.new(exception)
96
+ @exceptionBag.add(exceptionRecord)
97
+ end
98
+ rescue Exception=>e
99
+ end
100
+ end
101
+
102
+ def updateListenFlag
103
+ if !ManageEngine::APMObjectHolder.instance.txn_util.listen?(@rootTracker.url())
104
+ @listenFlag = 1
105
+ end
106
+
107
+ ## Check for sampling factor & for bg txn chk if enabled
108
+ end
109
+
110
+ def checkAndArrestSequence
111
+ @trackerCount += 1
112
+ if @trackerCount == 1000
113
+ @listenFlag = 1
114
+ end
115
+
116
+ ## Can check for timeout
117
+ end
118
+
119
+ def createDummyTracker
120
+ return ManageEngine::Tracker::DefaultTracker.new("dummy")
121
+ end
122
+
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,58 @@
1
+ require 'agent/handler/sequence_book'
2
+
3
+ module ManageEngine
4
+ module Agent
5
+ class TrackerHandler
6
+
7
+ def self.invokeTracker tracker
8
+ begin
9
+ @obj = ManageEngine::APMObjectHolder.instance
10
+
11
+ if !@obj.config.agent_enabled || tracker == nil
12
+ return nil
13
+ end
14
+
15
+ seqBook = Thread.current[:apminsight]
16
+ if seqBook != nil
17
+ if seqBook.listenFlag == 1
18
+ return nil
19
+ end
20
+ else
21
+ seqBook = ::APMInsight::Agent::SequenceBook.new
22
+ Thread.current[:apminsight] = seqBook
23
+ end
24
+
25
+ tracker = seqBook.attachTracker(tracker)
26
+
27
+ return tracker
28
+ rescue Exception=>ex
29
+ # Logging to be done here, Not sure whether its safe to do
30
+ if (@obj != nil)
31
+ @obj.log.logException "[TrackerHandler] Exception occurred at invoketracker.", ex
32
+ end
33
+ return nil
34
+ end
35
+ end
36
+
37
+
38
+ # Closes tracker properly and set everything ready to process next tracker
39
+ # If roottracker closes, sequence book is cleaned and data are push to store
40
+ def self.exitTracker tracker
41
+ begin
42
+ if tracker != nil
43
+ seqBook = Thread.current[:apminsight]
44
+ if seqBook != nil
45
+ seqBook.closeTracker tracker
46
+ end
47
+ end
48
+ rescue Exception=>ex
49
+ if (@obj != nil)
50
+ @obj.log.logException "[TrackerHandler] Exception occurred at exittracker.", ex
51
+ end
52
+ end
53
+ end
54
+
55
+ end # Class TrackerHandler
56
+
57
+ end # module Agent
58
+ end