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 +4 -4
- data/.github/workflows/main.yml +1 -1
- data/CHANGELOG.md +17 -0
- data/lib/appmap/event.rb +2 -1
- data/lib/appmap/handler/rails/request_handler.rb +10 -1
- data/lib/appmap/handler/rails/sql_handler.rb +8 -2
- data/lib/appmap/hook/method/ruby2.rb +13 -6
- data/lib/appmap/hook/method/ruby3.rb +13 -6
- data/lib/appmap/hook/method.rb +4 -5
- data/lib/appmap/util.rb +5 -0
- data/lib/appmap/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 837bc5a036d3217c12b40f46ed7e21406ef298b3ca5c8b712b8ce1f15707434e
|
4
|
+
data.tar.gz: 763d5c9abd0f8583035117a54c8a6bb0d841089c902ab2e1805ff0795f3acff1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7812c770c07f1e00dc93e0ce4c79598c26daff3fe1d737804dcfc012d29cdefe0754cd3ff06f2810feebe1952cb2038cee2f078d486067188875ec7eb71842de
|
7
|
+
data.tar.gz: 73db38443e22f4a57bf8575035b4735f7fe044f57dd78f6213ac2694434487732778cb0feacb3733c0565080dd859b22dfcf651ec129b70f028a1500a9ff63ea
|
data/.github/workflows/main.yml
CHANGED
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
|
-
|
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 =
|
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
|
-
|
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 =
|
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
|
-
|
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
|
data/lib/appmap/hook/method.rb
CHANGED
@@ -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
|
data/lib/appmap/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|