Commit | Line | Data |
---|---|---|
03b50438 S |
1 | require 'statsd-ruby' |
2 | require 'docker' | |
3 | ||
4 | $statsd = Statsd.new '10.0.0.1', 8125 | |
5 | ||
6 | module Docker | |
7 | class CloseConnectionError < StandardError; end | |
8 | class Container | |
9 | def name | |
10 | info["Names"].first[1..-1] | |
11 | end | |
12 | ||
13 | def stats | |
14 | path = path_for(:stats) | |
15 | ||
16 | result = nil | |
17 | ||
18 | streamer = lambda do |chunk, remaining, total| | |
19 | result ||= chunk | |
20 | raise CloseConnectionError if result | |
21 | end | |
22 | options = { response_block: streamer }.merge(connection.options) | |
23 | ||
24 | Excon.get(connection.url + path[1..-1], options) rescue CloseConnectionError | |
25 | ||
26 | Docker::Util.parse_json(result) | |
27 | end | |
28 | end | |
29 | end | |
30 | ||
31 | def median(array) | |
32 | sorted = array.sort | |
33 | len = sorted.length | |
34 | return ((sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0).to_i | |
35 | end | |
36 | ||
37 | ||
38 | def analyze_container(container) | |
39 | ||
40 | data = container.exec(["ps", "-eo", "rss,args"])[0].join("\n").split("\n") | |
41 | unicorns = data.grep(/unicorn/).map(&:to_i) | |
42 | sidekiqs = data.grep(/sidekiq/).map(&:to_i) | |
43 | ||
44 | result = {} | |
45 | ||
46 | if unicorns.length > 0 | |
47 | result["unicorn.max_rss"] = unicorns.max | |
48 | result["unicorn.median_rss"] = median(unicorns) | |
49 | end | |
50 | ||
51 | if sidekiqs.length > 0 | |
52 | result["sidekiq.max_rss"] = sidekiqs.max | |
53 | result["sidekiq.median_rss"] = median(sidekiqs) | |
54 | end | |
55 | result["total_mem_usage"] = container.stats["memory_stats"]["usage"] | |
56 | ||
57 | @prev_stats ||= {} | |
58 | prev_stats = @prev_stats[container.name] | |
59 | @prev_stats[container.name] = stats = container.stats | |
60 | ||
61 | if prev_stats | |
62 | cpu_delta = stats["cpu_stats"]["system_cpu_usage"] - prev_stats["cpu_stats"]["system_cpu_usage"] | |
63 | app_cpu_delta = stats["cpu_stats"]["cpu_usage"]["total_usage"] - prev_stats["cpu_stats"]["cpu_usage"]["total_usage"] | |
64 | ||
65 | result["cpu_usage"] = (app_cpu_delta.to_f / cpu_delta.to_f) * stats["cpu_stats"]["cpu_usage"]["percpu_usage"].length * 100.0 | |
66 | end | |
67 | ||
68 | result | |
69 | ||
70 | end | |
71 | ||
72 | def containers | |
73 | Docker::Container.all | |
74 | end | |
75 | ||
76 | hostname = Docker.info["Name"] | |
77 | ||
78 | STDERR.puts "#{Time.now} Starting Monitor" | |
79 | ||
80 | while true | |
81 | ||
82 | begin | |
83 | containers.each do |c| | |
84 | ||
85 | analyze_container(c).each do |k, v| | |
86 | if v && v > 0 | |
87 | $statsd.gauge "#{hostname}.#{c.name}.#{k}", v | |
88 | end | |
89 | end | |
90 | end | |
91 | rescue => e | |
92 | STDERR.puts e | |
93 | STDERR.puts e.backtrace | |
94 | end | |
95 | ||
96 | sleep 60 | |
97 | end | |
98 |