appmap 0.92.1 → 0.93.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f527f92e73d7e71cf5a4e9db3b71c570b39443ad0788bc2c6f4b4bae4bb215ba
4
- data.tar.gz: 6604ce77790645d5c5a60d37a2bc1116952909fe29856ea9fb36bac29d992d81
3
+ metadata.gz: 837bc5a036d3217c12b40f46ed7e21406ef298b3ca5c8b712b8ce1f15707434e
4
+ data.tar.gz: 763d5c9abd0f8583035117a54c8a6bb0d841089c902ab2e1805ff0795f3acff1
5
5
  SHA512:
6
- metadata.gz: 841907ab84538b09c9f83509d3c65dcd6d3b0be92e452a3558194fd33a8c90336f4f8294be91ac94a8631546acc89bef91807a451a546c3c1d9408110268e237
7
- data.tar.gz: 715e6d1e540a89c660f0d3a9794b0c199356b1557fc5921226a422b78eff9c62f6b696cd1d231f0c25d06b82c417f5fef4b9e613b564146a50779b6e4d4d6910
6
+ metadata.gz: 7812c770c07f1e00dc93e0ce4c79598c26daff3fe1d737804dcfc012d29cdefe0754cd3ff06f2810feebe1952cb2038cee2f078d486067188875ec7eb71842de
7
+ data.tar.gz: 73db38443e22f4a57bf8575035b4735f7fe044f57dd78f6213ac2694434487732778cb0feacb3733c0565080dd859b22dfcf651ec129b70f028a1500a9ff63ea
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # [0.93.0](https://github.com/getappmap/appmap-ruby/compare/v0.92.1...v0.93.0) (2022-09-22)
2
+
3
+
4
+ ### Features
5
+
6
+ * Record the time spent instrumentating a function, as opposed to only the time spend executing a function ([0941b4d](https://github.com/getappmap/appmap-ruby/commit/0941b4d343b1ea2964268d3a47d8f762de00deea))
7
+ * save elapsed_instrumentation for HTTP requests ([a32fb52](https://github.com/getappmap/appmap-ruby/commit/a32fb526a6f7b47ddc859e86a68b53b50b052061))
8
+ * save elapsed_instrumentation for RequestListener ([5a081cc](https://github.com/getappmap/appmap-ruby/commit/5a081ccf558a4591035acc81b1717b2ccef880ee))
9
+ * Save elapsed_instrumentation for sql_query ([40a851e](https://github.com/getappmap/appmap-ruby/commit/40a851e5d40cc5ada36ea52e32d5222da4c67d10))
10
+
1
11
  ## [0.92.1](https://github.com/getappmap/appmap-ruby/compare/v0.92.0...v0.92.1) (2022-09-21)
2
12
 
3
13
 
data/lib/appmap/event.rb CHANGED
@@ -262,7 +262,7 @@ module AppMap
262
262
  end
263
263
 
264
264
  class MethodReturnIgnoreValue < MethodEvent
265
- attr_accessor :parent_id, :elapsed
265
+ attr_accessor :parent_id, :elapsed, :elapsed_instrumentation
266
266
 
267
267
  class << self
268
268
  def build_from_invocation(parent_id, elapsed: nil, event: MethodReturnIgnoreValue.new)
@@ -279,6 +279,7 @@ module AppMap
279
279
  super.tap do |h|
280
280
  h[:parent_id] = parent_id
281
281
  h[:elapsed] = elapsed if elapsed
282
+ h[:elapsed_instrumentation] = elapsed_instrumentation if elapsed_instrumentation
282
283
  end
283
284
  end
284
285
  end
@@ -10,7 +10,7 @@ module AppMap
10
10
 
11
11
  module RequestHandler
12
12
  class HTTPServerRequest < AppMap::Event::MethodEvent
13
- attr_accessor :normalized_path_info, :request_method, :path_info, :params, :headers
13
+ attr_accessor :normalized_path_info, :request_method, :path_info, :params, :headers, :call_elapsed_instrumentation
14
14
 
15
15
  def initialize(request)
16
16
  super AppMap::Event.next_id_counter, :call, Thread.current.object_id
@@ -101,16 +101,21 @@ module AppMap
101
101
  protected
102
102
 
103
103
  def before_hook(receiver, *)
104
+ before_hook_start_time = AppMap::Util.gettime()
104
105
  call_event = HTTPServerRequest.new(receiver.request)
106
+ call_event.call_elapsed_instrumentation = (AppMap::Util.gettime() - before_hook_start_time)
105
107
  # http_server_request events are i/o and do not require a package name.
106
108
  AppMap.tracing.record_event call_event, defined_class: defined_class, method: hook_method
107
109
  call_event
108
110
  end
109
111
 
110
112
  def after_hook(receiver, call_event, elapsed, *)
113
+ after_hook_start_time = AppMap::Util.gettime()
111
114
  return_value = Thread.current[TEMPLATE_RENDER_VALUE]
112
115
  Thread.current[TEMPLATE_RENDER_VALUE] = nil
113
116
  return_event = HTTPServerResponse.build_from_invocation call_event.id, return_value, elapsed, receiver.response
117
+ return_event.elapsed_instrumentation = (AppMap::Util.gettime() - after_hook_start_time) + call_event.call_elapsed_instrumentation
118
+ call_event.call_elapsed_instrumentation = nil # to stay consistent with elapsed_instrumentation only being stored in return
114
119
  AppMap.tracing.record_event return_event
115
120
  end
116
121
  end
@@ -134,13 +139,16 @@ module AppMap
134
139
  end
135
140
 
136
141
  def before_hook(payload)
142
+ before_hook_start_time = AppMap::Util.gettime()
137
143
  @call_event = HTTPServerRequest.new payload[:request]
144
+ @call_event.call_elapsed_instrumentation = (AppMap::Util.gettime() - before_hook_start_time)
138
145
  AppMap.tracing.record_event @call_event
139
146
  end
140
147
 
141
148
  def after_hook(_name, started, finished, _unique_id, payload)
142
149
  return unless @request_id == payload[:request].request_id
143
150
 
151
+ after_hook_start_time = AppMap::Util.gettime()
144
152
  return_value = Thread.current[TEMPLATE_RENDER_VALUE]
145
153
  Thread.current[TEMPLATE_RENDER_VALUE] = nil
146
154
  return_event = HTTPServerResponse.build_from_invocation(
@@ -149,6 +157,7 @@ module AppMap
149
157
  finished - started,
150
158
  payload[:response] || payload
151
159
  )
160
+ return_event.elapsed_instrumentation = (AppMap::Util.gettime() - after_hook_start_time) + @call_event.call_elapsed_instrumentation
152
161
 
153
162
  AppMap.tracing.record_event return_event
154
163
  ActiveSupport::Notifications.unsubscribe(@subscriber)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'appmap/event'
4
4
  require 'appmap/hook/method'
5
+ require 'appmap/util'
5
6
 
6
7
  module AppMap
7
8
  module Handler
@@ -148,6 +149,8 @@ module AppMap
148
149
  reentry_key = "#{self.class.name}#call"
149
150
  return if Thread.current[reentry_key] == true
150
151
 
152
+ after_start_time = AppMap::Util.gettime()
153
+
151
154
  Thread.current[reentry_key] = true
152
155
  begin
153
156
  sql = payload[:sql].strip
@@ -156,7 +159,9 @@ module AppMap
156
159
 
157
160
  call = SQLCall.new(payload)
158
161
  AppMap.tracing.record_event(call)
159
- AppMap.tracing.record_event(SQLReturn.new(call.id, finished - started))
162
+ sql_return_event = SQLReturn.new(call.id, finished - started)
163
+ sql_return_event.elapsed_instrumentation = AppMap::Util.gettime() - after_start_time
164
+ AppMap.tracing.record_event(sql_return_event)
160
165
  ensure
161
166
  Thread.current[reentry_key] = nil
162
167
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'appmap/util'
4
+
3
5
  def ruby2_keywords(*); end unless respond_to?(:ruby2_keywords, true)
4
6
 
5
7
  module AppMap
@@ -8,15 +10,19 @@ module AppMap
8
10
  # cf. https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html
9
11
  class Method
10
12
  ruby2_keywords def call(receiver, *args, &block)
11
- call_event = trace? && with_disabled_hook { before_hook receiver, *args }
13
+ call_event = false
14
+ if trace?
15
+ call_event, elapsed_before = with_disabled_hook { before_hook receiver, *args }
16
+ end
12
17
  # note we can't short-circuit directly to do_call because then the call stack
13
18
  # depth changes and eval handler doesn't work correctly
14
- trace_call call_event, receiver, *args, &block
19
+ trace_call call_event, elapsed_before, receiver, *args, &block
15
20
  end
16
21
 
17
22
  protected
18
23
 
19
24
  def before_hook(receiver, *args)
25
+ before_hook_start_time = AppMap::Util.gettime()
20
26
  call_event = handle_call(receiver, args)
21
27
  if call_event
22
28
  AppMap.tracing.record_event \
@@ -25,7 +31,7 @@ module AppMap
25
31
  defined_class: defined_class,
26
32
  method: hook_method
27
33
  end
28
- call_event
34
+ [call_event, AppMap::Util.gettime() - before_hook_start_time]
29
35
  end
30
36
 
31
37
  ruby2_keywords def do_call(receiver, *args, &block)
@@ -33,17 +39,18 @@ module AppMap
33
39
  end
34
40
 
35
41
  # rubocop:disable Metrics/MethodLength
36
- ruby2_keywords def trace_call(call_event, receiver, *args, &block)
42
+ ruby2_keywords def trace_call(call_event, elapsed_before, receiver, *args, &block)
37
43
  return do_call(receiver, *args, &block) unless call_event
38
44
 
39
- start_time = gettime
45
+ start_time = AppMap::Util.gettime()
40
46
  begin
41
47
  return_value = do_call(receiver, *args, &block)
42
48
  rescue # rubocop:disable Style/RescueStandardError
43
49
  exception = $ERROR_INFO
44
50
  raise
45
51
  ensure
46
- with_disabled_hook { after_hook receiver, call_event, gettime - start_time, return_value, exception } \
52
+ after_start_time = AppMap::Util.gettime()
53
+ with_disabled_hook { after_hook receiver, call_event, elapsed_before, after_start_time - start_time, after_start_time, return_value, exception } \
47
54
  if call_event
48
55
  end
49
56
  end
@@ -1,19 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'appmap/util'
4
+
3
5
  module AppMap
4
6
  class Hook
5
7
  # Delegation methods for Ruby 3.
6
8
  class Method
7
9
  def call(receiver, *args, **kwargs, &block)
8
- call_event = trace? && with_disabled_hook { before_hook receiver, *args, **kwargs }
10
+ call_event = false
11
+ if trace?
12
+ call_event, elapsed_before = with_disabled_hook { before_hook receiver, *args, **kwargs }
13
+ end
9
14
  # note we can't short-circuit directly to do_call because then the call stack
10
15
  # depth changes and eval handler doesn't work correctly
11
- trace_call call_event, receiver, *args, **kwargs, &block
16
+ trace_call call_event, elapsed_before, receiver, *args, **kwargs, &block
12
17
  end
13
18
 
14
19
  protected
15
20
 
16
21
  def before_hook(receiver, *args, **kwargs)
22
+ before_hook_start_time = AppMap::Util.gettime()
17
23
  args = [*args, kwargs] if !kwargs.empty? || keyrest?
18
24
  call_event = handle_call(receiver, args)
19
25
  if call_event
@@ -23,7 +29,7 @@ module AppMap
23
29
  defined_class: defined_class,
24
30
  method: hook_method
25
31
  end
26
- call_event
32
+ [call_event, AppMap::Util.gettime() - before_hook_start_time]
27
33
  end
28
34
 
29
35
  def keyrest?
@@ -35,17 +41,18 @@ module AppMap
35
41
  end
36
42
 
37
43
  # rubocop:disable Metrics/MethodLength
38
- def trace_call(call_event, receiver, *args, **kwargs, &block)
44
+ def trace_call(call_event, elapsed_before, receiver, *args, **kwargs, &block)
39
45
  return do_call(receiver, *args, **kwargs, &block) unless call_event
40
46
 
41
- start_time = gettime
47
+ start_time = AppMap::Util.gettime()
42
48
  begin
43
49
  return_value = do_call(receiver, *args, **kwargs, &block)
44
50
  rescue # rubocop:disable Style/RescueStandardError
45
51
  exception = $ERROR_INFO
46
52
  raise
47
53
  ensure
48
- with_disabled_hook { after_hook receiver, call_event, gettime - start_time, return_value, exception } \
54
+ after_start_time = AppMap::Util.gettime()
55
+ with_disabled_hook { after_hook receiver, call_event, elapsed_before, after_start_time - start_time, after_start_time, return_value, exception } \
49
56
  if call_event
50
57
  end
51
58
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'appmap/util'
4
+
3
5
  module AppMap
4
6
  class Hook
5
7
  SIGNATURES = {}
@@ -78,10 +80,6 @@ module AppMap
78
80
  warn "#{hook_method.name} not found on #{hook_class}" if Hook::LOG
79
81
  end
80
82
 
81
- def gettime
82
- Process.clock_gettime Process::CLOCK_MONOTONIC
83
- end
84
-
85
83
  def trace?
86
84
  return false unless AppMap.tracing_enabled?
87
85
  return false if Thread.current[HOOK_DISABLE_KEY]
@@ -102,8 +100,9 @@ module AppMap
102
100
  @defined_class ||= Hook.qualify_method_name(hook_method)&.first
103
101
  end
104
102
 
105
- def after_hook(_receiver, call_event, elapsed, return_value, exception)
103
+ def after_hook(_receiver, call_event, elapsed_before, elapsed, after_start_time, return_value, exception)
106
104
  return_event = handle_return(call_event.id, elapsed, return_value, exception)
105
+ return_event.elapsed_instrumentation = elapsed_before + (AppMap::Util.gettime() - after_start_time)
107
106
  AppMap.tracing.record_event(return_event) if return_event
108
107
  end
109
108
 
data/lib/appmap/util.rb CHANGED
@@ -86,6 +86,7 @@ module AppMap
86
86
  def sanitize_event(event, &block)
87
87
  event.delete(:thread_id)
88
88
  event.delete(:elapsed)
89
+ event.delete(:elapsed_instrumentation)
89
90
  delete_object_id = ->(obj) { (obj || {}).delete(:object_id) }
90
91
  delete_object_id.call(event[:receiver])
91
92
  delete_object_id.call(event[:return_value])
@@ -231,6 +232,10 @@ module AppMap
231
232
  def ruby_minor_version
232
233
  @ruby_minor_version ||= RUBY_VERSION.split('.')[0..1].join('.').to_f
233
234
  end
235
+
236
+ def gettime
237
+ Process.clock_gettime Process::CLOCK_MONOTONIC
238
+ end
234
239
  end
235
240
  end
236
241
  end
@@ -3,7 +3,7 @@
3
3
  module AppMap
4
4
  URL = 'https://github.com/applandinc/appmap-ruby'
5
5
 
6
- VERSION = '0.92.1'
6
+ VERSION = '0.93.0'
7
7
 
8
8
  APPMAP_FORMAT_VERSION = '1.9.0'
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.92.1
4
+ version: 0.93.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Gilpin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-21 00:00:00.000000000 Z
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: method_source