fluent-plugin-docker-metrics 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []