cronitor 4.1.2 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
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