sidekiq-cronitor 2.0.0 → 3.1.1
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 +4 -4
- data/README.md +72 -16
- data/lib/sidekiq/cronitor/periodic_jobs.rb +14 -0
- data/lib/sidekiq/cronitor/sidekiq_scheduler.rb +21 -0
- data/lib/sidekiq/cronitor/version.rb +1 -1
- data/lib/sidekiq/cronitor.rb +43 -46
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fdd6b7a4900b0b4325bdecbb6774f71748e20d81aa44969b4687e6ee833e4b2
|
4
|
+
data.tar.gz: f61d0a3051c15d95d000273bca3b2f127e70d16a28e2769a19bf976a4e47f088
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f687f12236ef9af2041ff33a0ba5df7bdb378ee316ff84ce0c7ae298ab018a973ee168a88eadc07cc4a9d86a3d6ceca9d006a0a166c9f7e4d90462444e70720
|
7
|
+
data.tar.gz: b3d78f111182e36d322c1eaa41f7297b1bddcf286e8240780de2be6092ebd39c36ba9b708b4e013cde8fb8327c751f0a86e73d266951ea4978d5cd72e11c8f34
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Sidekiq Cronitor
|
2
2
|
|
3
|
-
|
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
|
-
|
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='
|
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
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
37
|
+
require 'cronitor'
|
38
|
+
Cronitor.api_key = 'api_key_123'
|
39
|
+
Cronitor.environment = 'development' #default: 'production'
|
40
|
+
```
|
35
41
|
|
36
|
-
|
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
|
-
|
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
|
48
|
-
include Sidekiq::
|
49
|
-
|
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
|
-
|
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
|
data/lib/sidekiq/cronitor.rb
CHANGED
@@ -3,75 +3,72 @@ require 'cronitor'
|
|
3
3
|
|
4
4
|
require 'sidekiq/cronitor/version'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
10
|
+
if defined? Sidekiq::Periodic
|
11
|
+
require 'sidekiq/cronitor/periodic_jobs'
|
12
|
+
end
|
44
13
|
|
45
|
-
|
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
|
58
|
+
return unless should_ping?(worker)
|
62
59
|
|
63
|
-
Sidekiq.logger.debug("[cronitor] ping: worker=#{worker
|
60
|
+
Sidekiq.logger.debug("[cronitor] ping: worker=#{job_key(worker)} state=#{state} message=#{message}")
|
64
61
|
|
65
|
-
worker.
|
62
|
+
cronitor(worker).ping(state: state)
|
66
63
|
rescue Cronitor::Error => e
|
67
|
-
Sidekiq.logger.error("[cronitor] error during ping: worker=#{worker
|
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
|
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
|
74
|
-
worker.
|
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:
|
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:
|
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:
|