app_profiler 0.2.0 → 0.2.1
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 +4 -4
- data/lib/app_profiler/backend/base_backend.rb +4 -4
- data/lib/app_profiler/backend/stackprof_backend.rb +6 -4
- data/lib/app_profiler/backend/vernier_backend.rb +6 -4
- data/lib/app_profiler/middleware/upload_action.rb +1 -1
- data/lib/app_profiler/middleware.rb +1 -1
- data/lib/app_profiler/profile.rb +18 -12
- data/lib/app_profiler/railtie.rb +1 -0
- data/lib/app_profiler/server.rb +2 -2
- data/lib/app_profiler/storage/base_storage.rb +7 -5
- data/lib/app_profiler/storage/google_cloud_storage.rb +5 -0
- data/lib/app_profiler/version.rb +1 -1
- data/lib/app_profiler/viewer/speedscope_remote_viewer/base_middleware.rb +47 -7
- data/lib/app_profiler/viewer/speedscope_remote_viewer/middleware.rb +2 -2
- data/lib/app_profiler/yarn/command.rb +1 -1
- data/lib/app_profiler.rb +2 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: daf174f3e936f7c9e466d16f75cc866f779944ae781e39501dae6d51cd74da42
|
4
|
+
data.tar.gz: 42871b642bf002450af142941793c41a1bfd76d6b6c6932b45e6cca9c287cb58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf696efe9cfe2582aafd201e30fe6f82aae17f1b137e93a7d2e2b2c34256f4ace88de0d771fc398844c1010999b5c9424f1b2ab0026395ee88b2ad440a88d54a
|
7
|
+
data.tar.gz: eb47ff8a3c0131065400a702d447fb8c170c9d2769860921be61d082ad6affe1ca714bbd211fd2cfe2aec78a89a57bbd32fc76d950d5fa1531feb5b43e29dac9
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module AppProfiler
|
4
4
|
module Backend
|
5
5
|
class BaseBackend
|
6
|
-
def self.name
|
7
|
-
raise NotImplementedError
|
8
|
-
end
|
9
|
-
|
10
6
|
def run(params = {}, &block)
|
11
7
|
raise NotImplementedError
|
12
8
|
end
|
@@ -31,6 +27,10 @@ module AppProfiler
|
|
31
27
|
def run_lock
|
32
28
|
@run_lock ||= Mutex.new
|
33
29
|
end
|
30
|
+
|
31
|
+
def name
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
34
|
end
|
35
35
|
|
36
36
|
protected
|
@@ -16,8 +16,10 @@ module AppProfiler
|
|
16
16
|
:object,
|
17
17
|
].freeze
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
class << self
|
20
|
+
def name
|
21
|
+
:stackprof
|
22
|
+
end
|
21
23
|
end
|
22
24
|
|
23
25
|
def run(params = {})
|
@@ -44,7 +46,7 @@ module AppProfiler
|
|
44
46
|
StackProf.start(**DEFAULTS, **params)
|
45
47
|
rescue => error
|
46
48
|
AppProfiler.logger.info(
|
47
|
-
"[Profiler] failed to start the profiler error_class=#{error.class} error_message=#{error.message}"
|
49
|
+
"[Profiler] failed to start the profiler error_class=#{error.class} error_message=#{error.message}",
|
48
50
|
)
|
49
51
|
release_run_lock
|
50
52
|
# This is a boolean instead of nil because StackProf#start returns a
|
@@ -66,7 +68,7 @@ module AppProfiler
|
|
66
68
|
BaseProfile.from_stackprof(stackprof_profile)
|
67
69
|
rescue => error
|
68
70
|
AppProfiler.logger.info(
|
69
|
-
"[Profiler] failed to obtain the profile error_class=#{error.class} error_message=#{error.message}"
|
71
|
+
"[Profiler] failed to obtain the profile error_class=#{error.class} error_message=#{error.message}",
|
70
72
|
)
|
71
73
|
nil
|
72
74
|
end
|
@@ -15,8 +15,10 @@ module AppProfiler
|
|
15
15
|
:retained,
|
16
16
|
].freeze
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
class << self
|
19
|
+
def name
|
20
|
+
:vernier
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
24
|
def run(params = {})
|
@@ -48,7 +50,7 @@ module AppProfiler
|
|
48
50
|
@collector.start
|
49
51
|
rescue => error
|
50
52
|
AppProfiler.logger.info(
|
51
|
-
"[Profiler] failed to start the profiler error_class=#{error.class} error_message=#{error.message}"
|
53
|
+
"[Profiler] failed to start the profiler error_class=#{error.class} error_message=#{error.message}",
|
52
54
|
)
|
53
55
|
release_run_lock
|
54
56
|
# This is a boolean instead of nil to be consistent with the stackprof backend behaviour
|
@@ -83,7 +85,7 @@ module AppProfiler
|
|
83
85
|
BaseProfile.from_vernier(data)
|
84
86
|
rescue => error
|
85
87
|
AppProfiler.logger.info(
|
86
|
-
"[Profiler] failed to obtain the profile error_class=#{error.class} error_message=#{error.message}"
|
88
|
+
"[Profiler] failed to obtain the profile error_class=#{error.class} error_message=#{error.message}",
|
87
89
|
)
|
88
90
|
nil
|
89
91
|
end
|
@@ -14,7 +14,7 @@ module AppProfiler
|
|
14
14
|
append_headers(
|
15
15
|
response,
|
16
16
|
upload: profile_upload,
|
17
|
-
autoredirect: autoredirect.nil? ? AppProfiler.autoredirect : autoredirect
|
17
|
+
autoredirect: autoredirect.nil? ? AppProfiler.autoredirect : autoredirect,
|
18
18
|
) if response
|
19
19
|
end
|
20
20
|
end
|
data/lib/app_profiler/profile.rb
CHANGED
@@ -15,20 +15,22 @@ module AppProfiler
|
|
15
15
|
|
16
16
|
delegate :[], to: :@data
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
class << self
|
19
|
+
# This function should not be called if `StackProf.results` returns nil.
|
20
|
+
def from_stackprof(data)
|
21
|
+
options = INTERNAL_METADATA_KEYS.map { |key| [key, data[:metadata]&.delete(key)] }.to_h
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
StackprofProfile.new(data, **options).tap do |profile|
|
24
|
+
raise ArgumentError, "invalid profile data" unless profile.valid?
|
25
|
+
end
|
24
26
|
end
|
25
|
-
end
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
def from_vernier(data)
|
29
|
+
options = INTERNAL_METADATA_KEYS.map { |key| [key, data[:meta]&.delete(key)] }.to_h
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
VernierProfile.new(data, **options).tap do |profile|
|
32
|
+
raise ArgumentError, "invalid profile data" unless profile.valid?
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -44,7 +46,7 @@ module AppProfiler
|
|
44
46
|
AppProfiler.storage.upload(self).tap do |upload|
|
45
47
|
if upload && defined?(upload.url)
|
46
48
|
AppProfiler.logger.info(
|
47
|
-
<<~INFO.squish
|
49
|
+
<<~INFO.squish,
|
48
50
|
[Profiler] data uploaded:
|
49
51
|
profile_url=#{upload.url}
|
50
52
|
profile_viewer_url=#{AppProfiler.profile_url(upload)}
|
@@ -54,7 +56,7 @@ module AppProfiler
|
|
54
56
|
end
|
55
57
|
rescue => error
|
56
58
|
AppProfiler.logger.info(
|
57
|
-
"[Profiler] failed to upload profile error_class=#{error.class} error_message=#{error.message}"
|
59
|
+
"[Profiler] failed to upload profile error_class=#{error.class} error_message=#{error.message}",
|
58
60
|
)
|
59
61
|
nil
|
60
62
|
end
|
@@ -78,6 +80,10 @@ module AppProfiler
|
|
78
80
|
@data
|
79
81
|
end
|
80
82
|
|
83
|
+
def metadata
|
84
|
+
@data[:metadata]
|
85
|
+
end
|
86
|
+
|
81
87
|
def mode
|
82
88
|
raise NotImplementedError
|
83
89
|
end
|
data/lib/app_profiler/railtie.rb
CHANGED
@@ -41,6 +41,7 @@ module AppProfiler
|
|
41
41
|
AppProfiler.profile_enqueue_failure = app.config.app_profiler.profile_enqueue_failure
|
42
42
|
AppProfiler.after_process_queue = app.config.app_profiler.after_process_queue
|
43
43
|
AppProfiler.backend = app.config.app_profiler.profiler_backend || :stackprof
|
44
|
+
AppProfiler.forward_metadata_on_upload = app.config.app_profiler.forward_metadata_on_upload || false
|
44
45
|
end
|
45
46
|
|
46
47
|
initializer "app_profiler.add_middleware" do |app|
|
data/lib/app_profiler/server.rb
CHANGED
@@ -280,7 +280,7 @@ module AppProfiler
|
|
280
280
|
@listen_thread = nil
|
281
281
|
|
282
282
|
@logger.info(
|
283
|
-
"[AppProfiler::Server] listening on addr=#{@transport.socket.addr}"
|
283
|
+
"[AppProfiler::Server] listening on addr=#{@transport.socket.addr}",
|
284
284
|
)
|
285
285
|
@pid = Process.pid
|
286
286
|
end
|
@@ -342,7 +342,7 @@ module AppProfiler
|
|
342
342
|
end
|
343
343
|
rescue => e
|
344
344
|
@logger.error(
|
345
|
-
"[AppProfiler::Server] exception #{e} responding to request #{request}: #{e.message}"
|
345
|
+
"[AppProfiler::Server] exception #{e} responding to request #{request}: #{e.message}",
|
346
346
|
)
|
347
347
|
ensure
|
348
348
|
session.close
|
@@ -6,12 +6,14 @@ module AppProfiler
|
|
6
6
|
class_attribute :bucket_name, default: "profiles"
|
7
7
|
class_attribute :credentials, default: {}
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
class << self
|
10
|
+
def upload(_profile)
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
def enqueue_upload(_profile)
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -15,6 +15,10 @@ module AppProfiler
|
|
15
15
|
def upload(profile, _params = {})
|
16
16
|
file = profile.file.open
|
17
17
|
|
18
|
+
metadata = if AppProfiler.forward_metadata_on_upload && profile.metadata.present?
|
19
|
+
profile.metadata
|
20
|
+
end
|
21
|
+
|
18
22
|
ActiveSupport::Notifications.instrument(
|
19
23
|
"gcs_upload.app_profiler",
|
20
24
|
file_size: file.size,
|
@@ -24,6 +28,7 @@ module AppProfiler
|
|
24
28
|
gcs_filename(profile),
|
25
29
|
content_type: "application/json",
|
26
30
|
content_encoding: "gzip",
|
31
|
+
metadata: metadata,
|
27
32
|
)
|
28
33
|
ensure
|
29
34
|
profile.file.unlink
|
data/lib/app_profiler/version.rb
CHANGED
@@ -9,17 +9,57 @@ module AppProfiler
|
|
9
9
|
class BaseMiddleware
|
10
10
|
class Sanitizer < Rails::HTML::Sanitizer.best_supported_vendor.safe_list_sanitizer
|
11
11
|
self.allowed_tags = Set.new([
|
12
|
-
"strong",
|
13
|
-
"
|
14
|
-
"
|
15
|
-
"
|
12
|
+
"strong",
|
13
|
+
"em",
|
14
|
+
"b",
|
15
|
+
"i",
|
16
|
+
"p",
|
17
|
+
"code",
|
18
|
+
"pre",
|
19
|
+
"tt",
|
20
|
+
"samp",
|
21
|
+
"kbd",
|
22
|
+
"var",
|
23
|
+
"sub",
|
24
|
+
"sup",
|
25
|
+
"dfn",
|
26
|
+
"cite",
|
27
|
+
"big",
|
28
|
+
"small",
|
29
|
+
"address",
|
30
|
+
"hr",
|
31
|
+
"br",
|
32
|
+
"div",
|
33
|
+
"span",
|
34
|
+
"h1",
|
35
|
+
"h2",
|
36
|
+
"h3",
|
37
|
+
"h4",
|
38
|
+
"h5",
|
39
|
+
"h6",
|
40
|
+
"ul",
|
41
|
+
"ol",
|
42
|
+
"li",
|
43
|
+
"dl",
|
44
|
+
"dt",
|
45
|
+
"dd",
|
46
|
+
"abbr",
|
47
|
+
"acronym",
|
48
|
+
"a",
|
49
|
+
"img",
|
50
|
+
"blockquote",
|
51
|
+
"del",
|
52
|
+
"ins",
|
53
|
+
"script",
|
16
54
|
])
|
17
55
|
end
|
18
56
|
|
19
57
|
private_constant(:Sanitizer)
|
20
58
|
|
21
|
-
|
22
|
-
file
|
59
|
+
class << self
|
60
|
+
def id(file)
|
61
|
+
file.basename.to_s.delete_suffix(".json")
|
62
|
+
end
|
23
63
|
end
|
24
64
|
|
25
65
|
def initialize(app)
|
@@ -87,7 +127,7 @@ module AppProfiler
|
|
87
127
|
</p>
|
88
128
|
HTML
|
89
129
|
end
|
90
|
-
end
|
130
|
+
end,
|
91
131
|
)
|
92
132
|
end
|
93
133
|
|
@@ -12,7 +12,7 @@ module AppProfiler
|
|
12
12
|
def initialize(app)
|
13
13
|
super
|
14
14
|
@speedscope = Rack::File.new(
|
15
|
-
File.join(AppProfiler.root, "node_modules/speedscope/dist/release")
|
15
|
+
File.join(AppProfiler.root, "node_modules/speedscope/dist/release"),
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
@@ -33,7 +33,7 @@ module AppProfiler
|
|
33
33
|
end || raise(ArgumentError)
|
34
34
|
|
35
35
|
render(
|
36
|
-
<<~HTML
|
36
|
+
<<~HTML,
|
37
37
|
<script type="text/javascript">
|
38
38
|
var graph = #{profile.read};
|
39
39
|
var json = JSON.stringify(graph);
|
data/lib/app_profiler.rb
CHANGED
@@ -61,6 +61,7 @@ module AppProfiler
|
|
61
61
|
mattr_reader :profile_enqueue_success, default: nil
|
62
62
|
mattr_reader :profile_enqueue_failure, default: nil
|
63
63
|
mattr_reader :after_process_queue, default: nil
|
64
|
+
mattr_accessor :forward_metadata_on_upload, default: false
|
64
65
|
|
65
66
|
class << self
|
66
67
|
def run(*args, backend: nil, **kwargs, &block)
|
@@ -70,7 +71,7 @@ module AppProfiler
|
|
70
71
|
profiler.run(*args, **kwargs, &block)
|
71
72
|
rescue BackendError => e
|
72
73
|
logger.error(
|
73
|
-
"[AppProfiler.run] exception #{e} configuring backend #{backend}: #{e.message}"
|
74
|
+
"[AppProfiler.run] exception #{e} configuring backend #{backend}: #{e.message}",
|
74
75
|
)
|
75
76
|
yield
|
76
77
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: app_profiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gannon McGibbon
|
@@ -10,10 +10,10 @@ authors:
|
|
10
10
|
- Jon Simpson
|
11
11
|
- Kevin Jalbert
|
12
12
|
- Scott Francis
|
13
|
-
autorequire:
|
13
|
+
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2024-
|
16
|
+
date: 2024-08-01 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activesupport
|
@@ -127,7 +127,7 @@ dependencies:
|
|
127
127
|
- - ">="
|
128
128
|
- !ruby/object:Gem::Version
|
129
129
|
version: '0'
|
130
|
-
description:
|
130
|
+
description:
|
131
131
|
email:
|
132
132
|
- gems@shopify.com
|
133
133
|
executables: []
|
@@ -165,7 +165,7 @@ homepage: https://github.com/Shopify/app_profiler
|
|
165
165
|
licenses: []
|
166
166
|
metadata:
|
167
167
|
allowed_push_host: https://rubygems.org
|
168
|
-
post_install_message:
|
168
|
+
post_install_message:
|
169
169
|
rdoc_options: []
|
170
170
|
require_paths:
|
171
171
|
- lib
|
@@ -180,8 +180,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
180
|
- !ruby/object:Gem::Version
|
181
181
|
version: '0'
|
182
182
|
requirements: []
|
183
|
-
rubygems_version: 3.5.
|
184
|
-
signing_key:
|
183
|
+
rubygems_version: 3.5.16
|
184
|
+
signing_key:
|
185
185
|
specification_version: 4
|
186
186
|
summary: Collect performance profiles for your Rails application.
|
187
187
|
test_files: []
|