timber 1.1.14 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -2
- data/.travis.yml +47 -0
- data/Gemfile +1 -28
- data/README.md +83 -298
- data/bin/timber +13 -0
- data/gemfiles/rails-3.0.gemfile +5 -0
- data/gemfiles/rails-3.1.gemfile +5 -0
- data/gemfiles/rails-3.2.gemfile +5 -0
- data/gemfiles/rails-4.0.gemfile +9 -0
- data/gemfiles/rails-4.1.gemfile +9 -0
- data/gemfiles/rails-4.2.gemfile +9 -0
- data/gemfiles/rails-5.0.gemfile +9 -0
- data/gemfiles/rails-edge.gemfile +7 -0
- data/lib/timber.rb +7 -7
- data/lib/timber/cli.rb +72 -0
- data/lib/timber/cli/api.rb +104 -0
- data/lib/timber/cli/application.rb +28 -0
- data/lib/timber/cli/install.rb +186 -0
- data/lib/timber/cli/io_helper.rb +58 -0
- data/lib/timber/cli/messages.rb +170 -0
- data/lib/timber/config.rb +47 -6
- data/lib/timber/contexts/http.rb +2 -2
- data/lib/timber/current_context.rb +1 -1
- data/lib/timber/event.rb +8 -0
- data/lib/timber/events.rb +2 -0
- data/lib/timber/events/controller_call.rb +12 -3
- data/lib/timber/events/exception.rb +4 -3
- data/lib/timber/events/http_client_request.rb +61 -0
- data/lib/timber/events/http_client_response.rb +47 -0
- data/lib/timber/events/http_server_request.rb +15 -23
- data/lib/timber/events/http_server_response.rb +9 -9
- data/lib/timber/events/sql_query.rb +2 -2
- data/lib/timber/events/template_render.rb +2 -2
- data/lib/timber/frameworks/rails.rb +31 -6
- data/lib/timber/integrations.rb +22 -0
- data/lib/timber/integrations/action_controller/log_subscriber.rb +25 -0
- data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +40 -0
- data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +51 -0
- data/lib/timber/integrations/action_view/log_subscriber.rb +25 -0
- data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +73 -0
- data/lib/timber/integrations/active_record/log_subscriber.rb +25 -0
- data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +39 -0
- data/lib/timber/integrations/active_support/tagged_logging.rb +71 -0
- data/lib/timber/integrations/rack.rb +16 -0
- data/lib/timber/integrations/rack/exception_event.rb +28 -0
- data/lib/timber/integrations/rack/http_context.rb +25 -0
- data/lib/timber/integrations/rack/http_events.rb +46 -0
- data/lib/timber/integrations/rack/user_context.rb +59 -0
- data/lib/timber/integrations/rails/rack_logger.rb +49 -0
- data/lib/timber/integrator.rb +24 -0
- data/lib/timber/log_devices/http.rb +14 -21
- data/lib/timber/log_entry.rb +1 -1
- data/lib/timber/logger.rb +38 -12
- data/lib/timber/overrides.rb +9 -0
- data/lib/timber/overrides/lograge.rb +14 -0
- data/lib/timber/overrides/rails_server.rb +10 -0
- data/lib/timber/util.rb +2 -0
- data/lib/timber/util/active_support_log_subscriber.rb +13 -9
- data/lib/timber/util/http_event.rb +54 -0
- data/lib/timber/util/request.rb +44 -0
- data/lib/timber/version.rb +1 -1
- data/spec/README.md +5 -9
- data/spec/spec_helper.rb +1 -4
- data/spec/support/action_controller.rb +7 -3
- data/spec/support/active_record.rb +23 -19
- data/spec/support/rails.rb +56 -32
- data/spec/support/timber.rb +2 -3
- data/spec/support/webmock.rb +1 -0
- data/spec/timber/integrations/action_controller/log_subscriber_spec.rb +55 -0
- data/spec/timber/integrations/action_dispatch/debug_exceptions_spec.rb +53 -0
- data/spec/timber/integrations/action_view/log_subscriber_spec.rb +115 -0
- data/spec/timber/integrations/active_record/log_subscriber_spec.rb +46 -0
- data/spec/timber/integrations/rack/http_context_spec.rb +60 -0
- data/spec/timber/integrations/rails/rack_logger_spec.rb +58 -0
- data/spec/timber/logger_spec.rb +45 -9
- data/timber.gemspec +29 -3
- metadata +143 -46
- data/Appraisals +0 -41
- data/circle.yml +0 -33
- data/lib/timber/overrides/logger_add.rb +0 -38
- data/lib/timber/probe.rb +0 -23
- data/lib/timber/probes.rb +0 -23
- data/lib/timber/probes/action_controller_log_subscriber.rb +0 -20
- data/lib/timber/probes/action_controller_log_subscriber/log_subscriber.rb +0 -64
- data/lib/timber/probes/action_controller_user_context.rb +0 -52
- data/lib/timber/probes/action_dispatch_debug_exceptions.rb +0 -80
- data/lib/timber/probes/action_view_log_subscriber.rb +0 -20
- data/lib/timber/probes/action_view_log_subscriber/log_subscriber.rb +0 -69
- data/lib/timber/probes/active_record_log_subscriber.rb +0 -20
- data/lib/timber/probes/active_record_log_subscriber/log_subscriber.rb +0 -31
- data/lib/timber/probes/active_support_tagged_logging.rb +0 -63
- data/lib/timber/probes/rails_rack_logger.rb +0 -77
- data/lib/timber/rack_middlewares.rb +0 -12
- data/lib/timber/rack_middlewares/http_context.rb +0 -30
- data/spec/support/action_view.rb +0 -4
- data/spec/support/coveralls.rb +0 -2
- data/spec/support/simplecov.rb +0 -9
- data/spec/timber/overrides/logger_add_spec.rb +0 -26
- data/spec/timber/probes/action_controller_log_subscriber_spec.rb +0 -65
- data/spec/timber/probes/action_controller_user_context_spec.rb +0 -53
- data/spec/timber/probes/action_dispatch_debug_exceptions_spec.rb +0 -48
- data/spec/timber/probes/action_view_log_subscriber_spec.rb +0 -107
- data/spec/timber/probes/active_record_log_subscriber_spec.rb +0 -47
- data/spec/timber/probes/rails_rack_logger_spec.rb +0 -46
- data/spec/timber/rack_middlewares/http_context_spec.rb +0 -47
data/lib/timber/log_entry.rb
CHANGED
@@ -3,7 +3,7 @@ module Timber
|
|
3
3
|
# `Logger` and the log device that you set it up with.
|
4
4
|
class LogEntry #:nodoc:
|
5
5
|
DT_PRECISION = 6.freeze
|
6
|
-
SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/1.2.
|
6
|
+
SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/1.2.20/schema.json".freeze
|
7
7
|
|
8
8
|
attr_reader :context_snapshot, :event, :level, :message, :progname, :tags, :time, :time_ms
|
9
9
|
|
data/lib/timber/logger.rb
CHANGED
@@ -16,7 +16,7 @@ module Timber
|
|
16
16
|
# @example Using a Hash
|
17
17
|
# # The :message key is required, the other additional key is your event type and data
|
18
18
|
# # :type is the namespace used in timber for the :data
|
19
|
-
# logger.info
|
19
|
+
# logger.info "Payment rejected", payment_rejected: {customer_id: customer_id, amount: 100}
|
20
20
|
#
|
21
21
|
# @example Using a Struct (a simple, more structured way, to define events)
|
22
22
|
# PaymentRejectedEvent = Struct.new(:customer_id, :amount, :reason) do
|
@@ -69,7 +69,7 @@ module Timber
|
|
69
69
|
"INFO" => :info,
|
70
70
|
"WARN" => :warn,
|
71
71
|
"ERROR" => :error,
|
72
|
-
"FATAL" => :
|
72
|
+
"FATAL" => :fatal,
|
73
73
|
"UNKNOWN" => :unknown
|
74
74
|
}
|
75
75
|
|
@@ -81,9 +81,12 @@ module Timber
|
|
81
81
|
tags = extract_active_support_tagged_logging_tags
|
82
82
|
time_ms = nil
|
83
83
|
if msg.is_a?(Hash)
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
if msg.key?(:tag) || msg.key?(:tags)
|
85
|
+
tags = tags.clone
|
86
|
+
tags << msg.delete(:tag) if msg.key?(:tag)
|
87
|
+
tags += msg.delete(:tags) if msg.key?(:tags)
|
88
|
+
tags.uniq!
|
89
|
+
end
|
87
90
|
time_ms = msg.delete(:time_ms) if msg.key?(:time_ms)
|
88
91
|
|
89
92
|
msg = msg[:message] if msg.length == 1
|
@@ -106,6 +109,16 @@ module Timber
|
|
106
109
|
end
|
107
110
|
end
|
108
111
|
|
112
|
+
# For use in development and test environments where you do not want metadata
|
113
|
+
# included in the log lines.
|
114
|
+
class SimpleFormatter < Formatter
|
115
|
+
|
116
|
+
# This method is invoked when a log event occurs
|
117
|
+
def call(severity, timestamp, progname, msg)
|
118
|
+
"#{String === msg ? msg : msg.inspect}\n"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
109
122
|
# Structures your log messages into Timber's hybrid format, which makes
|
110
123
|
# it easy to read while also appending the appropriate metadata.
|
111
124
|
#
|
@@ -153,6 +166,11 @@ module Timber
|
|
153
166
|
end
|
154
167
|
end
|
155
168
|
|
169
|
+
class << self
|
170
|
+
def new_from_config
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
156
174
|
# Creates a new Timber::Logger instances. Accepts the same arguments as `::Logger.new`.
|
157
175
|
# The only difference is that it default the formatter to {HybridFormatter}. Using
|
158
176
|
# a different formatter is easy. For example, if you prefer your logs in JSON.
|
@@ -175,26 +193,34 @@ module Timber
|
|
175
193
|
end
|
176
194
|
|
177
195
|
self.level = environment_level
|
196
|
+
|
197
|
+
@initialized = true
|
178
198
|
end
|
179
199
|
|
180
200
|
def formatter=(value)
|
181
|
-
if @dev.is_a?(Timber::LogDevices::HTTP)
|
201
|
+
if @initialized && @logdev && @logdev.dev.is_a?(Timber::LogDevices::HTTP) && !value.is_a?(PassThroughFormatter)
|
182
202
|
raise ArgumentError.new("The formatter cannot be changed when using the " +
|
183
203
|
"Timber::LogDevices::HTTP log device. The PassThroughFormatter must be used for proper " +
|
184
204
|
"delivery.")
|
185
205
|
end
|
186
206
|
|
187
|
-
|
188
|
-
# silently discard this value since rails calls this during initialization :/
|
189
|
-
nil
|
190
|
-
else
|
191
|
-
super
|
192
|
-
end
|
207
|
+
super
|
193
208
|
end
|
194
209
|
|
195
210
|
# Backwards compatibility with older ActiveSupport::Logger versions
|
196
211
|
Logger::Severity.constants.each do |severity|
|
197
212
|
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
213
|
+
def #{severity.downcase}(*args, &block)
|
214
|
+
progname = args.first
|
215
|
+
options = args.last
|
216
|
+
|
217
|
+
if args.length == 2 and options.is_a?(Hash) && options != {}
|
218
|
+
progname = options.merge(message: progname)
|
219
|
+
end
|
220
|
+
|
221
|
+
add(#{severity}, nil, progname, &block)
|
222
|
+
end
|
223
|
+
|
198
224
|
def #{severity.downcase}? # def debug?
|
199
225
|
Logger::#{severity} >= level # DEBUG >= level
|
200
226
|
end # end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Timber and lograge are not compatible installed together. Using lograge
|
2
|
+
# with the Timber.io *service* is perfectly fine, but not with the Timber *gem*.
|
3
|
+
begin
|
4
|
+
require "lograge"
|
5
|
+
|
6
|
+
module Lograge
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def setup(app)
|
10
|
+
return true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
rescue Exception
|
14
|
+
end
|
data/lib/timber/util.rb
CHANGED
@@ -5,7 +5,7 @@ module Timber
|
|
5
5
|
extend self
|
6
6
|
|
7
7
|
def find(component, type)
|
8
|
-
ActiveSupport::LogSubscriber.log_subscribers.find do |subscriber|
|
8
|
+
::ActiveSupport::LogSubscriber.log_subscribers.find do |subscriber|
|
9
9
|
subscriber.class == type
|
10
10
|
end
|
11
11
|
end
|
@@ -14,16 +14,20 @@ module Timber
|
|
14
14
|
!find(component, type).nil?
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
# I don't know why this has to be so complicated, but it is. This code was taken from
|
18
|
+
# lograge :/
|
19
|
+
def unsubscribe!(component, type)
|
18
20
|
subscriber = find(component, type)
|
19
21
|
|
20
|
-
if subscriber
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
if !subscriber
|
23
|
+
raise "We could not find a log subscriber for #{component.inspect} of type #{type.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
|
27
|
+
events.each do |event|
|
28
|
+
::ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
|
29
|
+
if listener.instance_variable_get('@delegate') == subscriber
|
30
|
+
::ActiveSupport::Notifications.unsubscribe listener
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Timber
|
2
|
+
module Util
|
3
|
+
module HTTPEvent
|
4
|
+
BODY_LIMIT = 5_000.freeze
|
5
|
+
QUERY_STRING_LIMIT = 5_000.freeze
|
6
|
+
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def full_path(path, query_string)
|
10
|
+
if query_string
|
11
|
+
"#{path}?#{query_string}"
|
12
|
+
else
|
13
|
+
path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def normalize_body(content_type, body)
|
18
|
+
if Config.instance.capture_http_body_content_types.include?(content_type)
|
19
|
+
if body.respond_to?(:body)
|
20
|
+
body = body.body.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
body[0..(BODY_LIMIT - 1)]
|
24
|
+
else
|
25
|
+
# Drop the body if it is not a format we want to capture.
|
26
|
+
# This gives users more control to avoid loggin files, etc.
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def normalize_headers(headers)
|
32
|
+
if headers.is_a?(::Hash)
|
33
|
+
headers.each_with_object({}) do |(k, v), h|
|
34
|
+
h[k.to_s.downcase] = v
|
35
|
+
end
|
36
|
+
else
|
37
|
+
headers
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def normalize_method(method)
|
42
|
+
method.is_a?(::String) ? method.upcase : method
|
43
|
+
end
|
44
|
+
|
45
|
+
def normalize_query_string(query_string)
|
46
|
+
if !query_string.nil?
|
47
|
+
query_string = query_string.to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
query_string[0..(QUERY_STRING_LIMIT - 1)]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
begin
|
2
|
+
require "rack"
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
if defined?(::Rack::Request)
|
7
|
+
module Timber
|
8
|
+
module Util
|
9
|
+
class Request < ::Rack::Request
|
10
|
+
def body_content
|
11
|
+
content = body.read
|
12
|
+
body.rewind
|
13
|
+
content
|
14
|
+
end
|
15
|
+
|
16
|
+
def headers
|
17
|
+
@headers ||= ::Hash[*@env.select {|k,v| k.start_with? 'HTTP_'}
|
18
|
+
.collect {|k,v| [k.sub(/^HTTP_/, ''), v]}
|
19
|
+
.collect {|k,v| [k.split('_').collect(&:capitalize).join('-'), v]}
|
20
|
+
.sort
|
21
|
+
.flatten]
|
22
|
+
end
|
23
|
+
|
24
|
+
def ip
|
25
|
+
@ip ||= if @env["action_dispatch.remote_ip"]
|
26
|
+
@env["action_dispatch.remote_ip"].to_s || super
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def referer
|
33
|
+
# Rails 3.X returns "/" for some reason
|
34
|
+
@referer ||= super == "/" ? nil : super
|
35
|
+
end
|
36
|
+
|
37
|
+
def request_id
|
38
|
+
@request_id ||= @env["action_dispatch.request_id"] || @env["X-Request-ID"] ||
|
39
|
+
@env["X-Request-Id"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/timber/version.rb
CHANGED
data/spec/README.md
CHANGED
@@ -1,23 +1,19 @@
|
|
1
1
|
# Testing
|
2
2
|
|
3
|
-
Testing Timber uses [`appraisal`](https://github.com/thoughtbot/appraisal). This allows us to
|
4
|
-
test across multiple versions and combinations of libraries.
|
5
|
-
|
6
3
|
To get started:
|
7
4
|
|
8
5
|
```shell
|
9
6
|
bundle install
|
10
|
-
bundle exec appraisal install
|
11
7
|
```
|
12
8
|
|
13
|
-
|
9
|
+
Be sure to install specific Gemfile dependencies:
|
14
10
|
|
15
|
-
```
|
16
|
-
|
11
|
+
```
|
12
|
+
BUNDLE_GEMFILE=gemfiles/rails-4.2.gemfile bundle install
|
17
13
|
```
|
18
14
|
|
19
|
-
You can run tests
|
15
|
+
You can run tests like this:
|
20
16
|
|
21
17
|
```shell
|
22
|
-
|
18
|
+
BUNDLE_GEMFILE=gemfiles/rails-4.2.gemfile bundle exec rspec
|
23
19
|
```
|
data/spec/spec_helper.rb
CHANGED
@@ -3,23 +3,20 @@ require 'rubygems'
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
|
5
5
|
# Testing
|
6
|
-
require 'pry'
|
7
6
|
require 'rspec'
|
8
7
|
require 'rspec/its'
|
9
8
|
require 'rspec/mocks'
|
10
9
|
|
11
10
|
# Support files, order is relevant
|
12
|
-
require File.join(File.dirname(__FILE__), 'support', 'coveralls')
|
13
11
|
require File.join(File.dirname(__FILE__), 'support', 'socket_hostname')
|
14
|
-
require File.join(File.dirname(__FILE__), 'support', 'simplecov')
|
15
12
|
require File.join(File.dirname(__FILE__), 'support', 'timecop')
|
16
13
|
require File.join(File.dirname(__FILE__), 'support', 'webmock')
|
17
14
|
require File.join(File.dirname(__FILE__), 'support', 'timber')
|
18
15
|
|
16
|
+
# Load framework files after we've setup everything
|
19
17
|
if !ENV["RAILS_23"]
|
20
18
|
require File.join(File.dirname(__FILE__), 'support', 'rails')
|
21
19
|
require File.join(File.dirname(__FILE__), 'support', 'action_controller')
|
22
|
-
require File.join(File.dirname(__FILE__), 'support', 'action_view')
|
23
20
|
require File.join(File.dirname(__FILE__), 'support', 'active_record')
|
24
21
|
end
|
25
22
|
|
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require "action_controller"
|
3
|
+
rescue LoadError
|
4
|
+
end
|
2
5
|
|
3
|
-
ActionController::Base
|
4
|
-
ActionController::Base.
|
6
|
+
if defined?(::ActionController::Base)
|
7
|
+
::ActionController::Base.prepend_view_path("#{File.dirname(__FILE__)}/rails/templates")
|
8
|
+
end
|
@@ -1,28 +1,32 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'active_record'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
2
5
|
|
3
|
-
ActiveRecord::Base
|
4
|
-
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
5
|
-
ActiveRecord::Schema.define do
|
6
|
-
|
6
|
+
if defined?(::ActiveRecord::Base)
|
7
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
8
|
+
ActiveRecord::Schema.define do
|
9
|
+
self.verbose = false
|
7
10
|
|
8
|
-
|
9
|
-
|
11
|
+
create_table :organizations, :force => true do |t|
|
12
|
+
t.string :name
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
t.timestamps :null => false
|
15
|
+
end
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
create_table :users, :force => true do |t|
|
18
|
+
t.integer :age
|
19
|
+
t.string :email
|
20
|
+
t.string :first_name
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
t.timestamps :null => false
|
23
|
+
end
|
21
24
|
|
22
|
-
end
|
25
|
+
end
|
23
26
|
|
24
|
-
class Organization < ::ActiveRecord::Base
|
25
|
-
end
|
27
|
+
class Organization < ::ActiveRecord::Base
|
28
|
+
end
|
26
29
|
|
27
|
-
class User < ::ActiveRecord::Base
|
30
|
+
class User < ::ActiveRecord::Base
|
31
|
+
end
|
28
32
|
end
|
data/spec/support/rails.rb
CHANGED
@@ -1,37 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# responsible for setting up the logger
|
5
|
-
logger = ::Logger.new(STDOUT) # change to STDOUT to see rails logs
|
6
|
-
Rails.logger = logger
|
7
|
-
|
8
|
-
class RailsApp < Rails::Application
|
9
|
-
if ::Rails.version =~ /^3\./
|
10
|
-
config.secret_token = '1e05af2b349457936a41427e63450937'
|
11
|
-
else
|
12
|
-
config.secret_key_base = '1e05af2b349457936a41427e63450937'
|
13
|
-
end
|
14
|
-
config.active_support.deprecation = :stderr
|
15
|
-
config.eager_load = false
|
1
|
+
begin
|
2
|
+
require "rails"
|
3
|
+
rescue LoadError
|
16
4
|
end
|
17
5
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
env = env.merge(additional_env_options)
|
30
|
-
::Rack::MockRequest.new(application).get(path, env)
|
6
|
+
if defined?(::Rails)
|
7
|
+
# Defualt the rails logger to nothing, each test shoould be
|
8
|
+
# responsible for setting up the logger
|
9
|
+
logger = Timber::Logger.new(nil) # change to STDOUT to see rails logs
|
10
|
+
Rails.logger = logger
|
11
|
+
|
12
|
+
class RailsApp < Rails::Application
|
13
|
+
if ::Rails.version =~ /^3\./
|
14
|
+
config.secret_token = '1e05af2b349457936a41427e63450937'
|
15
|
+
else
|
16
|
+
config.secret_key_base = '1e05af2b349457936a41427e63450937'
|
31
17
|
end
|
18
|
+
|
19
|
+
# This ensures our tests fail, otherwise exceptions get swallowed by ActionDispatch::DebugExceptions
|
20
|
+
config.action_dispatch.show_exceptions = false
|
21
|
+
config.active_support.deprecation = :stderr
|
22
|
+
config.eager_load = false
|
32
23
|
end
|
33
|
-
end
|
34
24
|
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
RailsApp.initialize!
|
26
|
+
|
27
|
+
module Support
|
28
|
+
module Rails
|
29
|
+
def dispatch_rails_request(path, additional_env_options = {})
|
30
|
+
application = ::Rails.application
|
31
|
+
env = application.respond_to?(:env_config) ? application.env_config.clone : application.env_defaults.clone
|
32
|
+
env["rack.request.cookie_hash"] = {}.with_indifferent_access
|
33
|
+
env["REMOTE_ADDR"] = "123.456.789.10"
|
34
|
+
env["HTTP_X_REQUEST_ID"] = "unique-request-id-1234"
|
35
|
+
env["action_dispatch.request_id"] = env["HTTP_X_REQUEST_ID"]
|
36
|
+
env = env.merge(additional_env_options)
|
37
|
+
::Rack::MockRequest.new(application).get(path, env)
|
38
|
+
end
|
39
|
+
|
40
|
+
def with_rails_logger(logger)
|
41
|
+
old_logger = ::Rails.logger
|
42
|
+
|
43
|
+
# We have to set these again because rails set's these after initialization.
|
44
|
+
# Since we've already booted the rails app we need to update them all as we
|
45
|
+
# change the logger.
|
46
|
+
#
|
47
|
+
# You can see here that they use simple class attribute, hence the reason we need
|
48
|
+
# to update all of them: https://github.com/rails/rails/blob/700ec897f97c60016ad748236bf3a49ef15a20de/actionview/lib/action_view/base.rb#L157
|
49
|
+
Timber::Frameworks::Rails.set_logger(logger)
|
50
|
+
|
51
|
+
yield
|
52
|
+
|
53
|
+
::Rails.logger = old_logger
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
RSpec.configure do |config|
|
59
|
+
config.include Support::Rails
|
60
|
+
end
|
61
|
+
end
|