dial 0.1.0 → 0.1.2

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: 1c66ebfd5f92223dfdb75e7f13880a293074408ccfbf835eae6b641bed9b8fcc
4
- data.tar.gz: ef11315610241303543d3319ead19364effe60b326ee29f901ece1623331e8f2
3
+ metadata.gz: c1ac4b6e83d9c20da87125b635bb0d9e98d71147d1fa0490606bc7f5431aa171
4
+ data.tar.gz: ad2c423d69ade789af8cb6c52776d1688607a6a97c04215c231f26931a986f0d
5
5
  SHA512:
6
- metadata.gz: 004b0ed1ce0ba338bce6ec32a9c15b634263d6bdac011215a49497923c5f72bd6730d31ea76a6f38ce910efe67e09322d25efdd5e2dd97a6fd91959afe14bdcc
7
- data.tar.gz: a60be22b96db02f9bdcfe3d1a314ef98fa1b1d51af6b2744962156fe191703ad07d1b7fc8242fbefcb8098d4d889302cc7f66a3a6a0775ee6758102f8904c50c
6
+ metadata.gz: 957163d6a4b723704c6956d0056f6f36a67f1ce07415b5e39ae84be396ca58a77cb5fd076ce8dec8471e019e10d7fb516594cb8c9ea5806b7c80f15af8063c17
7
+ data.tar.gz: df6125c631c2948aa24cc03508f951b47bc198c39ecc34d4a1a091eb265c0b6aa572f75d8e6b4883d6856b2bf830ba1bd7617e6e0fb5bacd924c7475876302fd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.2] - 2024-11-10
4
+
5
+ - Add support for request profiling with vernier
6
+
7
+ ## [0.1.1] - 2024-11-08
8
+
9
+ - Set upper bound on dependencies
10
+
3
11
  ## [0.1.0] - 2024-11-08
4
12
 
5
13
  - Initial release
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Dial
2
2
 
