rails-profiler 0.11.0 → 0.11.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/profiler/configuration.rb +15 -0
- data/lib/profiler/mcp/body_formatter.rb +12 -1
- data/lib/profiler/mcp/file_cache.rb +7 -4
- data/lib/profiler/models/profile.rb +17 -4
- data/lib/profiler/railtie.rb +1 -3
- data/lib/profiler/storage/file_store.rb +1 -5
- data/lib/profiler/storage/sqlite_store.rb +2 -10
- data/lib/profiler/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5895b7dd1e9141516af0f2a710c2eac52a458d6dcc6e7e8c0847577bb7dd1429
|
|
4
|
+
data.tar.gz: fd4c1d48bee719dff9a14b658389a2e0cad306a274cae92db4cf2ed0c4ddb11d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aea2caa0bde982cca5fc88a4fe7045b4600e0b293442477e105300514480a113ba8a93a10f568ee74ec2f21534c8c4e283dd70558392024a12f1219e38b31a72
|
|
7
|
+
data.tar.gz: 2a88a395c11f73907e383fd7b836f4f6c77974aed00c254fe3b586b77d81b7ab15c166641518642f91c39c7356c76d6111ab45bbd89eade95c05ed558c3e9077
|
|
@@ -13,6 +13,8 @@ module Profiler
|
|
|
13
13
|
:track_jobs,
|
|
14
14
|
:compress_bodies, :compress_body_threshold
|
|
15
15
|
|
|
16
|
+
attr_writer :tmp_path
|
|
17
|
+
|
|
16
18
|
attr_reader :authorize_block
|
|
17
19
|
|
|
18
20
|
def initialize
|
|
@@ -41,6 +43,11 @@ module Profiler
|
|
|
41
43
|
@track_jobs = true
|
|
42
44
|
@compress_bodies = true
|
|
43
45
|
@compress_body_threshold = 10 * 1024 # 10 KB
|
|
46
|
+
@tmp_path = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def tmp_path
|
|
50
|
+
@tmp_path || default_tmp_path
|
|
44
51
|
end
|
|
45
52
|
|
|
46
53
|
def authorize_with(&block)
|
|
@@ -64,6 +71,14 @@ module Profiler
|
|
|
64
71
|
|
|
65
72
|
private
|
|
66
73
|
|
|
74
|
+
def default_tmp_path
|
|
75
|
+
if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
|
|
76
|
+
Rails.root.join("tmp", "rails-profiler")
|
|
77
|
+
else
|
|
78
|
+
File.expand_path("tmp/rails-profiler", Dir.pwd)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
67
82
|
def build_storage_backend
|
|
68
83
|
case @storage
|
|
69
84
|
when :memory
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "base64"
|
|
4
|
+
require "zlib"
|
|
5
|
+
|
|
3
6
|
module Profiler
|
|
4
7
|
module MCP
|
|
5
8
|
module BodyFormatter
|
|
6
9
|
# Formats a body string for MCP output.
|
|
7
10
|
#
|
|
8
11
|
# params keys used:
|
|
9
|
-
# "save_bodies" (boolean) — save to
|
|
12
|
+
# "save_bodies" (boolean) — save to ./tmp/rails-profiler/{token}/{name} and return path
|
|
10
13
|
# "max_body_size" (number) — truncate inline body at N chars
|
|
11
14
|
# "json_path" (string) — JSONPath to extract from body when save_bodies is true
|
|
12
15
|
# "xml_path" (string) — XPath to extract from body when save_bodies is true
|
|
@@ -16,6 +19,14 @@ module Profiler
|
|
|
16
19
|
return " *(binary, base64 encoded)*" if encoding == "base64"
|
|
17
20
|
return nil if body.nil? || body.empty?
|
|
18
21
|
|
|
22
|
+
if encoding == "gzip+base64"
|
|
23
|
+
begin
|
|
24
|
+
body = Zlib::Inflate.inflate(Base64.strict_decode64(body))
|
|
25
|
+
rescue Zlib::Error, ArgumentError
|
|
26
|
+
# fall through with original body
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
19
30
|
if params["save_bodies"]
|
|
20
31
|
path = FileCache.save(token, name, body)
|
|
21
32
|
if path
|
|
@@ -5,12 +5,14 @@ require "fileutils"
|
|
|
5
5
|
module Profiler
|
|
6
6
|
module MCP
|
|
7
7
|
class FileCache
|
|
8
|
-
|
|
8
|
+
def self.base_dir
|
|
9
|
+
Profiler.configuration.tmp_path.to_s
|
|
10
|
+
end
|
|
9
11
|
|
|
10
12
|
def self.save(token, name, content)
|
|
11
13
|
cleanup if rand < 0.05
|
|
12
14
|
|
|
13
|
-
dir = File.join(
|
|
15
|
+
dir = File.join(base_dir, token)
|
|
14
16
|
FileUtils.mkdir_p(dir)
|
|
15
17
|
path = File.join(dir, name)
|
|
16
18
|
File.write(path, content)
|
|
@@ -20,9 +22,10 @@ module Profiler
|
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
def self.cleanup(max_age: 3600)
|
|
23
|
-
|
|
25
|
+
bd = base_dir
|
|
26
|
+
return unless Dir.exist?(bd)
|
|
24
27
|
|
|
25
|
-
Dir.glob(File.join(
|
|
28
|
+
Dir.glob(File.join(bd, "*")).each do |dir|
|
|
26
29
|
FileUtils.rm_rf(dir) if File.directory?(dir) && (Time.now - File.mtime(dir)) > max_age
|
|
27
30
|
end
|
|
28
31
|
end
|
|
@@ -74,6 +74,9 @@ module Profiler
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def to_h
|
|
77
|
+
req_body, req_enc = decode_body(@request_body, @request_body_encoding)
|
|
78
|
+
resp_body, resp_enc = decode_body(@response_body, @response_body_encoding)
|
|
79
|
+
|
|
77
80
|
{
|
|
78
81
|
profile_type: @profile_type,
|
|
79
82
|
token: @token,
|
|
@@ -87,10 +90,10 @@ module Profiler
|
|
|
87
90
|
params: @params,
|
|
88
91
|
headers: @headers,
|
|
89
92
|
response_headers: @response_headers,
|
|
90
|
-
request_body:
|
|
91
|
-
request_body_encoding:
|
|
92
|
-
response_body:
|
|
93
|
-
response_body_encoding:
|
|
93
|
+
request_body: req_body,
|
|
94
|
+
request_body_encoding: req_enc,
|
|
95
|
+
response_body: resp_body,
|
|
96
|
+
response_body_encoding: resp_enc,
|
|
94
97
|
collectors_data: @collectors_data,
|
|
95
98
|
tabs: @collectors_metadata,
|
|
96
99
|
parent_token: @parent_token,
|
|
@@ -173,6 +176,16 @@ module Profiler
|
|
|
173
176
|
text.bytesize > Profiler.configuration.compress_body_threshold
|
|
174
177
|
end
|
|
175
178
|
|
|
179
|
+
def decode_body(body, encoding)
|
|
180
|
+
return [body, encoding] unless encoding == "gzip+base64"
|
|
181
|
+
return [body, encoding] if body.nil? || body.empty?
|
|
182
|
+
|
|
183
|
+
decoded = Zlib::Inflate.inflate(Base64.strict_decode64(body))
|
|
184
|
+
[decoded, "text"]
|
|
185
|
+
rescue Zlib::Error, ArgumentError
|
|
186
|
+
[body, encoding]
|
|
187
|
+
end
|
|
188
|
+
|
|
176
189
|
def binary_content_type?(ct)
|
|
177
190
|
ct.to_s.match?(%r{image/(?!svg)|application/(?:pdf|octet-stream|zip)|audio/|video/})
|
|
178
191
|
end
|
data/lib/profiler/railtie.rb
CHANGED
|
@@ -11,9 +11,7 @@ module Profiler
|
|
|
11
11
|
Profiler.configure do |config|
|
|
12
12
|
config.enabled = Rails.env.development? || Rails.env.test?
|
|
13
13
|
config.storage = Rails.env.development? ? :file : :memory
|
|
14
|
-
config.
|
|
15
|
-
path: Rails.root.join("tmp", "profiler")
|
|
16
|
-
}
|
|
14
|
+
config.tmp_path = Rails.root.join("tmp", "rails-profiler")
|
|
17
15
|
end
|
|
18
16
|
end
|
|
19
17
|
|
|
@@ -253,19 +253,11 @@ module Profiler
|
|
|
253
253
|
end
|
|
254
254
|
|
|
255
255
|
def default_db_path
|
|
256
|
-
|
|
257
|
-
Rails.root.join("tmp", "profiler", "profiler.db")
|
|
258
|
-
else
|
|
259
|
-
File.expand_path("tmp/profiler/profiler.db", Dir.pwd)
|
|
260
|
-
end
|
|
256
|
+
File.join(Profiler.configuration.tmp_path.to_s, "profiler.db")
|
|
261
257
|
end
|
|
262
258
|
|
|
263
259
|
def default_blob_path
|
|
264
|
-
|
|
265
|
-
Rails.root.join("tmp", "profiler", "blobs")
|
|
266
|
-
else
|
|
267
|
-
File.expand_path("tmp/profiler/blobs", Dir.pwd)
|
|
268
|
-
end
|
|
260
|
+
File.join(Profiler.configuration.tmp_path.to_s, "blobs")
|
|
269
261
|
end
|
|
270
262
|
end
|
|
271
263
|
end
|
data/lib/profiler/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-profiler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.11.
|
|
4
|
+
version: 0.11.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sébastien Duplessy
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|