appmap 0.92.0 → 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: 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.