cronitor 4.1.2 → 5.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33e095f9fcce446c592729b13d8de07592c2549bdb4b4f19c5c4a09fe6024415
4
- data.tar.gz: f3d808e0588b6ac2e03dd4b0b79d41320b37f004f4c8858008076a307acfab84
3
+ metadata.gz: ac1824833468d92068ba5664ef8d667fbe2518b34caa8da2cae3a307a7a923e7
4
+ data.tar.gz: 18ff6d1f48bd6da9686930585b6eaab3d296caedb33c171a5d668c26b69fdaba
5
5
  SHA512:
6
- metadata.gz: 87bb2ea79e7d93ca390296964de090e08f7b010e65aa1626154bd7677c131ab01e896065cacece5701374aacfebc9d7e2823186302245a3dd3d45d1f0069db5d
7
- data.tar.gz: 035fa6604dbc17370f36d8b4833c2aa0938671cef3e85d600a82b811ac1df1306583870478a23be54e645f339d4fe4c504a73416d015a6bc35d11d88952f021b
6
+ metadata.gz: 3d6e6aeaaaf3c0a8e5942132e833f53169756717dfa49d52d6641dc0a644f470cac6cc2124fdaebf12fb7814b485f9a14753c78a2a059541b94662c9127279a7
7
+ data.tar.gz: e2d4da41d199b4ff8c01fa768f69f0a48303c98559a2766f537b0a25f6940df21c0ecd2c94d4318636623f230cd8ff7976b75a3219ece9cae419b6eafa8b10ff
@@ -15,15 +15,14 @@ jobs:
15
15
  runs-on: ubuntu-latest
16
16
 
17
17
  steps:
18
- - uses: actions/checkout@v2
19
- - name: Set up Ruby 2.7
20
- uses: actions/setup-ruby@v1
18
+ - uses: actions/checkout@v3
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
21
  with:
22
- ruby-version: 2.7.x
22
+ ruby-version: 2.7
23
+ bundler-cache: true
23
24
  - name: Build and test with Rake
24
25
  run: |
25
- gem install bundler
26
- bundle install --jobs 4 --retry 3
27
26
  bundle exec rake release
28
27
  with:
29
28
  api_key: ${{secrets.RUBYGEMS_API_KEY}}
@@ -10,25 +10,25 @@ on:
10
10
  - master
11
11
 
12
12
  jobs:
13
- lint:
14
- strategy:
15
- fail-fast: false
16
- matrix:
17
- ruby:
18
- - '2.7'
19
- - '3.0'
13
+ # lint:
14
+ # strategy:
15
+ # fail-fast: false
16
+ # matrix:
17
+ # ruby:
18
+ # - '2.7'
19
+ # - '3.0'
20
20
 
21
- runs-on: ubuntu-latest
21
+ # runs-on: ubuntu-latest
22
22
 
23
- steps:
24
- - uses: actions/checkout@v2
25
- - name: Set up Ruby 2.7
26
- uses: ruby/setup-ruby@v1
27
- with:
28
- ruby-version: ${{ matrix.ruby }}
29
- bundler-cache: true
30
- - name: Run Rubocop
31
- run: bundle exec rake rubocop
23
+ # steps:
24
+ # - uses: actions/checkout@v2
25
+ # - name: Set up Ruby 2.7
26
+ # uses: ruby/setup-ruby@v1
27
+ # with:
28
+ # ruby-version: ${{ matrix.ruby }}
29
+ # bundler-cache: true
30
+ # - name: Run Rubocop
31
+ # run: bundle exec rake rubocop
32
32
 
33
33
  spec:
34
34
  strategy:
@@ -37,18 +37,18 @@ jobs:
37
37
  ruby:
38
38
  - '2.7'
39
39
  - '3.0'
40
+ - '3.1'
41
+ - '3.2'
40
42
 
41
43
  runs-on: ubuntu-latest
42
44
 
43
45
  steps:
44
- - uses: actions/checkout@v2
45
- - name: Set up Ruby 2.7
46
+ - uses: actions/checkout@v3
47
+ - name: Set up Ruby
46
48
  uses: ruby/setup-ruby@v1
47
49
  with:
48
50
  ruby-version: ${{ matrix.ruby }}
