twirp-on-rails 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 308f1b4a611dd3496ffa026dae81410bffedffb0a2330ef009c4090b2ce71c24
4
- data.tar.gz: dcfba3e14253882f6b7ba0943a89876789fb0d8e68015e397c6143e5417f7d35
3
+ metadata.gz: c7200f05274651a90db8bd46ff410667dce35b41bb49da9a084f7a5c35fd6e1b
4
+ data.tar.gz: d7a993fea396f5449315431cb545f49f0b417ee31aa82b7626d451a65a224985
5
5
  SHA512:
6
- metadata.gz: 140d92258a215e8de86f641a39aeb7cf6e07034ee3c15e9ae187ed9a8f7d1d45d360a7240ecdc0599069dbe63558de7f2ba9ce15ecf7d7c538968bd96f784596
7
- data.tar.gz: 3dcfdf03ddab84f16a8b8a052439b22e982456a7076c2ac54d2580244c16846b17cf70709a72bfa4a0be42743f139624bf338a97ff454d9fba83455be77eef90
6
+ metadata.gz: 4cb878f46022e40efe060ee312954d2bc6432ecd7fffbac2949173e2f13531f4992665fd2e218d7d6b5308740df5e6acd1ed46b7310ed03a1429f435e94c27a0
7
+ data.tar.gz: 6a803bf6af2df2a8594cfcbc0b8844fc02651d1fc78d6241a25bd80ed9885b8cb3c0f63fba11bb1351000caf62f53400fc46f4478cb7713af6963f6c2e3912e0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.3.0] - 2025-01-20
4
+
5
+ - Add some logging.
3
6
 
4
7
  ## [1.2.0] - 2024-10-04
5
8
 
data/Gemfile CHANGED
@@ -9,7 +9,11 @@ gem "rake"
9
9
 
10
10
  gem "debug"
11
11
  gem "rspec-rails"
12
- gem "sqlite3", "~> 1.4"
13
12
  gem "standard", ">= 1.35.1"
14
13
  gem "standard-performance"
15
14
  gem "standard-rails"
15
+
16
+ # These standard library gems need to be here for with certain Rails 7/Ruby 3.4 combinations. Delete eventually.
17
+ gem "mutex_m"
18
+ gem "bigdecimal"
19
+ gem "drb"
data/README.md CHANGED
@@ -151,6 +151,22 @@ As an Engine, we avoid all the standard Rails middleware. That's nice for simpli
151
151
  Rails.application.config.twirp.middleware = [Rack::Deflater]
152
152
  ```
153
153
 
154
+ ### Logging
155
+
156
+ Our built-in logging outputs the result of each request.
157
+
158
+ You could replace our logger if you want different output:
159
+
160
+ ```ruby
161
+ Rails.application.config.twirp.logger = Rack::CommonLogger
162
+ ```
163
+
164
+ Additionally, you can log the full Twirp response object to help with debugging:
165
+
166
+ ```ruby
167
+ Rails.application.config.twirp.verbose_logging = true
168
+ ```
169
+
154
170
  ## Bonus Features
155
171
 
156
172
  Outside the [Twirp spec](https://twitchtv.github.io/twirp/docs/spec_v7.html), we have some (optional) extra magic. They might be useful to you, but you can easily ignore them too.
@@ -170,6 +186,8 @@ Rails.application.config.twirp.middleware = [
170
186
  ]
171
187
  ```
172
188
 
189
+ Note: The Handler will still be run, but you won't need to send back the response. Make sure your RPC is idempotent! Future versions hope to make it easier to short-circuit expensive parts of the handler.
190
+
173
191
  ## TODO
174
192
 
175
193
  * More docs!
@@ -9,6 +9,15 @@ module Twirp
9
9
  # Where to mount twirp routes. Defaults to /twirp
10
10
  attr_accessor :endpoint
11
11
 
12
+ # Logger to use for Twirp requests. Defaults to Rails.logger
13
+ attr_accessor :logger
14
+
15
+ # Whether to log full Twirp responses. Can be useful for debugging, but can expose sensitive data.
16
+ # Defauts to false
17
+ # Example:
18
+ # Twirp Response: <Twirp::Example::Haberdasher::Hat: inches: 24, color: "Tan", name: "Pork Pie">
19
+ attr_accessor :verbose_logging
20
+
12
21
  # An array of directories to search for *_twirp.rb files
