sidekiq-cronitor 2.0.0 → 3.1.1

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: 77c9e01c256be04515fbd21f7e467fb28e632a37f94d639847c6af8ad6e9823b
4
- data.tar.gz: 2c78645ae3fb16b98b52777b3b3124aaa76e6860fc606bee2bc2ab8696275663
3
+ metadata.gz: 7fdd6b7a4900b0b4325bdecbb6774f71748e20d81aa44969b4687e6ee833e4b2
4
+ data.tar.gz: f61d0a3051c15d95d000273bca3b2f127e70d16a28e2769a19bf976a4e47f088
5
5
  SHA512:
6
- metadata.gz: 70c63ea8977ac11afe3991a1290950ed1deaa95c0147e8434fc3d0cf0fd4ed965d6d31354b150ae74e505497d7a5499023ea93f41a7eeca14fdddefc2a38a2c7
7
- data.tar.gz: 6474a1e11df5373147b252fe327373e084f34abb60b6708f99c81df6b1c6d37643642228f1651fca7ddc4d9c0b988abec2f6a045f949f3e0a8e07dd5cc953b30
6
+ metadata.gz: 1f687f12236ef9af2041ff33a0ba5df7bdb378ee316ff84ce0c7ae298ab018a973ee168a88eadc07cc4a9d86a3d6ceca9d006a0a166c9f7e4d90462444e70720
7
+ data.tar.gz: b3d78f111182e36d322c1eaa41f7297b1bddcf286e8240780de2be6092ebd39c36ba9b708b4e013cde8fb8327c751f0a86e73d266951ea4978d5cd72e11c8f34
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # Sidekiq Cronitor
2
2
 
