bidu-mercy 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: 3ba27966c96140a28442d6b9a52b8c54500ee5dc
4
+ data.tar.gz: 378791324c844494e19e2b043e017f89aaecbd3c
5
+ SHA512:
6
+ metadata.gz: 80d9c849a716494ab02908d0ec612334762be08726f4e2dd14dddac677426a76ee9d8e68fa9bcfc76c1da413f638f6536634e097f802db02d15143f635ca0c73
7
+ data.tar.gz: 8782984c3bf03c608ab7a93189633eed7e486ef16af5c4a44ae5298dfd7730197c1b97e813cbd4c274628917751e954c08914fd39b859aa109fcc73a59cff3b3
@@ -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
+ bidu-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
+ bidu-mercy!
80
+ bundler
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