app_profiler 0.6.0 → 0.7.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: eded37ca4bd7b77dcf4bd68a1814eb0900ca1ba7e2cfdb0c5d2490d68f61ba7d
4
- data.tar.gz: e69bf61f50c4d7baf3a8d9b748fb5e295d0901fb7d0d0903d3689e230e5526df
3
+ metadata.gz: 414e73739d0778f252bdb142852ff9a7428a3b76388a5b46108546b91d6a682f
4
+ data.tar.gz: 1d87ba7dbcd9de74c55bbab01f6fcfa9c2882ca887c9384e06d9c8f54237b58b
5
5
  SHA512:
6
- metadata.gz: '098504043e35bf17909c781047ba83eacdff0dffd7115e9f3910d5d3e3664ef58ee726ced428c6f5fb4750b06eb0193755d096f93d41692074e2eeb049e7f23a'
7
- data.tar.gz: 7ea8cbe0cc7d6adfd7b386dae7386f7b08179f112d52e4280cce305e296bb70efe6baab5da983510832b4c511faa3ce9a789a377bd94a9816994c23122cec9ff
6
+ metadata.gz: ccd99ffeb214e7a854bde04fca23191d5cd46ab2b370df07e75e5866a6f0bdbb4af4125cad65774bed7984d228ab4ea90387466075aead7da484dc117b9bb70d
7
+ data.tar.gz: 2629a0e89e29791313b40f25b397cea321f1e27a58d5e42e2c2f18d31577842f94c127d1b2a2d5fa3fc8945539e0f81aa882ac792efb2f7ec8799069f5816cce
@@ -47,6 +47,10 @@ module AppProfiler
47
47
  @run_lock ||= Mutex.new
48
48
  end
49
49
 
50
+ def locked?
51
+ run_lock.locked?
52
+ end
53
+
50
54
  def name
51
55
  raise NotImplementedError
52
56
  end
@@ -24,15 +24,15 @@ module AppProfiler
24
24
  def append_headers(response, upload:, autoredirect:)
25
25
  return unless upload
26
26
 
27
- response[1][profile_header] = AppProfiler.profile_url(upload)
27
+ location = AppProfiler.profile_url(upload)
28
+ response[1][profile_header] = location if location
28
29
  response[1][profile_data_header] = profile_data_url(upload)
29
30
 
30
31
  return unless autoredirect
31
32
 
32
33
  # Automatically redirect to profile if autoredirect is true.
33
- location = AppProfiler.profile_url(upload)
34
34
  if response[0].to_i < 500 && location
35
- response[1]["Location"] = location
35
+ response[1]["location"] = location
36
36
  response[0] = 303
37
37
  end
38
38
  end
@@ -26,7 +26,8 @@ module AppProfiler
26
26
  AppProfiler.server.transport = app.config.app_profiler.server_transport || default_appprofiler_transport
27
27
  AppProfiler.server.port = app.config.app_profiler.server_port || 0
28
28
  AppProfiler.server.duration = app.config.app_profiler.server_duration || 30
29
- AppProfiler.server.cors = app.config.app_profiler.server_cors || true
29
+ server_cors = app.config.app_profiler.server_cors
30
+ AppProfiler.server.cors = server_cors.nil? ? true : server_cors
30
31
  AppProfiler.server.cors_host = app.config.app_profiler.server_cors_host || "*"
31
32
  AppProfiler.autoredirect = app.config.app_profiler.autoredirect || false
