fluent-plugin-docker-stats 1.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG +3 -0
- data/Gemfile +5 -0
- data/README.md +45 -0
- data/Rakefile +10 -0
- data/fluent-plugin-docker-stats.gemspec +26 -0
- data/lib/fluent/plugin/in_docker_stats.rb +135 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2190acce2c335545f820f349e2d54821554e6ee9c0adc3a89f41c49515176f70
|
4
|
+
data.tar.gz: 82bea8766f3244fcfc455e0a21c468f575633eaf1b1f4eed5b8739e9be37c2c4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b386ed72c8160e716b6c2b5579be825993555488045469099d17d2c4bb052db2736b81e7523922b3dbac32c1858f0fc8ac43f43dae4355736d16c86f63c7b5d5
|
7
|
+
data.tar.gz: 90b739fe4c659014cb4eb68d8d8b7cc65ea30c9afa73ddaa03149eb7583eef2174f0658f20d2a8c23045b182217f43bea621e2ca5e7284d0f732e951e1cf8c7a
|
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Fluentd Docker Stats Input Plugin
|
2
|
+
|
3
|
+
This is a [Fluentd](http://www.fluentd.org) plugin to collect Docker stats periodically.
|
4
|
+
Tested with Fluentd v1.16.2-1.1 and `docker-api` 1.34.2.
|
5
|
+
|
6
|
+
## How it works
|
7
|
+
|
8
|
+
The script connects to the Docker host using the `docker-api` SDK and periodically queries container statistics.
|
9
|
+
It provides insights into the resource usage, health, and other relevant information of the running Docker containers.
|
10
|
+
|
11
|
+
|
12
|
+
## Installing
|
13
|
+
|
14
|
+
Make sure you have a Ruby environment. Then initialize this repo:
|
15
|
+
|
16
|
+
gem install bundle
|
17
|
+
|
18
|
+
Then:
|
19
|
+
|
20
|
+
bundle install
|
21
|
+
|
22
|
+
## Example config
|
23
|
+
|
24
|
+
```
|
25
|
+
<source>
|
26
|
+
@type docker_stats
|
27
|
+
stats_interval 60s
|
28
|
+
tag docker.stats
|
29
|
+
</source>
|
30
|
+
```
|
31
|
+
|
32
|
+
## Parameters
|
33
|
+
|
34
|
+
* **stats_interval**: how often to poll Docker containers for stats. The default is every minute.
|
35
|
+
* **tag**: The tag for the input source. The default value is "docker
|
36
|
+
* **container_ids**: A list of container IDs for reading stats. The default value is empty, which will fetch stats for all containers.
|
37
|
+
|
38
|
+
## Example output
|
39
|
+
|
40
|
+
```
|
41
|
+
2023-12-15 09:49:12.530109174 +0000 docker.stats: {"container_id":"e59768d2f1cc8448cc1e609324cdddf70e8e26557bfe307a0887d11ec2132af3","container_name":"mysql","created_time":"2023-07-26T01:39:21.286462238Z","status":"running","is_runn
|
42
|
+
ing":true,"is_restarting":false,"is_paused":false,"is_oom_killed":false,"started_time":"2023-12-15T00:56:28.701735927Z","finished_time":"2023-12-15T00:56:24.669503934Z","mem_usage":264130560,"mem_limit":33356099584,"mem_max_usage":266227712,"cpu_system_usage":346646650000000,"cpu_total_usage":16206423900,"cpu_percent":0.004675199918995323,"networks":[{"network_name":"eth0","rx":2110,"tx":0}]}
|
43
|
+
```
|
44
|
+
|
45
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
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-stats"
|
7
|
+
spec.version = "1.0.0"
|
8
|
+
spec.authors = ["James Ma"]
|
9
|
+
spec.email = ["jamesmawm@gmail.com"]
|
10
|
+
spec.summary = %q{Fluentd plugin to collect Docker container stats}
|
11
|
+
spec.homepage = "https://github.com/jamesmawm/fluent-plugin-docker-stats"
|
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_development_dependency "fakefs"
|
22
|
+
spec.add_development_dependency "test-unit", "~> 3.1"
|
23
|
+
spec.add_development_dependency "minitest", "~> 5.8"
|
24
|
+
spec.add_runtime_dependency "fluentd"
|
25
|
+
spec.add_runtime_dependency "docker-api"
|
26
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'fluent/plugin/input'
|
2
|
+
require 'docker'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Fluent::Plugin
|
6
|
+
|
7
|
+
class DockerStatsInput < Input
|
8
|
+
Fluent::Plugin.register_input('docker_stats', self)
|
9
|
+
|
10
|
+
config_param :stats_interval, :string, :default => "60s"
|
11
|
+
config_param :tag, :string, :default => "docker"
|
12
|
+
config_param :container_ids, :array, :default => nil # mainly for testing
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
puts "Found Docker details: #{Docker.version}"
|
17
|
+
puts "Using interval: #{@stats_interval}"
|
18
|
+
puts "Using tag: #{@tag}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure(conf)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def start
|
26
|
+
@loop = Coolio::Loop.new
|
27
|
+
tw = TimerWatcher.new(@stats_interval, true, @log, &method(:get_metrics))
|
28
|
+
tw.attach(@loop)
|
29
|
+
@thread = Thread.new(&method(:run))
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
@loop.run
|
34
|
+
rescue
|
35
|
+
log.error "unexpected error", :error => $!.to_s
|
36
|
+
log.error_backtrace
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_metrics
|
40
|
+
ids = @container_ids || list_container_ids
|
41
|
+
ids.each do |container_id|
|
42
|
+
emit_container_stats(container_id)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def emit_container_stats(container_id)
|
47
|
+
puts "emit_container_stats: #{container_id}"
|
48
|
+
container = Docker::Container.get(container_id)
|
49
|
+
|
50
|
+
record = {
|
51
|
+
"container_id": container_id,
|
52
|
+
"container_name": container.info['Name'].sub(/^\//, ''),
|
53
|
+
"created_time": container.info["Created"]
|
54
|
+
}
|
55
|
+
|
56
|
+
state = container.info['State']
|
57
|
+
record["status"] = state['Status']
|
58
|
+
record["is_running"] = state['Running']
|
59
|
+
record["is_restarting"] = state['Restarting']
|
60
|
+
record["is_paused"] = state['Paused']
|
61
|
+
record["is_oom_killed"] = state['OOMKilled']
|
62
|
+
record["started_time"] = state['StartedAt']
|
63
|
+
record["finished_time"] = state['FinishedAt']
|
64
|
+
|
65
|
+
stats = container.stats(stream: false)
|
66
|
+
|
67
|
+
memory_stats = stats['memory_stats']
|
68
|
+
record["mem_usage"] = memory_stats['usage']
|
69
|
+
record["mem_limit"] = memory_stats['limit']
|
70
|
+
record["mem_max_usage"] = memory_stats['max_usage']
|
71
|
+
|
72
|
+
cpu_stats, = stats['cpu_stats']
|
73
|
+
cpu_usage = cpu_stats['cpu_usage']
|
74
|
+
|
75
|
+
cpu_system_usage = cpu_stats['system_cpu_usage']
|
76
|
+
cpu_total_usage = cpu_usage['total_usage']
|
77
|
+
cpu_percent = (cpu_total_usage.to_f / cpu_system_usage.to_f) * 100
|
78
|
+
|
79
|
+
record["cpu_system_usage"] = cpu_system_usage
|
80
|
+
record["cpu_total_usage"] = cpu_total_usage
|
81
|
+
record["cpu_percent"] = cpu_percent
|
82
|
+
|
83
|
+
record["networks"] = []
|
84
|
+
stats['networks'].each do |network_name, network_info|
|
85
|
+
record["networks"] << {
|
86
|
+
"network_name": network_name,
|
87
|
+
"rx": network_info['rx_bytes'],
|
88
|
+
"tx": network_info['tx_bytes'],
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
storage_stats = stats['storage_stats']
|
93
|
+
if stats['storage_stats'] && !stats['storage_stats'].empty?
|
94
|
+
record["volumes"] = []
|
95
|
+
volume_stats = storage_stats['volumes']
|
96
|
+
volume_stats.each do |volume_name, volume_info|
|
97
|
+
puts "Volume #{volume_name} - Used: #{volume_info['used']} bytes, Total: #{volume_info['total']} bytes"
|
98
|
+
record["volumes"] << {
|
99
|
+
"volume_name": volume_name,
|
100
|
+
"volume_used": volume_info['used'],
|
101
|
+
"volume_total": volume_info['total'],
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
router.emit(@tag, Fluent::Engine.now, record)
|
107
|
+
end
|
108
|
+
|
109
|
+
def list_container_ids
|
110
|
+
Docker::Container.all.map do |container|
|
111
|
+
container.id
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def shutdown
|
116
|
+
@loop.stop
|
117
|
+
@thread.join
|
118
|
+
end
|
119
|
+
|
120
|
+
class TimerWatcher < Coolio::TimerWatcher
|
121
|
+
def initialize(interval, repeat, log, &callback)
|
122
|
+
@callback = callback
|
123
|
+
@log = log
|
124
|
+
super(interval, repeat)
|
125
|
+
end
|
126
|
+
|
127
|
+
def on_timer
|
128
|
+
@callback.call
|
129
|
+
rescue
|
130
|
+
@log.error $!.to_s
|
131
|
+
@log.error_backtrace
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-docker-stats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Ma
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-12-15 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: fakefs
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: test-unit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fluentd
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: docker-api
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- jamesmawm@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- CHANGELOG
|
119
|
+
- Gemfile
|
120
|
+
- README.md
|
121
|
+
- Rakefile
|
122
|
+
- fluent-plugin-docker-stats.gemspec
|
123
|
+
- lib/fluent/plugin/in_docker_stats.rb
|
124
|
+
homepage: https://github.com/jamesmawm/fluent-plugin-docker-stats
|
125
|
+
licenses:
|
126
|
+
- Apache License, Version 2.0
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubygems_version: 3.4.10
|
144
|
+
signing_key:
|
145
|
+
specification_version: 4
|
146
|
+
summary: Fluentd plugin to collect Docker container stats
|
147
|
+
test_files: []
|