mercy 1.3.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +88 -0
  6. data/LICENSE +22 -0
  7. data/README.md +100 -0
  8. data/Rakefile +7 -0
  9. data/circle.yml +16 -0
  10. data/lib/bidu.rb +3 -0
  11. data/lib/bidu/mercy.rb +18 -0
  12. data/lib/bidu/mercy/class_methods.rb +19 -0
  13. data/lib/bidu/mercy/concern.rb +10 -0
  14. data/lib/bidu/mercy/report.rb +44 -0
  15. data/lib/bidu/mercy/report/active_record.rb +28 -0
  16. data/lib/bidu/mercy/report/error.rb +62 -0
  17. data/lib/bidu/mercy/report/multiple.rb +29 -0
  18. data/lib/bidu/mercy/report/range.rb +54 -0
  19. data/lib/bidu/mercy/report_builder.rb +24 -0
  20. data/lib/bidu/mercy/report_config.rb +37 -0
  21. data/lib/bidu/mercy/status.rb +27 -0
  22. data/lib/bidu/mercy/status_builder.rb +35 -0
  23. data/lib/bidu/mercy/version.rb +5 -0
  24. data/lib/bidu/period_parser.rb +32 -0
  25. data/lib/json_parser/type_cast_ext.rb +7 -0
  26. data/mercy.gemspec +33 -0
  27. data/spec/lib/bidu/mercy/report/error_spec.rb +385 -0
  28. data/spec/lib/bidu/mercy/report/multiple_spec.rb +122 -0
  29. data/spec/lib/bidu/mercy/report/range_spec.rb +302 -0
  30. data/spec/lib/bidu/mercy/report/report_config_spec.rb +39 -0
  31. data/spec/lib/bidu/mercy/report_builder_spec.rb +72 -0
  32. data/spec/lib/bidu/mercy/report_spec.rb +44 -0
  33. data/spec/lib/bidu/mercy/status_builder_spec.rb +84 -0
  34. data/spec/lib/bidu/mercy/status_spec.rb +135 -0
  35. data/spec/lib/bidu/period_parser_spec.rb +27 -0
  36. data/spec/spec_helper.rb +32 -0
  37. data/spec/support/fixture_helpers.rb +19 -0
  38. data/spec/support/models/document.rb +6 -0
  39. data/spec/support/report/dummy.rb +17 -0
  40. data/spec/support/schema.rb +11 -0
  41. metadata +236 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 68a29e5f4fa044fa73b32f12b346d4cceed9e412
4
+ data.tar.gz: daf14a5ee6e905a90fef1f07f0bfeed96ef7e88f
5
+ SHA512:
6
+ metadata.gz: 125286d85808a19342179001573365be133f7e88a0a2b847ca3b18a5d5627d41dd78061d1aa82cd82c1c1aa4484fa20f0d2716640fce8672e88a561a45c3f354
7
+ data.tar.gz: 8d67fde38e51096f1fb47f3fa272159658088a152bfadb7ad77d5b6e5a89d98cf9a85f2be2cd232a07e7d7632cbbcb173533b3a21a8bb51d6e57f2e4534fd923
@@ -0,0 +1,2 @@
1
+ coverage
2
+ pkg
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
@@ -0,0 +1,88 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mercy (1.3.0)
5
+ activesupport
6
+ concern_builder
7
+ darthjee-active_ext
8
+ json_parser (~> 1.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activemodel (5.1.1)
14
+ activesupport (= 5.1.1)
15
+ activerecord (5.1.1)
16
+ activemodel (= 5.1.1)
17
+ activesupport (= 5.1.1)
18
+ arel (~> 8.0)
19
+ activesupport (5.1.1)
20
+ concurrent-ruby (~> 1.0, >= 1.0.2)
21
+ i18n (~> 0.7)
22
+ minitest (~> 5.1)
23
+ tzinfo (~> 1.1)
24
+ arel (8.0.0)
25
+ coderay (1.1.1)
26
+ concern_builder (0.0.2)
27
+ activesupport
28
+ concurrent-ruby (1.0.5)
29
+ darthjee-active_ext (1.2.0)
30
+ activesupport (~> 5.1.1)
31
+ darthjee-core_ext (~> 1.2.6)
32
+ darthjee-core_ext (1.2.6)
33
+ activesupport (~> 5.1.1)
34
+ diff-lcs (1.3)
35
+ docile (1.1.5)
36
+ i18n (0.8.4)
37
+ json (2.1.0)
38
+ json_parser (1.1.0)
39
+ activesupport
40
+ concern_builder
41
+ method_source (0.8.2)
42
+ minitest (5.10.2)
43
+ pry (0.10.4)
44
+ coderay (~> 1.1.0)
45
+ method_source (~> 0.8.1)
46
+ slop (~> 3.4)
47
+ pry-nav (0.2.4)
48
+ pry (>= 0.9.10, < 0.11.0)
49
+ rake (12.0.0)
50
+ rspec (3.6.0)
51
+ rspec-core (~> 3.6.0)
52
+ rspec-expectations (~> 3.6.0)
53
+ rspec-mocks (~> 3.6.0)
54
+ rspec-core (3.6.0)
55
+ rspec-support (~> 3.6.0)
56
+ rspec-expectations (3.6.0)
57
+ diff-lcs (>= 1.2.0, < 2.0)
58
+ rspec-support (~> 3.6.0)
59
+ rspec-mocks (3.6.0)
60
+ diff-lcs (>= 1.2.0, < 2.0)
61
+ rspec-support (~> 3.6.0)
62
+ rspec-support (3.6.0)
63
+ simplecov (0.14.1)
64
+ docile (~> 1.1.0)
65
+ json (>= 1.8, < 3)
66
+ simplecov-html (~> 0.10.0)
67
+ simplecov-html (0.10.1)
68
+ slop (3.6.0)
69
+ sqlite3 (1.3.13)
70
+ thread_safe (0.3.6)
71
+ tzinfo (1.2.3)
72
+ thread_safe (~> 0.1)
73
+
74
+ PLATFORMS
75
+ ruby
76
+
77
+ DEPENDENCIES
78
+ activerecord
79
+ bundler
80
+ mercy!
81
+ pry-nav
82
+ rake
83
+ rspec
84
+ simplecov
85
+ sqlite3
86
+
87
+ BUNDLED WITH
88
+ 1.15.1
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Bidu Corretora
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,100 @@
1
+ Bidu House
2
+ ==========
3
+
4
+ [![Code Climate](https://codeclimate.com/github/darthjee/house/badges/gpa.svg)](https://codeclimate.com/github/darthjee/house)
5
+ [![Test Coverage](https://codeclimate.com/github/darthjee/house/badges/coverage.svg)](https://codeclimate.com/github/darthjee/house/coverage)
6
+ [![Issue Count](https://codeclimate.com/github/darthjee/house/badges/issue_count.svg)](https://codeclimate.com/github/darthjee/house)
7
+
8
+ This gem tries to make server monitoring easier and more reliable by adding an easly configurable
9
+ report and making it avaliable in a controller
10
+
11
+ Getting started
12
+ ---------------
13
+ 1. Add House to your `Gemfile` and `bundle install`:
14
+
15
+ ```ruby
16
+ gem 'bidu-house'
17
+ ```
18
+
19
+
20
+ 2. Include in your health check controller passing the configuration to fetch your Documents
21
+ with error and render the report
22
+
23
+ ```ruby
24
+ class HealthCheckController < ApplicationController
25
+ include Bidu::House
26
+
27
+ status_report :failures, clazz: Document
28
+ status_report :failures, clazz: Schedules, on: :schedules
29
+ status_report :delays, clazz: Schedules, scope: :late, on: :schedules
30
+ status_report :'documents.count', clazz: Document, scope: :active, type: House::Range, minimum: 100
31
+ status_report :'documents.errors', clazz: Document, scope: :'active.with_error', type: :range, maximum: 1000
32
+
33
+ def status
34
+ render_status
35
+ end
36
+
37
+ def late_status
38
+ render_status(:schedules)
39
+ end
40
+ end
41
+ ```
42
+
43
+ 3. Add a route to your controller
44
+
45
+ ```ruby
46
+ scope path: 'health-check', controller: :health_check do
47
+ get '/status' => :status
48
+ get '/late-status' => :late_status
49
+ end
50
+ ```
51
+
52
+ 3. Set the correct options on your status report to achieve a perfect report
53
+ - clazz: Class of the object that might contain error
54
+ - period: default search period (default: 1 day)
55
+ - on: report bucket (default: :default)
56
+ - type: report type (error, range or other custom report)
57
+
58
+ Remembering that each report may have its onw parameters
59
+
60
+ - ```House::Error```
61
+ - scope: scope to be fetched when trying to find objects with error (default: :with_error)
62
+ - external_key: column to be exposed as id for the objects with error
63
+ - threshold: default report threshold (default: 0.02)
64
+ - base_scope: scope to be universal sample
65
+ - uniq: when the output ids should not be repeated
66
+ - limit: limit of ids to be outputed
67
+ - ```House::Range```
68
+ - scope: scope of the query to be counted
69
+ - maximum: max value accepted in the range
70
+ - minimum: minimum value accepted in the range
71
+
72
+ 4. Run the server and hit the health-check routes
73
+
74
+ ```
75
+ wget http://localhost:3000/health-check/status
76
+ wget http://localhost:3000/health-check/late-status
77
+ ```
78
+
79
+ 5. Customize your request for multiple reports
80
+ ```
81
+ wget http://localhost:3000/health-check/status?period=3.days&threshold=0.005
82
+ wget http://localhost:3000/health-check/late-status?period=1.hours&threshold=0.1
83
+ ```
84
+
85
+ 6. Use the status json to understand what is wrong
86
+ ```json
87
+ {
88
+ "status": "error",
89
+ "failures": {
90
+ "ids": [10, 14],
91
+ "percentage": 0.5,
92
+ "status": "error"
93
+ },
94
+ "delays": {
95
+ "ids": [12],
96
+ "percentage": 0.001,
97
+ "status": "ok"
98
+ }
99
+ }
100
+ ```
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task test: :spec
@@ -0,0 +1,16 @@
1
+ dependencies:
2
+ post:
3
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
4
+ - chmod +x ./cc-test-reporter
5
+
6
+
7
+ database:
8
+ override:
9
+ - echo "Skipping DB section."
10
+
11
+ test:
12
+ pre:
13
+ - bundle install
14
+ - ./cc-test-reporter before-build
15
+ override:
16
+ - bundle exec rspec; ./cc-test-reporter after-build --exit-code $?
@@ -0,0 +1,3 @@
1
+ module Bidu
2
+ require 'bidu/mercy'
3
+ end
@@ -0,0 +1,18 @@
1
+ require 'darthjee/active_ext'
2
+ require 'concern_builder'
3
+ require 'darthjee/core_ext'
4
+ require 'bidu/period_parser'
5
+ require 'json_parser'
6
+ require 'json_parser/type_cast_ext'
7
+
8
+ module Bidu
9
+ module Mercy
10
+ require 'bidu/mercy/concern'
11
+ require 'bidu/mercy/report_config'
12
+ require 'bidu/mercy/report'
13
+ require 'bidu/mercy/status'
14
+ require 'bidu/mercy/report_builder'
15
+ require 'bidu/mercy/status_builder'
16
+ require 'bidu/mercy/class_methods'
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Bidu
2
+ module Mercy
3
+ module ClassMethods
4
+
5
+ def status_report(*attr_names)
6
+ id = attr_names.first
7
+ options = {
8
+ id: id
9
+ }.merge(attr_names.extract_options!)
10
+
11
+ self.status_builder.add_report_config(id, options)
12
+ end
13
+
14
+ def status_builder
15
+ @status_builder ||= Bidu::Mercy::StatusBuilder.new
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module Bidu
2
+ module Mercy
3
+ extend ActiveSupport::Concern
4
+
5
+ def render_status(key = :default)
6
+ status = self.class.status_builder.build(key, params)
7
+ render json: status.as_json.stringify_keys.to_deep_hash, status: status.status
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ module Bidu
2
+ module Mercy
3
+ class Report
4
+ include JsonParser
5
+ require 'bidu/mercy/report/active_record'
6
+ require 'bidu/mercy/report/error'
7
+ require 'bidu/mercy/report/range'
8
+ require 'bidu/mercy/report/multiple'
9
+ ALLOWED_PARAMETERS = []
10
+ DEFAULT_OPTION = {}
11
+
12
+ attr_reader :json
13
+
14
+ json_parse :id, case: :snake
15
+
16
+ def initialize(options = {})
17
+ @json = default_option.merge(options)
18
+ end
19
+
20
+ def status
21
+ @status ||= error? ? :error : :ok
22
+ end
23
+
24
+ def error?
25
+ raise 'Not implemented yet'
26
+ end
27
+
28
+ def as_json
29
+ { status: status }
30
+ end
31
+
32
+ private
33
+
34
+ def default_option
35
+ self.class.default_options
36
+ end
37
+
38
+ def self.default_options
39
+ return {} if self == Report
40
+ self.superclass.default_options.merge(self::DEFAULT_OPTION)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ module Bidu
2
+ module Mercy
3
+ class Report::ActiveRecord < Report
4
+ json_parse :period, type: :period
5
+ json_parse :clazz, :base_scope, case: :snake
6
+
7
+ private
8
+
9
+ def fetch_scoped(base, scope)
10
+ if (scope.is_a?(Symbol))
11
+ scope.to_s.split('.').inject(base) do |entries, method|
12
+ entries.public_send(method)
13
+ end
14
+ else
15
+ base.where(scope)
16
+ end
17
+ end
18
+
19
+ def last_entries
20
+ @last_entries ||= base.where('updated_at >= ?', period.seconds.ago)
21
+ end
22
+
23
+ def base
24
+ fetch_scoped(clazz, base_scope)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,62 @@
1
+ module Bidu
2
+ module Mercy
3
+ class Report
4
+ class Error < Report::ActiveRecord
5
+ ALLOWED_PARAMETERS=[:period, :threshold]
6
+ DEFAULT_OPTION = {
7
+ external_key: :id,
8
+ threshold: 0.02,
9
+ period: 1.day,
10
+ scope: :with_error,
11
+ base_scope: :all,
12
+ uniq: false
13
+ }
14
+
15
+ json_parse :threshold, type: :float
16
+ json_parse :scope, :external_key, :uniq, :limit, case: :snake
17
+
18
+ def initialize(options)
19
+ super(self.class::DEFAULT_OPTION.merge(options))
20
+ end
21
+
22
+ def percentage
23
+ @percentage ||= fetch_percentage
24
+ end
25
+
26
+ def scoped
27
+ @scoped ||= fetch_scoped(last_entries, scope)
28
+ end
29
+
30
+ def error?
31
+ @error ||= percentage > threshold
32
+ end
33
+
34
+ def as_json
35
+ {
36
+ ids: ids,
37
+ percentage: percentage,
38
+ status: status
39
+ }
40
+ end
41
+
42
+ private
43
+
44
+ def ids
45
+ relation = scoped
46
+ relation = relation.distinct if uniq
47
+ relation = relation.limit(limit) if limit
48
+
49
+ relation.pluck(external_key)
50
+ end
51
+
52
+ def fetch_percentage
53
+ if (scope.is_a?(Symbol))
54
+ last_entries.percentage(*(scope.to_s.split('.').map(&:to_sym)))
55
+ else
56
+ last_entries.percentage(scope)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end