bosh-monitor 1.2980.0 → 1.2981.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/bosh/monitor.rb +1 -0
- data/lib/bosh/monitor/plugins/README.md +57 -0
- data/lib/bosh/monitor/plugins/consul_event_forwarder.rb +170 -0
- data/lib/bosh/monitor/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de5c0802c02e2abd67ade2f77f300ef6e8438e9a
|
4
|
+
data.tar.gz: 4f2e36dc946ccab2afa26fb66f517fedf03bd97b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e883ab6db000252c6b5735f32724e1076a127ca847986cbf55d8035a3f325ee4155b43aaa8c2fb6c64f48c80a76cb0f3e38a64833a9a911c58ba730e78396e7
|
7
|
+
data.tar.gz: 2c1160cbf398c4b57e8b338b7d5547f1617f298aa7f5412156f3c45f6835ea2b01d036c33579252f32564eb4b6c63dfd9474dcb3ec70e6032d9d3df13b145de3
|
data/README.md
CHANGED
@@ -45,7 +45,8 @@ Among the included plugins are:
|
|
45
45
|
- DataDog - Sends various events to DataDog.com using their API
|
46
46
|
- AWS CloudWatch - Sends various events to Amazon's CloudWatch using their API
|
47
47
|
- Emailer - Sends configurable Emails on events reciept
|
48
|
-
|
48
|
+
Consul Event Forwarder - Sends heartbeats as events and TTL checks to a consul cluster
|
49
|
+
|
49
50
|
Plugins should conform to the following interface:
|
50
51
|
|
51
52
|
| *Method* | *Arguments* | *Description* |
|
data/lib/bosh/monitor.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
#Using Bosh Monitor Plugins
|
2
|
+
|
3
|
+
##AWS CloudWatch
|
4
|
+
Sends various events to Amazon's CloudWatch using their
|
5
|
+
|
6
|
+
##DataDog
|
7
|
+
Sends various events to DataDog.com using their API
|
8
|
+
|
9
|
+
| option | description |
|
10
|
+
|------------------|------------------------|
|
11
|
+
| api_key | Your api Key |
|
12
|
+
| application_key | Your Application Key |
|
13
|
+
|
14
|
+
##Consul Event Forwarder Plugin
|
15
|
+
The Consul plugin works by forwarding nats heartbeat events and alerts to a consul server or agent. The nats messages can be forwarded as ttl checks and events. Heartbeat messages will be forwarded as TTL checks, each time a heartbeat occurs it will update the ttl check with it's status. When an alert occurs it will be forwareded to Consul as an Event. The current best use case seems to be to forward to a consul agent (possibly on your inception server)
|
16
|
+
|
17
|
+
| option | description |
|
18
|
+
|-----------------------|-------------------------------------|
|
19
|
+
| host | The address of the cluster or agent |
|
20
|
+
| namespace | A namespace to separate multiple instances of the same release
|
21
|
+
| events_api | The events api endpoint defaults to /v1/event/fire/
|
22
|
+
| ttl_api | The Check update and registration endpoint defaults to /v1/agent/check/
|
23
|
+
| port | Defaults to 8500
|
24
|
+
| protocal | Defaults to HTTP
|
25
|
+
| params | Can be used to pass access token "token=MYACCESSTOKEN"
|
26
|
+
| ttl | TTL Checks will be used if a ttl period is set here. Example "120s"
|
27
|
+
| events | If set to true heartbeats will be forwarded as events
|
28
|
+
| ttl_note | A note that will be passed back to consul with a ttl check
|
29
|
+
| heartbeats_as_alerts | * If set to true all heartbeats will also be forwarded as event, this gives you 'real time' vitals data to correlate with
|
30
|
+
|
31
|
+
####* When heartbeats are sent as alerts the format has been made more concise to come in under the event payload bytesize limits that consul enforces
|
32
|
+
```ruby
|
33
|
+
{
|
34
|
+
:agent => agent_id,
|
35
|
+
:name => "job_name / index",
|
36
|
+
:state => job_state,
|
37
|
+
:data => {
|
38
|
+
:cpu => [sys, user, wait]
|
39
|
+
:dsk => {
|
40
|
+
:eph => [inode_percent, percent],
|
41
|
+
:sys =>[inode_percent, percent]
|
42
|
+
}
|
43
|
+
:ld => load,
|
44
|
+
:mem => [kb, percent],
|
45
|
+
:swp => [kb, percent]
|
46
|
+
}
|
47
|
+
}
|
48
|
+
```
|
49
|
+
|
50
|
+
## Event Logger
|
51
|
+
Logs all events
|
52
|
+
|
53
|
+
## PagerDuty
|
54
|
+
Sends various events to PagerDuty.com using their API
|
55
|
+
|
56
|
+
## Resurrector
|
57
|
+
Restarts VMs that have stopped heartbeating
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# Consul Bosh Monitor Plugin
|
2
|
+
# Forwards alert and heartbeat messages as events to a consul agent
|
3
|
+
module Bosh::Monitor
|
4
|
+
module Plugins
|
5
|
+
class ConsulEventForwarder < Base
|
6
|
+
include Bosh::Monitor::Plugins::HttpRequestHelper
|
7
|
+
|
8
|
+
CONSUL_REQUEST_HEADER = { 'Content-Type' => 'application/javascript' }
|
9
|
+
TTL_STATUS_MAP = { 'running' => :pass, 'failing' => :fail, 'unknown' => :fail, 'default' => :warn }
|
10
|
+
REQUIRED_OPTIONS = ["host", "port", "protocol" ]
|
11
|
+
CONSUL_MAX_EVENT_BYTESIZE = 512
|
12
|
+
|
13
|
+
CONSUL_ENDPOINTS = {
|
14
|
+
event: "/v1/event/fire/", #fire an event
|
15
|
+
register: "/v1/agent/check/register", #register a check
|
16
|
+
deregister: "/v1/agent/check/deregister/", #deregister a check
|
17
|
+
pass: "/v1/agent/check/pass/", #mark a check as passing
|
18
|
+
warn: "/v1/agent/check/warn/", #mark a check as warning
|
19
|
+
fail: "/v1/agent/check/fail/" #mark a check as failing
|
20
|
+
}
|
21
|
+
|
22
|
+
def run
|
23
|
+
@checklist = []
|
24
|
+
@host = options['host']
|
25
|
+
@namespace = options['namespace']
|
26
|
+
@port = options['port']
|
27
|
+
@protocol = options['protocol']
|
28
|
+
@params = options['params']
|
29
|
+
@ttl = options['ttl']
|
30
|
+
@use_events = options['events']
|
31
|
+
@ttl_note = options['ttl_note']
|
32
|
+
|
33
|
+
@heartbeats_as_alerts = options['heartbeats_as_alerts']
|
34
|
+
@use_ttl = !@ttl.nil?
|
35
|
+
|
36
|
+
@status_map = Hash.new(:warn)
|
37
|
+
@status_map.merge!(TTL_STATUS_MAP)
|
38
|
+
|
39
|
+
logger.info("Consul Event Forwarder plugin is running...")
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_options
|
43
|
+
valid_array = REQUIRED_OPTIONS.map{ |o| options[o].to_s.empty? }
|
44
|
+
!valid_array.include?(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
def process(event)
|
48
|
+
validate_options && forward_event(event)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def consul_uri(event, note_type)
|
54
|
+
path = get_path_for_note_type(event, note_type)
|
55
|
+
URI.parse("#{@protocol}://#{@host}:#{@port}#{path}?#{@params}")
|
56
|
+
end
|
57
|
+
|
58
|
+
#heartbeats get forwarded as ttl checks and alerts get forwarded as events
|
59
|
+
#if heartbeat_as_alert is true than a heartbeat gets forwarded as events as well
|
60
|
+
def forward_event(event)
|
61
|
+
|
62
|
+
if forward_this_event?(event)
|
63
|
+
notify_consul(event, :event)
|
64
|
+
end
|
65
|
+
|
66
|
+
if forward_this_ttl?(event)
|
67
|
+
event_unregistered?(event) ? notify_consul(event, :register, registration_payload(event)) : notify_consul(event, :ttl)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
#should an individual alert or heartbeat be forwarded as a consul event
|
73
|
+
def forward_this_event?(event)
|
74
|
+
@use_events && ( event.is_a?(Bosh::Monitor::Events::Alert) || ( event.is_a?(Bosh::Monitor::Events::Heartbeat) && @heartbeats_as_alerts) )
|
75
|
+
end
|
76
|
+
|
77
|
+
def forward_this_ttl?(event)
|
78
|
+
@use_ttl && event.is_a?(Bosh::Monitor::Events::Heartbeat)
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_path_for_note_type(event, note_type)
|
82
|
+
case note_type
|
83
|
+
when :event
|
84
|
+
CONSUL_ENDPOINTS[:event] + label_for_event(event)
|
85
|
+
when :ttl
|
86
|
+
job_state = event.attributes['job_state']
|
87
|
+
status_id = @status_map[job_state]
|
88
|
+
CONSUL_ENDPOINTS[status_id] + label_for_ttl(event)
|
89
|
+
when :register
|
90
|
+
CONSUL_ENDPOINTS[:register]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def label_for_event(event)
|
95
|
+
case event
|
96
|
+
when Bosh::Monitor::Events::Heartbeat
|
97
|
+
"#{@namespace}#{event.job}"
|
98
|
+
when Bosh::Monitor::Events::Alert
|
99
|
+
event_label = event.title.downcase.gsub(" ","_")
|
100
|
+
"#{@namespace}#{event_label}"
|
101
|
+
else
|
102
|
+
#Something we haven't encountered yet
|
103
|
+
"#{@namespace}event"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def label_for_ttl(event)
|
108
|
+
"#{@namespace}#{event.job}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Notify consul of an event
|
112
|
+
# note_type: the type of notice we are sending (:event, :ttl, :register)
|
113
|
+
# message: an optional body for the message, event.json is used by default
|
114
|
+
def notify_consul(event, note_type, message=nil)
|
115
|
+
body = message.nil? ? right_sized_body_for_consul(event).to_json : message.to_json
|
116
|
+
uri = consul_uri(event, note_type)
|
117
|
+
|
118
|
+
request = { :body => body }
|
119
|
+
|
120
|
+
send_http_put_request(uri , request)
|
121
|
+
|
122
|
+
#if a registration request returns without error we log it
|
123
|
+
#we don't want to send extra registrations
|
124
|
+
@checklist << event.job if note_type == :register
|
125
|
+
rescue => e
|
126
|
+
logger.error("Could not forward event to Consul Cluster @#{@host}: #{e.inspect}")
|
127
|
+
end
|
128
|
+
|
129
|
+
#consul limits event payload to < 512 bytes, unfortunately we have to do some pruning so this limit is not as likely to be reached
|
130
|
+
#this is suboptimal but otherwise the event post will fail, and how do we decide what data isn't important?
|
131
|
+
def right_sized_body_for_consul(event)
|
132
|
+
body = event.to_hash
|
133
|
+
if event.is_a?(Bosh::Monitor::Events::Heartbeat)
|
134
|
+
vitals = body[:vitals]
|
135
|
+
#currently assuming the event hash details are always put together in the same order
|
136
|
+
#this should yield consistent results from the values method
|
137
|
+
{
|
138
|
+
:agent => body[:agent_id],
|
139
|
+
:name => "#{body[:job]}/#{body[:index]}",
|
140
|
+
:state => "#{body[:job_state]}",
|
141
|
+
:data => {
|
142
|
+
:cpu => vitals['cpu'].values,
|
143
|
+
:dsk => {
|
144
|
+
:eph => vitals['disk']['ephemeral'].values,
|
145
|
+
:sys => vitals['disk']['system'].values,
|
146
|
+
},
|
147
|
+
:ld => vitals['load'],
|
148
|
+
:mem => vitals['mem'].values,
|
149
|
+
:swp => vitals['swap'].values
|
150
|
+
}
|
151
|
+
}
|
152
|
+
else
|
153
|
+
body
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
#Has this process not encountered a specific ttl check yet?
|
158
|
+
#We keep track so we aren't sending superfluous registrations
|
159
|
+
#Only register ttl for events that have a job assigned
|
160
|
+
def event_unregistered?(event)
|
161
|
+
@use_ttl && event.respond_to?(:job) && !@checklist.include?(event.job)
|
162
|
+
end
|
163
|
+
|
164
|
+
def registration_payload(event)
|
165
|
+
{ "name" => label_for_ttl(event), "notes" => @ttl_note, "ttl" => @ttl }
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/lib/bosh/monitor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh-monitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2981.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VMware
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -180,7 +180,7 @@ dependencies:
|
|
180
180
|
version: '0'
|
181
181
|
description: |-
|
182
182
|
BOSH Health Monitor
|
183
|
-
|
183
|
+
4246cc
|
184
184
|
email: support@cloudfoundry.com
|
185
185
|
executables:
|
186
186
|
- bosh-monitor-console
|
@@ -207,8 +207,10 @@ files:
|
|
207
207
|
- lib/bosh/monitor/events/base.rb
|
208
208
|
- lib/bosh/monitor/events/heartbeat.rb
|
209
209
|
- lib/bosh/monitor/metric.rb
|
210
|
+
- lib/bosh/monitor/plugins/README.md
|
210
211
|
- lib/bosh/monitor/plugins/base.rb
|
211
212
|
- lib/bosh/monitor/plugins/cloud_watch.rb
|
213
|
+
- lib/bosh/monitor/plugins/consul_event_forwarder.rb
|
212
214
|
- lib/bosh/monitor/plugins/datadog.rb
|
213
215
|
- lib/bosh/monitor/plugins/dummy.rb
|
214
216
|
- lib/bosh/monitor/plugins/email.rb
|