13
22
  # Defaults to ["lib"]
14
23
  attr_accessor :load_paths
@@ -25,6 +34,8 @@ module Twirp
25
34
  @auto_mount = false
26
35
  @endpoint = "/twirp"
27
36
  @load_paths = ["lib"]
37
+ @logger = Logger
38
+ @verbose_logging = false
28
39
  @middleware = []
29
40
  @service_hooks = {}
30
41
  end
@@ -26,26 +26,45 @@ module Twirp
26
26
  app.config.twirp.send(key)
27
27
  end
28
28
 
29
+ # Set up logging
30
+ app.config.middleware.use app.config.twirp.logger, ::Rails.logger
29
31
  app.config.twirp.middleware.each do |middleware|
30
32
  app.config.middleware.use middleware
31
33
  end
34
+
35
+ # Load all Twirp files
36
+ app.config.twirp.load_paths.each do |directory|
37
+ ::Rails.root.glob("#{directory}/**/*_twirp.rb").sort.each { |file| require file }
38
+ end
32
39
  end
33
40
  end
34
41
 
35
42
  class << self
36
43
  def services
37
44
  if @services.nil?
38
- ::Rails.application.config.twirp.load_paths.each do |directory|
39
- ::Rails.root.glob("#{directory}/**/*_twirp.rb").sort.each { |file| require file }
40
- end
41
-
42
45
  @services = Twirp::Service.subclasses.map(&:new)
43
46
 
44
47
  # Install hooks that may be defined in the config
45
48
  @services.each do |service|
49
+ # Add user-defined hooks
46
50
  ::Rails.application.config.twirp.service_hooks.each do |hook_name, hook|
47
51
  service.send(hook_name, &hook)
48
52
  end
53
+
54
+ # Add our own logging hooks
55
+ service.on_success do |env|
56
+ if ::Rails.application.config.twirp.verbose_logging
57
+ ::Rails.logger.debug { "Twirp Response: #{env[:output].inspect}" }
58
+ end
59
+ end
60
+
61
+ service.on_error do |error, _env|
62
+ ::Rails.logger.debug { "Twirp Response: #{error.inspect}" }
63
+ end
64
+
65
+ service.exception_raised do |exception, _env|
66
+ ::Rails.logger.error { "Twirp Exception (#{exception.class}: #{exception.message})\n#{exception.backtrace.join("\n")}" }
67
+ end
49
68
  end
50
69
  end
51
70
 
@@ -54,11 +73,3 @@ module Twirp
54
73
  end
55
74
  end
56
75
  end
57
-
58
- class Twirp::Service
59
- # Override inspect to show all available RPCs
60
- # This is used when displaying routes.
61
- def inspect
62
- self.class.rpcs.map { |rpc| "#{self.class.name.demodulize.underscore}_handler##{rpc[1][:ruby_method]}" }.join("\n")
63
- end
64
- end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Twirp
4
+ module Rails
5
+ class Error < StandardError
6
+ end
7
+ end
8
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "rescuable" # Ruby 2.7 fails without this. Remove eventually.
4
+
3
5
  module Twirp
4
6
  module Rails
5
7
  class Handler
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Rack::CommonLogger is nice but we can do better.
4
+ # Rails doesn't use it, but we need to log Twirp requests.
5
+ # Here's an example from Rack::CommonLogger:
6
+ # 127.0.0.1 - - [12/Jan/2025:17:09:49 -0500] "POST /twirp/twirp.example.haberdasher.Haberdasher/MakeHat HTTP/1.0" 200 - 439.0060
7
+ #
8
+ # Rails gives us this:
9
+ # Started POST "/twirp/twirp.example.haberdasher.Haberdasher/MakeHat" for 127.0.0.1 at 2025-01-12 22:48:00 -0500
10
+ # but we also want to know the result of the Twirp call.
11
+ # Here's what this Logger adds:
12
+ # Twirp 200 in 2ms as application/protobuf
13
+ #
14
+
15
+ module Twirp
16
+ module Rails
17
+ class Logger < ::Rack::CommonLogger
18
+ private
19
+
20
+ def log(env, status, response_headers, began_at)
21
+ content_type = response_headers["content-type"].presence
22
+ content_encoding = response_headers["content-encoding"].presence
23
+ @logger.info { "Twirp #{status} in #{duration_in_ms(began_at)}ms#{" as #{content_type}" if content_type}#{" with content-encoding: #{content_encoding}" if content_encoding}" }
24
+ end
25
+
26
+ def duration_in_ms(time)
27
+ ((::Rack::Utils.clock_time - time) * 1000).to_i
28
+ end
29
+ end
30
+ end
31
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Twirp
4
4
  module Rails
5
- VERSION = "1.2.0"
5
+ VERSION = "1.3.0"
6
6
  end
7
7
  end
data/lib/twirp/rails.rb CHANGED
@@ -1,31 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "rails/version"
3
+ require "twirp"
4
+ require "active_support/notifications"
4
5
 
5
- module Twirp
6
- module Rails
7
- class Error < StandardError; end
8
- # Your code goes here...
9
- end
6
+ require "zeitwerk"
7
+ loader = Zeitwerk::Loader.for_gem_extension(Twirp)
8
+ loader.ignore("#{__dir__}/on/rails.rb")
9
+ loader.setup
10
+
11
+ module Twirp::Rails
10
12
  end
11
13
 
12
- require "twirp"
13
- require "active_support/notifications"
14
- require_relative "rails/callbacks"
15
- require_relative "rails/configuration"
16
- require_relative "rails/dispatcher"
17
- require_relative "rails/engine"
18
- require_relative "rails/rescuable"
19
- require_relative "rails/handler"
14
+ loader.eager_load
15
+
16
+ Twirp::Service.class_eval do
17
+ # Override initialize to make handler argument optional.
18
+ # When left nil, we will use our dispatcher.
19
+ alias_method :original_initialize, :initialize
20
+ def initialize(handler = nil)
21
+ handler ||= Twirp::Rails::Dispatcher.new(self.class)
22
+ original_initialize(handler)
23
+ end
20
24
 
21
- module Twirp
22
- class Service
23
- # Override initialize to make handler argument optional.
24
- # When left nil, we will use our dispatcher.
25
- alias_method :original_initialize, :initialize
26
- def initialize(handler = nil)
27
- handler ||= Twirp::Rails::Dispatcher.new(self.class)
28
- original_initialize(handler)
29
- end
25
+ # Override inspect to show all available RPCs
26
+ # This is used when displaying routes.
27
+ def inspect
28
+ self.class.rpcs.map { |rpc| "#{self.class.name.demodulize.underscore}_handler##{rpc[1][:ruby_method]}" }.join("\n")
30
29
  end
31
30
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twirp-on-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Morrison
8
8
  - Darron Schall
9
- autorequire:
10
9
  bindir: exe
11
10
  cert_chain: []
12
- date: 2024-10-04 00:00:00.000000000 Z
11
+ date: 2025-01-20 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rails
@@ -61,7 +60,9 @@ files:
61
60
  - lib/twirp/rails/configuration.rb
62
61
  - lib/twirp/rails/dispatcher.rb
63
62
  - lib/twirp/rails/engine.rb
63
+ - lib/twirp/rails/error.rb
64
64
  - lib/twirp/rails/handler.rb
65
+ - lib/twirp/rails/logger.rb
65
66
  - lib/twirp/rails/rack/conditional_post.rb
66
67
  - lib/twirp/rails/rescuable.rb
67
68
  - lib/twirp/rails/version.rb
@@ -74,7 +75,6 @@ metadata:
74
75
  homepage_uri: https://github.com/collectiveidea/twirp-rails
75
76
  source_code_uri: https://github.com/collectiveidea/twirp-rails
76
77
  changelog_uri: https://github.com/collectiveidea/twirp-rails/blob/main/CHANGELOG.md
77
- post_install_message:
78
78
  rdoc_options: []
79
79
  require_paths:
80
80
  - lib
@@ -89,8 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  requirements: []
92
- rubygems_version: 3.5.16
93
- signing_key:
92
+ rubygems_version: 3.6.2
94
93
  specification_version: 4
95
94
  summary: Use Twirp RPC with Rails
96
95
  test_files: []