sapience 0.2.4 → 0.2.5
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 +4 -4
- data/.codeclimate.yml +21 -0
- data/.simplecov +19 -16
- data/.travis.yml +3 -3
- data/CHANGELOG.md +4 -0
- data/Gemfile +0 -8
- data/README.md +5 -0
- data/config/default.yml +4 -0
- data/docker-compose.yml +14 -0
- data/lib/sapience/appender/stream.rb +0 -1
- data/lib/sapience/base.rb +34 -4
- data/lib/sapience/configuration.rb +41 -20
- data/lib/sapience/core_ext/hash.rb +10 -7
- data/lib/sapience/core_ext/symbol.rb +15 -0
- data/lib/sapience/core_ext/thread.rb +1 -0
- data/lib/sapience/extensions/action_cable/tagged_logger_proxy.rb +2 -0
- data/lib/sapience/extensions/action_controller/live.rb +2 -0
- data/lib/sapience/extensions/action_controller/log_subscriber.rb +76 -121
- data/lib/sapience/extensions/action_dispatch/debug_exceptions.rb +2 -0
- data/lib/sapience/extensions/action_view/log_subscriber.rb +16 -6
- data/lib/sapience/extensions/action_view/streaming_template_renderer.rb +2 -0
- data/lib/sapience/extensions/active_job/logging.rb +1 -1
- data/lib/sapience/extensions/active_model_serializers/logging.rb +7 -2
- data/lib/sapience/extensions/active_record/log_subscriber.rb +45 -29
- data/lib/sapience/extensions/rails/rack/logger.rb +1 -0
- data/lib/sapience/extensions/rails/rack/logger_info_as_debug.rb +2 -0
- data/lib/sapience/formatters/color.rb +0 -1
- data/lib/sapience/formatters/default.rb +0 -1
- data/lib/sapience/formatters/json.rb +0 -1
- data/lib/sapience/formatters/raw.rb +0 -1
- data/lib/sapience/log.rb +54 -35
- data/lib/sapience/logger.rb +50 -71
- data/lib/sapience/rails.rb +17 -20
- data/lib/sapience/sapience.rb +23 -27
- data/lib/sapience/subscriber.rb +1 -13
- data/lib/sapience/version.rb +1 -1
- data/lib/sapience.rb +4 -3
- data/sapience.gemspec +6 -1
- data/test_app/Gemfile +7 -0
- data/test_app/Rakefile +2 -0
- data/test_app/app/models/post.rb +1 -1
- data/test_app/app/views/posts/_form.html.slim +18 -0
- data/test_app/app/views/posts/edit.html.slim +8 -0
- data/test_app/app/views/posts/index.html.slim +25 -0
- data/test_app/app/views/posts/new.html.slim +5 -0
- data/test_app/app/views/posts/show.html.slim +15 -0
- data/test_app/app/workers/test_worker.rb +17 -0
- data/test_app/bin/sneakers +10 -0
- data/test_app/config/initializers/sneakers.rb +15 -0
- data/test_app/config/sapience_example.yml +24 -0
- data/test_app/db/migrate/{20160812093621_create_posts.rb → 20160902141445_create_posts.rb} +1 -1
- data/test_app/db/schema.rb +1 -1
- data/test_app/lib/external_sneaker.rb +46 -0
- data/test_app/spec/factories/posts.rb +7 -0
- data/test_app/spec/factories/users.rb +8 -0
- data/test_app/spec/rails_helper.rb +8 -3
- data/test_app/spec/requests/posts_spec.rb +2 -1
- data/test_app/spec/views/posts/edit.html.slim_spec.rb +17 -0
- data/test_app/spec/views/posts/index.html.slim_spec.rb +17 -0
- data/test_app/spec/views/posts/new.html.slim_spec.rb +17 -0
- data/test_app/spec/views/posts/show.html.slim_spec.rb +14 -0
- data/test_app/spec/workers/test_worker_spec.rb +36 -0
- data/test_app.simplecov +19 -0
- metadata +95 -15
- data/.coveralls.yml +0 -1
- data/lib/sapience/extensions/action_controller/log_subscriber_processing.rb +0 -24
- data/test_app/app/views/posts/_form.html.erb +0 -32
- data/test_app/app/views/posts/create.html.erb +0 -2
- data/test_app/app/views/posts/destroy.html.erb +0 -2
- data/test_app/app/views/posts/edit.html.erb +0 -6
- data/test_app/app/views/posts/index.html.erb +0 -31
- data/test_app/app/views/posts/new.html.erb +0 -5
- data/test_app/app/views/posts/show.html.erb +0 -19
- data/test_app/app/views/posts/update.html.erb +0 -2
data/lib/sapience/logger.rb
CHANGED
@@ -7,31 +7,6 @@ module Sapience
|
|
7
7
|
class Logger < Base # rubocop:disable ClassLength, ClassVars
|
8
8
|
include Sapience::Concerns::Compatibility
|
9
9
|
|
10
|
-
# Returns a Logger instance
|
11
|
-
#
|
12
|
-
# Return the logger for a specific class, supports class specific log levels
|
13
|
-
# logger = Sapience::Logger.new(self)
|
14
|
-
# OR
|
15
|
-
# logger = Sapience::Logger.new('MyClass')
|
16
|
-
#
|
17
|
-
# Parameters:
|
18
|
-
# application
|
19
|
-
# A class, module or a string with the application/class name
|
20
|
-
# to be used in the logger
|
21
|
-
#
|
22
|
-
# level
|
23
|
-
# The initial log level to start with for this logger instance
|
24
|
-
# Default: Sapience.config.default_level
|
25
|
-
#
|
26
|
-
# filter [Regexp|Proc]
|
27
|
-
# RegExp: Only include log messages where the class name matches the supplied
|
28
|
-
# regular expression. All other messages will be ignored
|
29
|
-
# Proc: Only include log messages where the supplied Proc returns true
|
30
|
-
# The Proc must return true or false
|
31
|
-
def initialize(klass, level = nil, filter = nil)
|
32
|
-
super
|
33
|
-
end
|
34
|
-
|
35
10
|
# Flush all queued log entries disk, database, etc.
|
36
11
|
# All queued log messages are written and then each appender is flushed in turn
|
37
12
|
def self.flush # rubocop:disable AbcSize
|
@@ -73,51 +48,6 @@ module Sapience
|
|
73
48
|
Sapience.remove_appender(appender)
|
74
49
|
end
|
75
50
|
|
76
|
-
@@lag_check_interval = 5000
|
77
|
-
@@lag_threshold_s = 30
|
78
|
-
|
79
|
-
# Returns the check_interval which is the number of messages between checks
|
80
|
-
# to determine if the appender thread is falling behind
|
81
|
-
def self.lag_check_interval
|
82
|
-
@@lag_check_interval
|
83
|
-
end
|
84
|
-
|
85
|
-
# Set the check_interval which is the number of messages between checks
|
86
|
-
# to determine if the appender thread is falling behind
|
87
|
-
def self.lag_check_interval=(lag_check_interval)
|
88
|
-
@@lag_check_interval = lag_check_interval
|
89
|
-
end
|
90
|
-
|
91
|
-
# Returns the amount of time in seconds
|
92
|
-
# to determine if the appender thread is falling behind
|
93
|
-
def self.lag_threshold_s
|
94
|
-
@@lag_threshold_s
|
95
|
-
end
|
96
|
-
|
97
|
-
# Allow the internal logger to be overridden from its default to STDERR
|
98
|
-
# Can be replaced with another Ruby logger or Rails logger, but never to
|
99
|
-
# Sapience::Logger itself since it is for reporting problems
|
100
|
-
# while trying to log to the various appenders
|
101
|
-
def self.logger=(logger)
|
102
|
-
@@logger = logger
|
103
|
-
end
|
104
|
-
|
105
|
-
# Place log request on the queue for the Appender thread to write to each
|
106
|
-
# appender in the order that they were registered
|
107
|
-
def log(log, message = nil, progname = nil, &block)
|
108
|
-
# Compatibility with ::Logger
|
109
|
-
return add(log, message, progname, &block) unless log.is_a?(Sapience::Log)
|
110
|
-
@@appender_thread << lambda do
|
111
|
-
Sapience.appenders.each do |appender|
|
112
|
-
begin
|
113
|
-
appender.log(log)
|
114
|
-
rescue StandardError => exc
|
115
|
-
logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end if @@appender_thread
|
119
|
-
end
|
120
|
-
|
121
51
|
@@appender_thread = nil
|
122
52
|
|
123
53
|
# Internal logger for Sapience
|
@@ -135,7 +65,7 @@ module Sapience
|
|
135
65
|
def self.start_appender_thread
|
136
66
|
return false if appender_thread_active?
|
137
67
|
|
138
|
-
@@appender_thread =
|
68
|
+
@@appender_thread = Sapience.log_executor_class.new
|
139
69
|
fail "Failed to start Appender Thread" unless @@appender_thread
|
140
70
|
true
|
141
71
|
end
|
@@ -151,6 +81,55 @@ module Sapience
|
|
151
81
|
def self.appender_thread
|
152
82
|
@@appender_thread
|
153
83
|
end
|
84
|
+
|
85
|
+
# Allow the internal logger to be overridden from its default to STDERR
|
86
|
+
# Can be replaced with another Ruby logger or Rails logger, but never to
|
87
|
+
# Sapience::Logger itself since it is for reporting problems
|
88
|
+
# while trying to log to the various appenders
|
89
|
+
def self.logger=(logger)
|
90
|
+
@@logger = logger
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a Logger instance
|
94
|
+
#
|
95
|
+
# Return the logger for a specific class, supports class specific log levels
|
96
|
+
# logger = Sapience::Logger.new(self)
|
97
|
+
# OR
|
98
|
+
# logger = Sapience::Logger.new('MyClass')
|
99
|
+
#
|
100
|
+
# Parameters:
|
101
|
+
# application
|
102
|
+
# A class, module or a string with the application/class name
|
103
|
+
# to be used in the logger
|
104
|
+
#
|
105
|
+
# level
|
106
|
+
# The initial log level to start with for this logger instance
|
107
|
+
# Default: Sapience.config.default_level
|
108
|
+
#
|
109
|
+
# filter [Regexp|Proc]
|
110
|
+
# RegExp: Only include log messages where the class name matches the supplied
|
111
|
+
# regular expression. All other messages will be ignored
|
112
|
+
# Proc: Only include log messages where the supplied Proc returns true
|
113
|
+
# The Proc must return true or false
|
114
|
+
def initialize(klass, level = nil, filter = nil)
|
115
|
+
super
|
116
|
+
end
|
117
|
+
|
118
|
+
# Place log request on the queue for the Appender thread to write to each
|
119
|
+
# appender in the order that they were registered
|
120
|
+
def log(log, message = nil, progname = nil, &block)
|
121
|
+
# Compatibility with ::Logger
|
122
|
+
return add(log, message, progname, &block) unless log.is_a?(Sapience::Log)
|
123
|
+
@@appender_thread << lambda do
|
124
|
+
Sapience.appenders.each do |appender|
|
125
|
+
begin
|
126
|
+
appender.log(log)
|
127
|
+
rescue StandardError => exc
|
128
|
+
self.class.logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end if @@appender_thread
|
132
|
+
end
|
154
133
|
# rubocop:enable BlockNesting, AssignmentInCondition, PerceivedComplexity, CyclomaticComplexity, AbcSize, LineLength, RescueException
|
155
134
|
end
|
156
135
|
end
|
data/lib/sapience/rails.rb
CHANGED
@@ -1,4 +1,15 @@
|
|
1
1
|
require "sapience"
|
2
|
+
require "sapience/extensions/action_cable/tagged_logger_proxy"
|
3
|
+
require "sapience/extensions/action_controller/live"
|
4
|
+
require "sapience/extensions/action_controller/log_subscriber"
|
5
|
+
require "sapience/extensions/action_dispatch/debug_exceptions"
|
6
|
+
require "sapience/extensions/action_view/streaming_template_renderer"
|
7
|
+
require "sapience/extensions/active_job/logging"
|
8
|
+
require "sapience/extensions/active_model_serializers/logging"
|
9
|
+
require "sapience/extensions/active_record/log_subscriber"
|
10
|
+
require "sapience/extensions/rails/rack/logger"
|
11
|
+
require "sapience/extensions/rails/rack/logger_info_as_debug"
|
12
|
+
require "sapience/extensions/action_view/log_subscriber"
|
2
13
|
|
3
14
|
module Sapience
|
4
15
|
class Rails < ::Rails::Engine
|
@@ -35,38 +46,24 @@ module Sapience
|
|
35
46
|
Raven.send(:include) { Sapience::Loggable }
|
36
47
|
|
37
48
|
# Replace the Sneakers logger
|
38
|
-
Sneakers.
|
49
|
+
Sneakers.configure(log: Sapience[Sneakers]) if defined?(Sneakers)
|
39
50
|
|
40
51
|
# Replace the Bugsnag logger
|
41
52
|
Bugsnag.configure { |config| config.logger = Sapience[Bugsnag] } if defined?(Bugsnag)
|
42
53
|
|
43
54
|
# Set the logger for concurrent-ruby
|
44
55
|
Concurrent.global_logger = Sapience[Concurrent] if defined?(Concurrent)
|
45
|
-
|
46
|
-
# Rails Patches
|
47
|
-
Kernel.require "sapience/extensions/action_cable/tagged_logger_proxy" if defined?(ActionCable)
|
48
|
-
Kernel.require "sapience/extensions/action_controller/live" if defined?(ActionController::Live)
|
49
|
-
Kernel.require "sapience/extensions/action_dispatch/debug_exceptions" if defined?(ActionDispatch::DebugExceptions)
|
50
|
-
if defined?(ActionView::StreamingTemplateRenderer::Body)
|
51
|
-
Kernel.require "sapience/extensions/action_view/streaming_template_renderer"
|
52
|
-
end
|
53
|
-
Kernel.require "sapience/extensions/active_job/logging" if defined?(ActiveJob)
|
54
|
-
Kernel.require "sapience/extensions/active_model_serializers/logging" if defined?(ActiveModelSerializers)
|
55
|
-
Kernel.require "sapience/extensions/action_controller/log_subscriber" if defined?(ActionController)
|
56
|
-
Kernel.require "sapience/extensions/active_record/log_subscriber" if defined?(ActiveRecord::LogSubscriber)
|
57
|
-
Kernel.require "sapience/extensions/rails/rack/logger" if defined?(::Rails::Rack::Logger)
|
58
|
-
Kernel.require "sapience/extensions/rails/rack/logger_info_as_debug" if defined?(::Rails::Rack::Logger)
|
59
|
-
Kernel.require "sapience/extensions/action_view/log_subscriber" if defined?(ActionView::LogSubscriber)
|
60
|
-
if defined?(ActionView::LogSubscriber)
|
61
|
-
Kernel.require "sapience/extensions/action_controller/log_subscriber_processing"
|
62
|
-
end
|
63
56
|
end
|
64
57
|
|
65
58
|
# Before any initializers run, but after the gems have been loaded
|
66
59
|
config.after_initialize do
|
67
60
|
# Replace the Bugsnag logger
|
68
61
|
Bugsnag.configure { |config| config.logger = Sapience[Bugsnag] } if defined?(Bugsnag)
|
62
|
+
Sapience::Extensions::ActionController::LogSubscriber.attach_to :action_controller
|
63
|
+
# Sapience::Extensions::ActiveSupport::MailerLogSubscriber.attach_to :action_mailer
|
64
|
+
Sapience::Extensions::ActiveRecord::LogSubscriber.attach_to :active_record
|
65
|
+
Sapience::Extensions::ActionView::LogSubscriber.attach_to :action_view
|
66
|
+
# Sapience::Extensions::ActiveJob::LogSubscriber.attach_to :active_job
|
69
67
|
end
|
70
|
-
|
71
68
|
end
|
72
69
|
end
|
data/lib/sapience/sapience.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "concurrent"
|
2
2
|
require "socket"
|
3
3
|
require "sapience/descendants"
|
4
|
+
require "English"
|
4
5
|
|
5
6
|
# Example:
|
6
7
|
#
|
@@ -19,12 +20,16 @@ require "sapience/descendants"
|
|
19
20
|
|
20
21
|
# rubocop:disable ClassVars
|
21
22
|
module Sapience
|
23
|
+
UnknownClass = Class.new(NameError)
|
22
24
|
@@configured = nil
|
23
25
|
|
24
26
|
# Logging levels in order of most detailed to most severe
|
25
27
|
LEVELS = [:trace, :debug, :info, :warn, :error, :fatal].freeze
|
26
28
|
DEFAULT_ENV = "default".freeze
|
27
29
|
|
30
|
+
# TODO: Should we really always read from file?
|
31
|
+
# What if someone wants to configure sapience with a block
|
32
|
+
# without reading the default.yml?
|
28
33
|
def self.config
|
29
34
|
@@config ||= begin
|
30
35
|
config = ConfigLoader.load_from_file
|
@@ -48,6 +53,7 @@ module Sapience
|
|
48
53
|
@@logger = nil
|
49
54
|
@@metrix = nil
|
50
55
|
@@configured = nil
|
56
|
+
clear_tags!
|
51
57
|
reset_appenders!
|
52
58
|
end
|
53
59
|
|
@@ -68,6 +74,8 @@ module Sapience
|
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
77
|
+
# TODO: Maybe when configuring with a block we should create a new config?
|
78
|
+
# See the TODO note on .config for more information
|
71
79
|
def self.configure(force: false)
|
72
80
|
yield config if block_given?
|
73
81
|
return config if configured? && force == false
|
@@ -162,7 +170,7 @@ module Sapience
|
|
162
170
|
# logger.debug("Login time", user: 'Joe', duration: 100, ip_address: '127.0.0.1')
|
163
171
|
def self.add_appender(appender, options = {}, _deprecated_level = nil, &_block)
|
164
172
|
fail ArgumentError, "options should be a hash" unless options.is_a?(Hash)
|
165
|
-
options.
|
173
|
+
options.deep_symbolize_keyz!
|
166
174
|
appender_class = constantize_symbol(appender)
|
167
175
|
validate_appender!(appender_class)
|
168
176
|
|
@@ -273,19 +281,6 @@ module Sapience
|
|
273
281
|
Thread.current[:sapience_tags].pop
|
274
282
|
end
|
275
283
|
|
276
|
-
# Add the supplied named tags to the list of tags to log for this thread whilst
|
277
|
-
# the supplied block is active.
|
278
|
-
#
|
279
|
-
# Returns result of block
|
280
|
-
#
|
281
|
-
# Example:
|
282
|
-
def self.named_tags(tag)
|
283
|
-
(Thread.current[:sapience_tags] ||= []) << tag
|
284
|
-
yield
|
285
|
-
ensure
|
286
|
-
Thread.current[:sapience_tags].pop
|
287
|
-
end
|
288
|
-
|
289
284
|
# Add the supplied tags to the list of tags to log for this thread whilst
|
290
285
|
# the supplied block is active.
|
291
286
|
# Returns result of block
|
@@ -314,6 +309,10 @@ module Sapience
|
|
314
309
|
new_tags
|
315
310
|
end
|
316
311
|
|
312
|
+
def self.clear_tags!
|
313
|
+
Thread.current[:sapience_tags] = []
|
314
|
+
end
|
315
|
+
|
317
316
|
# Remove specified number of tags from the current tag list
|
318
317
|
def self.pop_tags(quantity = 1)
|
319
318
|
t = Thread.current[:sapience_tags]
|
@@ -366,11 +365,13 @@ module Sapience
|
|
366
365
|
|
367
366
|
reset_appenders!
|
368
367
|
|
368
|
+
def self.log_executor_class
|
369
|
+
constantize_symbol(config.log_executor, "Concurrent")
|
370
|
+
end
|
371
|
+
|
369
372
|
def self.constantize_symbol(symbol, namespace = "Sapience::Appender")
|
370
|
-
|
371
|
-
constantize(
|
372
|
-
rescue NameError
|
373
|
-
raise(ArgumentError, "Could not convert symbol: #{symbol} to a class in: #{namespace}. Looking for: #{klass}")
|
373
|
+
class_name = "#{namespace}::#{symbol.camelize}"
|
374
|
+
constantize(class_name)
|
374
375
|
end
|
375
376
|
|
376
377
|
def self.constantize(class_name)
|
@@ -380,16 +381,11 @@ module Sapience
|
|
380
381
|
else
|
381
382
|
class_name.split("::").inject(Object) { |o, name| o.const_get(name) } # rubocop:disable SingleLineBlockParams
|
382
383
|
end
|
384
|
+
rescue NameError
|
385
|
+
raise UnknownClass, "Could not find class: #{class_name}."
|
383
386
|
end
|
384
387
|
|
385
|
-
|
386
|
-
|
387
|
-
string = term.to_s
|
388
|
-
string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
|
389
|
-
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do
|
390
|
-
"#{Regexp.last_match[1]}#{inflections.acronyms[Regexp.last_match[2]] || Regexp.last_match[2].capitalize}"
|
391
|
-
end
|
392
|
-
string.gsub!("/".freeze, "::".freeze)
|
393
|
-
string
|
388
|
+
def self.root
|
389
|
+
@_root ||= Gem::Specification.find_by_name("sapience").gem_dir
|
394
390
|
end
|
395
391
|
end
|
data/lib/sapience/subscriber.rb
CHANGED
@@ -105,9 +105,7 @@ module Sapience
|
|
105
105
|
# rubocop:disable CyclomaticComplexity, AbcSize, PerceivedComplexity
|
106
106
|
def extract_formatter(formatter, &block)
|
107
107
|
case
|
108
|
-
when formatter.is_a?(Symbol)
|
109
|
-
Sapience.constantize_symbol(formatter, "Sapience::Formatters").new
|
110
|
-
when formatter.is_a?(String)
|
108
|
+
when formatter.is_a?(Symbol) || formatter.is_a?(String)
|
111
109
|
Sapience.constantize_symbol(formatter, "Sapience::Formatters").new
|
112
110
|
when formatter.is_a?(Hash) && formatter.size > 0
|
113
111
|
fmt, options = formatter.first
|
@@ -123,15 +121,5 @@ module Sapience
|
|
123
121
|
end
|
124
122
|
end
|
125
123
|
# rubocop:enable CyclomaticComplexity, AbcSize, PerceivedComplexity
|
126
|
-
|
127
|
-
SUBSCRIBER_OPTIONS = [:level, :formatter, :filter, :application, :host].freeze
|
128
|
-
|
129
|
-
# Returns [Hash] the subscriber common options from the supplied Hash
|
130
|
-
def extract_subscriber_options!(options)
|
131
|
-
subscriber_options = {}
|
132
|
-
SUBSCRIBER_OPTIONS.each { |key| subscriber_options[key] = options.delete(key) if options.key?(key) }
|
133
|
-
subscriber_options
|
134
|
-
end
|
135
|
-
|
136
124
|
end
|
137
125
|
end
|
data/lib/sapience/version.rb
CHANGED
data/lib/sapience.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
require "sapience/version"
|
2
|
+
require "sapience/ansi_colors"
|
3
|
+
require "sapience/core_ext/hash"
|
4
|
+
require "sapience/core_ext/symbol"
|
5
|
+
require "sapience/core_ext/thread"
|
2
6
|
require "sapience/sapience"
|
3
7
|
|
4
8
|
# @formatter:off
|
@@ -14,9 +18,6 @@ require "sapience/formatters/json"
|
|
14
18
|
require "sapience/config_loader"
|
15
19
|
require "sapience/configuration"
|
16
20
|
require "sapience/configuration/grape"
|
17
|
-
require "sapience/ansi_colors"
|
18
|
-
require "sapience/core_ext/hash"
|
19
|
-
require "sapience/core_ext/thread"
|
20
21
|
require "sapience/base"
|
21
22
|
require "sapience/log"
|
22
23
|
require "sapience/logger"
|
data/sapience.gemspec
CHANGED
@@ -36,7 +36,12 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency "simplecov"
|
37
37
|
spec.add_development_dependency "simplecov-json"
|
38
38
|
spec.add_development_dependency "rspec-its"
|
39
|
+
spec.add_development_dependency "pry-nav"
|
40
|
+
spec.add_development_dependency "sentry-raven"
|
41
|
+
spec.add_development_dependency "dogstatsd-ruby"
|
42
|
+
spec.add_development_dependency "rails", "~> 5.0.0.1"
|
43
|
+
spec.add_development_dependency "grape"
|
44
|
+
spec.add_development_dependency "active_model_serializers", "~> 0.10.0"
|
39
45
|
spec.add_development_dependency "codeclimate-test-reporter"
|
40
|
-
spec.add_development_dependency "coveralls"
|
41
46
|
spec.add_development_dependency "gem-release"
|
42
47
|
end
|
data/test_app/Gemfile
CHANGED
@@ -17,6 +17,9 @@ gem "puma", "~> 3.0"
|
|
17
17
|
gem "sapience", path: "../", require: "sapience/rails"
|
18
18
|
gem "sentry-raven"
|
19
19
|
gem "statsd-ruby"
|
20
|
+
gem "sneakers"
|
21
|
+
gem "slim-rails"
|
22
|
+
gem "active_model_serializers"
|
20
23
|
|
21
24
|
group :development, :test do
|
22
25
|
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
@@ -24,6 +27,7 @@ group :development, :test do
|
|
24
27
|
# gem "pry-nav"
|
25
28
|
gem "pry-byebug"
|
26
29
|
gem "rspec-rails"
|
30
|
+
gem "factory_girl_rails"
|
27
31
|
end
|
28
32
|
|
29
33
|
group :development do
|
@@ -34,6 +38,9 @@ end
|
|
34
38
|
|
35
39
|
group :test do
|
36
40
|
gem "rspec-its"
|
41
|
+
gem "bunny-mock"
|
42
|
+
gem "rspec-wait"
|
43
|
+
gem "rails-controller-testing"
|
37
44
|
end
|
38
45
|
|
39
46
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
data/test_app/Rakefile
CHANGED
data/test_app/app/models/post.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
= form_for @post do |f|
|
2
|
+
- if @post.errors.any?
|
3
|
+
#error_explanation
|
4
|
+
h2 = "#{pluralize(@post.errors.count, "error")} prohibited this post from being saved:"
|
5
|
+
ul
|
6
|
+
- @post.errors.full_messages.each do |message|
|
7
|
+
li = message
|
8
|
+
|
9
|
+
.field
|
10
|
+
= f.label :title
|
11
|
+
= f.text_field :title
|
12
|
+
.field
|
13
|
+
= f.label :body
|
14
|
+
= f.text_field :body
|
15
|
+
.field
|
16
|
+
= f.label :author
|
17
|
+
= f.text_field :author
|
18
|
+
.actions = f.submit
|
@@ -0,0 +1,25 @@
|
|
1
|
+
h1 Listing posts
|
2
|
+
|
3
|
+
table
|
4
|
+
thead
|
5
|
+
tr
|
6
|
+
th Title
|
7
|
+
th Body
|
8
|
+
th Author
|
9
|
+
th
|
10
|
+
th
|
11
|
+
th
|
12
|
+
|
13
|
+
tbody
|
14
|
+
- @posts.each do |post|
|
15
|
+
tr
|
16
|
+
td = post.title
|
17
|
+
td = post.body
|
18
|
+
td = post.author
|
19
|
+
td = link_to 'Show', post
|
20
|
+
td = link_to 'Edit', edit_post_path(post)
|
21
|
+
td = link_to 'Destroy', post, data: { confirm: 'Are you sure?' }, method: :delete
|
22
|
+
|
23
|
+
br
|
24
|
+
|
25
|
+
= link_to 'New Post', new_post_path
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "../../../spec/support/file_helper"
|
2
|
+
|
3
|
+
class TestWorker
|
4
|
+
QUEUE_NAME = :sneakers_queue
|
5
|
+
ROUTING_KEY = :sneakers_routing_key
|
6
|
+
VERIFICATION_FILE = "tmp/sneakers.verified".freeze
|
7
|
+
|
8
|
+
include Sneakers::Worker
|
9
|
+
include FileHelper
|
10
|
+
|
11
|
+
from_queue QUEUE_NAME, routing_key: ROUTING_KEY
|
12
|
+
|
13
|
+
def work(_message)
|
14
|
+
create_file(VERIFICATION_FILE)
|
15
|
+
ack!
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "bundler/setup"
|
3
|
+
require "serverengine"
|
4
|
+
require "sneakers"
|
5
|
+
require "sneakers/runner"
|
6
|
+
require_relative "../app/workers/test_worker"
|
7
|
+
require_relative "../config/initializers/sneakers"
|
8
|
+
|
9
|
+
runner = Sneakers::Runner.new([TestWorker])
|
10
|
+
runner.run
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "serverengine"
|
2
|
+
require "sneakers"
|
3
|
+
|
4
|
+
p ENV.fetch("AMQP") { "amqp://guest:guest@localhost:5672" }
|
5
|
+
|
6
|
+
Sneakers.configure(
|
7
|
+
amqp: ENV.fetch("AMQP") { "amqp://guest:guest@localhost:5672" },
|
8
|
+
exchange_type: :direct,
|
9
|
+
log: Sapience[Sneakers], # Log file
|
10
|
+
exchange: "sapience", # AMQP exchange
|
11
|
+
durable: false, # Is queue durable?
|
12
|
+
ack: true, # Must we acknowledge?
|
13
|
+
metrics: Sapience.metrix,
|
14
|
+
)
|
15
|
+
Sapience.logger.level = Logger::DEBUG
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
default:
|
3
|
+
log_level: error
|
4
|
+
appenders:
|
5
|
+
- stream:
|
6
|
+
file_name: log/error.log
|
7
|
+
formatter: default
|
8
|
+
|
9
|
+
development:
|
10
|
+
log_level: debug
|
11
|
+
appenders:
|
12
|
+
- stream:
|
13
|
+
io: STDOUT
|
14
|
+
formatter: color
|
15
|
+
- stream:
|
16
|
+
file_name: log/development.log
|
17
|
+
formatter: color
|
18
|
+
|
19
|
+
test:
|
20
|
+
log_level: fatal
|
21
|
+
appenders:
|
22
|
+
- stream:
|
23
|
+
file_name: log/fatal.log
|
24
|
+
formatter: json
|
data/test_app/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 20160902141445) do
|
14
14
|
|
15
15
|
create_table "posts", force: :cascade do |t|
|
16
16
|
t.string "title"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "timeout"
|
2
|
+
|
3
|
+
class ExternalSneaker
|
4
|
+
attr_accessor :worker_pid, :start_command
|
5
|
+
|
6
|
+
def initialize(start_command)
|
7
|
+
fail ArgumentError, "start_command was expected" if start_command.nil?
|
8
|
+
|
9
|
+
self.start_command = start_command
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
puts "Trying to start #{start_command}..."
|
14
|
+
self.worker_pid = fork do
|
15
|
+
start_child
|
16
|
+
end
|
17
|
+
|
18
|
+
at_exit do
|
19
|
+
stop_child
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def start_child
|
26
|
+
exec({ "RAILS_ENV" => Rails.env, "WORKERS" => "TestWorker" }, start_command)
|
27
|
+
end
|
28
|
+
|
29
|
+
def stop_child # rubocop:disable AbcSize
|
30
|
+
puts "Trying to stop #{start_command}, pid: #{worker_pid}"
|
31
|
+
|
32
|
+
# send TERM and wait for exit
|
33
|
+
Process.kill("TERM", worker_pid)
|
34
|
+
|
35
|
+
begin
|
36
|
+
Timeout.timeout(10) do
|
37
|
+
Process.waitpid(worker_pid)
|
38
|
+
puts "Process #{start_command} stopped successfully"
|
39
|
+
end
|
40
|
+
rescue Timeout::Error
|
41
|
+
# Kill process if could not exit in 10 seconds
|
42
|
+
puts "Sending KILL signal to #{start_command}, pid: #{worker_pid}"
|
43
|
+
Process.kill("KILL", worker_pid)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|