fluent-plugin-prometheus 2.2.1 → 2.2.2
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 +4 -4
- data/.github/workflows/linux.yml +12 -2
- data/.gitignore +1 -0
- data/ChangeLog +4 -0
- data/README.md +1 -1
- data/fluent-plugin-prometheus.gemspec +1 -1
- data/lib/fluent/plugin/in_prometheus/async_wrapper.rb +9 -2
- data/lib/fluent/plugin/in_prometheus.rb +50 -21
- data/spec/fluent/plugin/in_prometheus_spec.rb +53 -0
- data/spec/fluent/plugin/shared.rb +6 -1
- data/spec/spec_helper.rb +18 -0
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a2c3701c496726e677bf8182e4b549d493648b1f639930a7508ead0a07611ed6
|
|
4
|
+
data.tar.gz: c7f62e9dfc1a37d8089e07b41a6704e92fc365c0811b960bb628ffafe01134eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53f721520289f3ca5f8b7b47fe4c5daf7829fae4e22f4bd6145dffaa1d4d173fc81909576067136299b0e256a55d8b961d432ac15aa16074f73dfb6003b9fbfb
|
|
7
|
+
data.tar.gz: 5cdf65cb05bf988df0cfc255a2af2e0f5b8223e5b54c56d4bbabe081827c111e7e210d45d2256d6f3af9cf4dab9154d2b6aba85c7226a87ebb96b420e9230402
|
data/.github/workflows/linux.yml
CHANGED
|
@@ -4,20 +4,30 @@ on:
|
|
|
4
4
|
branches: [master]
|
|
5
5
|
pull_request:
|
|
6
6
|
branches: [master]
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '0 0 1 * *'
|
|
7
9
|
jobs:
|
|
10
|
+
ruby-versions:
|
|
11
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
|
12
|
+
with:
|
|
13
|
+
engine: cruby
|
|
14
|
+
min_version: 2.7
|
|
8
15
|
build:
|
|
16
|
+
needs: ruby-versions
|
|
9
17
|
runs-on: ${{ matrix.os }}
|
|
10
18
|
continue-on-error: ${{ matrix.experimental }}
|
|
11
19
|
strategy:
|
|
12
20
|
fail-fast: false
|
|
13
21
|
matrix:
|
|
14
|
-
ruby:
|
|
22
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
|
23
|
+
exclude:
|
|
24
|
+
- ruby: head
|
|
15
25
|
os:
|
|
16
26
|
- ubuntu-latest
|
|
17
27
|
experimental: [false]
|
|
18
28
|
name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
|
|
19
29
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
30
|
+
- uses: actions/checkout@v6
|
|
21
31
|
- uses: ruby/setup-ruby@v1
|
|
22
32
|
with:
|
|
23
33
|
ruby-version: ${{ matrix.ruby }}
|
data/.gitignore
CHANGED
data/ChangeLog
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# fluent-plugin-prometheus, a plugin for [Fluentd](https://www.fluentd.org)
|
|
2
2
|
|
|
3
|
-
[](https://github.com/fluent/fluent-plugin-prometheus/actions/workflows/linux.yml)
|
|
4
4
|
|
|
5
5
|
A fluent plugin that instruments metrics from records and exposes them via web interface. Intended to be used together with a [Prometheus server](https://github.com/prometheus/prometheus).
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Gem::Specification.new do |spec|
|
|
2
2
|
spec.name = "fluent-plugin-prometheus"
|
|
3
|
-
spec.version = "2.2.
|
|
3
|
+
spec.version = "2.2.2"
|
|
4
4
|
spec.authors = ["Masahiro Sano"]
|
|
5
5
|
spec.email = ["sabottenda@gmail.com"]
|
|
6
6
|
spec.summary = %q{A fluent plugin that collects metrics and exposes for Prometheus.}
|
|
@@ -4,13 +4,20 @@ module Fluent::Plugin
|
|
|
4
4
|
class PrometheusInput
|
|
5
5
|
module AsyncWrapper
|
|
6
6
|
def do_request(host:, port:, secure:)
|
|
7
|
+
# Format host for URI - bracket IPv6 addresses if not already bracketed
|
|
8
|
+
uri_host = if host.include?(':') && !host.start_with?('[')
|
|
9
|
+
"[#{host}]"
|
|
10
|
+
else
|
|
11
|
+
host
|
|
12
|
+
end
|
|
13
|
+
|
|
7
14
|
endpoint =
|
|
8
15
|
if secure
|
|
9
16
|
context = OpenSSL::SSL::SSLContext.new
|
|
10
17
|
context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
11
|
-
Async::HTTP::Endpoint.parse("https://#{
|
|
18
|
+
Async::HTTP::Endpoint.parse("https://#{uri_host}:#{port}", ssl_context: context)
|
|
12
19
|
else
|
|
13
|
-
Async::HTTP::Endpoint.parse("http://#{
|
|
20
|
+
Async::HTTP::Endpoint.parse("http://#{uri_host}:#{port}")
|
|
14
21
|
end
|
|
15
22
|
|
|
16
23
|
Async::HTTP::Client.open(endpoint) do |client|
|
|
@@ -67,12 +67,25 @@ module Fluent::Plugin
|
|
|
67
67
|
def start
|
|
68
68
|
super
|
|
69
69
|
|
|
70
|
+
# Normalize bind address: strip brackets if present (for consistency)
|
|
71
|
+
# Brackets are only for URI formatting, not for socket binding
|
|
72
|
+
@bind = @bind[1..-2] if @bind.start_with?('[') && @bind.end_with?(']')
|
|
73
|
+
|
|
70
74
|
scheme = @secure ? 'https' : 'http'
|
|
71
|
-
|
|
75
|
+
# Format bind address properly for URLs (add brackets for IPv6)
|
|
76
|
+
bind_display = @bind.include?(':') ? "[#{@bind}]" : @bind
|
|
77
|
+
log.debug "listening prometheus http server on #{scheme}://#{bind_display}:#{@port}/#{@metrics_path} for worker#{fluentd_worker_id}"
|
|
72
78
|
|
|
73
79
|
proto = @secure ? :tls : :tcp
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
# IPv6 + TLS combination is not currently supported
|
|
82
|
+
if @bind.include?(':') && @secure
|
|
83
|
+
raise Fluent::ConfigError, 'IPv6 with <transport tls> is not currently supported. Use bind 0.0.0.0 with TLS, or bind ::1 without TLS.'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Use webrick for IPv6 or SSL extra_conf
|
|
87
|
+
# The http_server helper has issues with IPv6 URI construction
|
|
88
|
+
if (@ssl && @ssl['enable'] && @ssl['extra_conf']) || @bind.include?(':')
|
|
76
89
|
start_webrick
|
|
77
90
|
return
|
|
78
91
|
end
|
|
@@ -110,6 +123,8 @@ module Fluent::Plugin
|
|
|
110
123
|
ssl_config
|
|
111
124
|
end
|
|
112
125
|
|
|
126
|
+
# Use raw bind address for socket binding (no brackets)
|
|
127
|
+
# Brackets are only for URL/URI formatting, not for bind()
|
|
113
128
|
http_server_create_http_server(:in_prometheus_server, addr: @bind, port: @port, logger: log, proto: proto, tls_opts: tls_opt) do |server|
|
|
114
129
|
server.get(@metrics_path) { |_req| all_metrics }
|
|
115
130
|
server.get(@aggregated_metrics_path) { |_req| all_workers_metrics }
|
|
@@ -127,6 +142,7 @@ module Fluent::Plugin
|
|
|
127
142
|
private
|
|
128
143
|
|
|
129
144
|
# For compatiblity because http helper can't support extra_conf option
|
|
145
|
+
# Also used for IPv6 addresses since http helper has IPv6 URI issues
|
|
130
146
|
def start_webrick
|
|
131
147
|
require 'webrick/https'
|
|
132
148
|
require 'webrick'
|
|
@@ -138,28 +154,32 @@ module Fluent::Plugin
|
|
|
138
154
|
Logger: WEBrick::Log.new(STDERR, WEBrick::Log::FATAL),
|
|
139
155
|
AccessLog: [],
|
|
140
156
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
157
|
+
|
|
158
|
+
# Configure SSL if enabled
|
|
159
|
+
if @ssl && @ssl['enable']
|
|
160
|
+
if (@ssl['certificate_path'] && @ssl['private_key_path'].nil?) || (@ssl['certificate_path'].nil? && @ssl['private_key_path'])
|
|
161
|
+
raise RuntimeError.new("certificate_path and private_key_path most both be defined")
|
|
162
|
+
end
|
|
144
163
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
164
|
+
ssl_config = {
|
|
165
|
+
SSLEnable: true,
|
|
166
|
+
SSLCertName: [['CN', 'nobody'], ['DC', 'example']]
|
|
167
|
+
}
|
|
149
168
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
if @ssl['certificate_path']
|
|
170
|
+
cert = OpenSSL::X509::Certificate.new(File.read(@ssl['certificate_path']))
|
|
171
|
+
ssl_config[:SSLCertificate] = cert
|
|
172
|
+
end
|
|
154
173
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
if @ssl['private_key_path']
|
|
175
|
+
key = OpenSSL::PKey.read(@ssl['private_key_path'])
|
|
176
|
+
ssl_config[:SSLPrivateKey] = key
|
|
177
|
+
end
|
|
159
178
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
179
|
+
ssl_config[:SSLCACertificateFile] = @ssl['ca_path'] if @ssl['ca_path']
|
|
180
|
+
ssl_config = ssl_config.merge(@ssl['extra_conf']) if @ssl['extra_conf']
|
|
181
|
+
config = ssl_config.merge(config)
|
|
182
|
+
end
|
|
163
183
|
|
|
164
184
|
@log.on_debug do
|
|
165
185
|
@log.debug("WEBrick conf: #{config}")
|
|
@@ -207,7 +227,16 @@ module Fluent::Plugin
|
|
|
207
227
|
end
|
|
208
228
|
|
|
209
229
|
def send_request_to_each_worker
|
|
210
|
-
|
|
230
|
+
# Convert bind address to localhost for inter-worker communication
|
|
231
|
+
# 0.0.0.0 and :: are not connectable, use localhost instead
|
|
232
|
+
bind = case @bind
|
|
233
|
+
when '0.0.0.0'
|
|
234
|
+
'127.0.0.1'
|
|
235
|
+
when '::'
|
|
236
|
+
'::1' # IPv6 localhost
|
|
237
|
+
else
|
|
238
|
+
@bind
|
|
239
|
+
end
|
|
211
240
|
[*(@base_port...(@base_port + @num_workers))].each do |worker_port|
|
|
212
241
|
do_request(host: bind, port: worker_port, secure: @secure) do |http|
|
|
213
242
|
yield(http.get(@metrics_path))
|
|
@@ -89,6 +89,22 @@ describe Fluent::Plugin::PrometheusInput do
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
context 'IPv6 with TLS' do
|
|
93
|
+
let(:config) do
|
|
94
|
+
%[
|
|
95
|
+
@type prometheus
|
|
96
|
+
bind ::1
|
|
97
|
+
<transport tls>
|
|
98
|
+
insecure true
|
|
99
|
+
</transport>
|
|
100
|
+
]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'raises ConfigError for unsupported combination' do
|
|
104
|
+
expect { driver.run(timeout: 1) }.to raise_error(Fluent::ConfigError, /IPv6 with <transport tls> is not currently supported/)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
92
108
|
context 'old parameters are given' do
|
|
93
109
|
context 'when extra_conf is used' do
|
|
94
110
|
let(:config) do
|
|
@@ -278,4 +294,41 @@ describe Fluent::Plugin::PrometheusInput do
|
|
|
278
294
|
end
|
|
279
295
|
end
|
|
280
296
|
end
|
|
297
|
+
|
|
298
|
+
describe '#run with IPv6' do
|
|
299
|
+
shared_examples 'IPv6 server binding' do |bind_addr, connect_addr, description|
|
|
300
|
+
let(:config) do
|
|
301
|
+
# Quote the bind address if it contains brackets
|
|
302
|
+
bind_value = bind_addr.include?('[') ? "\"#{bind_addr}\"" : bind_addr
|
|
303
|
+
%[
|
|
304
|
+
@type prometheus
|
|
305
|
+
bind #{bind_value}
|
|
306
|
+
]
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it description do
|
|
310
|
+
skip 'IPv6 not available on this system' unless ipv6_enabled?
|
|
311
|
+
|
|
312
|
+
driver.run(timeout: 3) do
|
|
313
|
+
Net::HTTP.start(connect_addr, port) do |http|
|
|
314
|
+
req = Net::HTTP::Get.new('/metrics')
|
|
315
|
+
res = http.request(req)
|
|
316
|
+
expect(res.code).to eq('200')
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context 'IPv6 loopback address ::1' do
|
|
323
|
+
include_examples 'IPv6 server binding', '::1', '::1', 'binds and serves on IPv6 loopback address'
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
context 'IPv6 any address ::' do
|
|
327
|
+
include_examples 'IPv6 server binding', '::', '::1', 'binds on :: and connects via ::1'
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
context 'pre-bracketed IPv6 address [::1]' do
|
|
331
|
+
include_examples 'IPv6 server binding', '[::1]', '::1', 'handles pre-bracketed address correctly'
|
|
332
|
+
end
|
|
333
|
+
end
|
|
281
334
|
end
|
|
@@ -289,7 +289,12 @@ end
|
|
|
289
289
|
|
|
290
290
|
shared_examples_for 'instruments record' do
|
|
291
291
|
before do
|
|
292
|
-
|
|
292
|
+
# Should not shut down driver because it will be used in subsequent tests.
|
|
293
|
+
driver.run(default_tag: tag, shutdown: false) { driver.feed(event_time, message) }
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
after do
|
|
297
|
+
driver.instance_shutdown
|
|
293
298
|
end
|
|
294
299
|
|
|
295
300
|
context 'full config' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -8,3 +8,21 @@ Test::Unit::AutoRunner.need_auto_run = false
|
|
|
8
8
|
|
|
9
9
|
Fluent::Test.setup
|
|
10
10
|
include Fluent::Test::Helpers
|
|
11
|
+
|
|
12
|
+
def ipv6_enabled?
|
|
13
|
+
require 'socket'
|
|
14
|
+
|
|
15
|
+
begin
|
|
16
|
+
# Try to actually bind to an IPv6 address to verify it works
|
|
17
|
+
sock = Socket.new(Socket::AF_INET6, Socket::SOCK_STREAM, 0)
|
|
18
|
+
sock.bind(Socket.sockaddr_in(0, '::1'))
|
|
19
|
+
sock.close
|
|
20
|
+
|
|
21
|
+
# Also test that we can resolve IPv6 addresses
|
|
22
|
+
# This is needed because some systems can bind but can't connect
|
|
23
|
+
Socket.getaddrinfo('::1', nil, Socket::AF_INET6)
|
|
24
|
+
true
|
|
25
|
+
rescue Errno::EADDRNOTAVAIL, Errno::EAFNOSUPPORT, SocketError
|
|
26
|
+
false
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fluent-plugin-prometheus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.2.
|
|
4
|
+
version: 2.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Masahiro Sano
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: fluentd
|
|
@@ -144,7 +143,6 @@ homepage: https://github.com/fluent/fluent-plugin-prometheus
|
|
|
144
143
|
licenses:
|
|
145
144
|
- Apache-2.0
|
|
146
145
|
metadata: {}
|
|
147
|
-
post_install_message:
|
|
148
146
|
rdoc_options: []
|
|
149
147
|
require_paths:
|
|
150
148
|
- lib
|
|
@@ -159,8 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
159
157
|
- !ruby/object:Gem::Version
|
|
160
158
|
version: '0'
|
|
161
159
|
requirements: []
|
|
162
|
-
rubygems_version:
|
|
163
|
-
signing_key:
|
|
160
|
+
rubygems_version: 4.0.8
|
|
164
161
|
specification_version: 4
|
|
165
162
|
summary: A fluent plugin that collects metrics and exposes for Prometheus.
|
|
166
163
|
test_files:
|