49
51
  bundler-cache: true
50
52
  - name: Build and test with Rake
51
53
  run: |
52
- gem install bundler
53
- bundle install --jobs 4 --retry 3
54
54
  bundle exec rake
data/.rubocop.yml CHANGED
@@ -12,6 +12,9 @@ AllCops:
12
12
  TargetRubyVersion: 2.5
13
13
  Exclude:
14
14
  - 'spec/cronitor_spec.rb'
15
+
16
+ RequireMFA:
17
+ Enabled: false
15
18
 
16
19
  Metrics/AbcSize:
17
20
  Enabled: false
data/README.md CHANGED
@@ -29,8 +29,8 @@ The `Cronitor#job` helper will send telemetry events before calling your block a
29
29
  require 'cronitor'
30
30
  Cronitor.api_key = 'api_key_123'
31
31
 
32
- Cronitor.job 'warehouse-replenishmenth-report' do
33
- ReplenishmentReport.new(Date.today).run()
32
+ Cronitor.job 'important-job' do
33
+ ImportantJob.new(Date.today).run()
34
34
  end
35
35
  ```
36
36
 
@@ -40,7 +40,7 @@ Cronitor provides a [separate library](https://github.com/cronitorio/cronitor-si
40
40
 
41
41
  ## Sending Telemetry Events
42
42
 
43
- If you want finer control over when/how [telemetry pings](https://cronitor.io/docs/telemetry-api) are sent,
43
+ If you want more control over when/how [telemetry pings](https://cronitor.io/docs/telemetry-api) are sent,
44
44
  you can instantiate a monitor and call `#ping`.
45
45
 
46
46
  ```ruby
@@ -69,7 +69,7 @@ a deployment or build process. For details on all of the attributes that can be
69
69
  require 'cronitor'
70
70
  Cronitor.api_key = 'api_key_123'
71
71
 
72
- # read config file and set credentials (if included).
72
+ # read config file.
73
73
  Cronitor.read_config('./cronitor.yaml')
74
74
 
75
75
  # sync config file's monitors to Cronitor.
@@ -78,6 +78,9 @@ Cronitor.apply_config
78
78
  # send config file's monitors to Cronitor to validate correctness.
79
79
  # monitors will not be saved.
80
80
  Cronitor.validate_config
81
+
82
+ # generate a new config file from the Cronitor API.
83
+ Cronitor.generate_config
81
84
  ```
82
85
 
83
86
  The `cronitor.yaml` file includes three top level keys `jobs`, `checks`, `heartbeats`. You can configure monitors under each key by defining [monitors](https://cronitor.io/docs/monitor-api#attributes).
@@ -129,7 +132,7 @@ You can also create and update monitors by calling `Monitor.put`.
129
132
  ```ruby
130
133
  require 'cronitor'
131
134
 
132
- monitors = Cronitor::Monitor.put([
135
+ monitors = [
133
136
  {
134
137
  type: 'job',
135
138
  key: 'send-customer-invoices',
@@ -145,13 +148,15 @@ monitors = Cronitor::Monitor.put([
145
148
  request: {
146
149
  url: 'https://cronitor.io'
147
150
  },
148
- schedule: 'every 45 seconds',
151
+ schedule: 'every 60 seconds',
149
152
  assertions: [
150
153
  'response.code = 200',
151
154
  'response.time < 600ms',
152
155
  ]
153
156
  }
154
- ])
157
+ ]
158
+
159
+ Cronitor::Monitor.put(monitors)
155
160
  ```
156
161
 
157
162
  ### Pause, Reset, Delete
@@ -178,6 +183,11 @@ require 'cronitor'
178
183
  Cronitor.api_key = 'apiKey123'
179
184
  Cronitor.api_version = '2020-10-01'
180
185
  Cronitor.environment = 'cluster_1_prod'
186
+
187
+ Cronitor.timeout = 20 # defaults to 10 can also be set with ENV['CRONITOR_TIMEOUT']
188
+ Cronitor.logger = nil # defaults to Logger.new($stdout)
189
+ # faster timeout for potentially more time sensitive call
190
+ Cronitor.ping_timeout = 10 # defaults to 5 can also be set with ENV['CRONITOR_PING_TIMEOUT']
181
191
  ```
182
192
 
183
193
  ## Contributing
@@ -1,33 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cronitor
4
- TYPE_JOB = 'job'
5
- TYPE_HEARTBEAT = 'heartbeat'
6
- TYPE_CHECK = 'check'
7
- MONITOR_TYPES = [TYPE_JOB, TYPE_HEARTBEAT, TYPE_CHECK].freeze
8
- YAML_KEYS = %w[
9
- api_key
10
- api_version
11
- environment
12
- ] + MONITOR_TYPES.map { |t| "#{t}s" }
4
+ MONITOR_TYPES = [
5
+ TYPE_JOB = 'job',
6
+ TYPE_HEARTBEAT = 'heartbeat',
7
+ TYPE_CHECK = 'check'
8
+ ].freeze
9
+ YAML_KEYS = MONITOR_TYPES.map { |t| "#{t}s" }
13
10
 
14
11
  class << self
15
- attr_accessor :api_key, :api_version, :environment, :logger, :config, :_headers
12
+ attr_accessor :api_key, :api_version, :environment, :logger, :config, :timeout, :ping_timeout, :auto_discover_sidekiq
16
13
 
17
14
  def configure(&block)
18
15
  block.call(self)
19
16
  end
20
17
  end
21
18
 
22
- self.api_key = ENV['CRONITOR_API_KEY']
23
- self.api_version = ENV['CRONITOR_API_VERSION']
24
- self.environment = ENV['CRONITOR_ENVIRONMENT']
25
- self.config = ENV['CRONITOR_CONFIG']
19
+ self.api_key = ENV.fetch('CRONITOR_API_KEY', nil)
20
+ self.api_version = ENV.fetch('CRONITOR_API_VERSION', nil)
21
+ self.environment = ENV.fetch('CRONITOR_ENVIRONMENT', nil)
22
+ self.timeout = ENV.fetch('CRONITOR_TIMEOUT', nil) || 10
23
+ self.ping_timeout = ENV.fetch('CRONITOR_PING_TIMEOUT', nil) || 5
24
+ self.config = ENV.fetch('CRONITOR_CONFIG', nil)
25
+ self.auto_discover_sidekiq = ENV.fetch('CRONITOR_AUTO_DISCOVER_SIDEKIQ', 'true').casecmp('true').zero? # https://github.com/cronitorio/cronitor-sidekiq
26
26
  self.logger = Logger.new($stdout)
27
27
  logger.level = Logger::INFO
28
- self._headers = {
29
- 'Content-Type': 'application/json',
30
- 'User-Agent': 'cronitor-ruby',
31
- 'Cronitor-Version': Cronitor.api_version
32
- }
33
28
  end
@@ -6,56 +6,89 @@ module Cronitor
6
6
 
7
7
  PING_RETRY_THRESHOLD = 5
8
8
 
9
+ module Formats
10
+ ALL = [
11
+ JSON = 'json',
12
+ YAML = 'yaml'
13
+ ].freeze
14
+ end
15
+
16
+ module Headers
17
+ JSON = {
18
+ 'Content-Type': 'application/json',
19
+ 'User-Agent': "cronitor-ruby-#{Cronitor::VERSION}",
20
+ 'Cronitor-Version': Cronitor.api_version
21
+ }.freeze
22
+ YAML = JSON.merge({
23
+ 'Content-Type': 'application/yaml'
24
+ })
25
+ end
26
+
9
27
  def self.put(opts = {})
10
28
  rollback = opts[:rollback] || false
11
29
  opts.delete(:rollback)
12
30
 
13
31
  monitors = opts[:monitors] || [opts]
14
32
 
33
+ if opts[:format] == Cronitor::Monitor::Formats::YAML
34
+ url = "#{Cronitor.monitor_api_url}.yaml"
35
+ monitors['rollback'] = true if rollback
36
+ body = YAML.dump(monitors)
37
+ headers = Cronitor::Monitor::Headers::YAML
38
+ else
39
+ url = Cronitor.monitor_api_url
40
+ body = {
41
+ monitors: monitors,
42
+ rollback: rollback
43
+ }.to_json
44
+ headers = Cronitor::Monitor::Headers::JSON
45
+ end
46
+
15
47
  resp = HTTParty.put(
16
- Cronitor.monitor_api_url,
48
+ url,
17
49
  basic_auth: {
18
50
  username: Cronitor.api_key,
19
51
  password: ''
20
52
  },
21
- body: {
22
- monitors: monitors,
23
- rollback: rollback
24
- }.to_json,
25
- headers: Cronitor._headers,
26
- timeout: opts[:timeout] || 10
53
+ body: body,
54
+ headers: headers,
55
+ timeout: opts[:timeout] || Cronitor.timeout
27
56
  )
28
57
 
29
58
  case resp.code
30
59
  when 200
31
- out = []
32
- data = JSON.parse(resp.body)
33
-
34
- (data['monitors'] || []).each do |md|
35
- m = Monitor.new(md['key'])
36
- m.data = Cronitor.symbolize_keys(md)
37
- out << m
60
+ if opts[:format] == Cronitor::Monitor::Formats::YAML
61
+ YAML.safe_load(resp.body)
62
+ else
63
+ out = []
64
+ data = JSON.parse(resp.body)
65
+
66
+ (data['monitors'] || []).each do |md|
67
+ m = Monitor.new(md['key'])
68
+ m.data = Cronitor.symbolize_keys(md)
69
+ out << m
70
+ end
71
+ out.length == 1 ? out[0] : out
38
72
  end
39
- out.length == 1 ? out[0] : out
40
73
  when 400
41
74
  raise ValidationError.new(resp.body)
42
75
  else
43
- raise Error.new("Error connecting to Cronitor: #{resp.code}")
76
+ raise Error.new("Error connecting to Cronitor: #{resp.code}\n #{resp.body}")
44
77
  end
45
78
  end
46
79
 
47
80
  def self.delete(key)
48
81
  resp = HTTParty.delete(
49
82
  "#{Cronitor.monitor_api_url}/#{key}",
50
- timeout: 10,
83
+ timeout: Cronitor.timeout,
51
84
  basic_auth: {
52
85
  username: Cronitor.api_key,
53
86
  password: ''
54
87
  },
55
- headers: Cronitor._headers
88
+ headers: Cronitor::Monitor::Headers::JSON
56
89
  )
57
90
  if resp.code != 204
58
- Cronitor.logger.error("Error deleting monitor: #{key}")
91
+ Cronitor.logger&.error("Error deleting monitor: #{key}")
59
92
  return false
60
93
  end
61
94
  true
@@ -81,7 +114,7 @@ module Cronitor
81
114
  def ping(params = {})
82
115
  retry_count = params[:retry_count] || 0
83
116
  if api_key.nil?
84
- Cronitor.logger.error('No API key detected. Set Cronitor.api_key or initialize Monitor with an api_key:')
117
+ Cronitor.logger&.error('No API key detected. Set Cronitor.api_key or initialize Monitor with an api_key:')
85
118
  return false
86
119
  end
87
120
 
@@ -92,8 +125,8 @@ module Cronitor
92
125
  response = HTTParty.get(
93
126
  ping_url,
94
127
  query: clean_params(params),
95
- timeout: 5,
96
- headers: Cronitor._headers,
128
+ timeout: Cronitor.ping_timeout,
129
+ headers: Cronitor::Monitor::Headers::JSON,
97
130
  query_string_normalizer: lambda do |query|
98
131
  query.compact!
99
132
  metrics = query[:metric]
@@ -106,13 +139,13 @@ module Cronitor
106
139
  )
107
140
 
108
141
  if response.code != 200
109
- Cronitor.logger.error("Cronitor Telemetry Error: #{response.code}")
142
+ Cronitor.logger&.error("Cronitor Telemetry Error: #{response.code}")
110
143
  return false
111
144
  end
112
145
  true
113
146
  rescue StandardError => e
114
147
  # rescue instances of StandardError i.e. Timeout::Error, SocketError, etc
115
- Cronitor.logger.error("Cronitor Telemetry Error: #{e}")
148
+ Cronitor.logger&.error("Cronitor Telemetry Error: #{e}")
116
149
  return false if retry_count >= Monitor::PING_RETRY_THRESHOLD
117
150
 
118
151
  # apply a backoff before sending the next ping
@@ -131,8 +164,8 @@ module Cronitor
131
164
 
132
165
  resp = HTTParty.get(
133
166
  pause_url,
134
- timeout: 5,
135
- headers: Cronitor._headers,
167
+ timeout: Cronitor.timeout,
168
+ headers: Cronitor::Monitor::Headers::JSON,
136
169
  basic_auth: {
137
170
  username: api_key,
138
171
  password: ''
@@ -162,13 +195,13 @@ module Cronitor
162
195
 
163
196
  def fetch
164
197
  unless api_key
165
- Cronitor.logger.error(
198
+ Cronitor.logger&.error(
166
199
  'No API key detected. Set Cronitor.api_key or initialize Monitor with the api_key kwarg'
167
200
  )
168
201
  return
169
202
  end
170
203
 
171
- HTTParty.get(monitor_api_url, timeout: 10, headers: Cronitor._headers, format: :json)
204
+ HTTParty.get(monitor_api_url, timeout: Cronitor.timeout, headers: Cronitor::Monitor::Headers::JSON, format: :json)
172
205
  end
173
206
 
174
207
  def clean_params(params)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cronitor
4
- VERSION = '4.1.2'
4
+ VERSION = '5.1.0'
5
5
  end
data/lib/cronitor.rb CHANGED
@@ -13,7 +13,7 @@ require 'cronitor/version'
13
13
  require 'cronitor/monitor'
14
14
 
15
15
  module Cronitor
16
- def self.read_config(path = nil, output: false)
16
+ def self.read_config(path = nil)
17
17
  Cronitor.config = path || Cronitor.config
18
18
  unless Cronitor.config
19
19
  raise ConfigurationError.new(
@@ -26,40 +26,23 @@ module Cronitor
26
26
  conf.each do |k, _v|
27
27
  raise ConfigurationError.new("Invalid configuration variable: #{k}") unless Cronitor::YAML_KEYS.include?(k)
28
28
  end
29
-
30
- Cronitor.api_key = conf[:api_key] if conf[:api_key]
31
- Cronitor.api_version = conf[:api_version] if conf[:api_version]
32
- Cronitor.environment = conf[:environment] if conf[:environment]
33
-
34
- return unless output
35
-
36
- monitors = []
37
- Cronitor::MONITOR_TYPES.each do |t|
38
- plural_t = "#{t}s"
39
- to_parse = conf[t] || conf[plural_t] || nil
40
- next unless to_parse
41
-
42
- unless to_parse.is_a?(Hash)
43
- raise ConfigurationError.new('A Hash with keys corresponding to monitor keys is expected.')
44
- end
45
-
46
- to_parse.each do |key, m|
47
- m['key'] = key
48
- m['type'] = t
49
- monitors << m
50
- end
51
- end
52
- conf['monitors'] = monitors
53
29
  conf
54
30
  end
55
31
 
56
32
  def self.apply_config(rollback: false)
57
- conf = read_config(output: true)
58
- # allow a significantly longer timeout on requests that are sending full yaml config
59
- monitors = Monitor.put(monitors: conf.fetch('monitors', []), rollback: rollback, timeout: 30)
60
- puts("#{monitors.length} monitors #{rollback ? 'validated' : 'synced to Cronitor'}.")
33
+ conf = read_config
34
+ # allow a significantly longer timeout on requests that are sending full yaml config. min 30 seconds.
35
+ timeout = Cronitor.timeout < 30 ? 30 : Cronitor.timeout
36
+ monitors = Monitor.put(monitors: conf, format: Cronitor::Monitor::Formats::YAML, rollback: rollback,
37
+ timeout: timeout)
38
+ count = 0
39
+ # step through the different monitor types and count up all the returned configurations
40
+ Cronitor::YAML_KEYS.each do |k|
41
+ count += (monitors[k]&.count || 0)
42
+ end
43
+ puts("#{count} monitors #{rollback ? 'validated' : 'synced to Cronitor'}.")
61
44
  rescue ValidationError => e
62
- Cronitor.logger.error(e)
45
+ Cronitor.logger&.error(e)
63
46
  end
64
47
 
65
48
  def self.validate_config
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cronitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.2
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Byrnes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-07-13 00:00:00.000000000 Z
12
+ date: 2023-03-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty