rollday 0.1.0 → 0.5.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: ad34763ae84ecaefbd8febab644f790d10a0cd18fe0cd425004e8c8b6464c10b
4
- data.tar.gz: 64474e52fb56a31a4cff7e4b11736d75163783b543bea30a6ca64b8054a5b366
3
+ metadata.gz: 02476ca50a8cb131cd458cffe10428026cee831d1c6ec555cc605541ebc20d9c
4
+ data.tar.gz: e4e0c9c14d3f02ea831fe77efe9a4142291c995d955200dd00085a136e6deba6
5
5
  SHA512:
6
- metadata.gz: fbb72f7c5446af3d674925b453bc92c978fc9db212a5ee36e905bc8775da81df6d91a477128f0cc0c0b0033f0a150ed58e017e5dd49b2af099502381d80bc57c
7
- data.tar.gz: 53b16030723f41849ec4271d55d5073b7dea6cb36b3e178b28dd24e8247abb5feb64f71385dce67b4b0d099d3fb7a3097f9d8cdbbc77722bd186509d1d2d65cd
6
+ metadata.gz: 9fc90d8d766d8687322349b6fae4bf8dc12fa7f0f1b40b81476b90a15c1980737879f92947b431d064c6e24f9da3a0cfae91c08340dbeefff4ceddda0463075a
7
+ data.tar.gz: 443ca20fde67b2447dc734c9bd3fba8b37f6373b35149cc52d5e824fc4432a59c2964cd0bd8d18e74171be934b875a85aa9a86033843404c14fd1499230508f5
data/CHANGELOG.md CHANGED
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [0.1.0] - YYYY-MM-DD
10
+ ## [0.2.0] - 2022-06-18
11
11
 
12
12
  ### Added
13
13
  - New feature 1
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rollday (0.1.0)
4
+ rollday (0.5.0)
5
+ class_composer
5
6
  faraday
6
7
  rollbar
7
8
 
@@ -9,6 +10,7 @@ GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
11
12
  byebug (11.1.3)
13
+ class_composer (1.0.0)
12
14
  coderay (1.1.3)
13
15
  concurrent-ruby (1.1.10)
14
16
  diff-lcs (1.5.0)
data/README.md CHANGED
@@ -1,11 +1,9 @@
1
1
  # Rollday
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be
4
- able to package up your Ruby library into a gem. Put your Ruby code in the file
5
- `lib/rollday`. To experiment with that code, run
6
- `bin/console` for an interactive prompt.
3
+ Rollday is a a gem to integrate with Faraday requests. It adds a default middleware for your projecrts Faraday client to send a rollbar for configurable response status codes.
4
+
5
+ It can be configured once for th eentire project, or customized per Faraday request
7
6
 
8
- TODO: Delete this and the text above, and describe your gem
9
7
 
10
8
  ## Installation
11
9
 
@@ -15,17 +13,95 @@ Add this line to your application's Gemfile:
15
13
  gem 'rollday'
16
14
  ```
17
15
 
18
- And then execute:
16
+ ## Usage
19
17
 
20
- $ bundle install
18
+ ### Initialization
21
19
 
22
- Or install it yourself as:
20
+ Intialization should happen in `app/initializers/rollday.rb`. All options below are the current defaults unless stated
21
+ ```ruby
22
+ Rollday.configure do |config|
23
+ config.use_default_middleware! # [Not default option] set middleware for all Faraday requests (Faraday.get(...)). Caution when used with Default Client Middleware
23
24
 
24
- $ gem install rollday
25
+ config.use_default_client_middleware! # [Not default option] set middleware for all Faraday instances. Caution when used with Default Middleware
25
26
 
26
- ## Usage
27
+ config.status_code_regex = /[45]\d\d$/ # If status code matches, will attempt to send a rollbar
28
+
29
+ config.use_person_scope = true # Assign a person scope to the rollbar scope
30
+
31
+ config.use_params_scope = true # Assign a params scope to the rollbar scope. Configured from Faraday params for request
32
+
33
+ config.params_scope_sanitizer = [] # Array of Procs to sanitize params. Can remove params or call Rollbar::Scrubbers.scrub_value(*) to assign value
34
+
35
+ config.use_query_scope = true # Assign the url queries to the scope
36
+
37
+ config.params_query_sanitizer = [] # Array of Procs to sanitize query params. Can remove params or call Rollbar::Scrubbers.scrub_value(*) to assign value
38
+
39
+ config.message = ->(status, phrase, body, path, domain) { "[#{status}]: #{domain} - #{path}" } # Message to set for the Rollbar item. Value can be a proc or a static message
40
+
41
+ config.use_message_exception = true # When set to true, Exception will be used to establish a backtrace
42
+
43
+ config.rollbar_level = ->(_status) { :warning } # Rollbar level can be configurable based on the status code
44
+ end
45
+ ```
46
+
47
+ ### Ex: Default Faraday Client
27
48
 
28
- TODO: Write usage instructions here
49
+ ```ruby
50
+ # Rollday initializer
51
+ Rollday.configure do |config|
52
+ config.use_default_middleware!
53
+ config.status_code_regex = /[2345]\d\d$/
54
+ config.message = -> (s, phrase, b, path, domain) { "[#{domain}] via #{path} returned #{status}" }
55
+ end
56
+
57
+ Farady.get("http://httpstat.us/207") # => 200 status code returned
58
+ # Will send a rollbar because Status code matches regex
59
+ ```
60
+
61
+ ### Ex: Default Faraday Instance
62
+
63
+ ```ruby
64
+ # Rollday initializer
65
+ Rollday.configure do |config|
66
+ config.use_default_client_middleware!
67
+ config.message = -> (s, phrase, b, path, domain) { "[#{domain}] via #{path} returned #{status} using default client middleware" }
68
+ end
69
+ Farady.get("http://httpstat.us/500") # => 500 status code returned
70
+ # Rollbar will not get sent because `use_default_middleware!` is not set
71
+
72
+ client = Faraday.new(url: base_url)
73
+ client.get("404") # => 404 status code returned
74
+ # Will send a rollbar because Status code matches regex
75
+ ```
76
+
77
+ ### Ex: Custom Faraday Instance
78
+
79
+ ```ruby
80
+ # Rollday initializer
81
+ Rollday.configure do |config|
82
+ config.status_code_regex = /[2]\d\d$/
83
+ config.message = -> (s, phrase, b, path, domain) { "[#{domain}] via #{path} returned #{status} using custom client middleware" }
84
+ end
85
+ Farady.get("http://httpstat.us/500") # => 500 status code returned
86
+ # Rollbar will not get sent because `use_default_middleware!` is not set
87
+
88
+ client = Faraday.new(url: base_url) do |conn|
89
+ conn.use Rollday::MIDDLEWARE_NAME
90
+ end
91
+ client.get("209") # => 209 status code returned
92
+ # Will send a rollbar because Status code matches regex
93
+ ```
94
+
95
+ ### Use Caution
96
+ ```ruby
97
+ # Rollday initializer
98
+ Rollday.configure do |config|
99
+ # Do not do this!
100
+ config.use_default_middleware!
101
+ config.use_default_client_middleware!
102
+ end
103
+ ```
104
+ Adding both the `use_default_middleware!` and the `use_default_client_middleware!` will cause double reporting of all default Faraday builders.
29
105
 
30
106
  ## Development
31
107
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rollday
4
+ module FaradayConnectionOptions
5
+ def new_builder(block)
6
+ super.tap do |builder|
7
+ # allow scope to remove usage of middleware for a request
8
+ # after it has been injected into the Connection
9
+ if Rollday.config.allow_client_middleware
10
+ builder.use(Rollday::MIDDLEWARE_NAME)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "class_composer"
4
+ require "rollbar"
5
+ require "rollday/errors"
6
+ require "rollday/use_middleware"
7
+
8
+ module Rollday
9
+ class Configuration
10
+ include ClassComposer::Generator
11
+
12
+ ROLLBAR_LEVELS = [
13
+ DEBUG = :debug,
14
+ INFO = :info,
15
+ WARNING = :warning,
16
+ ERROR = :error,
17
+ CRITICAL = :critical
18
+ ]
19
+ DEFAULT_ROLLBAR_LEVEL = WARNING
20
+
21
+ DEFAULT_STATUS_CODE_REGEX = /[45]\d\d$/
22
+ DEFAULT_MESSAGE_PROC = ->(status, phrase, body, path, domain) { "[#{status}]: #{domain} - #{path}" }
23
+ DEFAULT_LEVEL_PROC = ->(_status) { DEFAULT_ROLLBAR_LEVEL }
24
+ ROLLBAR_VALIDATOR = Proc.new do |value|
25
+ value.is_a?(Proc) || ROLLBAR_LEVELS.include?(value)
26
+ end
27
+
28
+ add_composer :message, allowed: [Proc, String], default: DEFAULT_MESSAGE_PROC
29
+ add_composer :params_query_sanitizer, allowed: Array, default: []
30
+ add_composer :params_scope_sanitizer, allowed: Array, default: []
31
+ add_composer :person_scope, allowed: Proc
32
+ add_composer :rollbar_level, allowed: [Proc, Symbol], default: DEFAULT_LEVEL_PROC, validator: ROLLBAR_VALIDATOR, invalid_message: -> (val) { "Value must be a Proc or one of #{ROLLBAR_LEVELS}" }
33
+ add_composer :status_code_regex, allowed: Regexp, default: DEFAULT_STATUS_CODE_REGEX
34
+ add_composer :use_message_exception, allowed: [TrueClass, FalseClass], default: true
35
+ add_composer :use_params_scope, allowed: [TrueClass, FalseClass], default: true
36
+ add_composer :use_person_scope, allowed: [TrueClass, FalseClass], default: true
37
+ add_composer :use_query_scope, allowed: [TrueClass, FalseClass], default: true
38
+ add_composer :exception_class, allowed: Class, default: Rollday::Faraday
39
+ add_composer :allow_client_middleware, allowed: [TrueClass, FalseClass], default: true
40
+
41
+ def person_scope
42
+ return -> {} unless @use_person_scope
43
+
44
+ @person_scope || Rollbar.scope.scope_object.raw[:person] || -> {}
45
+ end
46
+
47
+ def use_default_middleware!
48
+ Rollday.use_default_middleware!
49
+ end
50
+
51
+ def use_default_client_middleware!
52
+ Rollday.use_default_client_middleware!
53
+ end
54
+
55
+ def register_middleware!
56
+ Rollday.register_middleware!
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rollday
4
+ class Error < StandardError; end
5
+ class Faraday < Error; end # used to create backtrace for rollbar
6
+ class ConfigError < Error; end
7
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "rollday/rollbar_helper"
5
+
6
+ module Rollday
7
+ class Middleware < ::Faraday::Middleware
8
+ include RollbarHelper
9
+
10
+ def initialize(app, **)
11
+ super(app)
12
+
13
+ @app = app
14
+ end
15
+
16
+ def call(env)
17
+ result = @app.(env)
18
+ if ship_to_rollbar?(result.status)
19
+ send_rollbar(result)
20
+ end
21
+
22
+ result
23
+ end
24
+
25
+ private
26
+
27
+ def ship_to_rollbar?(status)
28
+ status.to_s =~ Rollday.config.status_code_regex
29
+ end
30
+
31
+ def send_rollbar(result)
32
+ scope = rollbar_scope(result)
33
+ message = rollbar_message(result)
34
+ level = rollbar_level(result)
35
+ ::Rollbar.log(level, message, **scope)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rollbar'
4
+
5
+ module Rollday
6
+ module RollbarHelper
7
+
8
+ def rollbar_level(result)
9
+ level = Rollday.config.rollbar_level
10
+ level.is_a?(Proc) ? level.(result.status) : level
11
+ end
12
+
13
+ def rollbar_message(result)
14
+ message = Rollday.config.message.(result.status, result.reason_phrase, result.body, URI(result.env.url).path, URI(result.env.url).host)
15
+ return message unless Rollday.config.use_message_exception
16
+
17
+ Rollday.config.exception_class.new(message)
18
+ end
19
+
20
+ def rollbar_scope(result)
21
+ {
22
+ framework: "Faraday: #{::Faraday::VERSION}; Rollday: #{Rollday::VERSION}",
23
+ host: URI(result.env.url).host,
24
+ method: result.env.method,
25
+ params: params_scope(result),
26
+ path: URI(result.env.url).path,
27
+ body: result.body,
28
+ person: person_scope,
29
+ query: query_scope(result),
30
+ status: result.status,
31
+ status_phrase: result.reason_phrase,
32
+ }
33
+ end
34
+
35
+ private
36
+
37
+ def query_scope(result)
38
+ return {} unless Rollday.config.use_query_scope
39
+ raw_query = URI(result.env.url).query
40
+ return if raw_query.nil?
41
+
42
+ query_scope = CGI::parse(raw_query)
43
+ Rollday.config.params_scope_sanitizer.each do |sanitizer|
44
+ query_scope = sanitizer.(query_params)
45
+ end
46
+
47
+ query_scope
48
+ end
49
+
50
+ def params_scope(result)
51
+
52
+ end
53
+
54
+ def person_scope
55
+ Rollday.config.person_scope.()
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rollday
4
+ module UseMiddleware
5
+ # https://github.com/lostisland/faraday/blob/816d824bc18453e86027c9c5fcf8427020566e50/lib/faraday/rack_builder.rb#L83-L86
6
+ # https://github.com/lostisland/faraday/blob/816d824bc18453e86027c9c5fcf8427020566e50/lib/faraday/rack_builder.rb#L156-L169
7
+ # Once the default middleware is crated and the Faraday Rack app has been built,
8
+ # it can not be removed from the middleware Faraday stack
9
+ # If removal is needed, then use the middleware per request instead of defaulted
10
+ # or use the `with_scope` to modify the parameters of the rollday gem
11
+ def self.use_default_middleware!
12
+ register_middleware!
13
+
14
+ return false if @add_default_middleware
15
+
16
+ idx = ::Faraday.default_connection.builder.handlers.size - 1
17
+ ::Faraday.default_connection.builder.insert(idx, Middleware)
18
+ @add_default_middleware = true
19
+ end
20
+
21
+ # https://github.com/lostisland/faraday/issues/946#issuecomment-500607890
22
+ # Monkey patch to force this middleware into every single Faraday.new client
23
+ def self.use_default_client_middleware!
24
+ return false if @use_default_client_middleware
25
+
26
+ register_middleware!
27
+ require "rollday/client_middleware"
28
+ ::Faraday::ConnectionOptions.prepend(Rollday::FaradayConnectionOptions)
29
+
30
+ @use_default_client_middleware = true
31
+ end
32
+
33
+ def self.register_middleware!
34
+ return false if @register_middleware
35
+
36
+ ::Faraday::Middleware.register_middleware(Rollday::MIDDLEWARE_NAME => Middleware)
37
+ @register_middleware = true
38
+ end
39
+ end
40
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rollday
4
- VERSION = "0.1.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/rollday.rb CHANGED
@@ -1,8 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "faraday"
4
+ require "rollday/configuration"
5
+ require "rollday/errors"
6
+ require "rollday/middleware"
3
7
  require "rollday/version"
4
8
 
5
9
  module Rollday
6
- class Error < StandardError; end
7
- # Your code goes here...
10
+ MIDDLEWARE_NAME = :rollday.freeze
11
+
12
+ def self.configure
13
+ yield configuration if block_given?
14
+ end
15
+
16
+ def self.configuration
17
+ @configuration ||= Rollday::Configuration.new
18
+ end
19
+
20
+ def self.configuration=(object)
21
+ raise ConfigError, "Expected configuration to be a Rollday::Configuration" unless object.is_a?(Rollday::Configuration)
22
+
23
+ @configuration = object
24
+ end
25
+
26
+ def self.reset_configuration!
27
+ @configuration = Rollday::Configuration.new
28
+ end
29
+
30
+ class << self
31
+ alias_method :config, :configuration
32
+ alias_method :config=, :configuration=
33
+ alias_method :reset_config!, :reset_configuration!
34
+ end
35
+
36
+ def self.use_default_middleware!
37
+ Rollday::UseMiddleware.use_default_middleware!
38
+ end
39
+
40
+ def self.use_default_client_middleware!
41
+ Rollday::UseMiddleware.use_default_client_middleware!
42
+ end
43
+
44
+ def self.register_middleware!
45
+ Rollday::UseMiddleware.register_middleware!
46
+ end
47
+
48
+ def self.with_scope()
49
+ end
8
50
  end
data/rollday.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
31
 
32
+ spec.add_dependency "class_composer"
32
33
  spec.add_dependency "faraday"
33
34
  spec.add_dependency "rollbar"
34
35
 
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rollday
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Taylor
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-18 00:00:00.000000000 Z
11
+ date: 2022-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: class_composer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: faraday
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -117,6 +131,12 @@ files:
117
131
  - bin/setup
118
132
  - docker-compose.yml
119
133
  - lib/rollday.rb
134
+ - lib/rollday/client_middleware.rb
135
+ - lib/rollday/configuration.rb
136
+ - lib/rollday/errors.rb
137
+ - lib/rollday/middleware.rb
138
+ - lib/rollday/rollbar_helper.rb
139
+ - lib/rollday/use_middleware.rb
120
140
  - lib/rollday/version.rb
121
141
  - rollday.gemspec
122
142
  homepage: https://github.com/matt-taylor/rollday