fluent-plugin-docker-metrics 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/README.md +37 -0
- data/fluent-plugin-docker-metrics.gemspec +22 -0
- data/lib/fluent/plugin/in_docker_metrics.rb +136 -0
- metadata +90 -0
checksums.yaml
ADDED
@@ -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
data/README.md
ADDED
@@ -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: []
|