appmap 0.92.0 → 0.93.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78d8c3cf7967b06242390e3d11ddd24c5cf29fd70244b93b2bf170323747b762
4
- data.tar.gz: 10147c54915b55d8a67723d1721c31a9e809983bb9b0012cdb2f480e9dcf3695
3
+ metadata.gz: 837bc5a036d3217c12b40f46ed7e21406ef298b3ca5c8b712b8ce1f15707434e
4
+ data.tar.gz: 763d5c9abd0f8583035117a54c8a6bb0d841089c902ab2e1805ff0795f3acff1
5
5
  SHA512:
6
- metadata.gz: 7ce433191ab8e3699feeb995951df0653ef9b89bb11edc7ca671b80011a2af1818e08c22eaa4f0777ec364be9e6e9d8bfec84099ff518d43768fb710e005b681
7
- data.tar.gz: f0c99190697605e71658d9c3c602913954604396c7fb3cc31db09edb1b4cb8bdd1fb4f184e762ff15458b64e5078cd69ac04c324eddd0b4d83e28e3c2b324bb0
6
+ metadata.gz: 7812c770c07f1e00dc93e0ce4c79598c26daff3fe1d737804dcfc012d29cdefe0754cd3ff06f2810feebe1952cb2038cee2f078d486067188875ec7eb71842de
7
+ data.tar.gz: 73db38443e22f4a57bf8575035b4735f7fe044f57dd78f6213ac2694434487732778cb0feacb3733c0565080dd859b22dfcf651ec129b70f028a1500a9ff63ea
@@ -12,5 +12,5 @@ jobs:
12
12
  steps:
13
13
  - uses: actions/add-to-project@main
14
14
  with:
15
- project-url: https://github.com/orgs/applandinc/projects/15
15
+ project-url: https://github.com/orgs/getappmap/projects/15
16
16
  github-token: ${{ secrets.ADD_TO_PROJECT_BOARD_PAT }}
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
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
+
11
+ ## [0.92.1](https://github.com/getappmap/appmap-ruby/compare/v0.92.0...v0.92.1) (2022-09-21)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * Drop database server version ([e52f210](https://github.com/getappmap/appmap-ruby/commit/e52f210baa26be49232003c224e4ffee19be823d))
17
+
1
18
  # [0.92.0](https://github.com/applandinc/appmap-ruby/compare/v0.91.0...v0.92.0) (2022-09-19)
2
19
 
3
20
 
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
@@ -75,7 +76,6 @@ module AppMap
75
76
  end
76
77
  end
77
78
 
78
- payload[:server_version] = examiner.server_version
79
79
  payload[:database_type] = examiner.database_type.to_s
80
80
  end
81
81
 
@@ -92,6 +92,8 @@ module AppMap
92
92
 
93
93
  class SequelExaminer
94
94
  def server_version
95
+ # Queries the database, therefore this is pretty unsafe to do inside of a hook.
96
+ # As a result, this is not being used at the moment.
95
97
  Sequel::Model.db.server_version
96
98
  end
97
99
 
@@ -147,6 +149,8 @@ module AppMap
147
149
  reentry_key = "#{self.class.name}#call"
148
150
  return if Thread.current[reentry_key] == true
149
151
 
152
+ after_start_time = AppMap::Util.gettime()
153
+
150
154
  Thread.current[reentry_key] = true
151
155
  begin
152
156
  sql = payload[:sql].strip
@@ -155,7 +159,9 @@ module AppMap
155
159
 
156
160
  call = SQLCall.new(payload)
157
161
  AppMap.tracing.record_event(call)
158
- 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)
159
165
  ensure
160
166
  Thread.current[reentry_key] = nil
161
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.0'
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.0
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-19 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
@@ -455,7 +455,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
455
455
  - !ruby/object:Gem::Version
456
456
  version: '0'
457
457
  requirements: []
458
- rubygems_version: 3.0.6
458
+ rubygems_version: 3.1.6
459
459
  signing_key:
460
460
  specification_version: 4
461
461
  summary: Record the operation of a Ruby program, using the AppLand 'AppMap' format.