3
+ ![Version](https://img.shields.io/gem/v/dial)
4
+ ![Build](https://img.shields.io/github/actions/workflow/status/joshuay03/dial/.github/workflows/main.yml?branch=main)
5
+
3
6
  WIP
4
7
 
5
8
  A modern profiler for Rails applications.
@@ -7,19 +10,24 @@ A modern profiler for Rails applications.
7
10
  <details>
8
11
  <summary>POC</summary>
9
12
 
10
- ![Demo 1](https://github.com/user-attachments/assets/904daaf5-3f18-4c94-a7e4-9418539a19f3)
11
- ![Demo 2](https://github.com/user-attachments/assets/eb6ed9f5-b258-42df-8901-222c7d969fdd)
13
+ ![Snapshot 1](https://github.com/user-attachments/assets/904daaf5-3f18-4c94-a7e4-9418539a19f3)
14
+
15
+ ![Snapshot 2](https://github.com/user-attachments/assets/eb6ed9f5-b258-42df-8901-222c7d969fdd)
16
+
17
+ https://github.com/user-attachments/assets/bae59681-ebeb-42b3-9489-9692c072c3dc
12
18
 
13
19
  </details>
14
20
 
15
21
  ## Installation
16
22
 
17
- Install the gem and add it to your application's Gemfile by executing:
23
+ Install the gem and add it to your Rails application's Gemfile by executing:
18
24
 
19
25
  ```bash
20
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
26
+ bundle add dial
21
27
  ```
22
28
 
29
+ and everything should just work.
30
+
23
31
  ## Development
24
32
 
25
33
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the
data/dial.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "A modern Rails profiler"
12
12
  spec.homepage = "https://github.com/joshuay03/dial"
13
13
  spec.license = "MIT"
14
- spec.required_ruby_version = ">= 3.0.0"
14
+ spec.required_ruby_version = ">= 3.2.1"
15
15
 
16
16
  spec.metadata["source_code_uri"] = spec.homepage
17
17
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
@@ -19,7 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.files = Dir["{lib}/**/*", "**/*.{gemspec,md,txt}"]
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "railties", ">= 7.0.0", "<= 8.0"
23
- spec.add_dependency "activerecord", ">= 7.0.0", "<= 8.0"
24
- spec.add_dependency "actionpack", ">= 7.0.0", "<= 8.0"
22
+ spec.add_dependency "railties", ">= 7", "< 8.2"
23
+ spec.add_dependency "activerecord", ">= 7", "< 8.2"
24
+ spec.add_dependency "actionpack", ">= 7", "< 8.2"
25
+ spec.add_dependency "vernier", "~> 1.3"
25
26
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dial
4
- module Constants
5
- DIAL_REQUEST_TIMING = "dial_request_timing"
6
- end
4
+ REQUEST_TIMING_HEADER = "dial_request_timing"
5
+ PROFILE_OUT_RELATIVE_DIRNAME = "tmp/dial/profile/"
7
6
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dial::Engine.routes.draw do
4
+ scope path: "/dial", as: "dial" do
5
+ get "profile", to: lambda { |env|
6
+ uuid = env[Rack::QUERY_STRING].sub("uuid=", "")
7
+ path = String ::Rails.root.join Dial::PROFILE_OUT_RELATIVE_DIRNAME, "#{uuid}.json"
8
+
9
+ if File.exist? path
10
+ [
11
+ 200,
12
+ { "Content-Type" => "application/json", "Access-Control-Allow-Origin" => "https://vernier.prof" },
13
+ [File.read(path)]
14
+ ]
15
+ else
16
+ [
17
+ 404,
18
+ { "Content-Type" => "text/plain" },
19
+ ["Not Found"]
20
+ ]
21
+ end
22
+ }
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+
5
+ module Dial
6
+ class Engine < ::Rails::Engine
7
+ isolate_namespace Dial
8
+
9
+ paths["config/routes.rb"] = ["lib/dial/engine/routes.rb"]
10
+ end
11
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "vernier"
4
+
3
5
  require_relative "ruby_stat"
4
6
  require_relative "rails_stat"
5
7
  require_relative "constants"
@@ -9,7 +11,6 @@ module Dial
9
11
  class Middleware
10
12
  include RubyStat
11
13
  include RailsStat
12
- include Constants
13
14
 
14
15
  def initialize app
15
16
  @app = app
@@ -22,11 +23,23 @@ module Dial
22
23
  gc_stat_before = GC.stat
23
24
  gc_stat_heap_before = GC.stat_heap
24
25
 
25
- status, headers, rack_body = @app.call env
26
- return [status, headers, rack_body] unless headers[::Rack::CONTENT_TYPE]&.include? "text/html"
26
+ profile_out_dirname = String ::Rails.root.join PROFILE_OUT_RELATIVE_DIRNAME
27
+ FileUtils.mkdir_p profile_out_dirname
28
+ profile_out_filename = "#{SecureRandom.uuid}.json"
29
+ profile_out_pathname = "#{profile_out_dirname}#{profile_out_filename}"
30
+
31
+ status, headers, rack_body = nil
32
+ ::Vernier.profile out: profile_out_pathname do
33
+ status, headers, rack_body = @app.call env
34
+ end
35
+
36
+ unless headers[::Rack::CONTENT_TYPE]&.include? "text/html"
37
+ File.delete profile_out_pathname if File.exist? profile_out_pathname
38
+ return [status, headers, rack_body]
39
+ end
27
40
 
28
41
  finish_time = ::Process.clock_gettime ::Process::CLOCK_MONOTONIC
29
- env[DIAL_REQUEST_TIMING] = ((finish_time - start_time) * 1_000).round 2
42
+ env[REQUEST_TIMING_HEADER] = ((finish_time - start_time) * 1_000).round 2
30
43
 
31
44
  ruby_vm_stat_diff = ruby_vm_stat_diff ruby_vm_stat_before, RubyVM.stat
32
45
  gc_stat_diff = gc_stat_diff gc_stat_before, GC.stat
@@ -37,7 +50,7 @@ module Dial
37
50
  rack_body.each { |chunk| str << chunk }
38
51
  rack_body.close if body.respond_to? :close
39
52
  end.sub "</body>", <<~HTML
40
- #{Panel.html env, ruby_vm_stat_diff, gc_stat_diff, gc_stat_heap_diff, server_timing}
53
+ #{Panel.html env, profile_out_filename, ruby_vm_stat_diff, gc_stat_diff, gc_stat_heap_diff, server_timing}
41
54
  </body>
42
55
  HTML
43
56
 
data/lib/dial/panel.rb CHANGED
@@ -1,19 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  require_relative "constants"
4
6
 
5
7
  module Dial
6
8
  class Panel
7
9
  class << self
8
- include Constants
9
-
10
- def html env, ruby_vm_stat, gc_stat, gc_stat_heap, server_timing
10
+ def html env, profile_out_filename, ruby_vm_stat, gc_stat, gc_stat_heap, server_timing
11
11
  <<~HTML
12
12
  <style>#{style}</style>
13
13
 
14
14
  <div id="dial">
15
15
  <div id="dial-preview">
16
- <span>#{formatted_rails_route_info(env)} | #{formatted_request_timing(env)}</span>
16
+ <span>
17
+ #{formatted_rails_route_info(env)} |
18
+ #{formatted_request_timing(env)} |
19
+ #{formatted_profile_ouput(env, profile_out_filename)}
20
+ </span>
17
21
  <span>#{formatted_rails_version}</span>
18
22
  <span>#{formatted_rack_version}</span>
19
23
  <span>#{formatted_ruby_version}</span>
@@ -135,7 +139,18 @@ module Dial
135
139
  end
136
140
 
137
141
  def formatted_request_timing env
138
- "<b>Request timing:</b> #{env[DIAL_REQUEST_TIMING]}ms"
142
+ "<b>Request timing:</b> #{env[REQUEST_TIMING_HEADER]}ms"
143
+ end
144
+
145
+ def formatted_profile_ouput env, profile_out_filename
146
+ uuid = profile_out_filename.sub ".json", ""
147
+ path = "dial/profile?uuid=#{uuid}"
148
+ host = env[::Rack::HTTP_HOST]
149
+ base_url = ::Rails.application.routes.url_helpers.dial_url host: host
150
+ profile_out_url = CGI.escape base_url + path
151
+ url = "https://vernier.prof/from-url/#{profile_out_url}"
152
+
153
+ "<a href='#{url}' target='_blank'>View profile</a>"
139
154
  end
140
155
 
141
156
  def formatted_rails_version
data/lib/dial/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dial
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/dial.rb CHANGED
@@ -2,3 +2,4 @@
2
2
 
3
3
  require_relative "dial/version"
4
4
  require_relative "dial/railtie"
5
+ require_relative "dial/engine"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dial
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Young
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-11-08 00:00:00.000000000 Z
10
+ date: 2024-11-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: railties
@@ -15,60 +15,74 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 7.0.0
19
- - - "<="
18
+ version: '7'
19
+ - - "<"
20
20
  - !ruby/object:Gem::Version
21
- version: '8.0'
21
+ version: '8.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: 7.0.0
29
- - - "<="
28
+ version: '7'
29
+ - - "<"
30
30
  - !ruby/object:Gem::Version
31
- version: '8.0'
31
+ version: '8.2'
32
32
  - !ruby/object:Gem::Dependency
33
33
  name: activerecord
34
34
  requirement: !ruby/object:Gem::Requirement
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: 7.0.0
39
- - - "<="
38
+ version: '7'
39
+ - - "<"
40
40
  - !ruby/object:Gem::Version
41
- version: '8.0'
41
+ version: '8.2'
42
42
  type: :runtime
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 7.0.0
49
- - - "<="
48
+ version: '7'
49
+ - - "<"
50
50
  - !ruby/object:Gem::Version
51
- version: '8.0'
51
+ version: '8.2'
52
52
  - !ruby/object:Gem::Dependency
53
53
  name: actionpack
54
54
  requirement: !ruby/object:Gem::Requirement
55
55
  requirements:
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
- version: 7.0.0
59
- - - "<="
58
+ version: '7'
59
+ - - "<"
60
60
  - !ruby/object:Gem::Version
61
- version: '8.0'
61
+ version: '8.2'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 7.0.0
69
- - - "<="
68
+ version: '7'
69
+ - - "<"
70
70
  - !ruby/object:Gem::Version
71
- version: '8.0'
71
+ version: '8.2'
72
+ - !ruby/object:Gem::Dependency
73
+ name: vernier
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "~>"
77
+ - !ruby/object:Gem::Version
78
+ version: '1.3'
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '1.3'
72
86
  email:
73
87
  - djry1999@gmail.com
74
88
  executables: []
@@ -82,6 +96,8 @@ files:
82
96
  - dial.gemspec
83
97
  - lib/dial.rb
84
98
  - lib/dial/constants.rb
99
+ - lib/dial/engine.rb
100
+ - lib/dial/engine/routes.rb
85
101
  - lib/dial/middleware.rb
86
102
  - lib/dial/panel.rb
87
103
  - lib/dial/rails_stat.rb
@@ -101,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
117
  requirements:
102
118
  - - ">="
103
119
  - !ruby/object:Gem::Version
104
- version: 3.0.0
120
+ version: 3.2.1
105
121
  required_rubygems_version: !ruby/object:Gem::Requirement
106
122
  requirements:
107
123
  - - ">="