fluent-plugin-docker-stats 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ ## v1.0.0 2023/12/15
2
+
3
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'docker-api', '~> 1.34.2'
4
+
5
+ gemspec
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,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << "test" << "lib"
6
+ test.pattern = 'test/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :test
@@ -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: []