32
33
  AppProfiler.speedscope_host = app.config.app_profiler.speedscope_host || ENV.fetch(
@@ -31,9 +31,7 @@ module AppProfiler
31
31
  return false
32
32
  end
33
33
 
34
- return false if backend != AppProfiler::Backend::StackprofBackend.name && !AppProfiler.vernier_supported?
35
-
36
- if AppProfiler.vernier_supported? && backend == AppProfiler::VernierProfile::BACKEND_NAME &&
34
+ if backend == AppProfiler::VernierProfile::BACKEND_NAME &&
37
35
  !AppProfiler::Backend::VernierBackend::AVAILABLE_MODES.include?(mode.to_sym)
38
36
  AppProfiler.logger.info("[AppProfiler] unsupported profiling mode=#{mode} for backend #{backend}")
39
37
  return false
@@ -7,7 +7,7 @@ module AppProfiler
7
7
 
8
8
  class << self
9
9
  def backend_name
10
- # cannot reference Backend::VernierBackend because of different ruby versions we have to support
10
+ # Keep metadata access independent of the optional Vernier gem.
11
11
  BACKEND_NAME.to_s
12
12
  end
13
13
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppProfiler
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -86,7 +86,7 @@ module AppProfiler
86
86
  def render(html)
87
87
  [
88
88
  200,
89
- { "Content-Type" => "text/html" },
89
+ { "content-type" => "text/html" },
90
90
  [
91
91
  +<<~HTML,
92
92
  <!doctype html>
@@ -11,7 +11,7 @@ module AppProfiler
11
11
 
12
12
  def initialize(app)
13
13
  super
14
- @firefox_profiler = Rack::File.new(
14
+ @firefox_profiler = Rack::Files.new(
15
15
  File.join(AppProfiler.root, "node_modules/firefox-profiler/dist"),
16
16
  )
17
17
  end
@@ -40,9 +40,9 @@ module AppProfiler
40
40
  source = "#{proto}://#{host}/app_profiler/firefox/#{path}"
41
41
  target = "/from-url/#{CGI.escape(source)}"
42
42
 
43
- [302, { "Location" => target }, [""]]
43
+ [302, { "location" => target }, [""]]
44
44
  else
45
- env[Rack::PATH_INFO] = path.delete_prefix("/app_profiler")
45
+ env[Rack::PATH_INFO] = "/#{path.delete_prefix("/")}"
46
46
  firefox_profiler.call(env)
47
47
  end
48
48
  end
@@ -50,7 +50,7 @@ module AppProfiler
50
50
  def from(env, path)
51
51
  setup_yarn unless yarn_setup
52
52
  index = File.read(File.join(AppProfiler.root, "node_modules/firefox-profiler/dist/index.html"))
53
- [200, { "Content-Type" => "text/html" }, [index]]
53
+ [200, { "content-type" => "text/html" }, [index]]
54
54
  end
55
55
 
56
56
  def show(_env, name)
@@ -58,7 +58,7 @@ module AppProfiler
58
58
  id(file) == name
59
59
  end || raise(ArgumentError)
60
60
 
61
- [200, { "Content-Type" => "application/json" }, [profile.read]]
61
+ [200, { "content-type" => "application/json" }, [profile.read]]
62
62
  end
63
63
  end
64
64
  end
@@ -22,7 +22,7 @@ module AppProfiler
22
22
  id = Middleware.id(@profile.file)
23
23
 
24
24
  if response && response[0].to_i < 500
25
- response[1]["Location"] = "/app_profiler/#{NAME}/viewer/#{id}"
25
+ response[1]["location"] = "/app_profiler/#{NAME}/viewer/#{id}"
26
26
  response[0] = 303
27
27
  else
28
28
  AppProfiler.logger.info("[Profiler] Profile available at /app_profiler/#{id}\n")
@@ -11,7 +11,7 @@ module AppProfiler
11
11
 
12
12
  def initialize(app)
13
13
  super
14
- @speedscope = Rack::File.new(
14
+ @speedscope = Rack::Files.new(
15
15
  File.join(AppProfiler.root, "node_modules/speedscope/dist/release"),
16
16
  )
17
17
  end
@@ -32,7 +32,7 @@ module AppProfiler
32
32
  def viewer(env, path)
33
33
  setup_yarn unless yarn_setup
34
34
 
35
- env[Rack::PATH_INFO] = path.delete_prefix("/app_profiler/speedscope")
35
+ env[Rack::PATH_INFO] = "/#{path.delete_prefix("/")}"
36
36
  speedscope.call(env)
37
37
  end
38
38
 
@@ -41,7 +41,7 @@ module AppProfiler
41
41
  id(file) == name
42
42
  end || raise(ArgumentError)
43
43
 
44
- [200, { "Content-Type" => "application/json" }, [profile.read]]
44
+ [200, { "content-type" => "application/json" }, [profile.read]]
45
45
  end
46
46
  end
47
47
  end
@@ -29,7 +29,7 @@ module AppProfiler
29
29
  id = Middleware.id(@profile.file)
30
30
 
31
31
  if response && response[0].to_i < 500
32
- response[1]["Location"] = "/app_profiler/#{NAME}/viewer/#{id}"
32
+ response[1]["location"] = "/app_profiler/#{NAME}/viewer/#{id}"
33
33
  response[0] = 303
34
34
  else
35
35
  AppProfiler.logger.info("[Profiler] Profile available at /app_profiler/#{id}\n")
@@ -42,7 +42,7 @@ module AppProfiler
42
42
  package_json = JSON.parse(package_contents)
43
43
  package_json["name"] ||= "firefox-profiler"
44
44
  package_json["version"] ||= "0.0.1"
45
- File.write("firefox-profiler/package.json", package_json.to_json)
45
+ File.write("firefox-profiler/package.json", JSON.generate(package_json))
46
46
  end
47
47
  yarn("--cwd", "#{dir}/firefox-profiler")
48
48
 
data/lib/app_profiler.rb CHANGED
@@ -58,8 +58,8 @@ module AppProfiler
58
58
 
59
59
  mattr_accessor :speedscope_host, default: "https://speedscope.app"
60
60
  mattr_accessor :autoredirect, default: false
61
- mattr_reader :profile_header, default: "X-Profile"
62
- mattr_accessor :profile_async_header, default: "X-Profile-Async"
61
+ mattr_reader :profile_header, default: "x-profile"
62
+ mattr_reader :profile_async_header, default: "x-profile-async"
63
63
  mattr_accessor :profile_param, default: "profile"
64
64
  mattr_accessor :context, default: nil
65
65
  mattr_reader :profile_url_formatter, default: DefaultProfileFormatter
@@ -92,14 +92,9 @@ module AppProfiler
92
92
  end
93
93
  profiler.run(*args, **kwargs, &block)
94
94
  rescue BackendError => e
95
- if ActiveSupport.respond_to?(:error_reporter)
96
- ActiveSupport.error_reporter.report(e, context: { app_profiler: { backend: backend } })
97
- else
98
- logger.error(
99
- "[AppProfiler.run] exception #{e} configuring backend #{backend}: #{e.message}",
100
- )
101
- end
95
+ ActiveSupport.error_reporter.report(e, context: { app_profiler: { backend: backend } })
102
96
  yield
97
+ nil # no profile result
103
98
  ensure
104
99
  self.backend = original_backend if backend
105
100
  ProfileId::Current.reset
@@ -126,7 +121,7 @@ module AppProfiler
126
121
  def backend=(new_backend)
127
122
  return if (new_profiler_backend = backend_for(new_backend)) == profiler_backend
128
123
 
129
- if running?
124
+ if profiler_backend.locked?
130
125
  raise BackendError,
131
126
  "cannot change backend to #{new_backend} while #{backend} backend is running"
132
127
  end
@@ -165,13 +160,7 @@ module AppProfiler
165
160
 
166
161
  @profile_sampler_enabled.is_a?(Proc) ? @profile_sampler_enabled.call : @profile_sampler_enabled
167
162
  rescue => e
168
- if ActiveSupport.respond_to?(:error_reporter)
169
- ActiveSupport.error_reporter.report(e)
170
- else
171
- logger.error(
172
- "[AppProfiler.profile_sampler_enabled] exception: #{e}, message: #{e.message}",
173
- )
174
- end
163
+ ActiveSupport.error_reporter.report(e)
175
164
  false
176
165
  end
177
166
 
@@ -185,8 +174,7 @@ module AppProfiler
185
174
  end
186
175
 
187
176
  def backend_for(backend_name)
188
- if vernier_supported? &&
189
- backend_name&.to_sym == AppProfiler::VernierProfile::BACKEND_NAME
177
+ if backend_name&.to_sym == AppProfiler::VernierProfile::BACKEND_NAME
190
178
  AppProfiler::Backend::VernierBackend
191
179
  elsif backend_name&.to_sym == AppProfiler::Backend::StackprofBackend.name
192
180
  AppProfiler::Backend::StackprofBackend
@@ -199,22 +187,22 @@ module AppProfiler
199
187
  profiler_backend.name
200
188
  end
201
189
 
202
- def vernier_supported?
203
- RUBY_VERSION >= "3.2.1" && defined?(AppProfiler::VernierProfile::BACKEND_NAME)
204
- end
205
-
206
190
  def profile_header=(profile_header)
207
- @@profile_header = profile_header # rubocop:disable Style/ClassVars
191
+ @@profile_header = profile_header.downcase # rubocop:disable Style/ClassVars
208
192
  @@request_profile_header = nil # rubocop:disable Style/ClassVars
209
193
  @@profile_data_header = nil # rubocop:disable Style/ClassVars
210
194
  end
211
195
 
196
+ def profile_async_header=(profile_async_header)
197
+ @@profile_async_header = profile_async_header.downcase # rubocop:disable Style/ClassVars
198
+ end
199
+
212
200
  def request_profile_header
213
201
  @@request_profile_header ||= profile_header.upcase.tr("-", "_").prepend("HTTP_") # rubocop:disable Style/ClassVars
214
202
  end
215
203
 
216
204
  def profile_data_header
217
- @@profile_data_header ||= profile_header.dup << "-Data" # rubocop:disable Style/ClassVars
205
+ @@profile_data_header ||= profile_header.dup << "-data" # rubocop:disable Style/ClassVars
218
206
  end
219
207
 
220
208
  def profile_url_formatter=(block)
@@ -268,7 +256,7 @@ module AppProfiler
268
256
  end
269
257
 
270
258
  def clear
271
- profiler.stop if running?
259
+ profiler.stop if profiler_backend.locked?
272
260
  @profiler = nil
273
261
  @profiler_backend = nil
274
262
  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.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gannon McGibbon
@@ -20,14 +20,14 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: '5.2'
23
+ version: '7.2'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
28
  - - ">="
29
29
  - !ruby/object:Gem::Version
30
- version: '5.2'
30
+ version: '7.2'
31
31
  - !ruby/object:Gem::Dependency
32
32
  name: base64
33
33
  requirement: !ruby/object:Gem::Requirement
@@ -116,16 +116,16 @@ dependencies:
116
116
  name: minitest
117
117
  requirement: !ruby/object:Gem::Requirement
118
118
  requirements:
119
- - - ">="
119
+ - - "<"
120
120
  - !ruby/object:Gem::Version
121
- version: '0'
121
+ version: '6'
122
122
  type: :development
123
123
  prerelease: false
124
124
  version_requirements: !ruby/object:Gem::Requirement
125
125
  requirements:
126
- - - ">="
126
+ - - "<"
127
127
  - !ruby/object:Gem::Version
128
- version: '0'
128
+ version: '6'
129
129
  - !ruby/object:Gem::Dependency
130
130
  name: minitest-stub-const
131
131
  requirement: !ruby/object:Gem::Requirement
@@ -236,14 +236,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
236
236
  requirements:
237
237
  - - ">="
238
238
  - !ruby/object:Gem::Version
239
- version: 3.2.1
239
+ version: '3.3'
240
240
  required_rubygems_version: !ruby/object:Gem::Requirement
241
241
  requirements:
242
242
  - - ">="
243
243
  - !ruby/object:Gem::Version
244
244
  version: '0'
245
245
  requirements: []
246
- rubygems_version: 4.0.10
246
+ rubygems_version: 4.0.21
247
247
  specification_version: 4
248
248
  summary: Collect performance profiles for your Rails application.
249
249
  test_files: []