rest-client-jogger 0.3.5 → 1.0.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
  SHA1:
3
- metadata.gz: ecd6f48719589c8f47c7e92403107cd44aa6d72c
4
- data.tar.gz: d64c118b0c6e7c9d895e8c5702435170636a78d9
3
+ metadata.gz: 1b29dc3193cd558f466136f495d7ea42a94d0953
4
+ data.tar.gz: 43728ec66a9b0793099dd2bbd62929be94f9f477
5
5
  SHA512:
6
- metadata.gz: dca84f7028099bfaa5e29752a823aaeda30918fe2ac9c702a8e5cd7f626e53178c57f5e2b6900c00a0d42715099a0e29c5bccf5fc342e193cac36057b24de351
7
- data.tar.gz: 985b32ef827f83d61f779e7bf08c20238c7074ede4ad10f15a75fdec44059add01c3878a8e6bccdd626577beeb29bf6916bf2c960699a7bf9a7d8a0385070a21
6
+ metadata.gz: 91ebfb31dd64d8a640cc74411d5b80034ab923b21bc5de164df4c0d75a9c3556f4dc241b8b1c115e3eb1171b9fde1226acff6cf016bdd58b9e92ec8ccc7ea357
7
+ data.tar.gz: 3058eb900be88211bd950a75bf91fec49bd22af6cf3fa815a370601fc90293f0a633191e765149e84fa4228d31e9d94955dfa658129396d98a732bf1c317a1ff
data/.travis.yml CHANGED
@@ -7,4 +7,5 @@ rvm:
7
7
  - 2.2.2
8
8
  - 2.2.3
9
9
  - 2.3.0
10
+ - 2.5.1
10
11
  before_install: gem install bundler -v 1.12.3
data/README.md CHANGED
@@ -35,6 +35,20 @@ RestClient::Jogger::EventSubscriber.new.subscribe
35
35
 
36
36
  This will log all requests made with the `logged_request` method to a logfile in `log/rest_client.log`.
37
37
 
38
+ ## Configuration
39
+
40
+ Some of the parameters used in this gem can be configured in the host application:
41
+
42
+ ```ruby
43
+ # in an initializer somewhere
44
+ RestClient::Jogger.configure do |config|
45
+ config.request_pattern = 'my.request' # optional
46
+ config.response_pattern = 'my.response' # optional
47
+ config.default_content_type = 'application/json' # optional
48
+ config.default_filter_replacement = '[SECRET]' # optional
49
+ end
50
+ ```
51
+
38
52
  ## Development
39
53
 
40
54
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,60 +1,42 @@
1
1
  module LoggedRequest
2
- PATTERN = 'rest_client.request'.freeze
3
- DEFAULT_CONTENT_TYPE = 'application/json'.freeze
4
-
5
2
  def logged_request(opts = {}, &block)
6
3
  # We intend on using the following variables in this method's
7
4
  # ensure block. This means that we must take care to ensure
8
5
  # that we check for nil against these variables whenever they
9
6
  # are accessed.
10
- response, exception = nil, nil
11
7
  started = Time.now
8
+ log_request(opts, started)
9
+ response, exception = nil, nil
12
10
  response = execute(opts, &block)
13
11
  rescue StandardError => ex
14
12
  exception = ex.class.to_s
15
- response = ex.respond_to?(:response) && ex.response
13
+ response = ex.respond_to?(:response) ? ex.response : nil
16
14
  raise ex # Re-raise the exception, we just wanted to capture it
17
15
  ensure
18
- time = (Time.now - started).round(2)
19
- content_type = content_type_from_headers(opts[:headers])
20
- payload = filter(content_type).new(data: opts[:payload]).filter
21
- opts[:headers].reject! { |k, _| k.to_s.casecmp('authorization').zero? } if opts[:headers]
22
- params = opts.except(:user, :password, :payload).merge(payload: payload)
23
- ActiveSupport::Notifications.instrument PATTERN,
24
- log_data(params, response, exception, time)
16
+ logged_response = opts.merge(exception: exception, response: response)
17
+ ActiveSupport::Notifications.instrument(
18
+ RestClient::Jogger.response_pattern,
19
+ log_payload(logged_response, started)
20
+ )
25
21
  end
26
22
 
27
23
  private
28
24
 