3
- Call a [Cronitor](https://cronitor.io) around your [Sidekiq](https://sidekiq.org) jobs.
3
+ [Cronitor](https://cronitor.io/) provides dead simple monitoring for cron jobs, daemons, queue workers, websites, APIs, and anything else that can send or receive an HTTP request. The Cronitor Sidekiq library provides a drop in integration for monitoring any Sidekiq Job.
4
+
5
+
6
+ #### NOTE: Version 3.0.0 changes the integration method from 2.x.x. This is a breaking change. You now add the middleware in the Sidekiq initializer. You can opt of out telemetry for specific jobs with a sidekiq_options (see below)
4
7
 
5
8
  ## Installation
6
9
 
@@ -19,43 +22,96 @@ bundle
19
22
 
20
23
  ## Usage
21
24
 
22
- Make sure you've got a Cronitor [API Key](https://cronitor.io/docs/api-overview) from [your settings](https://cronitor.io/settings) in your ENV as `CRONITOR_API_KEY` before starting Sidekiq:
25
+ Configure `sidekiq-cronitor` with an [API Key](https://cronitor.io/docs/api-overview) from [your settings](https://cronitor.io/settings). You can use ENV variables to configure Cronitor:
23
26
 
24
27
  ```sh
25
- export CRONITOR_API_KEY='abcdef1234567890abcdef1234567890'
28
+ export CRONITOR_API_KEY='api_key_123'
29
+ export CRONITOR_ENVIRONMENT='development' #default: 'production'
30
+
26
31
  bundle exec sidekiq
27
32
  ```
28
33
 
29
- Any sidekiq worker you'd like to monitor just includes `Sidekiq::Cronitor` right after `Sidekiq::Worker`:
34
+ Or declare the API key directly on the Cronitor module from within your application (e.g. the Sidekiq initializer).
30
35
 
31
36
  ```ruby
32
- class MyWorker
33
- include Sidekiq::Worker
34
- include Sidekiq::Cronitor
37
+ require 'cronitor'
38
+ Cronitor.api_key = 'api_key_123'
39
+ Cronitor.environment = 'development' #default: 'production'
40
+ ```
35
41
 
36
- def perform
37
- # ...
42
+
43
+ To monitor jobs insert the server middleware (most people do this in the Sidekiq initializer)
44
+
45
+ ```ruby
46
+ Sidekiq.configure_server do |config|
47
+ config.server_middleware do |chain|
48
+ chain.add Sidekiq::Cronitor::ServerMiddleware
38
49
  end
39
50
  end
40
51
  ```
41
52
 
42
- By default this will look for an existing monitor named after your worker, `MyWorker` in the case above, and pings that. Otherwise it will try to create a new monitor with the worker's name, which you can configure rules for at a later time via your Cronitor dashboard.
43
53
 
44
- To use a monitor you've already created, you can configure the monitor's `key` directly:
54
+ When this job is invoked, Cronitor will send telemetry pings with a `key` matching the name of your job class (`MyJob` in the example below). If no monitor exists it will create one on the first event. You can configure rules at a later time via the Cronitor dashboard, API, or [YAML config](https://github.com/cronitorio/cronitor-ruby#configuring-monitors) file.
55
+
56
+ Optional: You can specify the monitor key directly using `sidekiq_options`:
45
57
 
46
58
  ```ruby
47
- class MyWorker
48
- include Sidekiq::Worker
49
- include Sidekiq::Cronitor
59
+ class MyJob
60
+ include Sidekiq::Job
61
+ sidekiq_options cronitor_key: 'abc123'
62
+
63
+ def perform
64
+ end
65
+ end
66
+ ```
67
+
50
68
 
51
- sidekiq_options cronitor: { key: 'abc123' }
69
+ To disable Cronitor for a specific job you can set the following option:
70
+
71
+ ```ruby
72
+ class MyJob
73
+ include Sidekiq::Job
74
+ sidekiq_options cronitor_disabled: true
52
75
 
53
76
  def perform
54
- # ...
55
77
  end
56
78
  end
57
79
  ```
58
80
 
81
+ ## Disabling For Some Jobs
82
+ If you have an entire group or category of jobs you wish to disable monitoring on, it's easiest to create a base class with that option set and then have all your jobs inherit from that base class.
83
+
84
+ ```ruby
85
+ class UnmonitoredJob
86
+ include Sidekiq::Job
87
+ sidekiq_options cronitor_disabled: true
88
+ end
89
+
90
+ class NoInstrumentationJob < UnmonitoredJob
91
+ def perform
92
+ end
93
+ end
94
+ ```
95
+
96
+ Note: Do NOT set a cronitor_key option on your base class or all your inherited jobs will report under the same job in Cronitor.
97
+
98
+ ## Job Monitoring
99
+ If you are using Cronitor to monitor scheduled/periodic jobs and have jobs schedules already defined you can use rake tasks to upload the schedule to Cronitor for monitoring.
100
+
101
+ In your projects Rakefile you can load the task to be available to you in your project.
102
+ It might be a good idea to sync these schedules on every deploy
103
+
104
+ ```ruby
105
+ # your Rakefile, find the path to the gem
106
+ spec = Gem::Specification.find_by_name 'sidekiq-cronitor'
107
+ # if you are using sidekiq_scheduler this task should parse and upload the schedule.
108
+ load "#{spec.gem_dir}/lib/tasks/sidekiq_scheduler.rake"
109
+ # if you are using Sidekiq Pro Periodic Jobs this is an example script
110
+ # Note: this hasn't been tested on Sidekiq Pro yet
111
+ load "#{spec.gem_dir}/lib/tasks/periodic_jobs.rake"
112
+ # You only really need to load one of the rake files unless you are somehow running both systems
113
+ ```
114
+
59
115
  ## Development
60
116
 
61
117
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,14 @@
1
+ module Sidekiq::Cronitor
2
+ class PeriodicJobs
3
+ def self.sync_schedule!
4
+ monitors_payload = []
5
+ loops = Sidekiq::Periodic::LoopSet.new
6
+ loops.each do |lop|
7
+ job_key = lop.klass.sidekiq_options.fetch("cronitor_key", nil) || lop.klass.to_s
8
+ cronitor_disabled = lop.klass.sidekiq_options.fetch("cronitor_disabled", false)
9
+ monitors_payload << {key: job_key, schedule: lop.schedule, metadata: lop.options, platform: 'sidekiq', type: 'job' } unless cronitor_disabled
10
+ end
11
+ Cronitor::Monitor.put(monitors: monitors_payload)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module Sidekiq::Cronitor
2
+ class SidekiqScheduler
3
+ def self.sync_schedule!
4
+ monitors_payload = []
5
+ # go through the scheduled jobs and find cron defined ones
6
+ Sidekiq.get_schedule.each do |k, v|
7
+ # make sure the job has a cron or every definition, we skip non cron/every defined jobs for now
8
+ if !v["cron"].nil? || !v["every"].nil?
9
+ schedule = v["cron"] || v["every"]
10
+ # just in case an explicit job key has been set
11
+ job_klass = Object.const_get(v["class"])
12
+ job_key = job_klass.sidekiq_options.fetch("cronitor_key", nil) || v["class"]
13
+ # if monitoring for this job is turned off
14
+ cronitor_disabled = job_klass.sidekiq_options.fetch("cronitor_disabled", false)
15
+ monitors_payload << {key: job_key.to_s, schedule: schedule, platform: 'sidekiq', type: 'job' } unless cronitor_disabled
16
+ end
17
+ end
18
+ Cronitor::Monitor.put(monitors: monitors_payload)
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  module Sidekiq
2
2
  module Cronitor
3
- VERSION = '2.0.0'
3
+ VERSION = '3.1.1'
4
4
  end
5
5
  end
@@ -3,75 +3,72 @@ require 'cronitor'
3
3
 
4
4
  require 'sidekiq/cronitor/version'
5
5
 
6
- module Sidekiq::Cronitor
7
- def self.included(base)
8
- unless base.ancestors.include?(Sidekiq::Worker)
9
- raise ArgumentError, 'Sidekiq::Cronitor can only be included in a Sidekiq::Worker'
10
- end
11
-
12
- base.extend(ClassMethods)
13
-
14
- # Automatically add sidekiq middleware when we're first included
15
- Sidekiq.configure_server do |config|
16
- unless config.server_middleware.exists?(Sidekiq::Cronitor::Middleware)
17
- config.server_middleware.add(Sidekiq::Cronitor::Middleware)
18
- end
19
- end
20
- end
21
-
22
- def cronitor
23
- self.class.cronitor
24
- end
25
-
26
- module ClassMethods
27
- def cronitor
28
- return @cronitor if defined?(@cronitor)
29
-
30
- opts = sidekiq_options.fetch('cronitor', {})
31
- key = opts.symbolize_keys.fetch(:key, name)
32
-
33
- Sidekiq.logger.debug("[cronitor] initializing monitor: worker=#{name} key=#{key}")
34
-
35
- begin
36
- @cronitor = Cronitor::Monitor.new(key)
37
- rescue Cronitor::Error => e
38
- Sidekiq.logger.error("[cronitor] failed to initialize monitor: worker=#{name} error=#{e.message}")
6
+ if defined? SidekiqScheduler
7
+ require 'sidekiq/cronitor/sidekiq_scheduler'
8
+ end
39
9
 
40
- @cronitor = nil
41
- end
42
- end
43
- end
10
+ if defined? Sidekiq::Periodic
11
+ require 'sidekiq/cronitor/periodic_jobs'
12
+ end
44
13
 
45
- class Middleware
14
+ module Sidekiq::Cronitor
15
+ class ServerMiddleware
46
16
  def call(worker, message, queue)
47
17
  ping(worker: worker, state: 'run')
48
18
 
49
- yield
19
+ result = yield
50
20
  rescue => e
51
21
  ping(worker: worker, state: 'fail', message: e.to_s)
52
22
 
53
23
  raise e
54
24
  else
55
25
  ping(worker: worker, state: 'complete')
26
+ result # to be consistent with client middleware, return results of yield
56
27
  end
57
28
 
58
29
  private
30
+ def cronitor(worker)
31
+ Cronitor::Monitor.new(job_key(worker))
32
+ end
33
+
34
+ def cronitor_disabled?(worker)
35
+ disabled = worker.class.sidekiq_options.fetch("cronitor_disabled", nil)
36
+ if disabled.nil?
37
+ options(worker).fetch(:disabled, false)
38
+ else
39
+ !!disabled
40
+ end
41
+ end
42
+
43
+ def job_key(worker)
44
+ worker.class.sidekiq_options.fetch("cronitor_key", nil) ||
45
+ options(worker).fetch(:key, worker.class.name)
46
+ end
47
+
48
+ def options(worker)
49
+ # eventually we will delete this method of passing options
50
+ # ultimately we want all cronitor options to be top level keys
51
+ opts = worker.class.sidekiq_options.fetch("cronitor", {})
52
+ # symbolize_keys is a rails helper, so only use it if it's defined
53
+ opts = opts.symbolize_keys if opts.respond_to?(:symbolize_keys)
54
+ opts
55
+ end
59
56
 
60
57
  def ping(worker:, state:, message: nil)
61
- return unless has_cronitor?(worker)
58
+ return unless should_ping?(worker)
62
59
 
63
- Sidekiq.logger.debug("[cronitor] ping: worker=#{worker.class.name} state=#{state} message=#{message}")
60
+ Sidekiq.logger.debug("[cronitor] ping: worker=#{job_key(worker)} state=#{state} message=#{message}")
64
61
 
65
- worker.cronitor.ping(state: state)
62
+ cronitor(worker).ping(state: state)
66
63
  rescue Cronitor::Error => e
67
- Sidekiq.logger.error("[cronitor] error during ping: worker=#{worker.class.name} error=#{e.message}")
64
+ Sidekiq.logger.error("[cronitor] error during ping: worker=#{job_key(worker)} error=#{e.message}")
68
65
  rescue => e
69
- Sidekiq.logger.error("[cronitor] unexpected error: worker=#{worker.class.name} error=#{e.message}")
66
+ Sidekiq.logger.error("[cronitor] unexpected error: worker=#{job_key(worker)} error=#{e.message}")
70
67
  Sidekiq.logger.error(e.backtrace.first)
71
68
  end
72
69
 
73
- def has_cronitor?(worker)
74
- worker.is_a?(Sidekiq::Cronitor) && worker.respond_to?(:cronitor) && !worker.cronitor.api_key.nil?
70
+ def should_ping?(worker)
71
+ !cronitor(worker).api_key.nil? && !cronitor_disabled?(worker)
75
72
  end
76
73
  end
77
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-cronitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zeke Gabrielse
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-05-11 00:00:00.000000000 Z
12
+ date: 2022-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sidekiq
@@ -107,6 +107,8 @@ files:
107
107
  - LICENSE
108
108
  - README.md
109
109
  - lib/sidekiq/cronitor.rb
110
+ - lib/sidekiq/cronitor/periodic_jobs.rb
111
+ - lib/sidekiq/cronitor/sidekiq_scheduler.rb
110
112
  - lib/sidekiq/cronitor/version.rb
111
113
  homepage: https://github.com/cronitor/sidekiq-cronitor
112
114
  licenses: