riemann-docker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +10 -0
  4. data/bin/riemann-docker +205 -0
  5. metadata +74 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 18789e6607828d9b9942daa049e237d4db277d00
4
+ data.tar.gz: 88c3041ff216855fcdda256ade673ccbbab14540
5
+ SHA512:
6
+ metadata.gz: afb2483d328a5c8fe160244acecb4ad0041a933b7b77283a5fda376f3ccfeaf5ec0dc6763004f03e0c95e3b888e741690bedee9a0da31eb52e9df02827296dd1
7
+ data.tar.gz: 1e82590ded355a73df4ff5354d63a5d2f5a36926157a730482ecf2d1d89cd53e92f7f58e004316d72e14cd577731e04b4abc1bb3087b3b7d091553215864ad20
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Kyle Kingsbury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # Riemann Docker
2
+
3
+ Gathers Docker container metrics and sends them to Riemann.
4
+
5
+ # Getting started
6
+
7
+ ```
8
+ gem install riemann-docker
9
+ riemann-docker --help
10
+ ```
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Reports current CPU, disk, load average, and memory use to riemann.
4
+
5
+ require 'riemann/tools'
6
+
7
+ class Riemann::Tools::DockerHealth
8
+ require 'docker'
9
+ require 'socket'
10
+ include Riemann::Tools
11
+ include Docker
12
+
13
+ opt :docker_host, "Docker Container Host (see https://github.com/swipely/docker-api#host)", :default => nil
14
+ opt :cpu_warning, "CPU warning threshold (fraction of total jiffies)", :default => 0.9
15
+ opt :cpu_critical, "CPU critical threshold (fraction of total jiffies)", :default => 0.95
16
+ opt :disk_warning, "Disk warning threshold (fraction of space used)", :default => 0.9
17
+ opt :disk_critical, "Disk critical threshold (fraction of space used)", :default => 0.95
18
+ opt :memory_warning, "Memory warning threshold (fraction of RAM)", :default => 0.85
19
+ opt :memory_critical, "Memory critical threshold (fraction of RAM)", :default => 0.95
20
+ opt :host_hostname, "Suffix of host", :type => String, :default => nil
21
+ opt :checks, "A list of checks to run.", :type => :strings, :default => ['cpu', 'memory', 'disk', 'basic']
22
+
23
+ def get_containers
24
+ Docker::Container.all
25
+ end
26
+
27
+ def get_container_name(container)
28
+ container.json['Name'][1..-1]
29
+ end
30
+
31
+ def initialize
32
+
33
+ if (opts[:docker_host] != nil)
34
+ Docker.url = opts[:docker_host]
35
+ end
36
+
37
+ @hostname = opts[:host_hostname]
38
+ if (@hostname.nil? || !(@hostname.is_a? String) || @hostname.empty?)
39
+ @hostname = Socket.gethostname
40
+ end
41
+
42
+ @cpu_coefficient = 1000 * 1000 * 1000
43
+
44
+ @limits = {
45
+ :cpu => {:critical => opts[:cpu_critical], :warning => opts[:cpu_warning]},
46
+ :disk => {:critical => opts[:disk_critical], :warning => opts[:disk_warning]},
47
+ :memory => {:critical => opts[:memory_critical], :warning => opts[:memory_warning]}
48
+ }
49
+
50
+ @last_cpu_reads = Hash.new
51
+ @last_uptime_reads = Hash.new
52
+
53
+ opts[:checks].each do |check|
54
+ case check
55
+ when 'disk'
56
+ @disk_enabled = true
57
+ when 'cpu'
58
+ @cpu_enabled = true
59
+ when 'memory'
60
+ @memory_enabled = true
61
+ when 'basic'
62
+ @basic_inspection_enabled = true
63
+ end
64
+ end
65
+ end
66
+
67
+ def alert(container, service, state, metric, description)
68
+
69
+ opts = { :service => service.to_s,
70
+ :state => state.to_s,
71
+ :metric => metric.to_f,
72
+ :description => description }
73
+
74
+ if (container != nil)
75
+ opts[:host] = "#{@hostname}-#{container}"
76
+ else
77
+ opts[:host] = @hostname
78
+ end
79
+
80
+ report(opts)
81
+ end
82
+
83
+ def report_pct(container, service, fraction, report = '', name = nil)
84
+ if fraction
85
+
86
+ if (name == nil)
87
+ name = service
88
+ end
89
+
90
+ if fraction > @limits[service][:critical]
91
+ alert container, name, :critical, fraction, "#{sprintf("%.2f", fraction * 100)}% #{report}"
92
+ elsif fraction > @limits[service][:warning]
93
+ alert container, name, :warning, fraction, "#{sprintf("%.2f", fraction * 100)}% #{report}"
94
+ else
95
+ alert container, name, :ok, fraction, "#{sprintf("%.2f", fraction * 100)}% #{report}"
96
+ end
97
+ end
98
+ end
99
+
100
+
101
+ def cpu(id, name, stats)
102
+
103
+ current = stats['precpu_stats']['cpu_usage']['total_usage'] / stats['precpu_stats']['cpu_usage']['percpu_usage'].count
104
+
105
+ unless current
106
+ alert name, :cpu, :unknown, nil, 'no total usage found in docker remote api stats'
107
+ return false
108
+ end
109
+
110
+ current_time = Time.parse(stats['read']);
111
+ if (@last_cpu_reads[id] != nil)
112
+ last = @last_cpu_reads[id]
113
+ used = (current - last[:v]) / (current_time - last[:t]) / @cpu_coefficient
114
+
115
+ report_pct name, :cpu, used
116
+ end
117
+
118
+ @last_cpu_reads[id] = { v: current, t: current_time }
119
+ end
120
+
121
+ def memory(id, name, stats)
122
+ memory_stats = stats['memory_stats']
123
+ usage = memory_stats['usage'].to_f
124
+ total = memory_stats['limit'].to_f
125
+ fraction = (usage / total)
126
+
127
+ report_pct name, :memory, fraction, "#{usage} / #{total}"
128
+ end
129
+
130
+ def disk
131
+ `df -P`.split(/\n/).each do |r|
132
+ f = r.split(/\s+/)
133
+ next if f[0] == 'Filesystem'
134
+ next unless f[0] =~ /\// # Needs at least one slash in the mount path
135
+
136
+ # Calculate capacity
137
+ x = f[4].to_f/100
138
+ report_pct(nil, :disk, x, "#{f[3].to_i / 1024} mb left", "disk #{f[5]}")
139
+ end
140
+ end
141
+
142
+ def basic_inspection(id, name, inspection)
143
+
144
+ state = inspection['State']
145
+ json_state = JSON.generate(state)
146
+
147
+ running = state['Running']
148
+
149
+ alert(name, "status",
150
+ running ? "ok" : "critical",
151
+ running ? 1 : 0,
152
+ json_state)
153
+
154
+ if (running)
155
+ start_time = DateTime.rfc3339(state['StartedAt']).to_time.utc.to_i
156
+ now = DateTime.now.to_time.utc.to_i
157
+ uptime = now - start_time
158
+
159
+ if (@last_uptime_reads[id] != nil)
160
+ last = @last_uptime_reads[id]
161
+ restarted = start_time != last
162
+ alert(name, "uptime",
163
+ restarted ? "critical" : "ok",
164
+ uptime,
165
+ "last 'StartedAt' measure was #{last} (#{Time.at(last).utc.to_s}), " +
166
+ "now it's #{start_time} (#{Time.at(start_time).utc.to_s})")
167
+ end
168
+
169
+ @last_uptime_reads[id] = start_time
170
+ end
171
+ end
172
+
173
+ def tick
174
+
175
+ # Disk is the same in every container
176
+ if @disk_enabled
177
+ disk()
178
+ end
179
+
180
+ # Get CPU, Memory and Load of each container
181
+ containers = get_containers()
182
+ containers.each do |container|
183
+
184
+ id = container.id
185
+ name = get_container_name(container)
186
+
187
+ stats = Docker::Util.parse_json(container.connection.get("/containers/#{id}/stats", {stream:false}))
188
+
189
+ if @basic_inspection_enabled
190
+ inspection = Docker::Util.parse_json(container.connection.get("/containers/#{id}/json"))
191
+ basic_inspection(id, name, inspection)
192
+ end
193
+ if @cpu_enabled
194
+ cpu(id, name, stats)
195
+ end
196
+ if @memory_enabled
197
+ memory(id, name, stats)
198
+ end
199
+ end
200
+
201
+ end
202
+ end
203
+
204
+ Riemann::Tools::DockerHealth.run
205
+
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: riemann-docker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shani Elharrar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: riemann-tools
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: docker-api
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.22.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.22.0
41
+ description:
42
+ email: ''
43
+ executables:
44
+ - riemann-docker
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - bin/riemann-docker
51
+ homepage: https://github.com/riemann/riemann-docker
52
+ licenses: []
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.8.7
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project: riemann-docker
70
+ rubygems_version: 2.4.5
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Submits Docker container stats to riemann.
74
+ test_files: []