evenitron 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +65 -0
- data/lib/evenitron/collector_client.rb +76 -0
- data/lib/evenitron/delayed_job.rb +112 -0
- data/lib/evenitron/evenitron.rb +32 -0
- data/lib/evenitron/logger.rb +11 -0
- data/lib/evenitron/resque.rb +149 -0
- data/lib/evenitron.rb +12 -0
- metadata +64 -0
data/README.markdown
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Setting up with delayed_job
|
2
|
+
|
3
|
+
There are two options for setting up Evenitron to monitor your delayed_job tasks.
|
4
|
+
|
5
|
+
Firstly, add the gem to your Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'evenitron-ruby', :git => 'git@github.com:evenitron/evenitron-ruby.git'
|
9
|
+
```
|
10
|
+
|
11
|
+
*We'll use the git references if possible until things are public.*
|
12
|
+
|
13
|
+
Then you need to configure it within your `boot.rb` for Rails (I have no idea if this is the right file but it works). You can either do this explicitly:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'evenitron/delayed_job'
|
17
|
+
|
18
|
+
Evenitron::DelayedJob.configure do
|
19
|
+
system_key 'benchmarking'
|
20
|
+
# collector_url 'http://localhost:5000/'
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
Or you can rely on the environment variables `EVENITRON_SYSTEM_KEY` and `EVENITRON_COLLECTOR_URL`:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'evenitron/delayed_job'
|
28
|
+
|
29
|
+
Evenitron::DelayedJob.configure
|
30
|
+
```
|
31
|
+
|
32
|
+
You must specify your system key either through configuration or the `EVENITRON_SYSTEM_KEY` environment variable but you will normally rely on the default collector URL of `https://collector.evenitron.com/`.
|
33
|
+
|
34
|
+
# Setting up with resque
|
35
|
+
|
36
|
+
There are two options for setting up Evenitron to monitor your delayed_job tasks.
|
37
|
+
|
38
|
+
Firstly, add the gem to your Gemfile:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
gem 'evenitron-ruby', :git => 'git@github.com:evenitron/evenitron-ruby.git'
|
42
|
+
```
|
43
|
+
|
44
|
+
*We'll use the git references if possible until things are public.*
|
45
|
+
|
46
|
+
Then you need to configure it within your `boot.rb` for Rails (I have no idea if this is the right file but it works). You can either do this explicitly:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'evenitron/resque'
|
50
|
+
|
51
|
+
Evenitron::Resque.configure do
|
52
|
+
system_key 'benchmarking'
|
53
|
+
# collector_url 'http://localhost:5000/'
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
Or you can rely on the environment variables `EVENITRON_SYSTEM_KEY` and `EVENITRON_COLLECTOR_URL`:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
require 'evenitron/resque'
|
61
|
+
|
62
|
+
Evenitron::Resque.configure
|
63
|
+
```
|
64
|
+
|
65
|
+
You must specify your system key either through configuration or the `EVENITRON_SYSTEM_KEY` environment variable but you will normally rely on the default collector URL of `https://collector.evenitron.com/`.
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Evenitron
|
2
|
+
|
3
|
+
class CollectorClient
|
4
|
+
|
5
|
+
include Evenitron::Logger
|
6
|
+
|
7
|
+
DEFAULT_URL = "https://collector.evenitron.com/"
|
8
|
+
|
9
|
+
def initialize(system_key, url = DEFAULT_URL, component = nil)
|
10
|
+
@system_key = system_key
|
11
|
+
@url = url
|
12
|
+
@user_agent = 'evenitron-ruby 0.1'
|
13
|
+
@user_agent = "#{@user_agent} (#{component})" if component
|
14
|
+
@simulate_requests = ENV['EVENITRON_SIMULATE_REQUESTS'] == 'true'
|
15
|
+
log.warn 'Simulating Evenitron messages' if @simulate_requests
|
16
|
+
end
|
17
|
+
|
18
|
+
def job_queued(args)
|
19
|
+
send_message :queued, args
|
20
|
+
end
|
21
|
+
|
22
|
+
def job_started(args)
|
23
|
+
send_message :started, args
|
24
|
+
end
|
25
|
+
|
26
|
+
def job_failed(args)
|
27
|
+
send_message :failed, args
|
28
|
+
end
|
29
|
+
|
30
|
+
def job_complete(args)
|
31
|
+
send_message :complete, args
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def send_message(stage, args)
|
37
|
+
send message(stage, args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def send(msg)
|
41
|
+
json = msg.to_json
|
42
|
+
|
43
|
+
if @simulate_requests
|
44
|
+
log.info "Simulating message for #{@system_key} to #{@url} - #{json}"
|
45
|
+
return nil
|
46
|
+
else
|
47
|
+
log.debug "Sending message for #{@system_key} to #{@url} - #{json}"
|
48
|
+
end
|
49
|
+
|
50
|
+
Thread.new do
|
51
|
+
begin
|
52
|
+
RestClient.post @url, json, :content_type => nil, 'Evenitron-Key' => @system_key, 'User-Agent' => @user_agent
|
53
|
+
rescue => e
|
54
|
+
log.error "Failed to send message for #{@system_key} to #{@url} - #{json}"
|
55
|
+
log.debug e
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def message(stage, args)
|
63
|
+
msg = args.dup
|
64
|
+
msg[:stage] = stage
|
65
|
+
msg[:version] = 1
|
66
|
+
msg[:timestamp] = since_epoch(Time.now)
|
67
|
+
msg
|
68
|
+
end
|
69
|
+
|
70
|
+
def since_epoch(time)
|
71
|
+
(time.to_f * 1000).to_i
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require_relative '../evenitron'
|
2
|
+
require 'delayed_job'
|
3
|
+
|
4
|
+
module Evenitron
|
5
|
+
|
6
|
+
module DelayedJob
|
7
|
+
|
8
|
+
def self.configure(&block)
|
9
|
+
dj = Evenitron::DelayedJobCollector.new
|
10
|
+
dj.configure &block unless block.nil?
|
11
|
+
dj.start!
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class DelayedJobCollector
|
18
|
+
|
19
|
+
include Evenitron::Logger
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@collector_url = ENV['EVENITRON_COLLECTOR_URL']
|
23
|
+
@system_key = ENV['EVENITRON_SYSTEM_KEY']
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure(&block)
|
27
|
+
instance_eval &block
|
28
|
+
end
|
29
|
+
|
30
|
+
def system_key(key)
|
31
|
+
@system_key = key
|
32
|
+
end
|
33
|
+
|
34
|
+
def api_key(key)
|
35
|
+
@api_key = key
|
36
|
+
end
|
37
|
+
|
38
|
+
def collector_url(url)
|
39
|
+
@collector_url = url
|
40
|
+
end
|
41
|
+
|
42
|
+
def start!
|
43
|
+
log.info "Registering delayed_job evenitron collector with system key #{@system_key} to send messages to #{@collector_url}"
|
44
|
+
@client = Evenitron::CollectorClient.new @system_key, @collector_url, 'dj'
|
45
|
+
register_lifecycle_hooks
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def lifecycle
|
51
|
+
Delayed::Worker.lifecycle
|
52
|
+
end
|
53
|
+
|
54
|
+
def register_lifecycle_hooks
|
55
|
+
log.info "Registering delayed_job job queued callback"
|
56
|
+
lifecycle.around :enqueue do |job, &block|
|
57
|
+
result = block.call(job)
|
58
|
+
job_queued job
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
log.info "Registering delayed_job job failed callback"
|
63
|
+
lifecycle.before :failure do |worker, job|
|
64
|
+
job_failed job
|
65
|
+
end
|
66
|
+
|
67
|
+
log.info "Registering delayed_job job requeued callback"
|
68
|
+
lifecycle.after :error do |worker, job|
|
69
|
+
job_queued job unless job.failed? or job.frozen?
|
70
|
+
end
|
71
|
+
|
72
|
+
log.info "Registering delayed_job job started callback"
|
73
|
+
log.info "Registering delayed_job job complete callback"
|
74
|
+
lifecycle.around :perform do |worker, job, &block|
|
75
|
+
job_started job, worker
|
76
|
+
result = block.call(worker, job)
|
77
|
+
job_complete job if result
|
78
|
+
result
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def job_queued(job)
|
83
|
+
id = get_id(job)
|
84
|
+
log.info "Sending job queued message for job #{job.id} (evenitron id #{id})"
|
85
|
+
@client.job_queued :id => id, :queue => job.class.table_name, :task => job.name
|
86
|
+
end
|
87
|
+
|
88
|
+
def job_started(job, worker)
|
89
|
+
id = get_id(job)
|
90
|
+
log.info "Sending job started message for job #{job.id} (evenitron id #{id})"
|
91
|
+
@client.job_started :id => id, :worker => worker.name, :task => job.name
|
92
|
+
end
|
93
|
+
|
94
|
+
def job_failed(job)
|
95
|
+
id = get_id(job)
|
96
|
+
log.info "Sending job failed message for job #{job.id} (evenitron id #{id})"
|
97
|
+
@client.job_failed :id => id, :task => job.name
|
98
|
+
end
|
99
|
+
|
100
|
+
def job_complete(job)
|
101
|
+
id = get_id(job)
|
102
|
+
log.info "Sending job complete message for job #{job.id} (evenitron id #{id})"
|
103
|
+
@client.job_complete :id => id, :task => job.name
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_id(job)
|
107
|
+
Evenitron.encode job.class.table_name, job.id
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Evenitron
|
2
|
+
|
3
|
+
def self.logger
|
4
|
+
@@logger ||= default_logger
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.logger=(logger)
|
8
|
+
@@logger = logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.encode(*values)
|
12
|
+
value = values.join ':'
|
13
|
+
cleanse_base64 Base64.encode64(value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.generate_id(length = 64)
|
17
|
+
cleanse_base64 SecureRandom.base64(length)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def self.default_logger
|
23
|
+
logger = ::Logger.new(STDOUT)
|
24
|
+
logger.level = ::Logger::INFO
|
25
|
+
logger
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.cleanse_base64(value)
|
29
|
+
value.gsub /[\s=]/, ''
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require_relative '../evenitron'
|
2
|
+
require 'resque'
|
3
|
+
|
4
|
+
module Evenitron
|
5
|
+
|
6
|
+
class NullResqueCollector
|
7
|
+
|
8
|
+
include Evenitron::Logger
|
9
|
+
|
10
|
+
def job_queued(queue, item)
|
11
|
+
log.warn "EVENITRON NOT CONFIGURED : Not sending job queued message for job #{item['evenitron_id']}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def job_started(job)
|
15
|
+
log.info "EVENITRON NOT CONFIGURED : Not sending job started message for job #{job.evenitron_id}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def job_failed(job)
|
19
|
+
log.info "EVENITRON NOT CONFIGURED : Not sending job failed message for job #{job.evenitron_id}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def job_complete(job)
|
23
|
+
log.info "EVENITRON NOT CONFIGURED : Not sending job complete message for job #{job.evenitron_id}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
module Resque
|
29
|
+
|
30
|
+
@@collector = Evenitron::NullResqueCollector.new
|
31
|
+
|
32
|
+
def self.configure(&block)
|
33
|
+
rc = Evenitron::ResqueCollector.new
|
34
|
+
rc.configure &block unless block.nil?
|
35
|
+
rc.start!
|
36
|
+
@@collector = rc
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.collector
|
41
|
+
@@collector
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class ResqueCollector
|
47
|
+
|
48
|
+
include Evenitron::Logger
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
@collector_url = ENV['EVENITRON_COLLECTOR_URL']
|
52
|
+
@system_key = ENV['EVENITRON_SYSTEM_KEY']
|
53
|
+
end
|
54
|
+
|
55
|
+
def configure(&block)
|
56
|
+
instance_eval &block
|
57
|
+
end
|
58
|
+
|
59
|
+
def system_key(key)
|
60
|
+
@system_key = key
|
61
|
+
end
|
62
|
+
|
63
|
+
def api_key(key)
|
64
|
+
@api_key = key
|
65
|
+
end
|
66
|
+
|
67
|
+
def collector_url(url)
|
68
|
+
@collector_url = url
|
69
|
+
end
|
70
|
+
|
71
|
+
def start!
|
72
|
+
log.info "Registering resque evenitron collector with system key #{@system_key} to send messages to #{@collector_url}"
|
73
|
+
@client = Evenitron::CollectorClient.new @system_key, @collector_url, 'resque'
|
74
|
+
end
|
75
|
+
|
76
|
+
def job_queued(queue, item)
|
77
|
+
id = get_id(item)
|
78
|
+
log.info "Sending job queued message for job #{id}"
|
79
|
+
@client.job_queued :id => id, :queue => queue, :task => item[:class]
|
80
|
+
end
|
81
|
+
|
82
|
+
def job_started(job)
|
83
|
+
log.info "Sending job started message for job #{job.evenitron_id}"
|
84
|
+
@client.job_started :id => job.evenitron_id, :worker => job.worker.to_s, :task => job.payload['class']
|
85
|
+
end
|
86
|
+
|
87
|
+
def job_failed(job)
|
88
|
+
log.info "Sending job failed message for job #{job.evenitron_id}"
|
89
|
+
@client.job_failed :id => job.evenitron_id, :task => job.payload['class']
|
90
|
+
end
|
91
|
+
|
92
|
+
def job_complete(job)
|
93
|
+
log.info "Sending job complete message for job #{job.evenitron_id}"
|
94
|
+
@client.job_complete :id => job.evenitron_id, :task => job.payload['class']
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def get_id(item)
|
100
|
+
item['evenitron_id']
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
module Resque
|
108
|
+
|
109
|
+
class << self
|
110
|
+
|
111
|
+
alias :base_push :push
|
112
|
+
|
113
|
+
def push(queue, item)
|
114
|
+
item['evenitron_id'] ||= Evenitron.generate_id
|
115
|
+
base_push(queue, item)
|
116
|
+
Evenitron::Resque.collector.job_queued queue, item
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
class Job
|
122
|
+
|
123
|
+
alias :base_perform :perform
|
124
|
+
|
125
|
+
def perform
|
126
|
+
begin
|
127
|
+
Evenitron.logger.debug "Processing job #{evenitron_id}"
|
128
|
+
Evenitron::Resque.collector.job_started self
|
129
|
+
|
130
|
+
result = base_perform
|
131
|
+
Evenitron::Resque.collector.job_complete self
|
132
|
+
|
133
|
+
Evenitron.logger.debug "Processed job #{evenitron_id}, result was #{result}"
|
134
|
+
result
|
135
|
+
rescue => e
|
136
|
+
Evenitron.logger.fatal "Exception occurred whilst processing job #{evenitron_id}"
|
137
|
+
Evenitron.logger.debug e.inspect
|
138
|
+
Evenitron::Resque.collector.job_failed self
|
139
|
+
raise e
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def evenitron_id
|
144
|
+
@payload['evenitron_id']
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
data/lib/evenitron.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'base64'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'securerandom'
|
5
|
+
require 'logger'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Evenitron ; end
|
9
|
+
|
10
|
+
require_relative 'evenitron/evenitron'
|
11
|
+
require_relative 'evenitron/logger'
|
12
|
+
require_relative 'evenitron/collector_client'
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evenitron
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Evenitron
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-25 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: &70228307216040 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.6.7
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70228307216040
|
25
|
+
description: Ruby client for Evenitron with hooks for delayed_job and resque
|
26
|
+
email:
|
27
|
+
- support@evenitron.com
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- lib/evenitron/collector_client.rb
|
33
|
+
- lib/evenitron/delayed_job.rb
|
34
|
+
- lib/evenitron/evenitron.rb
|
35
|
+
- lib/evenitron/logger.rb
|
36
|
+
- lib/evenitron/resque.rb
|
37
|
+
- lib/evenitron.rb
|
38
|
+
- README.markdown
|
39
|
+
homepage: https://github.com/evenitron/evenitron-ruby
|
40
|
+
licenses: []
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project: evenitron-ruby
|
59
|
+
rubygems_version: 1.8.15
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Ruby client for Evenitron
|
63
|
+
test_files: []
|
64
|
+
has_rdoc:
|