fluent-plugin-docker-metrics 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fe3c77f3d0e10766bb18060d471de817455fd9cb
4
+ data.tar.gz: f56a4465bb6a566240a4c27276bca97d07081222
5
+ SHA512:
6
+ metadata.gz: bcbcfd347ac2a1a7cb1e06bc0cdce38fce40968a3405c75577b50a0782cb5ea341c41cdad4a56b42139a4a450278347dba0777001799d8c85e4fb941454e05d5
7
+ data.tar.gz: 6d4ad921e6da4e8be9c4da6581a79253fe17cbbe692ab6e88d18e24778173da75e4c503b1fc0ee2d5bf953270dd376f367f9c6d52434a2a4063a15675048d1aa
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,37 @@
1
+ # Fluentd Docker Metrics Input Plugin
2
+
3
+ This is a [Fluentd](http://www.fluentd.org) plugin to collect Docker metrics periodically.
4
+
5
+ ## How it works
6
+
7
+ It's assumed to run on the host server. It periodically runs `docker ps --no-trunc -q`
8
+ to get a list of running Docker container IDs, and it looks at `/sys/fs/cgroups/<metric_type>/docker/<container_id>/`
9
+ for relevant stats. You can say this is an implementation of the metric collection strategy outlined in [this blog post](http://blog.docker.com/2013/10/gathering-lxc-docker-containers-metrics/).
10
+
11
+ ## Installing
12
+
13
+ to be uploaded on Rubygems
14
+
15
+ ## Example config
16
+
17
+ ```
18
+ <source>
19
+ type docker_metrics
20
+ stats_interval 1m
21
+ </source>
22
+ ```
23
+
24
+ ## Parameters
25
+
26
+ * **stats_interval**: how often to poll Docker containers for stats. The default is every minute.
27
+ * **cgroup_path**: The path to cgroups pseudofiles. The default is `sys/fs/cgroup`.
28
+ * **tag_prefix**: The tag prefix. The default value is "docker"
29
+
30
+ ## Example output
31
+
32
+ ```
33
+ 2014-06-26 18:16:43 +0000 docker.memory.stat: {"key":"memory_stat_total_active_anon","value":26025984,"source":"docker:precise64:b7f17c393775476bc0999cb6dcb4c6416e94b0473317375b9a245985dc6e91c5"}
34
+ 2014-06-26 18:16:43 +0000 docker.memory.stat: {"key":"memory_stat_total_inactive_file","value":131072,"source":"docker:precise64:b7f17c393775476bc0999cb6dcb4c6416e94b0473317375b9a245985dc6e91c5"}
35
+ ```
36
+
37
+ In particular, each event is a key-value pair of individual metrics. Also, it has a field whose value is "\<tag_prefix\>:\<hostname\>:\<container_id\>"
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-docker-metrics"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["kiyoto"]
9
+ spec.email = ["kiyoto@treasure-data.com"]
10
+ spec.summary = %q{Fluentd plugin to collect Docker container metrics}
11
+ spec.homepage = "https://github.com/kiyoto/fluent-plugin-docker-metrics"
12
+ spec.license = "Apache License, Version 2.0"
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler"
20
+ spec.add_development_dependency "rake"
21
+ spec.add_runtime_dependency "fluentd"
22
+ end
@@ -0,0 +1,136 @@
1
+ module Fluent
2
+ class DockerMetricsInput < Input
3
+ Plugin.register_input('docker_metrics', self)
4
+
5
+ config_param :cgroup_path, :string, :default => '/sys/fs/cgroup'
6
+ config_param :stats_interval, :time, :default => 60 # every minute
7
+ config_param :tag_prefix, :string, :default => "docker"
8
+
9
+ def initialize
10
+ super
11
+ require 'socket'
12
+ @hostname = Socket.gethostname
13
+ end
14
+
15
+ def configure(conf)
16
+ super
17
+
18
+ end
19
+
20
+ def start
21
+ @loop = Coolio::Loop.new
22
+ tw = TimerWatcher.new(@stats_interval, true, @log, &method(:get_metrics))
23
+ tw.attach(@loop)
24
+ @thread = Thread.new(&method(:run))
25
+ end
26
+ def run
27
+ @loop.run
28
+ rescue
29
+ log.error "unexpected error", :error=>$!.to_s
30
+ log.error_backtrace
31
+ end
32
+
33
+ # Metrics collection methods
34
+ def get_metrics
35
+ list_container_ids.each do |id|
36
+ emit_container_metric(id, 'memory', 'memory.stat')
37
+ emit_container_metric(id, 'cpuacct', 'cpuacct.stat')
38
+ emit_container_metric(id, 'blkio', 'blkio.io_serviced')
39
+ emit_container_metric(id, 'blkio', 'blkio.io_service_bytes')
40
+ emit_container_metric(id, 'blkio', 'blkio.io_service_queued')
41
+ emit_container_metric(id, 'blkio', 'blkio.sectors')
42
+ end
43
+ end
44
+
45
+ def list_container_ids
46
+ `docker ps --no-trunc -q`.split /\s+/
47
+ end
48
+
49
+ def emit_container_metric(id, metric_type, metric_filename, opts = {})
50
+ path = "#{@cgroup_path}/#{metric_type}/docker/#{id}/#{metric_filename}"
51
+ if File.exists?(path)
52
+ parser = if metric_type != 'blkio'
53
+ KeyValueStatsParser.new(path, metric_filename.gsub('.', '_'))
54
+ else
55
+ BlkioStatsParser.new(path, metric_filename.gsub('.', '_'))
56
+ end
57
+ time = Engine.now
58
+ tag = "#{@tag_prefix}.#{metric_filename}"
59
+ mes = MultiEventStream.new
60
+ parser.parse_each_line do |data|
61
+ next if not data
62
+ # TODO: address this more elegantly
63
+ if data[:key] =~ /^(?:cpuacct|blkio|memory_stat_pg)/
64
+ data[:type] = 'counter'
65
+ end
66
+ data["source"] = "#{@tag_prefix}:#{@hostname}:#{id}"
67
+ mes.add(time, data)
68
+ end
69
+ Engine.emit_stream(tag, mes)
70
+ else
71
+ nil
72
+ end
73
+ end
74
+
75
+ def shutdown
76
+ @loop.stop
77
+ @thread.join
78
+ end
79
+
80
+ class TimerWatcher < Coolio::TimerWatcher
81
+
82
+ def initialize(interval, repeat, log, &callback)
83
+ @callback = callback
84
+ @log = log
85
+ super(interval, repeat)
86
+ end
87
+ def on_timer
88
+ @callback.call
89
+ rescue
90
+ @log.error $!.to_s
91
+ @log.error_backtrace
92
+ end
93
+ end
94
+
95
+ class CGroupStatsParser
96
+ def initialize(path, metric_type)
97
+ raise ConfigError if not File.exists?(path)
98
+ @path = path
99
+ @metric_type = metric_type
100
+ end
101
+
102
+ def parse_line(line)
103
+ end
104
+
105
+ def parse_each_line(&block)
106
+ File.new(@path).each_line do |line|
107
+ block.call(parse_line(line))
108
+ end
109
+ end
110
+ end
111
+
112
+ class KeyValueStatsParser < CGroupStatsParser
113
+ def parse_line(line)
114
+ k, v = line.split(/\s+/, 2)
115
+ if k and v
116
+ { key: @metric_type + "_" + k, value: v.to_i }
117
+ else
118
+ nil
119
+ end
120
+ end
121
+ end
122
+
123
+ class BlkioStatsParser < CGroupStatsParser
124
+ BlkioLineRegexp = /^(?<major>\d+):(?<minor>\d+) (?<key>[^ ]+) (?<value>\d+)/
125
+
126
+ def parse_line(line)
127
+ m = BlkioLineRegexp.match(line)
128
+ if m
129
+ { key: @metric_type + "_" + m["key"].downcase, value: m["value"] }
130
+ else
131
+ nil
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-docker-metrics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - kiyoto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fluentd
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - kiyoto@treasure-data.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - README.md
64
+ - fluent-plugin-docker-metrics.gemspec
65
+ - lib/fluent/plugin/in_docker_metrics.rb
66
+ homepage: https://github.com/kiyoto/fluent-plugin-docker-metrics
67
+ licenses:
68
+ - Apache License, Version 2.0
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.2.2
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Fluentd plugin to collect Docker container metrics
90
+ test_files: []