smith-datadog 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/smith-datadog +155 -0
  3. metadata +179 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cd9057a6a6acefdea335d979828646067a44e353
4
+ data.tar.gz: 47ea2a06c836ad9c7e824989a992faa46aa7bdfb
5
+ SHA512:
6
+ metadata.gz: 4bfd71b8a6955411a9c4291083487d174fffe5b8ad93d2c401c3e5f6f4bf2f62e3ff3b74d95e8b68686881351ea01d2d0c9a73e3c70228a7373510bcccfa6413
7
+ data.tar.gz: c086efc6de1645a97b4a0ab367558c71c62b29025a5ca7430d6e8059ac1a940a7ff08b8bb796114ecf8d04bc5dc78299fd4941b57803465825a22417bb7be4d1
data/bin/smith-datadog ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pp'
4
+ require 'dogapi'
5
+ require 'sys/proctable'
6
+
7
+ require 'smith'
8
+ require 'smith/commands/common'
9
+
10
+ class Smith::Datadog
11
+
12
+ include Smith::Commands::Common
13
+ include Smith::Logger
14
+
15
+ SERVICE_NAME = "Smith"
16
+ API_KEY = ENV.fetch('DATADOG_API_KEY')
17
+
18
+ def initialize
19
+ @datadog = Dogapi::Client.new(API_KEY)
20
+ end
21
+
22
+ def run
23
+ Smith::Messaging::Sender.new(Smith::QueueDefinitions::Agency_control.call) do |queue|
24
+ on_check do |check|
25
+ @datadog.emit_event(Dogapi::Event.new(check[:description], check))
26
+ end
27
+
28
+ queue.on_error do |channel, channel_close|
29
+ logger.fatal { "Channel error: #{channel_close.reply_code}: #{channel_close.reply_text}." }
30
+ Smith.stop
31
+ end
32
+
33
+ EM.add_periodic_timer(options[:interval]) { run_check(queue) }
34
+ end
35
+ end
36
+
37
+ def run_check(queue)
38
+ @on_check.call(alert(:heartbeat, :running, "smith-datadog heatbeat"))
39
+
40
+ queue.on_timeout(options[:timeout]) do |message_id|
41
+ @on_check.call(alert(:agency, :timeout, "Agency timeout."))
42
+ end
43
+
44
+ queue.on_reply(:auto_ack => true, :reply_queue_name => "datadog.#{Digest::SHA1.hexdigest($$.to_s)}") do |reply_payload, r|
45
+ check(reply_payload.response).each do |agent|
46
+ @on_check.call(agent)
47
+ end
48
+ end
49
+
50
+ queue.consumer_count do |count|
51
+ if count > 0
52
+ queue.publish(Smith::ACL::AgencyCommand.new(:command => 'list', :args => ['-a', '-l']))
53
+ else
54
+ @on_check.call(alert(:agency, :critical, "Agency not running."))
55
+ end
56
+ end
57
+ end
58
+
59
+ def on_check(&blk)
60
+ @on_check = blk
61
+ end
62
+
63
+ # Checks that the list of agents return from the list command matches
64
+ # the list of know agents and composes an appropriate alert.
65
+ def check(response)
66
+ options[:group].map do |group|
67
+ begin
68
+ group_agents = options[:agents] + agent_group(group)
69
+ running_agents = parse_response(response)
70
+
71
+ group_agents.map do |agent_name|
72
+ if running_agents.has_key?(agent_name) && running_agents[agent_name].any? { |a| a[:state] == "running" && running?(a[:pid]) }
73
+ alert(agent_name, :running, "Agent running")
74
+ else
75
+ alert(agent_name, :critical, "Agent not running")
76
+ end
77
+ end
78
+ rescue RuntimeError => e
79
+ alert("Group #{group}: #{e.message}", :critical, e.message)
80
+ end
81
+ end.flatten
82
+ end
83
+
84
+ # Returns a Nested hash representing the running agents.
85
+ def parse_response(response)
86
+ split_response = response.split(/\n/).map(&:strip)
87
+ ((/^total/.match(split_response.first)) ? split_response[1..-1] : []).each_with_object(Hash.new { |h,k| h[k] = []}) do |e, acc|
88
+ fields = e.split(/\s +/)
89
+ acc[fields.last] << { :state => fields[0], :uuid => fields[1], :pid => fields[2], :description => fields.last }
90
+ end
91
+ end
92
+
93
+ # Construct an alert messages
94
+ def alert(service, state, description, extra={})
95
+ {:source_type_name => 'name', :description => description, :alert_type => 'info', :source_type_name => SERVICE_NAME, :msg_title => "#{service} #{description}", :aggregation_key => service(service)}.merge(extra).tap { |a| logger.info { "#{a[:service]}: #{state(state)}" } }
96
+ end
97
+
98
+ # Return true if the given pid exists in the process table.
99
+ def running?(pid)
100
+ !(pid.nil? || Sys::ProcTable.ps(pid.to_i).nil?)
101
+ end
102
+
103
+ # Return the service name
104
+ def service(name)
105
+ "#{SERVICE_NAME} #{name}"
106
+ end
107
+
108
+ def state(state)
109
+ {:timeout => "warning", :running => "info", :critical => "error"}[state]
110
+ end
111
+
112
+ def options
113
+ @options ||= begin
114
+ OptionParser.accept(Pathname) {|p,| Pathname.new(p) if p}
115
+
116
+ defaults = {:interval => 30, :timeout => 11, :agents => [], :group => [], :tags => [], :host => 'localhost', :port => 5555, :agency_timeout => 60}
117
+ defaults.tap do |options|
118
+ parser = OptionParser.new do |opts|
119
+ opts.separator "\n"
120
+ opts.set_summary_indent " "
121
+
122
+ opts.banner = "\nUsage: #{opts.program_name} OPTIONS"
123
+ opts.on_head "\n Periodically lists the running agents and sends the result to datadog."
124
+
125
+ opts.on("--interval <i>", Integer, "Polling interval in seconds (default #{options[:interval]})") { |t| options[:interval] = t }
126
+ opts.on("--timeout <i>", Integer, "Agency timeout (default #{options[:timeout]})") { |t| options[:interval] = t }
127
+ opts.on("--host <s>", String, "Riemann host (default #{options[:host]})") { |v| options[:host] = v }
128
+ opts.on("--port <i>", Integer, "Riemann port (default #{options[:port]})") { |v| options[:port] = v }
129
+ opts.on("--tags <tag1,tag1,...>", Array, "Tags to add to the alert") { |t| options[:tags] = t }
130
+
131
+ opts.on("--agents <agent1,agent2,...>", Array, "Agents to monitor") { |v| options[:agents] + v }
132
+ opts.on("--agent-group <group name>>", Array, "The name of an 'agent group' to monitor") { |g| options[:group] += g }
133
+
134
+ opts.separator "\n"
135
+ end
136
+
137
+ parser.parse!
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ checker = Smith::Datadog.new
144
+
145
+ begin
146
+ include Smith::Logger
147
+
148
+ Smith.compile_acls
149
+ Smith.start do
150
+ checker.run
151
+ end
152
+ rescue => e
153
+ logger.fatal(e.message)
154
+ logger.fatal("Exiting")
155
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smith-datadog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.1
5
+ platform: ruby
6
+ authors:
7
+ - Richard Heycock
8
+ - Rob Sharp
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-10-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: smith
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.8'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.8.3
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '0.8'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.3
34
+ - !ruby/object:Gem::Dependency
35
+ name: dogapi
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: sys-proctable
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.9'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ - !ruby/object:Gem::Dependency
63
+ name: activesupport
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: yard
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.8.7
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.8.7
90
+ - !ruby/object:Gem::Dependency
91
+ name: bundler
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1'
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1'
104
+ - !ruby/object:Gem::Dependency
105
+ name: rake
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '10'
118
+ - !ruby/object:Gem::Dependency
119
+ name: git-version-bump
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ - !ruby/object:Gem::Dependency
133
+ name: rspec
134
+ requirement: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ type: :development
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ description: Integrate smith agent monitoring with Datadog
147
+ email: rob.sharp@digivizer.com
148
+ executables:
149
+ - smith-datadog
150
+ extensions: []
151
+ extra_rdoc_files: []
152
+ files:
153
+ - bin/smith-datadog
154
+ homepage: https://github.com/dgvz/smith-datadog
155
+ licenses:
156
+ - GPL-3.0
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.5.1
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: Monitor smith agents, reporting to Datadog
178
+ test_files: []
179
+ has_rdoc: