apminsight 1.0.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/VERSION +1 -1
  2. data/apm-agent.gemspec +64 -0
  3. data/conf/apminsight.conf +15 -24
  4. data/lib/agent/am_objectholder.rb +25 -19
  5. data/lib/agent/api/custom_tracker.rb +79 -0
  6. data/lib/agent/configuration/am_configuration.rb +249 -37
  7. data/lib/agent/handler/custom_api_handler.rb +40 -0
  8. data/lib/agent/handler/sequence_book.rb +118 -0
  9. data/lib/agent/handler/tracker_handler.rb +58 -0
  10. data/lib/agent/logging/am_logger.rb +13 -9
  11. data/lib/agent/metrics/am_metricsformatter.rb +117 -59
  12. data/lib/agent/metrics/am_metricsparser.rb +195 -468
  13. data/lib/agent/metrics/am_metricstore.rb +7 -6
  14. data/lib/agent/metrics/exception_record.rb +24 -0
  15. data/lib/agent/server/am_agent.rb +42 -17
  16. data/lib/agent/server/am_connector.rb +65 -21
  17. data/lib/agent/server/instrument/action_view.rb +64 -0
  18. data/lib/agent/server/instrument/active_record.rb +52 -0
  19. data/lib/agent/server/instrument/am_apm.rb +107 -97
  20. data/lib/agent/server/instrument/am_instrumenter.rb +54 -42
  21. data/lib/agent/server/instrument/environment.rb +42 -0
  22. data/lib/agent/server/instrument/rails.rb +56 -0
  23. data/lib/agent/server/instrument/sinatra.rb +97 -0
  24. data/lib/agent/server/worker/am_worker.rb +93 -49
  25. data/lib/agent/trackers/database_tracker.rb +107 -0
  26. data/lib/agent/trackers/default_tracker.rb +57 -0
  27. data/lib/agent/trackers/root_tracker.rb +43 -0
  28. data/lib/agent/util/am_constants.rb +46 -3
  29. data/lib/agent/util/am_util.rb +64 -1
  30. data/lib/agent/util/transaction_util.rb +35 -0
  31. data/lib/agent/version.rb +13 -0
  32. data/lib/apminsight.rb +4 -1
  33. metadata +114 -76
@@ -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,118 @@
1
+ require 'agent/metrics/exception_record'
2
+
3
+ module APMInsight
4
+ module Agent
5
+ class SequenceBook
6
+ attr_reader :openTracker, :closedTracker, :rootTracker, :trackerCount, :exceptionBag, :listenFlag
7
+
8
+ def initialize
9
+ @rootTracker = createDummyTracker()
10
+ @closedTracker = @rootTracker
11
+ @openTracker = nil
12
+
13
+ @trackerCount = 0
14
+ @listenFlag = -1
15
+ # @exceptionBag = Array.new
16
+ end
17
+
18
+ def attachTracker tracker
19
+ if tracker == nil
20
+ return nil
21
+ end
22
+
23
+ # If RootTracker is not set, check type and set
24
+ if @rootTracker == @closedTracker
25
+ if !tracker.is_a?(ManageEngine::Tracker::RootTracker)
26
+ closeSequence()
27
+ return nil
28
+ end
29
+ @rootTracker = tracker
30
+
31
+ updateListenFlag()
32
+ end
33
+
34
+
35
+ # Attach tracker as Sibling or Child and set nominee
36
+ if @closedTracker != nil
37
+ tracker.sibling = @closedTracker
38
+ @closedTracker.sibling = tracker # Nominee - if dropped/corrupted, defaults to this tracker
39
+ @openTracker = tracker
40
+ @closedTracker = nil
41
+ else
42
+ if tracker.equal?(@openTracker)
43
+ return nil
44
+ end
45
+
46
+ @openTracker.child = tracker
47
+ tracker.sibling = @openTracker
48
+ @openTracker = tracker
49
+ end
50
+
51
+ checkAndArrestSequence()
52
+
53
+ return tracker
54
+ end
55
+
56
+ def closeTracker tracker
57
+ @closedTracker = tracker
58
+ tracker.sibling = nil
59
+ @openTracker = nil
60
+
61
+ # Marks end of transaction
62
+ if @rootTracker == tracker
63
+ if @listenFlag < 1 || (@listenFlag >= 1 && @trackerCount > 1)
64
+
65
+ sequenceBag = Hash.new
66
+ sequenceBag["roottracker"] = @rootTracker
67
+ sequenceBag["exceptions"] = @exceptionBag
68
+
69
+ ManageEngine::APMObjectHolder.instance.collector.updateTransaction(@rootTracker.url, sequenceBag)
70
+ end
71
+ closeSequence()
72
+ end
73
+ end
74
+
75
+ def closeSequence
76
+ @rootTracker = nil
77
+ @openTracker = @closedTracker = nil
78
+ @trackerCount = 0
79
+ Thread.current[:apminsight] = nil
80
+ end
81
+
82
+ def addExceptionInfo(exception)
83
+ begin
84
+ if @exceptionBag == nil
85
+ @exceptionBag = Set.new
86
+ end
87
+ if (@exceptionBag.size() < 10)
88
+ exceptionRecord = ::APMInsight::Errors::ExceptionRecord.new(exception)
89
+ @exceptionBag.add(exceptionRecord)
90
+ end
91
+ rescue Exception=>e
92
+ end
93
+ end
94
+
95
+ def updateListenFlag
96
+ if !ManageEngine::APMObjectHolder.instance.txn_util.listen?(@rootTracker.url())
97
+ @listenFlag = 1
98
+ end
99
+
100
+ ## Check for sampling factor & for bg txn chk if enabled
101
+ end
102
+
103
+ def checkAndArrestSequence
104
+ @trackerCount += 1
105
+ if @trackerCount == 1000
106
+ @listenFlag = 1
107
+ end
108
+
109
+ ## Can check for timeout
110
+ end
111
+
112
+ def createDummyTracker
113
+ return ManageEngine::Tracker::DefaultTracker.new("dummy")
114
+ end
115
+
116
+ end
117
+ end
118
+ 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
@@ -14,12 +14,18 @@ module ManageEngine
14
14
  path= path + '/apm.log'
15
15
  #puts "#{path}"
16
16
  # file = open(path, File::WRONLY | File::APPEND | File::CREAT)
17
- @apmlog = Logger.new(path, 10, 100 * 1024 * 1024)
18
- # @apmlog = Logger.new(file)
19
- @apmlog.level = Logger::INFO
20
- @apmlog.datetime_format = "%Y-%m-%d %H:%M:%S"
17
+ begin
18
+ @apmlog = Logger.new(path, 10, 5 * 1024 * 1024)
19
+ @apmlog.level = Logger::INFO
20
+ rescue Exception => e
21
+ puts "Unable to create/edit the log file #{path}. Writing agent logs to STDOUT.\nError: #{e.message}"
22
+ @apmlog = Logger.new(STDOUT)
23
+ @apmlog.level = Logger::WARN
24
+ end
25
+ # @apmlog = Logger.new(file)
26
+ @apmlog.datetime_format = "%Y-%m-%d %H:%M:%S"
21
27
  @apmlog.formatter = proc do |severity, datetime, progname, msg|
22
- "[#{datetime}|#{Process.pid}]:#{msg}\n"
28
+ "[#{datetime}|#{Process.pid}][#{severity}]:#{msg}\n"
23
29
  end
24
30
  @apmlog.debug("[LOGGER] APM Agent Logging Initialized")
25
31
 
@@ -96,10 +102,8 @@ module ManageEngine
96
102
 
97
103
 
98
104
  def logException(msg,e)
99
- @apmlog.info( "#{msg} => #{e.message}")
100
- @apmlog.debug( "!!!!!!!!!!!!!!!!!!!!!!EXCEPTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!")
101
- @apmlog.debug( "Message : #{msg}\nTrace :\n#{e.backtrace}")
102
- @apmlog.debug( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
105
+ @apmlog.warn( "#{msg} => #{e.message}")
106
+ @apmlog.warn( "Message : #{msg}\nTrace :\n#{e.backtrace}")
103
107
  end
104
108
 
105
109
  def close
@@ -6,8 +6,8 @@ module ManageEngine
6
6
  @obj = ManageEngine::APMObjectHolder.instance
7
7
  @apdex_threshold = 0
8
8
  end
9
- #trans Vs #[0-rspTime,1-min rt,2-max rt,3-cnt,4-apdx,5-stat,6-toler,7-frustating]
10
- #DBtrans Vs #[rspTime,min rt,max rt,cnt]
9
+ #trans Vs #[0-rspTime,1-min rt,2-max rt,3-cnt,4-apdx,5-stat,6-toler,7-frustating,8-error_count]
10
+ #DBtrans Vs #[rspTime,min rt,max rt,cnt,error_count]
11
11
  #trace
12
12
 
13
13
  def format d
@@ -95,34 +95,41 @@ module ManageEngine
95
95
  end
96
96
 
97
97
  def updateinstance
98
- ins_apdx = Array.new
99
- cnt = 0;
100
- rt = 0;
101
- s=0;
102
- t=0;
103
- f=0;
104
- min = -1;
105
- max = 0;
98
+ ins_apdx = [0,-1,-1,0,0,0,0,0,0]
99
+ logmetric = Hash.new
106
100
  @transaction.each do |key,value|
107
- rt = rt + value[0]
108
- if min == -1
109
- min = value[1]
110
- max = value[2]
111
- end
112
- if(value[1]<min)
113
- min = value[1]
114
- end
115
- if (value[2]>max)
116
- max = value[2]
101
+ apdexValue = value[0]
102
+ ins_apdx[0] += apdexValue[0]
103
+ if ins_apdx[1] == -1
104
+ ins_apdx[1] = apdexValue[1]
105
+ ins_apdx[2] = apdexValue[2]
106
+ else
107
+ if(apdexValue[1]<ins_apdx[1])
108
+ ins_apdx[1] = apdexValue[1]
109
+ end
110
+ if (apdexValue[2]>ins_apdx[2])
111
+ ins_apdx[2] = apdexValue[2]
112
+ end
117
113
  end
118
- cnt = cnt + value[3]
114
+ ins_apdx[3] += apdexValue[3]
119
115
 
120
- s = s + value[5]
121
- t = t + value[6]
122
- f = f + value[7]
116
+ ins_apdx[5] += apdexValue[5]
117
+ ins_apdx[6] += apdexValue[6]
118
+ ins_apdx[7] += apdexValue[7]
119
+ ins_apdx[8] += apdexValue[8]
120
+
121
+ exceptions = value[1][@obj.constants.mf_logmetric]
122
+ if (exceptions != nil)
123
+ exceptions.each do |name, count|
124
+ logmetric[name] = logmetric[name].to_i + count
125
+ end
126
+ end
127
+ end
128
+ if (ins_apdx[3] > 0)
129
+ ins_apdx[4] = (ins_apdx[5].to_f + (ins_apdx[6]/2).to_f).to_f/ins_apdx[3].to_f
130
+ ins_apdx[0] = ins_apdx[0].round(2)
123
131
  end
124
- apx = (s.to_f + (t/2).to_f).to_f/cnt.to_f
125
- @instance[":apdex"]=[rt.round(2),min,max,cnt,apx,s,t,f]
132
+ @instance[":apdex"]=[ins_apdx, {@obj.constants.mf_logmetric=>logmetric}]
126
133
  end
127
134
 
128
135
  def updatedbinstance
@@ -130,6 +137,7 @@ module ManageEngine
130
137
  rt = 0;
131
138
  min = -1;
132
139
  max = 0;
140
+ error_count = 0;
133
141
  if(@db.length>0)
134
142
  @db.each do |key,val|
135
143
  value = val["metrics"]
@@ -145,8 +153,9 @@ module ManageEngine
145
153
  max = value[2]
146
154
  end
147
155
  cnt = cnt + value[3]
156
+ error_count += value[4]
148
157
  end
149
- @dbinstance[":apdex"]=[rt.round(2),min,max,cnt]
158
+ @dbinstance[":apdex"]=[rt.round(2),min,max,cnt,error_count]
150
159
  end
151
160
  end
152
161
 
@@ -154,25 +163,61 @@ module ManageEngine
154
163
  begin
155
164
  pl = d["td"]
156
165
  dbl = d["db"]
166
+ exc = d["exception"]
157
167
 
158
168
  rt = pl["rt"].round(2)
159
- path = pl["path"]
160
- name = pl["name"]
161
-
162
- path = @obj.constants.mf_transaction + @obj.constants.mf_separator + path + " " +name
169
+ path = @obj.constants.mf_transaction + @obj.constants.mf_separator + pl["path"]
163
170
 
164
171
 
165
172
  apx_stat = nil
173
+ additionalInfo = nil
166
174
  if(@transaction.has_key?(path))
167
- apx_stat = @transaction[path]
175
+ apx_stat = @transaction[path][0]
176
+ additionalInfo = @transaction[path][1]
168
177
  else
178
+ if @transaction.length == @obj.config.metric_overflow_t
179
+ @obj.log.debug "Metricstore overflow. Current Size: #{@obj.config.metric_overflow_t} #{path}"
180
+ return
181
+ end
169
182
  apx_stat = Array.new
170
- apx_stat = [0,rt,rt,0,0,0,0,0]
183
+ apx_stat = [0,0,0,0,0,0,0,0,0]
184
+ additionalInfo = Hash.new
171
185
  end
172
- apx_stat = apxarray apx_stat,rt
173
- @transaction[path] = apx_stat
186
+
187
+ if (pl.has_key?("error"))
188
+ apx_stat[8] += 1
189
+ else
190
+ apx_stat = apxarray apx_stat,rt
191
+ end
192
+
193
+ if (exc != nil)
194
+ logmetric = additionalInfo[@obj.constants.mf_logmetric]
195
+ if (logmetric == nil)
196
+ additionalInfo[@obj.constants.mf_logmetric] = exc
197
+ else
198
+ exc.each do |name, count|
199
+ logmetric[name] = logmetric[name].to_i + count
200
+ end
201
+ end
202
+ end
203
+
204
+ @transaction[path] = [apx_stat, additionalInfo]
174
205
  if(dbl!=nil)
175
- updatedb dbl,path
206
+ if @db.length < @obj.config.dbmetric_overflow_t
207
+ updatedb dbl,path
208
+ elsif @db.length == @obj.config.dbmetric_overflow_t
209
+ @obj.log.debug "DB metric overflow. Current Size: #{@obj.config.dbmetric_overflow_t} #{path}"
210
+ #@obj.log.info "data = #{@db}"
211
+ of = Hash.new
212
+ stats = Array.new
213
+ stats = [0,0,0,0,0]
214
+ of["tpath"] = @obj.constants.mf_overflow
215
+ #of["tpath"] = @obj.constants.mf_transaction + @obj.constants.mf_separator + @obj.constants.mf_overflow #using this for testing purpose
216
+ of["path"] = @obj.constants.mf_db + @obj.constants.mf_separator + @obj.constants.mf_overflow + @obj.constants.mf_separator + "-" + @obj.constants.mf_separator
217
+ of["metrics"] = stats
218
+ @db[@obj.constants.mf_overflow]=of
219
+ #@obj.log.info "data updated = #{@db}"
220
+ end
176
221
  end
177
222
  rescue Exception=>e
178
223
  @obj.log.info "#{e.message}"
@@ -181,6 +226,7 @@ module ManageEngine
181
226
  # Apmagent::ApmLogger.instance.info "update transaction end"
182
227
  end
183
228
 
229
+ # Updates apdex score and increases statisfied, tolerating, frustrated count accordingly
184
230
  def apxarray apx_stat,rt
185
231
 
186
232
  # Apmagent::ApmLogger.instance.info "apxarray : start #{apx_stat}"
@@ -193,16 +239,19 @@ module ManageEngine
193
239
  apx_stat[6] = apx_stat[6] + 1
194
240
  end
195
241
 
196
- apx_stat[4] = (apx_stat[5].to_f + (apx_stat[6].to_f/2).to_f)/apx_stat[3].to_f
242
+ if (apx_stat[3] > 0)
243
+ apx_stat[4] = (apx_stat[5].to_f + (apx_stat[6].to_f/2).to_f)/apx_stat[3].to_f
244
+ end
197
245
  # Apmagent::ApmLogger.instance.info "apxarray : end #{apx_stat}"
198
246
  apx_stat
199
247
  end
200
248
 
249
+ # Updates resp time, min rt and max rt in apdex metric
201
250
  def updatert apx_stat,rt
202
251
  # Apmagent::ApmLogger.instance.info "updatert : start"
203
- apx_stat[3] = apx_stat[3] +1
252
+ apx_stat[3] = apx_stat[3] + 1
204
253
  apx_stat[0] = apx_stat[0] + rt
205
- if(rt < apx_stat[1])
254
+ if(apx_stat[1] == 0 || rt < apx_stat[1])
206
255
  apx_stat[1] = rt
207
256
  end
208
257
  if(rt > apx_stat[2])
@@ -211,7 +260,8 @@ module ManageEngine
211
260
  #Apmagent::ApmLogger.instance.info "updatert : end"
212
261
  apx_stat
213
262
  end
214
- #DBtrans Vs #[rspTime,min rt,max rt,cnt]
263
+
264
+ #DBtrans Vs #[rspTime,min rt,max rt,cnt,error_count]
215
265
  def updatedb dpl,tpath
216
266
  # Apmagent::ApmLogger.instance.info "updatedb : start"
217
267
  dpl.each do |pl|
@@ -227,37 +277,45 @@ module ManageEngine
227
277
  stat = val["metrics"]
228
278
  else
229
279
  val=Hash.new
280
+ val["tpath"] = tpath
281
+ val["path"] = dpath
230
282
  stat = Array.new
231
- stat = [rt,rt,rt,0]
283
+ stat = [0,rt,rt,0,0]
284
+ end
285
+ if (pl.has_key?("error"))
286
+ stat[4] += 1
287
+ else
288
+ stat = updatert stat,rt
232
289
  end
233
- stat = updatert stat,rt
234
- val["tpath"] = tpath
235
- val["path"] = dpath
236
290
  val["metrics"] = stat
237
291
  @db[path] = val
238
- updatedboperations rt, pl["operation"]
292
+ updatedboperations rt, pl["operation"], pl["error"]
239
293
  end
240
294
  #Apmagent::ApmLogger.instance.info "updatedb : end"
241
295
  end
242
296
 
243
- def updatedboperations rt,operation
244
- opstats = Array.new;
245
- #puts "#{operation} "
297
+ def updatedboperations rt, operation, isError
246
298
  if(@dboperations.has_key?(operation))
247
299
  opstats = @dboperations[operation]
248
300
  else
249
- opstats = [0.0,rt,rt,0]
250
- end
251
- opstats[0] = opstats[0] + rt
252
- if(rt<opstats[1])
253
- opstats[1] = rt
301
+ opstats = Array.new;
302
+ opstats = [0.0,rt,rt,0,0]
254
303
  end
255
- if (rt>opstats[2])
256
- opstats[2] = rt
257
- end
258
- opstats[3] = opstats[3] +1
304
+
305
+ if (isError)
306
+ opstats[4] += 1
307
+ else
308
+ opstats[0] = opstats[0] + rt
309
+ if(rt<opstats[1])
310
+ opstats[1] = rt
311
+ end
312
+ if (rt>opstats[2])
313
+ opstats[2] = rt
314
+ end
315
+ opstats[3] = opstats[3] +1
316
+ end
259
317
  @dboperations[operation]=opstats
260
318
  end
261
319
 
262
- end
263
- end
320
+ end#class
321
+ end#module