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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: adb80970d221b0ba7554aefd49426eb7018de773f7148200ba1fe588f4ccbc20
4
+ data.tar.gz: 7b080f2c0979e732dafa40243b63d56c23c4ccf6636f21a14959bf062cd9bb62
5
+ SHA512:
6
+ metadata.gz: a9e3eafe53eb9b3a117926a0c8b1d59e83816a86156888212827adc949f463f0efe35a01496e7a3d98c61a8c93ee86daf6df44ac2318055d63d8d76f40981b00
7
+ data.tar.gz: b07f078fae394db5cad93fde00a8871b24535006dc803ac2404f8584a964be0355d099fb6f9ce586d3b07405c98aa2183630f22ab144fc5f902f00a60ccfdd31
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 BigBinary
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.
data/README.md ADDED
@@ -0,0 +1,288 @@
1
+ # neeto-monitor-ruby
2
+
3
+ neetoMonitor - A ruby gem for monitoring application's uptime and performance.
4
+
5
+ Installation:
6
+
7
+ ##### 1. Add the gem
8
+
9
+ ```bash
10
+ gem "neeto-monitor-ruby", git: "https://github.com/bigbinary/neeto-monitor-ruby.git"
11
+ ```
12
+
13
+ ##### 2. Install the gems
14
+
15
+ ```bash
16
+ bundle install
17
+ ```
18
+
19
+ ##### 3. Add configuration
20
+
21
+ The neetoMonitor can be configured at multiple levels. i.e. using
22
+ `env variables`, adding a `config file` or manually passing the configuration
23
+ hash to `NeetoMonitorRuby.init!`.
24
+
25
+ ###### 3.1 Setting the config via `NeetoMonitorRuby.init!`
26
+
27
+ ```ruby
28
+ NeetoMonitorRuby.init!({
29
+ api_key: your_app_api_key,
30
+ environment: production
31
+
32
+ ...
33
+
34
+ })
35
+ ```
36
+
37
+ ###### 3.2 Using a config file
38
+
39
+ ```yaml
40
+ # config/neetomonitor.yml
41
+ ---
42
+ api_key: [API_KEY]
43
+ ping_timeout: 5
44
+ ```
45
+
46
+ Following are the available configuration options with their default values.
47
+
48
+ ```yaml
49
+ base_url: (default: https://neetomonitor.com)
50
+ # The monitor server base URL. In `development` or `staging` we can set this to local/staging URL.
51
+
52
+ api_key: (default: nil)
53
+ # A unique api key for an organization.
54
+
55
+ environment: (default: nil)
56
+ # The monitoring environment name for an application
57
+
58
+ ping_timeout: (default: 8 seconds)
59
+ # The request timeout for ping requests.
60
+
61
+ sidekiq_enabled:
62
+ # Enables sidekiq plugin to report worker/job events.
63
+
64
+ config_path: (default: "config/neetomonitor.yml")
65
+ # The config file path
66
+
67
+ key_prefix_enabled: (default: true)
68
+ # This allows to enable/disable prefix for monitor key.
69
+
70
+ key_prefix: (default: application's name e.g. NeetoKb if integrated in neetoKb)
71
+ # The prefix added to the monitor key. e.g. if the check name is ArticleWorker, the result will be NeetoKb::ArticleWorker.
72
+
73
+ monitors:
74
+ # more on this in next section
75
+ ```
76
+
77
+ ###### 3.3 Using ENV variables:
78
+
79
+ The `ENV` variables must start with `NEETO_MONITOR` e.g.
80
+ `NEETO_MONITOR_API_KEY`.
81
+
82
+ Similarly, other ENV variables can also be set by prefixing with
83
+ `NEETO_MONITOR_`.
84
+
85
+ The precedence of the configuration is as follows:
86
+
87
+ ```
88
+ Options passed to NeetoMonitorRuby.init! > Config file > ENV variables > default values
89
+ ```
90
+
91
+ ##### 4. Configuring monitors
92
+
93
+ The monitors can be added in bulk using a config file. e.g.
94
+
95
+ ```yaml
96
+ api_key: [API_KEY]
97
+ monitors:
98
+ checks:
99
+ - name: "neeto-monitor"
100
+ request_attributes:
101
+ endpoint: "http://app.neetomonitor.test/health_check/"
102
+ kind: "http"
103
+ verb: "get"
104
+ interval: 10
105
+ timeout: 20
106
+ assertions_attributes:
107
+ - kind: "response_code"
108
+ verb: "equal"
109
+ value: 200
110
+ jobs:
111
+ - name: "neeto-job"
112
+ assertions_attributes:
113
+ - kind: max_duration
114
+ verb: less_than
115
+ value: 10
116
+ - name: "hard-job",
117
+ schedule: "* * * * *"
118
+ heartbeats:
119
+ - name: "neeto-heartbeat"
120
+ schedule: "* * * * *"
121
+ ```
122
+
123
+ The above config will create total four monitors i.e. 2 jobs and 1 check and 1
124
+ heartbeat.
125
+
126
+ ###### 4.1 Checks monitors (Checks)
127
+
128
+ The checks are used for monitoring website's uptime. The website requests are made at regular intervals which is configured via `interval` attribute.
129
+
130
+ ```yaml
131
+ name: # The name of check monitor e.g. "neeto-auth"
132
+ request_attributes: # This specifies configuring options for the website request.
133
+ endpoint: # The request URL endpoint
134
+
135
+ kind: # The request protocol
136
+
137
+ verb: # The request verb/method i.e. get/post/head etc.
138
+
139
+ interval: # The request frequency
140
+
141
+ timeout: # The request timeout
142
+
143
+ assertions_attributes: # This specifies the assertion to be made when a request is made.
144
+ kind:# The kind of assertion to be made
145
+ # available options => response_code, response_time, response_body, response_json, response_header, ssl_expiry, min_duration, max_duration
146
+
147
+ verb:# The operation verb for assertion
148
+ # available options => less_than, less_than_equal, equal, not_equal, greater_than, greater_than_equal, contains, not_contains
149
+
150
+ key:# The key from the response body json or headers
151
+ # e.g. if response body = { "success": true }, key can be "success"
152
+
153
+ value: # Any value to be checked for the assertion
154
+ ```
155
+
156
+ ###### 4.2 Heartbeat monitors (Heartbeats)
157
+
158
+ The heartbeats are used for monitoring the website/service uptime. The basic
159
+ difference between `checks` and `heartbeats` is that the heartbeats requests are
160
+ sent from the host application. Where as the checks requests are made from the
161
+ `neetoMonitor` server application.
162
+
163
+ The heartbeats can be added via the config file. When it is mentioned in the
164
+ config, the heartbeats will be created in neetoMonitor upon the app
165
+ initialization.
166
+
167
+ When `schedule` is defined for the heartbeats, the gem will send the heartbeats
168
+ using the schedule frequency and neetoMonitor can send alerts when heartbeats are not received in this frequency.
169
+
170
+ The heartbeats events are sent using the `HeartbeatRunnerJob`. This sends the ping at time intervals based on the schedule. E.g. following heartbeat sends a ping every minute.
171
+
172
+ ```ruby
173
+ monitors:
174
+ heartbeats:
175
+ - name: "neeto-heartbeat"
176
+ schedule: "* * * * *" # heartbeat frequency
177
+ ```
178
+
179
+ **Trigger heartbeats from application manually**
180
+ The heartbeats can be triggered manually using a periodic job. If you are using `sidekiq`, you can use `sidekiq-cron` to trigger heartbeats at desired frequency.
181
+
182
+ Here is an example of how you can configure heartbeats manually.
183
+
184
+ ```ruby
185
+ # Worker for sending heartbeat
186
+ class HeartbeatsWorker < BaseWorker
187
+ sidekiq_options neeto_monitor_disabled: true
188
+
189
+ def perform
190
+ super
191
+
192
+ NeetoMonitor::Monitor.new("test-heartbeat").ping
193
+ end
194
+ end
195
+
196
+ # config/schedule.yml
197
+ heartbeat:
198
+ cron: "* * * * *"
199
+ class: "HeartbeatsWorker"
200
+ ```
201
+ ###### 4.3 Job monitors (Jobs)
202
+
203
+ The `jobs` are used for checking reliability and performance of background
204
+ workers.
205
+
206
+ All the monitors can be added either via the web application or from the
207
+ mentioned config file.
208
+
209
+ The `jobs` can be created by other methods as well i.e. without adding `jobs` to
210
+ config section or web application UI. This is done using `Sidekiq` plugin
211
+ included in the gem. When any new worker starts execution e.g. `ArticleJob`, the
212
+ job monitor's `run` event is sent automatically. The `complete` event is sent
213
+ when the job execution is successfully completed. Similarly, `fail` event is
214
+ sent when job execution fails. This `ArticleJob` monitor is created at
215
+ `neetoMonitor` application if it is not created already. If we want `schedule`
216
+ field i.e. periodic job events to be sent to neetoMonitor application, we must
217
+ add such jobs to a config file. e.g.
218
+
219
+ ```yaml
220
+ monitors:
221
+ jobs:
222
+ - name: "NeetoWorker"
223
+ schedule: "* * * * *" # frequency of periodic jobs
224
+ - name: "neeto-job"
225
+ assertions_attributes:
226
+ - kind:
227
+ # available values => max_duration, min_duration
228
+ verb:
229
+ # available values => less_than_or_equal, less_than, greater_than, greater_than_or_equal, equal
230
+ value:
231
+ # allowed values => integer/float value
232
+ ```
233
+
234
+ The job events are automatically sent from the `sidekiq` plugin when
235
+ `sidekiq_enabled` is set to true. This flag is set to `true` by default. The job
236
+ events are not sent when this plugin is not enabled. The gem currently supports
237
+ only `Sidekiq` for background job monitoring. If we are using any other library
238
+ for background jobs, we can send the events manually. E.g.
239
+
240
+ ```ruby
241
+ class ArticleJob
242
+ ..
243
+
244
+ ...
245
+
246
+ def perform
247
+ job_monitor = NeetoMonitorRuby::Monitor.new("ArticleJob")
248
+ series_stamp = Time.now.utc.to_f
249
+ job_monitor.job_ping(state: "run", series: series_stamp)
250
+
251
+ process_article_job # job business logic
252
+
253
+ job_monitor.job_ping(state: "complete", series: series_stamp)
254
+ rescue StandardError => error
255
+ job_monitor.job_ping(state: "fail", series: series_stamp, message: error.message)
256
+ end
257
+
258
+ private
259
+
260
+ ..
261
+ end
262
+ ```
263
+
264
+ Sometimes we don't want to monitor some `Sidekiq` workers. We have an option to
265
+ disable the monitoring for such workers.
266
+
267
+ ```ruby
268
+ class MonitorDisabledWorker
269
+ include Sidekiq::Worker
270
+ sidekiq_options neeto_monitor_disabled: true
271
+
272
+ ...
273
+
274
+ end
275
+ ```
276
+
277
+ The default `monitor key` for `jobs` are the class name of the `Sidekiq` worker
278
+ itself. We can change the `key` of the monitored job by setting
279
+ `neeto_monitor_key` in `sidekiq_options`.
280
+
281
+ ```ruby
282
+ class CustomMonitorWorker
283
+ include Sidekiq::Worker
284
+ sidekiq_options neeto_monitor_key: "super_worker"
285
+
286
+ ...
287
+ end
288
+ ```
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "bundler/gem_tasks"
5
+ require "rake/testtask"
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << "test"
9
+ t.pattern = "test/**/*_test.rb"
10
+ t.verbose = false
11
+ t.warning = false
12
+ end
13
+
14
+ task default: :test
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(::Rails::Railtie)
4
+ require "neeto_monitor_ruby/init/rails"
5
+ else
6
+ require "neeto_monitor_ruby/init/ruby"
7
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module NeetoMonitorRuby
6
+ class ConfigurationError < StandardError; end
7
+
8
+ class Configuration
9
+ BASE_URL = "https://neetomonitor.com".freeze
10
+ DEFAULT_PING_TIMEOUT = 8
11
+ DEFAULT_CONFIG_PATH = "config/neetomonitor.yml"
12
+
13
+ class << self
14
+ attr_accessor :config
15
+
16
+ def configure!(options = {}, reset = false)
17
+ return config if !config.nil? && !reset
18
+
19
+ reset! if reset
20
+
21
+ config_options = options.dup
22
+
23
+ config_path = if options[:config_path]
24
+ options[:config_path]
25
+ else
26
+ file_path = ENV.fetch("NEETO_MONITOR_CONFIG_PATH", DEFAULT_CONFIG_PATH)
27
+
28
+ defined?(Rails) && Rails.respond_to?(:root) ? Rails.root.join(file_path) : file_path
29
+ end
30
+
31
+ config_options = load_config(config_path).merge(config_options) if config_path && load_config?(config_path)
32
+
33
+ self.config = Configuration.new(config_options)
34
+ config
35
+ end
36
+
37
+ def reset!
38
+ self.config = Configuration.new
39
+
40
+ config
41
+ end
42
+
43
+ def load_config?(config_path)
44
+ File.exist?(config_path)
45
+ end
46
+
47
+ def load_config(file_path)
48
+ config = YAML.load(ERB.new(File.read(file_path)).result(binding))
49
+
50
+ JSON.parse(JSON[config], symbolize_names: true)
51
+
52
+ rescue Errno::ENOENT
53
+ raise ConfigurationError.new("#{file_path} not found")
54
+ rescue Psych::SyntaxError => e
55
+ raise ConfigurationError.new("#{file_path} is malformed: #{e.message}")
56
+ end
57
+ end
58
+
59
+ attr_accessor :base_url, :api_key, :environment, :ping_timeout, :logger, :config_path, :monitors,
60
+ :sidekiq_enabled, :key_prefix_enabled, :key_prefix
61
+
62
+ attr_reader :options
63
+
64
+ def initialize(options = {})
65
+ @options = options
66
+ @base_url = fetch_or_set_value(:base_url, BASE_URL)
67
+ @api_key = fetch_or_set_value(:api_key)
68
+ @environment = fetch_or_set_value(:environment)
69
+ @ping_timeout = fetch_or_set_value(:ping_timeout, DEFAULT_PING_TIMEOUT)
70
+ @logger = Logger.new($stdout)
71
+ @sidekiq_enabled = fetch_or_set_value(:sidekiq_enabled, true)
72
+ @config_path = fetch_or_set_value(:config_path)
73
+ @monitors = options[:monitors]
74
+ @key_prefix_enabled = fetch_or_set_value(:key_prefix_enabled, true)
75
+ @key_prefix = fetch_or_set_value(:key_prefix, app_key_prefix)
76
+ end
77
+
78
+ private
79
+
80
+ def fetch_or_set_value(key, default_value = nil)
81
+ env_or_default_value = ENV.fetch("NEETO_MONITOR_#{key.to_s.upcase}", default_value)
82
+
83
+ options.fetch(key, env_or_default_value)
84
+ end
85
+
86
+ def app_key_prefix
87
+ if defined?(Rails) && Rails.respond_to?(:application)
88
+ Rails.application.class.to_s.split("::").first
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fugit"
4
+ require "active_job"
5
+
6
+ module NeetoMonitorRuby
7
+ class HeartbeatRunnerJob < ActiveJob::Base
8
+ queue_as :default
9
+
10
+ def perform(heartbeat_name, schedule)
11
+ NeetoMonitorRuby::Monitor.new(heartbeat_name).ping
12
+
13
+ fugit = Fugit.do_parse_cronish(schedule)
14
+ next_time_string = fugit.next_time(Time.now).to_s
15
+ next_time = Time.parse(next_time_string)
16
+
17
+ NeetoMonitorRuby::HeartbeatRunnerJob.set(wait_until: next_time).perform_later(heartbeat_name, schedule)
18
+ rescue Date::Error, ArgumentError => exception
19
+ NeetoMonitor.logger.error "Error while parsing fugit date time: #{error.message}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "json"
5
+ require "httparty"
6
+ require "socket"
7
+ require "time"
8
+ require "yaml"
9
+
10
+ require "neeto_monitor_ruby/version"
11
+ require "neeto_monitor_ruby/monitor_utils"
12
+ require "neeto_monitor_ruby/monitor"
13
+ require "neeto_monitor_ruby/neeto_monitor"
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails"
4
+
5
+ require_relative "common"
6
+
7
+ module NeetoMonitorRuby
8
+ module Init
9
+ module Rails
10
+ class Railtie < ::Rails::Railtie
11
+ config.before_initialize do
12
+ NeetoMonitorRuby.init!(
13
+ {
14
+ environment: ::Rails.env,
15
+ logger: ::Rails.logger,
16
+ config_path: ::Rails.root.join(Configuration::DEFAULT_CONFIG_PATH)
17
+ })
18
+ end
19
+
20
+ config.after_initialize do
21
+ NeetoMonitorRuby.load_plugins!
22
+ NeetoMonitorRuby.load_monitors!
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "common"
4
+
5
+ NeetoMonitorRuby.init!(
6
+ {
7
+ environment: ENV["RUBY_ENV"] || ENV["RACK_ENV"]
8
+ })
9
+
10
+ NeetoMonitorRuby.load_plugins!
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "httparty"
4
+ require "sidekiq/api"
5
+ require_relative "heartbeat_runner_job"
6
+
7
+ module NeetoMonitorRuby
8
+ class Monitor
9
+ include MonitorUtils
10
+
11
+ REQUEST_HEADERS = {
12
+ 'Content-Type': "application/json",
13
+ 'Accept': "application/json",
14
+ 'User-Agent': "neeto-monitor-ruby"
15
+ }.freeze
16
+
17
+ MAX_RETRY_COUNT = 3
18
+ BULK_CREATE_PATH = "/api/v1/clients/bulk_checks".freeze
19
+
20
+ class << self
21
+ def load_monitors!
22
+ return unless NeetoMonitorRuby.config.api_key
23
+
24
+ config_monitors = NeetoMonitorRuby.config.monitors&.except(:heartbeats)
25
+
26
+ if !config_monitors.blank?
27
+ environment = NeetoMonitorRuby.config.environment
28
+
29
+ all_monitors = config_monitors.each_with_object([]) do |(type, monitors), result|
30
+ monitors.each { |m| result << m.merge(kind: type.to_s.chop, environment:) }
31
+ end
32
+
33
+ make_bulk_create_request({ checks: all_monitors, api_key: NeetoMonitorRuby.config.api_key })
34
+ else
35
+ NeetoMonitorRuby.logger.debug "No monitors found in config"
36
+ end
37
+ end
38
+
39
+ def make_bulk_create_request(check_params)
40
+ bulk_monitors_url = "#{NeetoMonitorRuby.config.base_url}#{BULK_CREATE_PATH}"
41
+
42
+ response = HTTParty.post(
43
+ bulk_monitors_url,
44
+ body: check_params.to_json,
45
+ headers: REQUEST_HEADERS
46
+ )
47
+
48
+ result = response.code >= 200 && response.code < 300
49
+
50
+ NeetoMonitor.logger.error "Bulk create response code: #{response.code}" unless result
51
+
52
+ load_heartbeats! if defined?(ActiveJob::Base)
53
+
54
+ result
55
+ rescue StandardError => exception
56
+ NeetoMonitor.logger.error exception.message
57
+ NeetoMonitor.logger.error exception.backtrace.join("\n")
58
+ end
59
+
60
+ def load_heartbeats!
61
+ NeetoMonitor.logger.debug "Loading heartbeats!!!"
62
+ NeetoMonitor.logger.debug "NeetoMonitor.config.monitors #{NeetoMonitor.config.monitors}"
63
+ heartbeats = NeetoMonitor.config.monitors[:heartbeats]
64
+ prefix = NeetoMonitor.config.key_prefix_enabled ? NeetoMonitor.config.key_prefix : nil
65
+
66
+ heartbeats.each do |heartbeat|
67
+ heartbeat_name = prefix ? [prefix, heartbeat[:name]].join("::") : heartbeat[:name]
68
+
69
+ delete_old_heartbeat_jobs!
70
+
71
+ HeartbeatRunnerJob.perform_later(heartbeat_name, heartbeat[:schedule])
72
+ end
73
+ end
74
+
75
+ def delete_old_heartbeat_jobs!
76
+ if ActiveJob::Base.queue_adapter.respond_to?(:enqueued_jobs)
77
+ ActiveJob::Base.queue_adapter.enqueued_jobs.reject! do |job|
78
+ job["job_class"] == "NeetoMonitorRuby::HeartbeatRunnerJob"
79
+ end
80
+ elsif ActiveJob::Base.queue_adapter.class == ActiveJob::QueueAdapters::SidekiqAdapter
81
+ Sidekiq::ScheduledSet.new.scan("NeetoMonitorRuby::HeartbeatRunnerJob").each do |job|
82
+ job.delete if job.display_class == "NeetoMonitorRuby::HeartbeatRunnerJob"
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ attr_reader :api_key, :environment, :monitor_key
89
+
90
+ def initialize(monitor_key, api_key: nil, environment: nil)
91
+ @monitor_key = monitor_key
92
+ @api_key = api_key || NeetoMonitorRuby.config.api_key
93
+ @environment = environment || NeetoMonitorRuby.config.environment
94
+ end
95
+
96
+ def ping(params = {})
97
+ if api_key.nil?
98
+ log_error "No API key is provided, please pass the api_key or configure."
99
+ return false
100
+ end
101
+
102
+ retry_count = params[:retry_count] || 0
103
+ response = make_ping_request(params)
104
+ response.code >= 200 && response.code < 300
105
+ rescue StandardError => exception
106
+ return false if retry_count >= MAX_RETRY_COUNT
107
+
108
+ retry_ping(params, retry_count)
109
+ end
110
+
111
+ def job_ping(params)
112
+ ping(params.merge(kind: MONITOR_TYPES[:job]))
113
+ end
114
+
115
+ private
116
+
117
+ def make_ping_request(params)
118
+ response = HTTParty.get(
119
+ monitor_ping_url,
120
+ query: sanitize_params(params),
121
+ headers: REQUEST_HEADERS,
122
+ timeout: NeetoMonitorRuby.config.ping_timeout
123
+ )
124
+ end
125
+
126
+ def retry_ping(params, retry_count)
127
+ retry_count += 1
128
+ sleep(retry_count)
129
+ ping(params.merge(retry_count:))
130
+ end
131
+
132
+ def monitor_ping_url
133
+ "#{NeetoMonitorRuby.config.base_url}/tm/#{api_key}/#{CGI.escape(monitor_key)}"
134
+ end
135
+
136
+ def sanitize_params(params)
137
+ {
138
+ state: params.fetch(:state, nil),
139
+ kind: params.fetch(:kind, MONITOR_TYPES[:heartbeat]),
140
+ message: params.fetch(:message, nil),
141
+ series: params.fetch(:series, nil),
142
+ host: params.fetch(:host, Socket.gethostname),
143
+ metrics: params.fetch(:metrics, nil),
144
+ stamp: generate_stamp,
145
+ env: params.fetch(:env, environment)
146
+ }
147
+ end
148
+
149
+ def log_exception(exception)
150
+ log_error exception.message
151
+ log_error exception.backtrace.join("\n")
152
+ end
153
+
154
+ def log_error(text)
155
+ NeetoMonitorRuby.logger.error text
156
+ end
157
+ end
158
+ end