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 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: []