29
- def log_data(params, response, exception, time)
30
- request_data(params).merge(
31
- response: response_data(response),
32
- exception: exception,
33
- time_elapsed: time
25
+ def log_payload(params, started)
26
+ params.merge(
27
+ headers: filtered_headers(params),
28
+ start_time: started
34
29
  )
35
30
  end
36
31
 
37
- def response_data(response = nil)
38
- if response
39
- {
40
- code: response.code,
41
- headers: response.headers.reject { |k, _| k.to_s.casecmp('authorization').zero? },
42
- body: response.body.to_s.force_encoding('UTF-8')
43
- }
44
- end
32
+ def filtered_headers(opts)
33
+ opts.fetch(:headers, {}).reject { |k, _| k.to_s.casecmp('authorization').zero? }
45
34
  end
46
35
 
47
- def request_data(params)
48
- {
49
- request: params
50
- }
51
- end
52
-
53
- def filter(content_type)
54
- RestClient::Jogger::Filters::Base.filter_class(content_type)
55
- end
56
-
57
- def content_type_from_headers(headers)
58
- (headers && headers[:content_type]) || DEFAULT_CONTENT_TYPE
36
+ def log_request(opts, started)
37
+ ActiveSupport::Notifications.instrument(
38
+ RestClient::Jogger.request_pattern,
39
+ log_payload(opts, started)
40
+ )
59
41
  end
60
42
  end
@@ -0,0 +1,59 @@
1
+ module RestClient
2
+ module Jogger
3
+ class Action
4
+ include ActiveModel::Model
5
+ attr_accessor :logger, :notifier
6
+
7
+ def initialize(args = {})
8
+ self.logger = args.fetch :logger
9
+ super
10
+ end
11
+
12
+ def notifier
13
+ @notifier ||= ::Rollbar
14
+ end
15
+
16
+ def call(name, start, finish, id, payload)
17
+ start_time = payload.fetch(:start_time)
18
+ render_params = {
19
+ args: payload,
20
+ payload: filter(payload),
21
+ verify_ssl: payload[:verify_ssl],
22
+ read_timeout: payload.fetch(:timeout) { payload[:read_timeout] },
23
+ open_timeout: payload.fetch(:timeout) { payload[:open_timeout] },
24
+ event_id: id,
25
+ timestamp: start,
26
+ time_elapsed: (finish - start_time).round(10),
27
+ ip_address: ip_address
28
+ }
29
+ json = template.render nil, render_params
30
+ name =~ /error/ ? logger.error(json) : logger.debug(json)
31
+ rescue StandardError => e
32
+ notifier.error e, payload: payload
33
+ end
34
+
35
+ def template
36
+ raise NotImplementedError, 'define a #template method in a subclass'
37
+ end
38
+
39
+ private
40
+
41
+ def filter(opts = {})
42
+ filter_class(opts[:headers] || {}).new(data: opts[:payload].to_s).filter
43
+ end
44
+
45
+ def filter_class(headers = {})
46
+ content_type = headers.fetch(:content_type) { 'application/json' }
47
+ RestClient::Jogger::Filters::Base.filter_class(content_type)
48
+ end
49
+
50
+ def root
51
+ Pathname.new(ROOT_PATH).freeze
52
+ end
53
+
54
+ def ip_address
55
+ Socket.ip_address_list.select(&:ipv4_private?).first.try(:ip_address)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,34 @@
1
+ module RestClient
2
+ module Jogger
3
+ class Configuration
4
+ include ActiveModel::Model
5
+
6
+ REQUIRED_ATTRIBUTES = %i().freeze
7
+ OPTIONAL_ATTRIBUTES = %i(
8
+ request_pattern
9
+ response_pattern
10
+ default_content_type
11
+ default_filter_replacement
12
+ ).freeze
13
+ ATTRIBUTES = (REQUIRED_ATTRIBUTES | OPTIONAL_ATTRIBUTES).freeze
14
+
15
+ attr_accessor *ATTRIBUTES
16
+
17
+ def request_pattern
18
+ @request_pattern || 'rest_client.request'
19
+ end
20
+
21
+ def response_pattern
22
+ @response_pattern || 'rest_client.response'
23
+ end
24
+
25
+ def default_content_type
26
+ @default_content_type || 'application/json'
27
+ end
28
+
29
+ def default_filter_replacement
30
+ @default_filter_replacement || '[FILTERED]'
31
+ end
32
+ end
33
+ end
34
+ end
@@ -7,14 +7,18 @@ module RestClient
7
7
  @logger ||= ActiveSupport::Logger.new('log/rest_client.log').tap { |l| l.level = Logger::DEBUG }
8
8
  end
9
9
 
10
- def pattern
11
- LoggedRequest::PATTERN
10
+ def request_pattern
11
+ RestClient::Jogger.request_pattern
12
12
  end
13
13
 
14
- def subscribe
15
- ActiveSupport::Notifications.subscribe pattern, RequestComplete.new(logger: logger)
14
+ def response_pattern
15
+ RestClient::Jogger.response_pattern
16
16
  end
17
17
 
18
+ def subscribe
19
+ ActiveSupport::Notifications.subscribe request_pattern, Request.new(logger: logger)
20
+ ActiveSupport::Notifications.subscribe response_pattern, Response.new(logger: logger)
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -2,8 +2,6 @@ module RestClient
2
2
  module Jogger
3
3
  module Filters
4
4
  class Base
5
- DEFAULT_REPLACEMENT = '[FILTERED]'.freeze
6
-
7
5
  include ActiveModel::Model
8
6
 
9
7
  attr_accessor :data, :content_type, :filters, :filter_replacement
@@ -17,6 +15,11 @@ module RestClient
17
15
  end
18
16
  end
19
17
 
18
+ def initialize(opts = {})
19
+ super
20
+ self.data = data.dup
21
+ end
22
+
20
23
  def filter
21
24
  filters.each do |filter|
22
25
  filter_data filter
@@ -29,7 +32,7 @@ module RestClient
29
32
  end
30
33
 
31
34
  def filter_replacement
32
- @filter_replacement ||= DEFAULT_REPLACEMENT
35
+ @filter_replacement ||= RestClient::Jogger.default_filter_replacement
33
36
  end
34
37
 
35
38
  def filters
@@ -37,7 +40,7 @@ module RestClient
37
40
  end
38
41
 
39
42
  def content_type
40
- @content_type ||= 'application/json'
43
+ @content_type ||= RestClient::Jogger.default_content_type
41
44
  end
42
45
 
43
46
  private
@@ -0,0 +1,9 @@
1
+ module RestClient
2
+ module Jogger
3
+ class Request < Action
4
+ def template
5
+ Tilt::JbuilderTemplate.new root.join('templates', 'request_logging_template.json.jbuilder')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module RestClient
2
+ module Jogger
3
+ class Response < Action
4
+ def template
5
+ Tilt::JbuilderTemplate.new root.join('templates', 'response_logging_template.json.jbuilder')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  module RestClient
2
2
  module Jogger
3
- VERSION = '0.3.5'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end
5
5
  end
@@ -1,19 +1,42 @@
1
- require "json"
2
- require "mime/types"
3
- require "active_model"
4
- require "rollbar"
5
- require "rest_client/jogger/version"
6
- require "rest_client/jogger/event_subscriber"
7
- require "rest_client/jogger/request_complete"
8
- require "rest_client/jogger/filters/base"
9
- require "rest_client/jogger/filters/json"
10
- require "rest_client/jogger/filters/xml"
11
- require "rest_client/core_ext/logged_request"
1
+ require 'json'
2
+ require 'mime/types'
3
+ require 'active_model'
4
+ require 'active_support/all'
5
+ require 'rollbar'
6
+ require 'tilt/jbuilder'
7
+ require 'rest_client/jogger/version'
8
+ require 'rest_client/jogger/configuration'
9
+ require 'rest_client/jogger/event_subscriber'
10
+ require 'rest_client/jogger/action'
11
+ require 'rest_client/jogger/request'
12
+ require 'rest_client/jogger/response'
13
+ require 'rest_client/jogger/filters/base'
14
+ require 'rest_client/jogger/filters/json'
15
+ require 'rest_client/jogger/filters/xml'
16
+ require 'rest_client/core_ext/logged_request'
12
17
 
13
18
  module RestClient
14
19
  class Request
15
20
  extend LoggedRequest
16
21
  end
22
+
17
23
  module Jogger
24
+ ROOT_PATH = File.expand_path(File.dirname(__FILE__)).freeze
25
+
26
+ class << self
27
+ Configuration::ATTRIBUTES.each do |attribute|
28
+ delegate attribute, to: :configuration
29
+ end
30
+
31
+ attr_writer :configuration
32
+
33
+ def configuration
34
+ @configuration ||= Configuration.new
35
+ end
36
+
37
+ def configure
38
+ yield(configuration)
39
+ end
40
+ end
18
41
  end
19
42
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ json.ignore_nil!
3
+ json.url args[:url]
4
+ json.method args[:method]
5
+ json.verifySsl verify_ssl
6
+ json.requestHeaders args.fetch(:headers, {})
7
+ json.requestBody payload
8
+ json.sourceIp ip_address
9
+ json.eventName RestClient::Jogger.request_pattern
10
+ json.eventId event_id
11
+ json.timeElapsed time_elapsed
12
+ json.openTimeout open_timeout
13
+ json.readTimeout read_timeout
14
+ json.timestamp timestamp.iso8601
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ json.ignore_nil!
3
+ json.exception args[:exception]
4
+ json.url args[:url]
5
+ json.method args[:method]
6
+ json.verifySsl verify_ssl
7
+ json.requestHeaders args.fetch(:headers, {})
8
+ json.responseHeaders args[:response].try(:headers)
9
+ json.requestBody payload
10
+ json.responseBody args[:response].try(:body).to_s.force_encoding('UTF-8')
11
+ json.sourceIp ip_address
12
+ json.eventName RestClient::Jogger.response_pattern
13
+ json.eventId event_id
14
+ json.timeElapsed time_elapsed
15
+ json.openTimeout open_timeout
16
+ json.readTimeout read_timeout
17
+ json.code args[:response].try(:code)
18
+ json.timestamp timestamp.iso8601
Binary file
@@ -30,6 +30,9 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency "mime-types"
32
32
  spec.add_dependency "rollbar"
33
+ spec.add_dependency "jbuilder"
34
+ spec.add_dependency 'tilt'
35
+ spec.add_dependency 'tilt-jbuilder'
33
36
 
34
37
  spec.add_development_dependency "bundler", "~> 1.12"
35
38
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-client-jogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Babe
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2018-04-30 00:00:00.000000000 Z
13
+ date: 2018-10-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -68,6 +68,48 @@ dependencies:
68
68
  - - ">="
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: jbuilder
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: tilt
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :runtime
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: tilt-jbuilder
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ type: :runtime
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
71
113
  - !ruby/object:Gem::Dependency
72
114
  name: bundler
73
115
  requirement: !ruby/object:Gem::Requirement
@@ -217,12 +259,18 @@ files:
217
259
  - bin/setup
218
260
  - lib/rest_client/core_ext/logged_request.rb
219
261
  - lib/rest_client/jogger.rb
262
+ - lib/rest_client/jogger/action.rb
263
+ - lib/rest_client/jogger/configuration.rb
220
264
  - lib/rest_client/jogger/event_subscriber.rb
221
265
  - lib/rest_client/jogger/filters/base.rb
222
266
  - lib/rest_client/jogger/filters/json.rb
223
267
  - lib/rest_client/jogger/filters/xml.rb
224
- - lib/rest_client/jogger/request_complete.rb
268
+ - lib/rest_client/jogger/request.rb
269
+ - lib/rest_client/jogger/response.rb
225
270
  - lib/rest_client/jogger/version.rb
271
+ - lib/rest_client/templates/request_logging_template.json.jbuilder
272
+ - lib/rest_client/templates/response_logging_template.json.jbuilder
273
+ - rest-client-jogger-0.3.4.gem
226
274
  - rest-client-jogger.gemspec
227
275
  homepage: https://github.com/amaabca/rest-client-jogger
228
276
  licenses:
@@ -244,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
292
  version: '0'
245
293
  requirements: []
246
294
  rubyforge_project:
247
- rubygems_version: 2.5.1
295
+ rubygems_version: 2.5.2.3
248
296
  signing_key:
249
297
  specification_version: 4
250
298
  summary: Logs RestClient requests in a JSON format
@@ -1,25 +0,0 @@
1
- module RestClient
2
- module Jogger
3
- class RequestComplete
4
- include ::ActiveModel::Model
5
- attr_accessor :logger, :notifier
6
-
7
- def initialize(args = {})
8
- self.logger = args.fetch :logger
9
- super
10
- end
11
-
12
- def notifier
13
- @notifier ||= ::Rollbar
14
- end
15
-
16
- def call(name, start, finish, id, payload)
17
- message = ::JSON.dump(payload.merge(event_name: name, event_id: id, timestamp: start))
18
- name =~ /error/ ? logger.error(message) : logger.debug(message)
19
- rescue StandardError => e
20
- notifier.error e, payload: payload
21
- end
22
-
23
- end
24
- end
25
- end