abril_heartbeat 1.0.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 (36) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +122 -0
  8. data/Rakefile +6 -0
  9. data/abril_heartbeat.gemspec +32 -0
  10. data/lib/abril_heartbeat.rb +46 -0
  11. data/lib/abril_heartbeat/checkers/abstract_checker.rb +22 -0
  12. data/lib/abril_heartbeat/checkers/mongo_checker.rb +20 -0
  13. data/lib/abril_heartbeat/checkers/mysql_checker.rb +20 -0
  14. data/lib/abril_heartbeat/checkers/redis_checker.rb +20 -0
  15. data/lib/abril_heartbeat/checkers/rest_checker.rb +38 -0
  16. data/lib/abril_heartbeat/config_loader.rb +22 -0
  17. data/lib/abril_heartbeat/heartbeater.rb +23 -0
  18. data/lib/abril_heartbeat/version.rb +3 -0
  19. data/lib/abril_heartbeat/wrappers/mongo_wrapper.rb +11 -0
  20. data/lib/abril_heartbeat/wrappers/mysql_wrapper.rb +11 -0
  21. data/lib/abril_heartbeat/wrappers/redis_wrapper.rb +11 -0
  22. data/spec/cassettes/AbrilHeartbeat_Middleware/when_middleware_handles_the_request/responds_success.yml +111 -0
  23. data/spec/cassettes/HeartbeatAbril_Middleware/when_middleware_handles_the_request/responds_success.yml +111 -0
  24. data/spec/checkers/abstract_checker_spec.rb +5 -0
  25. data/spec/checkers/mongo_checker_spec.rb +42 -0
  26. data/spec/checkers/mysql_checker_spec.rb +42 -0
  27. data/spec/checkers/redis_checker_spec.rb +42 -0
  28. data/spec/checkers/rest_checker_spec.rb +35 -0
  29. data/spec/factories/rest_status.rb +31 -0
  30. data/spec/heartbeater_spec.rb +53 -0
  31. data/spec/middleware/abril_heartbeat_spec.rb +38 -0
  32. data/spec/spec_helper.rb +43 -0
  33. data/spec/support/heartbeat_example.yml +11 -0
  34. data/spec/support/shared_examples/checker_share.rb +21 -0
  35. data/spec/support/vcr.rb +7 -0
  36. metadata +234 -0
@@ -0,0 +1,3 @@
1
+ module AbrilHeartbeat
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,11 @@
1
+ module AbrilHeartbeat
2
+ class MongoWrapper
3
+ def self.check_status!
4
+ ::Mongoid.default_session.command(ping: 1)
5
+ end
6
+
7
+ def self.has_client?
8
+ !!defined?(Mongoid)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module AbrilHeartbeat
2
+ class MysqlWrapper
3
+ def self.check_status!
4
+ ::ActiveRecord::Base.connection.current_database
5
+ end
6
+
7
+ def self.has_client?
8
+ !!defined?(ActiveRecord::Base.connection)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module AbrilHeartbeat
2
+ class RedisWrapper
3
+ def self.check_status!
4
+ ::REDIS.get(:version)
5
+ end
6
+
7
+ def self.has_client?
8
+ !!defined?(REDIS)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,111 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://www.scudelletti.com/
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*; q=0.5, application/xml"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Mon, 29 Sep 2014 17:42:59 GMT
23
+ Server:
24
+ - Apache/2.2.15 (Red Hat)
25
+ Last-Modified:
26
+ - Mon, 14 Jul 2014 11:37:00 GMT
27
+ Etag:
28
+ - '"540027-942-4fe25b58cef00"'
29
+ Accept-Ranges:
30
+ - none
31
+ Content-Type:
32
+ - text/html
33
+ Vary:
34
+ - Accept-Encoding
35
+ Content-Encoding:
36
+ - gzip
37
+ Content-Length:
38
+ - '948'
39
+ body:
40
+ encoding: ASCII-8BIT
41
+ string: !binary |-
42
+ H4sIAAAAAAAAA51W32/bNhB+319x0AsdxJacdGuHxEoRI10bYOuCOsMegqCg
43
+ qbPMhiI1krIqrPvfd5TkWG7aZcmTqfvF7+4+3nm29oU6+wFgtkaetQcvvcKz
44
+ C2lyAwtRZagUei9hAh+qZQMLs/I1twhvdC61RkuKP3EZ1FwqR78Lqbm3nE5X
45
+ PLNSm1nSxQzRC/QcNC8wjTJ0wsrSS6MjEEZ71D6NLlkBDy/nUNMdGW5QmRLt
46
+ GOq1gdrYOzAaLq/BSS0QjqfTl2O4BK5q3jjwtgFvIJNOmA0B5cqjJWxygy4o
47
+ Cn6HUDRdHJ5LhXGb47hLZbzNZAy/GZ2bi/l4m9GHeQRJm4+S+g7WFlcpW3tf
48
+ niTJijJxcW5MrpCX0sXCFIlw7vWKF1I16bnC3GLDDxdcu5Mfp9PxT9MpA4sq
49
+ Zc43Ct0a0TPwTYkp8/jZB28Wbtve98C2A9BK4mD8tXMHdg9uFOA6wluqagu3
50
+ hXrYVn9Q/Ki9LyqrpZJ0n426zJN7xixN1vTxM7kBobhzaRQ6yiURJOp0D7XU
51
+ 73vdvrbgnydCWqFwYPBVgF49S0g4iNJ9fjOq1CtjC94Sbi/s+ugh3ym/o32j
52
+ 47NvPAAMvPIw//3XC7jUPb+M5gq4zuCtrUoD50srFcU73oun+Wb4TRI+6Aw1
53
+ pq7rOPQLM6nbzkiduB3ABPezaEPIIgdnBeVa8Bxdcu9f6jwKDyCN5srk0ZYQ
54
+ u7LxQdEeoAk8yaVfV8sWyADF4xB6vx2At9K/q5bPgeBr6anELYbsSSC2njsU
55
+ 153kOTBCY1Zc4NKYuxbL4ilQ7j13WH7pRc8B8/jzfbxDbYxBg9pocEXSpyLq
56
+ q0NASqnoBZjY2PxxBEvi5P+i6PBz7wHtv/vBUBgeu32zddpwCx9z/hek3c+X
57
+ L3Bze9orgyQuK7ce3bCPDv25EKbSno2B/XE+OT56+erFz69eTI7Y7cH3XC5M
58
+ QfPvPe264DWgayjPf/idK2Xqd9ytg9uKK4ffM6bdJO6uqIIbiXVr1FuNVpUW
59
+ YQ6NDuDvQbo5p2QzI6qCZm8sLHKPbxSGrxHrqsMOTsksDguEbLsV8olveK9t
60
+ ldw1WpDW2wq3wEhMHSXhiHXUZJAO7lJGtIMxLq3xRhgFr4FtOeycYnACbMcg
61
+ dgCHwHpeTzjN08ZL0e1SuumTY6eDtNwwqxx9n5KbN9c8Dw3YJXczvT0FIjsN
62
+ cO3fmwxjqR1aP0faDTjKadm7+2L/czBqz7Nkx5xZ0q07muftX6d/AeG2G0BC
63
+ CQAA
64
+ http_version:
65
+ recorded_at: Mon, 29 Sep 2014 17:42:59 GMT
66
+ - request:
67
+ method: get
68
+ uri: http://www.scudelletti.com/not_found
69
+ body:
70
+ encoding: US-ASCII
71
+ string: ''
72
+ headers:
73
+ Accept:
74
+ - "*/*; q=0.5, application/xml"
75
+ Accept-Encoding:
76
+ - gzip, deflate
77
+ User-Agent:
78
+ - Ruby
79
+ response:
80
+ status:
81
+ code: 404
82
+ message: ''
83
+ headers:
84
+ Date:
85
+ - Mon, 29 Sep 2014 17:42:59 GMT
86
+ Server:
87
+ - Apache/2.2.15 (Red Hat)
88
+ X-Powered-By:
89
+ - Phusion Passenger (mod_rails/mod_rack) 3.0.21
90
+ X-Cascade:
91
+ - pass
92
+ X-Xss-Protection:
93
+ - 1; mode=block
94
+ X-Content-Type-Options:
95
+ - nosniff
96
+ X-Frame-Options:
97
+ - SAMEORIGIN
98
+ Content-Length:
99
+ - '18'
100
+ Status:
101
+ - '404'
102
+ Content-Type:
103
+ - text/html;charset=utf-8
104
+ Accept-Ranges:
105
+ - none
106
+ body:
107
+ encoding: UTF-8
108
+ string: "<h1>Not Found</h1>"
109
+ http_version:
110
+ recorded_at: Mon, 29 Sep 2014 17:42:59 GMT
111
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,111 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://www.scudelletti.com/
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*; q=0.5, application/xml"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Fri, 26 Sep 2014 13:09:40 GMT
23
+ Server:
24
+ - Apache/2.2.15 (Red Hat)
25
+ Last-Modified:
26
+ - Mon, 14 Jul 2014 11:37:00 GMT
27
+ Etag:
28
+ - '"540027-942-4fe25b58cef00"'
29
+ Accept-Ranges:
30
+ - none
31
+ Content-Type:
32
+ - text/html
33
+ Vary:
34
+ - Accept-Encoding
35
+ Content-Encoding:
36
+ - gzip
37
+ Content-Length:
38
+ - '948'
39
+ body:
40
+ encoding: ASCII-8BIT
41
+ string: !binary |-
42
+ H4sIAAAAAAAAA51W32/bNhB+319x0AsdxJacdGuHxEoRI10bYOuCOsMegqCg
43
+ qbPMhiI1krIqrPvfd5TkWG7aZcmTqfvF7+4+3nm29oU6+wFgtkaetQcvvcKz
44
+ C2lyAwtRZagUei9hAh+qZQMLs/I1twhvdC61RkuKP3EZ1FwqR78Lqbm3nE5X
45
+ PLNSm1nSxQzRC/QcNC8wjTJ0wsrSS6MjEEZ71D6NLlkBDy/nUNMdGW5QmRLt
46
+ GOq1gdrYOzAaLq/BSS0QjqfTl2O4BK5q3jjwtgFvIJNOmA0B5cqjJWxygy4o
47
+ Cn6HUDRdHJ5LhXGb47hLZbzNZAy/GZ2bi/l4m9GHeQRJm4+S+g7WFlcpW3tf
48
+ niTJijJxcW5MrpCX0sXCFIlw7vWKF1I16bnC3GLDDxdcu5Mfp9PxT9MpA4sq
49
+ Zc43Ct0a0TPwTYkp8/jZB28Wbtve98C2A9BK4mD8tXMHdg9uFOA6wluqagu3
50
+ hXrYVn9Q/Ki9LyqrpZJ0n426zJN7xixN1vTxM7kBobhzaRQ6yiURJOp0D7XU
51
+ 73vdvrbgnydCWqFwYPBVgF49S0g4iNJ9fjOq1CtjC94Sbi/s+ugh3ym/o32j
52
+ 47NvPAAMvPIw//3XC7jUPb+M5gq4zuCtrUoD50srFcU73oun+Wb4TRI+6Aw1
53
+ pq7rOPQLM6nbzkiduB3ABPezaEPIIgdnBeVa8Bxdcu9f6jwKDyCN5srk0ZYQ
54
+ u7LxQdEeoAk8yaVfV8sWyADF4xB6vx2At9K/q5bPgeBr6anELYbsSSC2njsU
55
+ 153kOTBCY1Zc4NKYuxbL4ilQ7j13WH7pRc8B8/jzfbxDbYxBg9pocEXSpyLq
56
+ q0NASqnoBZjY2PxxBEvi5P+i6PBz7wHtv/vBUBgeu32zddpwCx9z/hek3c+X
57
+ L3Bze9orgyQuK7ce3bCPDv25EKbSno2B/XE+OT56+erFz69eTI7Y7cH3XC5M
58
+ QfPvPe264DWgayjPf/idK2Xqd9ytg9uKK4ffM6bdJO6uqIIbiXVr1FuNVpUW
59
+ YQ6NDuDvQbo5p2QzI6qCZm8sLHKPbxSGrxHrqsMOTsksDguEbLsV8olveK9t
60
+ ldw1WpDW2wq3wEhMHSXhiHXUZJAO7lJGtIMxLq3xRhgFr4FtOeycYnACbMcg
61
+ dgCHwHpeTzjN08ZL0e1SuumTY6eDtNwwqxx9n5KbN9c8Dw3YJXczvT0FIjsN
62
+ cO3fmwxjqR1aP0faDTjKadm7+2L/czBqz7Nkx5xZ0q07muftX6d/AeG2G0BC
63
+ CQAA
64
+ http_version:
65
+ recorded_at: Fri, 26 Sep 2014 13:09:41 GMT
66
+ - request:
67
+ method: get
68
+ uri: http://www.scudelletti.com/not_found
69
+ body:
70
+ encoding: US-ASCII
71
+ string: ''
72
+ headers:
73
+ Accept:
74
+ - "*/*; q=0.5, application/xml"
75
+ Accept-Encoding:
76
+ - gzip, deflate
77
+ User-Agent:
78
+ - Ruby
79
+ response:
80
+ status:
81
+ code: 404
82
+ message: ''
83
+ headers:
84
+ Date:
85
+ - Fri, 26 Sep 2014 13:09:41 GMT
86
+ Server:
87
+ - Apache/2.2.15 (Red Hat)
88
+ X-Powered-By:
89
+ - Phusion Passenger (mod_rails/mod_rack) 3.0.21
90
+ X-Cascade:
91
+ - pass
92
+ X-Xss-Protection:
93
+ - 1; mode=block
94
+ X-Content-Type-Options:
95
+ - nosniff
96
+ X-Frame-Options:
97
+ - SAMEORIGIN
98
+ Content-Length:
99
+ - '18'
100
+ Status:
101
+ - '404'
102
+ Content-Type:
103
+ - text/html;charset=utf-8
104
+ Accept-Ranges:
105
+ - none
106
+ body:
107
+ encoding: UTF-8
108
+ string: "<h1>Not Found</h1>"
109
+ http_version:
110
+ recorded_at: Fri, 26 Sep 2014 13:09:41 GMT
111
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe AbrilHeartbeat::AbstractChecker do
4
+ it_behaves_like "a checker"
5
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe AbrilHeartbeat::MongoChecker do
4
+ let(:success_response) {{ "MONGO" => {"status" => "OK", "status_message" => "Everything is under control" }}}
5
+ let(:fail_response) {{ "MONGO" => {"status" => "FAIL", "status_message" => "XXXX" }}}
6
+
7
+ it_behaves_like "a checker"
8
+
9
+ describe "#run!" do
10
+ context "when the mongo is online" do
11
+ before { allow(AbrilHeartbeat::MongoWrapper).to receive(:check_status!) }
12
+
13
+ subject { described_class.run! }
14
+
15
+ it { is_expected.to eql(success_response) }
16
+ end
17
+
18
+ context "when the mongo offline" do
19
+ before { allow(AbrilHeartbeat::MongoWrapper).to receive(:check_status!) { raise "XXXX" } }
20
+
21
+ subject { described_class.run! }
22
+
23
+ it { is_expected.to eql(fail_response) }
24
+ end
25
+ end
26
+
27
+ describe "#is_running?" do
28
+ context "when the app has a mongo client" do
29
+ before { allow(AbrilHeartbeat::MongoWrapper).to receive(:has_client?) { "constant" } }
30
+
31
+ subject { described_class.is_running? }
32
+
33
+ it { is_expected.to be_truthy }
34
+ end
35
+
36
+ context "when the app does not have a mongo client" do
37
+ subject { described_class.is_running? }
38
+
39
+ it { is_expected.to be_falsy }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe AbrilHeartbeat::MysqlChecker do
4
+ let(:success_response) {{ "MYSQL" => {"status" => "OK", "status_message" => "Everything is under control" }}}
5
+ let(:fail_response) {{ "MYSQL" => {"status" => "FAIL", "status_message" => "YYYY" }}}
6
+
7
+ it_behaves_like "a checker"
8
+
9
+ describe "#run!" do
10
+ context "when the mongo is online" do
11
+ before { allow(AbrilHeartbeat::MysqlWrapper).to receive(:check_status!) }
12
+
13
+ subject { described_class.run! }
14
+
15
+ it { is_expected.to eql(success_response) }
16
+ end
17
+
18
+ context "when the mongo offline" do
19
+ before { allow(AbrilHeartbeat::MysqlWrapper).to receive(:check_status!) { raise "YYYY" } }
20
+
21
+ subject { described_class.run! }
22
+
23
+ it { is_expected.to eql(fail_response) }
24
+ end
25
+ end
26
+
27
+ describe "#is_running?" do
28
+ context "when the app has a mysql client" do
29
+ before { allow(AbrilHeartbeat::MysqlWrapper).to receive(:has_client?) { "constant" } }
30
+
31
+ subject { described_class.is_running? }
32
+
33
+ it { is_expected.to be_truthy }
34
+ end
35
+
36
+ context "when the app does not have a mysql client" do
37
+ subject { described_class.is_running? }
38
+
39
+ it { is_expected.to be_falsy }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe AbrilHeartbeat::RedisChecker do
4
+ let(:success_response) {{ "REDIS" => {"status" => "OK", "status_message" => "Everything is under control" }}}
5
+ let(:fail_response) {{ "REDIS" => {"status" => "FAIL", "status_message" => "ZZZZ" }}}
6
+
7
+ it_behaves_like "a checker"
8
+
9
+ describe "#run!" do
10
+ context "when the mongo is online" do
11
+ before { allow(AbrilHeartbeat::RedisWrapper).to receive(:check_status!) }
12
+
13
+ subject { described_class.run! }
14
+
15
+ it { is_expected.to eql(success_response) }
16
+ end
17
+
18
+ context "when the mongo offline" do
19
+ before { allow(AbrilHeartbeat::RedisWrapper).to receive(:check_status!) { raise "ZZZZ" } }
20
+
21
+ subject { described_class.run! }
22
+
23
+ it { is_expected.to eql(fail_response) }
24
+ end
25
+ end
26
+
27
+ describe "#is_running?" do
28
+ context "when the app has a redis client" do
29
+ before { allow(AbrilHeartbeat::RedisWrapper).to receive(:has_client?) { "constant" } }
30
+
31
+ subject { described_class.is_running? }
32
+
33
+ it { is_expected.to be_truthy }
34
+ end
35
+
36
+ context "when the app does not have a redis client" do
37
+ subject { described_class.is_running? }
38
+
39
+ it { is_expected.to be_falsy }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe AbrilHeartbeat::RestChecker do
4
+ let(:response) {{ "REST" => [build(:api_success), build(:api_not_found), build(:api_wrong_url)] }}
5
+
6
+ let(:input_hash) do
7
+ {
8
+ "api_success" => { "url" => "http://www.scudelletti.com", "type" => "rest" },
9
+ "api_not_found" => { "url" => "http://www.scudelletti.com/not_found", "type" => "rest" },
10
+ "api_wrong_url" => { "url" => "I am a wrong url", "type" => "rest" }
11
+ }
12
+ end
13
+
14
+ before { allow(AbrilHeartbeat::ConfigLoader).to receive(:load) { input_hash } }
15
+
16
+ it_behaves_like "a checker" do
17
+ let(:response) {{ "MODEL" => [{"api_success"=>{"url"=>"http://www.scudelletti.com", "status"=>"OK", "status_message"=>"Everything is OK"}}, {"api_not_found"=>{"url"=>"http://www.scudelletti.com/not_found", "status"=>"OK", "status_message"=>"Everything is OK"}}, {"api_wrong_url"=>{"url"=>"I am a wrong url", "status"=>"OK", "status_message"=>"Everything is OK"}}] }}
18
+ end
19
+
20
+ describe "#is_running?" do
21
+ context "when there is rest calls" do
22
+ subject { described_class.is_running? }
23
+
24
+ it { is_expected.to be_truthy }
25
+ end
26
+
27
+ context "when there is not rest calls" do
28
+ before { allow(AbrilHeartbeat::ConfigLoader).to receive(:load) { {} } }
29
+
30
+ subject { described_class.is_running? }
31
+
32
+ it { is_expected.to be_falsy }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ FactoryGirl.define do
2
+ factory :api_success, class:Hash do
3
+ initialize_with {{
4
+ "api_success" => {
5
+ "url" => "http://www.scudelletti.com",
6
+ "status" => 200,
7
+ "status_message" => "OK"
8
+ }
9
+ }}
10
+ end
11
+
12
+ factory :api_not_found, class:Hash do
13
+ initialize_with {{
14
+ "api_not_found" => {
15
+ "url" => "http://www.scudelletti.com/not_found",
16
+ "status" => 404,
17
+ "status_message" => "Page Not Found"
18
+ }
19
+ }}
20
+ end
21
+
22
+ factory :api_wrong_url, class:Hash do
23
+ initialize_with {{
24
+ "api_wrong_url" => {
25
+ "url" => "I am a wrong url",
26
+ "status" => nil,
27
+ "status_message" => "bad URI(is not URI?): http://I am a wrong url"
28
+ }
29
+ }}
30
+ end
31
+ end