neeto-monitor-ruby 1.0.42
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/LICENSE +21 -0
- data/README.md +288 -0
- data/Rakefile +14 -0
- data/lib/neeto-monitor-ruby.rb +7 -0
- data/lib/neeto_monitor_ruby/configuration.rb +92 -0
- data/lib/neeto_monitor_ruby/heartbeat_runner_job.rb +22 -0
- data/lib/neeto_monitor_ruby/init/common.rb +13 -0
- data/lib/neeto_monitor_ruby/init/rails.rb +27 -0
- data/lib/neeto_monitor_ruby/init/ruby.rb +10 -0
- data/lib/neeto_monitor_ruby/monitor.rb +158 -0
- data/lib/neeto_monitor_ruby/monitor_utils.rb +47 -0
- data/lib/neeto_monitor_ruby/neeto_monitor.rb +28 -0
- data/lib/neeto_monitor_ruby/plugin.rb +86 -0
- data/lib/neeto_monitor_ruby/plugins/sidekiq.rb +90 -0
- data/lib/neeto_monitor_ruby/version.rb +5 -0
- data/test/dummy/failure_worker.rb +14 -0
- data/test/dummy/monitor_disabled_worker.rb +14 -0
- data/test/dummy/success_worker.rb +13 -0
- data/test/neeto_monitor/configuration_test.rb +97 -0
- data/test/neeto_monitor/heartbeat_runner_job_test.rb +36 -0
- data/test/neeto_monitor/monitor_test.rb +164 -0
- data/test/neeto_monitor/neeto_monitor_test.rb +10 -0
- data/test/neeto_monitor/plugin_test.rb +78 -0
- data/test/neeto_monitor/plugins/sidekiq_test.rb +75 -0
- data/test/test_helper.rb +15 -0
- metadata +155 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NeetoMonitorRuby
|
4
|
+
module MonitorUtils
|
5
|
+
MONITOR_TYPES = {
|
6
|
+
check: "check",
|
7
|
+
job: "job",
|
8
|
+
heartbeat: "heartbeat"
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
JOB_STATES = {
|
12
|
+
run: "run",
|
13
|
+
complete: "complete",
|
14
|
+
fail: "fail"
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def self.included(klass)
|
18
|
+
klass.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def job(monitor_key, &block)
|
23
|
+
monitor = Monitor.new(monitor_key)
|
24
|
+
series = monitor.generate_stamp
|
25
|
+
monitor.job_ping(state: JOB_STATES[:run], series:)
|
26
|
+
|
27
|
+
block.call
|
28
|
+
monitor.job_ping(state: JOB_STATES[:complete], series:)
|
29
|
+
rescue StandardError => exception
|
30
|
+
monitor.job_ping(state: JOB_STATES[:fail], message: exception.message, series:)
|
31
|
+
raise exception
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_stamp
|
36
|
+
Time.now.utc.to_f
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_series
|
40
|
+
"#{generate_stamp}-#{random_string}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def random_string
|
44
|
+
rand(2**256).to_s(36)[0..7]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require_relative "configuration"
|
5
|
+
require_relative "plugin"
|
6
|
+
|
7
|
+
module NeetoMonitorRuby
|
8
|
+
extend Forwardable
|
9
|
+
extend self
|
10
|
+
|
11
|
+
attr_accessor :config, :logger
|
12
|
+
|
13
|
+
def_delegator "NeetoMonitorRuby::Monitor", :load_monitors!
|
14
|
+
|
15
|
+
def init!(options = {})
|
16
|
+
self.config = Configuration.configure!(options, true)
|
17
|
+
self.logger = self.config.logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_plugins!
|
21
|
+
Dir[File.expand_path("../plugins/*.rb", __FILE__)].each do |plugin|
|
22
|
+
require plugin
|
23
|
+
end
|
24
|
+
Plugin.load!(self.config)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
NeetoMonitor = NeetoMonitorRuby
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NeetoMonitorRuby
|
4
|
+
class Plugin
|
5
|
+
class << self
|
6
|
+
@@instances = {}
|
7
|
+
|
8
|
+
def instances
|
9
|
+
@@instances
|
10
|
+
end
|
11
|
+
|
12
|
+
def register(name = nil, &block)
|
13
|
+
raise(ArgumentError, "Plugin name is required, but was nil.") unless name
|
14
|
+
|
15
|
+
key = name.to_sym
|
16
|
+
raise("Already registered: #{name}") if instances[key]
|
17
|
+
|
18
|
+
instances[key] = new(name).tap { |d| d.instance_eval(&block) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def load!(config)
|
22
|
+
instances.each_pair do |name, plugin|
|
23
|
+
if config.public_send("#{name}_enabled")
|
24
|
+
plugin.load!
|
25
|
+
else
|
26
|
+
NeetoMonitorRuby.logger.debug("skipped plugin #{name} load because it's disabled")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :name, :requirements, :executions, :config
|
33
|
+
|
34
|
+
def initialize(name)
|
35
|
+
@name = name
|
36
|
+
@loaded = false
|
37
|
+
@requirements = []
|
38
|
+
@executions = []
|
39
|
+
end
|
40
|
+
|
41
|
+
def requirement(&block)
|
42
|
+
@requirements << block
|
43
|
+
end
|
44
|
+
|
45
|
+
def execution(&block)
|
46
|
+
@executions << block
|
47
|
+
end
|
48
|
+
|
49
|
+
def load!
|
50
|
+
if loaded?
|
51
|
+
NeetoMonitorRuby.logger.debug("skip plugin #{name} as already loaded")
|
52
|
+
return false
|
53
|
+
elsif fulfilled?
|
54
|
+
NeetoMonitorRuby.logger.debug("load plugin #{name}")
|
55
|
+
@executions.each { |block| instance_eval(&block) }
|
56
|
+
@loaded = true
|
57
|
+
else
|
58
|
+
NeetoMonitorRuby.logger.debug("skip plugin load #{name} requirement not fulfilled")
|
59
|
+
end
|
60
|
+
|
61
|
+
@loaded
|
62
|
+
rescue => exception
|
63
|
+
log_plugin_exception(exception)
|
64
|
+
@loaded = true
|
65
|
+
false
|
66
|
+
end
|
67
|
+
|
68
|
+
def fulfilled?
|
69
|
+
@requirements.all? { |block| instance_eval(&block) }
|
70
|
+
rescue => exception
|
71
|
+
log_plugin_exception(exception)
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
75
|
+
def loaded?
|
76
|
+
@loaded
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def log_plugin_exception(exception)
|
82
|
+
NeetoMonitorRuby.logger.error("plugin error name=#{name} class=#{exception.class} #{exception.message}")
|
83
|
+
NeetoMonitorRuby.logger.error e.backtrace
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../monitor_utils"
|
4
|
+
|
5
|
+
module NeetoMonitorRuby
|
6
|
+
module Plugins
|
7
|
+
module Sidekiq
|
8
|
+
class ServerMiddleware
|
9
|
+
SKIPPED_WORKERS = %w(ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper).freeze
|
10
|
+
|
11
|
+
attr_reader :sidekiq_worker
|
12
|
+
|
13
|
+
def call(worker, _message, _queue)
|
14
|
+
@sidekiq_worker = worker
|
15
|
+
|
16
|
+
job_ping(state: MonitorUtils::JOB_STATES[:run])
|
17
|
+
|
18
|
+
worker_result = yield
|
19
|
+
|
20
|
+
job_ping(state: MonitorUtils::JOB_STATES[:complete])
|
21
|
+
|
22
|
+
worker_result
|
23
|
+
rescue => exception
|
24
|
+
job_ping(state: MonitorUtils::JOB_STATES[:fail], message: exception.message)
|
25
|
+
|
26
|
+
raise exception
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def job_ping(state:, message: nil)
|
32
|
+
return unless can_monitor?
|
33
|
+
|
34
|
+
::Sidekiq.logger.debug("neetoMonitor pinging key: #{monitor_key} state: #{state} message: #{message}")
|
35
|
+
|
36
|
+
neeto_monitor.job_ping(state:, message:, series:)
|
37
|
+
|
38
|
+
rescue => exception
|
39
|
+
::Sidekiq.logger.error("Error: neetoMonitor ping #{monitor_key} - #{exception.message}")
|
40
|
+
::Sidekiq.logger.error(exception.backtrace)
|
41
|
+
end
|
42
|
+
|
43
|
+
def series
|
44
|
+
@_series ||= neeto_monitor.generate_series
|
45
|
+
end
|
46
|
+
|
47
|
+
def neeto_monitor
|
48
|
+
@_neeto_monitor ||= NeetoMonitorRuby::Monitor.new(monitor_key)
|
49
|
+
end
|
50
|
+
|
51
|
+
def monitor_key
|
52
|
+
return @_monitor_key if @_monitor_key
|
53
|
+
|
54
|
+
@_monitor_key = fetch_sidekiq_option("neeto_monitor_key", sidekiq_worker.class.name)
|
55
|
+
return @_monitor_key unless NeetoMonitorRuby.config.key_prefix_enabled && NeetoMonitorRuby.config.key_prefix
|
56
|
+
|
57
|
+
@_monitor_key = [NeetoMonitorRuby.config.key_prefix, @_monitor_key].join("::")
|
58
|
+
end
|
59
|
+
|
60
|
+
def neeto_monitor_disabled?
|
61
|
+
fetch_sidekiq_option("neeto_monitor_disabled", false)
|
62
|
+
end
|
63
|
+
|
64
|
+
def fetch_sidekiq_option(key, default = nil)
|
65
|
+
sidekiq_worker.class.sidekiq_options.fetch(key, default)
|
66
|
+
end
|
67
|
+
|
68
|
+
def can_monitor?
|
69
|
+
@_can_monitor ||= !neeto_monitor.api_key.nil? && !neeto_monitor_disabled? && !skip?
|
70
|
+
end
|
71
|
+
|
72
|
+
def skip?
|
73
|
+
SKIPPED_WORKERS.include?(monitor_key) || SKIPPED_WORKERS.include?(monitor_key.split("::", 2).last)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
Plugin.register "sidekiq" do
|
78
|
+
requirement { defined?(::Sidekiq) }
|
79
|
+
|
80
|
+
execution do
|
81
|
+
::Sidekiq.configure_server do |sidekiq|
|
82
|
+
sidekiq.server_middleware do |chain|
|
83
|
+
chain.prepend ServerMiddleware
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../test_helper"
|
4
|
+
|
5
|
+
module NeetoMonitor
|
6
|
+
class ConfigurationTest < Minitest::Test
|
7
|
+
attr_reader :yaml_file_path
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@yaml_file_path = "./test/config.yml"
|
11
|
+
NeetoMonitor::Configuration.reset!
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_configure_with_options
|
15
|
+
config = NeetoMonitor::Configuration.configure!({ api_key: "api_key", environment: "test" }, true)
|
16
|
+
|
17
|
+
assert_equal "api_key", config.api_key
|
18
|
+
assert_equal "test", config.environment
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_configure_with_default_values
|
22
|
+
config = NeetoMonitor::Configuration.configure!
|
23
|
+
|
24
|
+
assert_equal NeetoMonitor::Configuration::BASE_URL, config.base_url
|
25
|
+
assert_equal NeetoMonitor::Configuration::DEFAULT_PING_TIMEOUT, config.ping_timeout
|
26
|
+
assert_equal true, config.sidekiq_enabled
|
27
|
+
assert_nil config.config_path
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_load_config_with_valid_file
|
31
|
+
config_file = File.new(yaml_file_path, "w")
|
32
|
+
config_file.write(YAML.dump(api_key: "dgs56sds7d", environment: "test"))
|
33
|
+
config_file.close
|
34
|
+
|
35
|
+
config = NeetoMonitor::Configuration.configure!({ config_path: config_file.path }, true)
|
36
|
+
|
37
|
+
assert_equal "dgs56sds7d", config.api_key
|
38
|
+
assert_equal "test", config.environment
|
39
|
+
assert_equal "https://neetomonitor.com", config.base_url
|
40
|
+
|
41
|
+
File.delete(yaml_file_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_load_config_with_invalid_file
|
45
|
+
config_file = File.new(yaml_file_path, "w")
|
46
|
+
config_file.write("api_key kbkj'api_key'\" \n}environment: 'test'")
|
47
|
+
config_file.close
|
48
|
+
|
49
|
+
assert_raises NeetoMonitor::ConfigurationError do
|
50
|
+
NeetoMonitor::Configuration.load_config(config_file.path)
|
51
|
+
end
|
52
|
+
|
53
|
+
File.delete(yaml_file_path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_reset
|
57
|
+
config = NeetoMonitor::Configuration.configure!({ api_key: "api_key", config_path: "no-config.yml" }, true)
|
58
|
+
|
59
|
+
assert_equal "https://neetomonitor.com", config.base_url
|
60
|
+
|
61
|
+
NeetoMonitor::Configuration.reset!
|
62
|
+
|
63
|
+
assert_equal "3d6d07b40ac6", NeetoMonitor::Configuration.config.api_key
|
64
|
+
assert_nil NeetoMonitor::Configuration.config.config_path
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_load_config_with_file_not_found
|
68
|
+
assert_raises NeetoMonitor::ConfigurationError do
|
69
|
+
NeetoMonitor::Configuration.load_config("./test/not_found.yml")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_fetch_or_set_value_with_environment_variable
|
74
|
+
original_value = ENV["NEETO_MONITOR_API_KEY"]
|
75
|
+
ENV["NEETO_MONITOR_API_KEY"] = "env_api_key"
|
76
|
+
|
77
|
+
config = NeetoMonitor::Configuration.new
|
78
|
+
|
79
|
+
assert_equal "env_api_key", config.api_key
|
80
|
+
|
81
|
+
ENV["NEETO_MONITOR_API_KEY"] = original_value
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_fetch_or_set_value_with_options
|
85
|
+
config = NeetoMonitor::Configuration.new(api_key: "options_api_key")
|
86
|
+
|
87
|
+
assert_equal "options_api_key", config.api_key
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_fetch_or_set_value_with_default_value
|
91
|
+
config = NeetoMonitor::Configuration.new
|
92
|
+
|
93
|
+
assert_equal 8, config.ping_timeout
|
94
|
+
assert_equal true, config.sidekiq_enabled
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class NeetoMonitor::HeartbeatRunnerJobTest < ActiveJob::TestCase
|
6
|
+
def test_job_pings_heartbeat_and_enqueues_another_job
|
7
|
+
heartbeat_name = "neeto-heartbeat"
|
8
|
+
schedule = "* * * * *"
|
9
|
+
stub_ping_request
|
10
|
+
|
11
|
+
NeetoMonitorRuby::HeartbeatRunnerJob.perform_now(heartbeat_name, schedule)
|
12
|
+
|
13
|
+
assert_enqueued_with(
|
14
|
+
job: NeetoMonitorRuby::HeartbeatRunnerJob,
|
15
|
+
args: [heartbeat_name, schedule],
|
16
|
+
at: ->(t) { t > Time.now }
|
17
|
+
) do
|
18
|
+
NeetoMonitorRuby::HeartbeatRunnerJob.perform_now(heartbeat_name, schedule)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def stub_ping_request(monitor_key = "neeto-heartbeat", params = {}, status_code = 200)
|
25
|
+
stub_request(:get, "https://neetomonitor.com/tm/3d6d07b40ac6/#{monitor_key}")
|
26
|
+
.with(
|
27
|
+
query: hash_including({ "env" => "test" }.merge(params)),
|
28
|
+
headers: {
|
29
|
+
"Accept" => "application/json",
|
30
|
+
"Content-Type" => "application/json",
|
31
|
+
"User-Agent" => "neeto-monitor-ruby"
|
32
|
+
}
|
33
|
+
)
|
34
|
+
.to_return(status: status_code, body: "", headers: {})
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../test_helper"
|
4
|
+
|
5
|
+
class NeetoMonitor::MonitorTest < Minitest::Test
|
6
|
+
include ActiveJob::TestHelper
|
7
|
+
|
8
|
+
def test_monitor_sends_telemetry_event
|
9
|
+
stub_ping_request
|
10
|
+
monitor = NeetoMonitor::Monitor.new("website-check")
|
11
|
+
|
12
|
+
assert monitor.ping
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_monitor_sends_telemetry_event_with_params
|
16
|
+
params = { state: "run", series: "job101" }
|
17
|
+
job_monitor_key = "night-job-check"
|
18
|
+
|
19
|
+
stub_ping_request(job_monitor_key, params)
|
20
|
+
monitor = NeetoMonitor::Monitor.new(job_monitor_key)
|
21
|
+
|
22
|
+
assert monitor.ping(params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_monitor_job_sends_complete_event
|
26
|
+
job_monitor_key = "night-job-check"
|
27
|
+
|
28
|
+
stub_ping_request(job_monitor_key, { state: "run", kind: "job" })
|
29
|
+
stub_ping_request(job_monitor_key, { state: "complete", kind: "job" })
|
30
|
+
|
31
|
+
response = NeetoMonitor::Monitor.job job_monitor_key do
|
32
|
+
perform_addition_work(100, 200)
|
33
|
+
end
|
34
|
+
|
35
|
+
assert response
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_monitor_job_sends_fail_event
|
39
|
+
job_monitor_key = "night-job-check"
|
40
|
+
|
41
|
+
stub_ping_request(job_monitor_key, { state: "run", kind: "job" })
|
42
|
+
stub_ping_request(job_monitor_key, { state: "fail", kind: "job" })
|
43
|
+
|
44
|
+
assert_raises(StandardError) do
|
45
|
+
NeetoMonitor::Monitor.job job_monitor_key { raise StandardError.new }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_load_monitors!
|
50
|
+
yaml_file_path = "./test/config.yml"
|
51
|
+
reset = true
|
52
|
+
stub_bulk_create_request
|
53
|
+
stub_ping_request("neeto-heartbeat")
|
54
|
+
|
55
|
+
assert_no_enqueued_jobs
|
56
|
+
|
57
|
+
NeetoMonitorRuby::HeartbeatRunnerJob.perform_later("neeto-heartbeat", "* * * * *")
|
58
|
+
|
59
|
+
assert_enqueued_jobs 1
|
60
|
+
|
61
|
+
config_file = File.new(yaml_file_path, "w")
|
62
|
+
config_file.write(YAML.dump(config_hash))
|
63
|
+
config_file.close
|
64
|
+
|
65
|
+
NeetoMonitor.init!({ config_path: config_file.path })
|
66
|
+
NeetoMonitor::Monitor.load_monitors!
|
67
|
+
|
68
|
+
assert_enqueued_jobs 1
|
69
|
+
|
70
|
+
NeetoMonitor.init!
|
71
|
+
File.delete(yaml_file_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def stub_ping_request(monitor_key = "website-check", params = {}, status_code = 200)
|
77
|
+
stub_request(:get, "https://neetomonitor.com/tm/3d6d07b40ac6/#{monitor_key}")
|
78
|
+
.with(
|
79
|
+
query: hash_including({ "env" => "test" }.merge(params)),
|
80
|
+
headers: {
|
81
|
+
"Accept" => "application/json",
|
82
|
+
"Content-Type" => "application/json",
|
83
|
+
"User-Agent" => "neeto-monitor-ruby"
|
84
|
+
}
|
85
|
+
)
|
86
|
+
.to_return(status: status_code, body: "", headers: {})
|
87
|
+
end
|
88
|
+
|
89
|
+
def perform_addition_work(param1, param2)
|
90
|
+
param1 + param2
|
91
|
+
end
|
92
|
+
|
93
|
+
def stub_bulk_create_request
|
94
|
+
stub_request(:post, "https://neetomonitor.com/api/v1/clients/bulk_checks")
|
95
|
+
.with(
|
96
|
+
body: bulk_create_params.to_json,
|
97
|
+
headers: {
|
98
|
+
"Accept" => "application/json",
|
99
|
+
"Content-Type" => "application/json",
|
100
|
+
"User-Agent" => "neeto-monitor-ruby"
|
101
|
+
}
|
102
|
+
)
|
103
|
+
.to_return(status: 200, body: "", headers: {})
|
104
|
+
end
|
105
|
+
|
106
|
+
def config_hash
|
107
|
+
{
|
108
|
+
api_key: "3d6d07b40ac6",
|
109
|
+
environment: "test",
|
110
|
+
monitors: {
|
111
|
+
jobs: [
|
112
|
+
{
|
113
|
+
name: "neeto-job",
|
114
|
+
schedule: "0 0 * * *"
|
115
|
+
}
|
116
|
+
],
|
117
|
+
checks: [
|
118
|
+
{
|
119
|
+
name: "neeto-monitor",
|
120
|
+
request_attributes: {
|
121
|
+
endpoint: "http://app.neetomonitor.test/health_check/",
|
122
|
+
kind: "http",
|
123
|
+
verb: "get",
|
124
|
+
interval: 10,
|
125
|
+
timeout: 20
|
126
|
+
}
|
127
|
+
}
|
128
|
+
],
|
129
|
+
heartbeats: [
|
130
|
+
{
|
131
|
+
name: "neeto-heartbeat",
|
132
|
+
schedule: "* * * * *"
|
133
|
+
}
|
134
|
+
]
|
135
|
+
}
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
def bulk_create_params
|
140
|
+
{
|
141
|
+
checks: [
|
142
|
+
{
|
143
|
+
name: "neeto-job",
|
144
|
+
schedule: "0 0 * * *",
|
145
|
+
kind: "job",
|
146
|
+
environment: "test"
|
147
|
+
},
|
148
|
+
{
|
149
|
+
name: "neeto-monitor",
|
150
|
+
request_attributes: {
|
151
|
+
endpoint: "http://app.neetomonitor.test/health_check/",
|
152
|
+
kind: "http",
|
153
|
+
verb: "get",
|
154
|
+
interval: 10,
|
155
|
+
timeout: 20
|
156
|
+
},
|
157
|
+
kind: "check",
|
158
|
+
environment: "test"
|
159
|
+
}
|
160
|
+
],
|
161
|
+
api_key: "3d6d07b40ac6"
|
162
|
+
}
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../test_helper"
|
4
|
+
|
5
|
+
module NeetoMonitor
|
6
|
+
class PluginTest < Minitest::Test
|
7
|
+
attr_reader :config
|
8
|
+
|
9
|
+
def setup
|
10
|
+
NeetoMonitor::Plugin.instances.clear
|
11
|
+
@config = Configuration.new({ sidekiq_enabled: true })
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_register
|
15
|
+
NeetoMonitor::Plugin.register("sidekiq", &requirement_block)
|
16
|
+
instances = NeetoMonitor::Plugin.instances
|
17
|
+
|
18
|
+
assert_equal 1, instances.size
|
19
|
+
assert_equal "sidekiq", instances[:sidekiq].name
|
20
|
+
assert_instance_of NeetoMonitor::Plugin, instances[:sidekiq]
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_register_without_name
|
24
|
+
assert_raises(ArgumentError) { NeetoMonitor::Plugin.register }
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_register_with_duplicate_name
|
28
|
+
NeetoMonitor::Plugin.register("sidekiq", &requirement_block)
|
29
|
+
|
30
|
+
assert_raises(RuntimeError) { NeetoMonitor::Plugin.register("sidekiq", &requirement_block) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_load_enabled_plugins
|
34
|
+
@@executed = false
|
35
|
+
|
36
|
+
NeetoMonitor::Plugin.register("sidekiq") do
|
37
|
+
requirement { true }
|
38
|
+
execution { @@executed = true }
|
39
|
+
end
|
40
|
+
|
41
|
+
NeetoMonitor::Plugin.load!(config)
|
42
|
+
|
43
|
+
sidekiq_instance = NeetoMonitor::Plugin.instances[:sidekiq]
|
44
|
+
|
45
|
+
assert sidekiq_instance.loaded?
|
46
|
+
assert @@executed
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_skip_disabled_plugins
|
50
|
+
NeetoMonitor::Plugin.register("sidekiq", &requirement_block)
|
51
|
+
|
52
|
+
new_config = Configuration.new({ sidekiq_enabled: false })
|
53
|
+
NeetoMonitor::Plugin.load!(new_config)
|
54
|
+
|
55
|
+
instances = NeetoMonitor::Plugin.instances
|
56
|
+
refute instances[:sidekiq].loaded?
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_skip_plugins_with_unfulfilled_requirements
|
60
|
+
NeetoMonitor::Plugin.register("sidekiq", &requirement_unfulfilled_block)
|
61
|
+
|
62
|
+
NeetoMonitor::Plugin.load!(config)
|
63
|
+
|
64
|
+
instances = NeetoMonitor::Plugin.instances
|
65
|
+
refute instances[:sidekiq].loaded?
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def requirement_block
|
71
|
+
proc { requirement { true } }
|
72
|
+
end
|
73
|
+
|
74
|
+
def requirement_unfulfilled_block
|
75
|
+
proc { requirement { false } }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|