notable 0.0.1
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 +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +122 -0
- data/Rakefile +2 -0
- data/app/models/notable/job.rb +5 -0
- data/app/models/notable/request.rb +8 -0
- data/lib/generators/notable/jobs_generator.rb +30 -0
- data/lib/generators/notable/requests_generator.rb +30 -0
- data/lib/generators/notable/templates/create_jobs.rb +14 -0
- data/lib/generators/notable/templates/create_requests.rb +22 -0
- data/lib/notable/debug_exceptions.rb +15 -0
- data/lib/notable/engine.rb +9 -0
- data/lib/notable/job_backends/delayed_job.rb +15 -0
- data/lib/notable/job_backends/sidekiq.rb +26 -0
- data/lib/notable/middleware.rb +77 -0
- data/lib/notable/throttle.rb +5 -0
- data/lib/notable/unpermitted_parameters.rb +3 -0
- data/lib/notable/unverified_request.rb +19 -0
- data/lib/notable/validation_errors.rb +17 -0
- data/lib/notable/version.rb +3 -0
- data/lib/notable.rb +101 -0
- data/notable.gemspec +26 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1c151df90eb28af125393e544de6e488a7a44d0b
|
4
|
+
data.tar.gz: ce0488e566db76802d5647e56663d08e25adad45
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 998e60bed494684299530eb3282b8a8981c825c5402f8ce19cca9f7accd5e60769eaae9ec4a2ee1c7f82e9227f8225dc2bab06fc879d005d79e2242919fe3733
|
7
|
+
data.tar.gz: 706cefe72681ea3a33937a4d21ca69a6ab431aff1c617c4f71bbea09c2800d5d7e89e64ce6cbb17da3ac26418eb278cc391c4297d01300a077b923c3de2434b3
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Andrew Kane
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# Notable
|
2
|
+
|
3
|
+
Track notable requests and background jobs
|
4
|
+
|
5
|
+
See users affected by:
|
6
|
+
|
7
|
+
- errors
|
8
|
+
- slow requests, jobs, and timeouts
|
9
|
+
- 404s
|
10
|
+
- validation failures
|
11
|
+
- CSRF failures
|
12
|
+
- unpermitted parameters
|
13
|
+
- blocked and throttled requests
|
14
|
+
|
15
|
+
:tangerine: Battle-tested at [Instacart](https://www.instacart.com)
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application’s Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'notable'
|
23
|
+
```
|
24
|
+
|
25
|
+
And run:
|
26
|
+
|
27
|
+
```sh
|
28
|
+
rails generate notable:requests
|
29
|
+
rails generate notable:jobs # optional
|
30
|
+
rake db:migrate
|
31
|
+
```
|
32
|
+
|
33
|
+
For a web interface, check out [Notable Web](https://github.com/ankane/notable_web).
|
34
|
+
|
35
|
+
## Requests
|
36
|
+
|
37
|
+
A `Notable::Request` is created for:
|
38
|
+
|
39
|
+
- errors
|
40
|
+
- slow requests and timeouts
|
41
|
+
- 404s
|
42
|
+
- validation failures
|
43
|
+
- CSRF failures
|
44
|
+
- unpermitted parameters
|
45
|
+
- blocked and throttled requests
|
46
|
+
|
47
|
+
## Jobs
|
48
|
+
|
49
|
+
A `Notable::Job` is created for:
|
50
|
+
|
51
|
+
- errors
|
52
|
+
- slow jobs
|
53
|
+
|
54
|
+
Currently works with Delayed Job and Sidekiq.
|
55
|
+
|
56
|
+
## Manual Tracking
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
Notable.track(note_type, note)
|
60
|
+
```
|
61
|
+
|
62
|
+
## Customize
|
63
|
+
|
64
|
+
Disable tracking in certain environments
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Notable.enabled = Rails.env.production?
|
68
|
+
```
|
69
|
+
|
70
|
+
### Requests
|
71
|
+
|
72
|
+
Set slow threshold
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
Notable.slow_request_threshold = 5 # seconds (default)
|
76
|
+
```
|
77
|
+
|
78
|
+
Custom user method
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
Notable.user_method = proc do |env|
|
82
|
+
env["warden"].try(:user) || env["action_controller.instance"].try(:current_visit)
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
Custom track method
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
Notable.track_request_method = proc do |data, env|
|
90
|
+
Notable::Request.create!(data)
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
### Jobs
|
95
|
+
|
96
|
+
Set slow threshold
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
Notable.slow_job_threshold = 60 # seconds (default)
|
100
|
+
```
|
101
|
+
|
102
|
+
Custom track method
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
Notable.track_job_method = proc do |data|
|
106
|
+
Notable::Job.create!(data)
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
## TODO
|
111
|
+
|
112
|
+
- ability to disable features
|
113
|
+
- add indexes
|
114
|
+
|
115
|
+
## Contributing
|
116
|
+
|
117
|
+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
118
|
+
|
119
|
+
- [Report bugs](https://github.com/ankane/notable/issues)
|
120
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/notable/pulls)
|
121
|
+
- Write, clarify, or fix documentation
|
122
|
+
- Suggest or add new features
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
|
2
|
+
require "rails/generators"
|
3
|
+
require "rails/generators/migration"
|
4
|
+
require "active_record"
|
5
|
+
require "rails/generators/active_record"
|
6
|
+
|
7
|
+
module Notable
|
8
|
+
module Generators
|
9
|
+
class JobsGenerator < Rails::Generators::Base
|
10
|
+
include Rails::Generators::Migration
|
11
|
+
|
12
|
+
source_root File.expand_path("../templates", __FILE__)
|
13
|
+
|
14
|
+
# Implement the required interface for Rails::Generators::Migration.
|
15
|
+
def self.next_migration_number(dirname) #:nodoc:
|
16
|
+
next_migration_number = current_migration_number(dirname) + 1
|
17
|
+
if ActiveRecord::Base.timestamped_migrations
|
18
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
19
|
+
else
|
20
|
+
"%.3d" % next_migration_number
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def copy_migration
|
25
|
+
migration_template "create_jobs.rb", "db/migrate/create_notable_jobs.rb"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
|
2
|
+
require "rails/generators"
|
3
|
+
require "rails/generators/migration"
|
4
|
+
require "active_record"
|
5
|
+
require "rails/generators/active_record"
|
6
|
+
|
7
|
+
module Notable
|
8
|
+
module Generators
|
9
|
+
class RequestsGenerator < Rails::Generators::Base
|
10
|
+
include Rails::Generators::Migration
|
11
|
+
|
12
|
+
source_root File.expand_path("../templates", __FILE__)
|
13
|
+
|
14
|
+
# Implement the required interface for Rails::Generators::Migration.
|
15
|
+
def self.next_migration_number(dirname) #:nodoc:
|
16
|
+
next_migration_number = current_migration_number(dirname) + 1
|
17
|
+
if ActiveRecord::Base.timestamped_migrations
|
18
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
19
|
+
else
|
20
|
+
"%.3d" % next_migration_number
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def copy_migration
|
25
|
+
migration_template "create_requests.rb", "db/migrate/create_notable_requests.rb"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :notable_jobs do |t|
|
4
|
+
t.string :note_type
|
5
|
+
t.text :note
|
6
|
+
t.text :job
|
7
|
+
t.string :job_id
|
8
|
+
t.string :queue
|
9
|
+
t.decimal :runtime
|
10
|
+
t.decimal :queued_time
|
11
|
+
t.timestamp :created_at
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :notable_requests do |t|
|
4
|
+
t.string :note_type
|
5
|
+
t.text :note
|
6
|
+
t.integer :user_id
|
7
|
+
t.string :user_type
|
8
|
+
t.text :action
|
9
|
+
t.integer :status
|
10
|
+
t.text :url
|
11
|
+
t.string :request_id
|
12
|
+
t.string :ip
|
13
|
+
t.text :user_agent
|
14
|
+
t.text :referrer
|
15
|
+
t.text :params
|
16
|
+
t.decimal :request_time
|
17
|
+
t.timestamp :created_at
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index :notable_requests, [:user_id, :user_type]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Notable
|
2
|
+
module DebugExceptions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
alias_method_chain :render_exception, :pass
|
7
|
+
end
|
8
|
+
|
9
|
+
def render_exception_with_pass(env, exception)
|
10
|
+
env["action_dispatch.exception"] = exception
|
11
|
+
render_exception_without_pass(env, exception)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Notable
|
2
|
+
module JobBackends
|
3
|
+
class DelayedJob < Delayed::Plugin
|
4
|
+
callbacks do |lifecycle|
|
5
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
6
|
+
Notable.track_job job.name, job.id, job.queue, job.created_at do
|
7
|
+
block.call(job, *args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Delayed::Worker.plugins << Notable::JobBackends::DelayedJob
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Notable
|
2
|
+
module JobBackends
|
3
|
+
class Sidekiq
|
4
|
+
WRAPPER_CLASSES = Set.new(["ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"])
|
5
|
+
|
6
|
+
def call(worker, job, queue)
|
7
|
+
name =
|
8
|
+
if WRAPPER_CLASSES.include?(job["class"])
|
9
|
+
job["args"].first["job_class"]
|
10
|
+
else
|
11
|
+
job["class"]
|
12
|
+
end
|
13
|
+
|
14
|
+
Notable.track_job name, job["jid"], queue, Time.at(job["enqueued_at"]) do
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Sidekiq.configure_server do |config|
|
23
|
+
config.server_middleware do |chain|
|
24
|
+
chain.add Notable::JobBackends::Sidekiq
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Notable
|
2
|
+
class Middleware
|
3
|
+
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
if Notable.enabled
|
10
|
+
start_time = Time.now
|
11
|
+
status, headers, body = @app.call(env)
|
12
|
+
request_time = Time.now - start_time
|
13
|
+
|
14
|
+
safely do
|
15
|
+
if env["action_dispatch.exception"]
|
16
|
+
e = env["action_dispatch.exception"]
|
17
|
+
message =
|
18
|
+
case status.to_i
|
19
|
+
when 404
|
20
|
+
"Not Found"
|
21
|
+
when 503
|
22
|
+
"Timeout"
|
23
|
+
else
|
24
|
+
"Error"
|
25
|
+
end
|
26
|
+
Notable.track message, "#{e.class.name}: #{e.message}"
|
27
|
+
elsif (!status or status.to_i >= 400) and !Notable.notes.any?
|
28
|
+
Notable.track Rack::Utils::HTTP_STATUS_CODES[status.to_i]
|
29
|
+
end
|
30
|
+
|
31
|
+
if request_time > Notable.slow_request_threshold and status.to_i != 503
|
32
|
+
Notable.track "Slow Request"
|
33
|
+
end
|
34
|
+
|
35
|
+
notes = Notable.notes
|
36
|
+
if notes.any?
|
37
|
+
request = ActionDispatch::Request.new(env)
|
38
|
+
|
39
|
+
# hack since Rails modifies PATH_INFO
|
40
|
+
# and we don't want to modify env
|
41
|
+
url = request.base_url + request.script_name + env["REQUEST_PATH"]
|
42
|
+
url << "?#{request.query_string}" unless request.query_string.empty?
|
43
|
+
|
44
|
+
controller = env["action_controller.instance"]
|
45
|
+
action = controller && "#{controller.params["controller"]}##{controller.params["action"]}"
|
46
|
+
params = controller && controller.request.filtered_parameters.except("controller", "action")
|
47
|
+
|
48
|
+
user = Notable.user_method.call(env)
|
49
|
+
|
50
|
+
notes.each do |note|
|
51
|
+
data = {
|
52
|
+
note_type: note[:note_type],
|
53
|
+
note: note[:note],
|
54
|
+
user: user,
|
55
|
+
action: action,
|
56
|
+
status: status,
|
57
|
+
params: params,
|
58
|
+
request_id: request.uuid,
|
59
|
+
ip: request.remote_ip,
|
60
|
+
user_agent: request.user_agent,
|
61
|
+
url: url,
|
62
|
+
referrer: request.referer,
|
63
|
+
request_time: request_time
|
64
|
+
}
|
65
|
+
Notable.track_request_method.call(data, env)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
[status, headers, body]
|
71
|
+
else
|
72
|
+
@app.call(env)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Notable
|
2
|
+
module UnverifiedRequest
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
prepend_before_filter :track_unverified_request
|
7
|
+
end
|
8
|
+
|
9
|
+
def track_unverified_request
|
10
|
+
if !verified_request?
|
11
|
+
expected = form_authenticity_token
|
12
|
+
actual = form_authenticity_param || request.headers["X-CSRF-Token"]
|
13
|
+
Notable.track "Unverified Request", "#{actual || "nil"} != #{expected}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
ActionController::Base.send(:include, Notable::UnverifiedRequest)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Notable
|
2
|
+
module ValidationErrors
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
after_validation :track_validation_errors
|
7
|
+
end
|
8
|
+
|
9
|
+
def track_validation_errors
|
10
|
+
if errors.any?
|
11
|
+
Notable.track "Validation Errors", "#{self.class.name}: #{errors.full_messages.join(", ")}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveRecord::Base.send(:include, Notable::ValidationErrors)
|
data/lib/notable.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "notable/version"
|
2
|
+
|
3
|
+
require "request_store"
|
4
|
+
require "robustly"
|
5
|
+
require "action_dispatch/middleware/debug_exceptions"
|
6
|
+
|
7
|
+
# middleware
|
8
|
+
require "notable/middleware"
|
9
|
+
require "notable/engine" if defined?(Rails)
|
10
|
+
|
11
|
+
# requests
|
12
|
+
require "notable/unpermitted_parameters"
|
13
|
+
require "notable/unverified_request"
|
14
|
+
require "notable/validation_errors"
|
15
|
+
require "notable/debug_exceptions"
|
16
|
+
require "notable/throttle"
|
17
|
+
|
18
|
+
# jobs
|
19
|
+
require "notable/job_backends/sidekiq" if defined?(Sidekiq)
|
20
|
+
require "notable/job_backends/delayed_job" if defined?(Delayed::Job)
|
21
|
+
|
22
|
+
module Notable
|
23
|
+
class << self
|
24
|
+
attr_accessor :enabled
|
25
|
+
|
26
|
+
# requests
|
27
|
+
attr_accessor :track_request_method
|
28
|
+
attr_accessor :user_method
|
29
|
+
attr_accessor :slow_request_threshold
|
30
|
+
|
31
|
+
# jobs
|
32
|
+
attr_accessor :track_job_method
|
33
|
+
attr_accessor :slow_job_threshold
|
34
|
+
end
|
35
|
+
self.enabled = true
|
36
|
+
|
37
|
+
# requests
|
38
|
+
self.track_request_method = proc{|data, env| Notable::Request.create!(data) }
|
39
|
+
self.user_method = proc{|env| env["warden"].user if env["warden"] }
|
40
|
+
self.slow_request_threshold = 5
|
41
|
+
|
42
|
+
# jobs
|
43
|
+
self.track_job_method = proc{|data| Notable::Job.create!(data) }
|
44
|
+
self.slow_job_threshold = 60
|
45
|
+
|
46
|
+
def self.note(note_type, note = nil)
|
47
|
+
(RequestStore.store[:notable_notes] ||= []) << {note_type: note_type, note: note}
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.notes
|
51
|
+
RequestStore.store[:notable_notes].to_a
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.clear_notes
|
55
|
+
RequestStore.store.delete(:notable_notes)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.track_job(job, job_id, queue, created_at, &block)
|
59
|
+
if Notable.enabled
|
60
|
+
exception = nil
|
61
|
+
notes = nil
|
62
|
+
start_time = Time.now
|
63
|
+
queued_time = start_time - created_at
|
64
|
+
begin
|
65
|
+
yield
|
66
|
+
rescue Exception => e
|
67
|
+
exception = e
|
68
|
+
ensure
|
69
|
+
notes = Notable.notes
|
70
|
+
Notable.clear_notes
|
71
|
+
end
|
72
|
+
runtime = Time.now - start_time
|
73
|
+
|
74
|
+
safely do
|
75
|
+
notes << {note_type: "Error", note: "#{exception.class.name}: #{exception.message}"} if exception
|
76
|
+
notes << {note_type: "Slow Job"} if runtime > Notable.slow_job_threshold
|
77
|
+
|
78
|
+
notes.each do |note|
|
79
|
+
data = {
|
80
|
+
note_type: note[:note_type],
|
81
|
+
note: note[:note],
|
82
|
+
job: job,
|
83
|
+
job_id: job_id,
|
84
|
+
queue: queue,
|
85
|
+
runtime: runtime,
|
86
|
+
queued_time: queued_time
|
87
|
+
}
|
88
|
+
|
89
|
+
Notable.track_job_method.call(data)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
raise exception if exception
|
94
|
+
else
|
95
|
+
yield
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
ActionDispatch::DebugExceptions.send(:include, Notable::DebugExceptions)
|
data/notable.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'notable/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "notable"
|
8
|
+
spec.version = Notable::VERSION
|
9
|
+
spec.authors = ["Andrew Kane"]
|
10
|
+
spec.email = ["andrew@chartkick.com"]
|
11
|
+
spec.summary = %q{Track notable requests and background jobs}
|
12
|
+
spec.description = %q{Track notable requests and background jobs}
|
13
|
+
spec.homepage = "https://github.com/ankane/notable"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "request_store"
|
22
|
+
spec.add_dependency "robustly"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: notable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Kane
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: request_store
|
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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: robustly
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
description: Track notable requests and background jobs
|
70
|
+
email:
|
71
|
+
- andrew@chartkick.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- app/models/notable/job.rb
|
82
|
+
- app/models/notable/request.rb
|
83
|
+
- lib/generators/notable/jobs_generator.rb
|
84
|
+
- lib/generators/notable/requests_generator.rb
|
85
|
+
- lib/generators/notable/templates/create_jobs.rb
|
86
|
+
- lib/generators/notable/templates/create_requests.rb
|
87
|
+
- lib/notable.rb
|
88
|
+
- lib/notable/debug_exceptions.rb
|
89
|
+
- lib/notable/engine.rb
|
90
|
+
- lib/notable/job_backends/delayed_job.rb
|
91
|
+
- lib/notable/job_backends/sidekiq.rb
|
92
|
+
- lib/notable/middleware.rb
|
93
|
+
- lib/notable/throttle.rb
|
94
|
+
- lib/notable/unpermitted_parameters.rb
|
95
|
+
- lib/notable/unverified_request.rb
|
96
|
+
- lib/notable/validation_errors.rb
|
97
|
+
- lib/notable/version.rb
|
98
|
+
- notable.gemspec
|
99
|
+
homepage: https://github.com/ankane/notable
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
metadata: {}
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.2.2
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: Track notable requests and background jobs
|
123
|
+
test_files: []
|