fluent-plugin-opentelemetry 0.5.2 → 0.5.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7caa8c736a332ab38da184793751d6760bc1d8bf59c996bffcbe324dd5da7ab5
4
- data.tar.gz: d4c07bffd3ccdd29e8b151a134e5bbe77e1686d8e0ad9a84e5ecd432224d1dd1
3
+ metadata.gz: 2e1331e92688a03b2da70e3712257f4dfd4ae1cec7c5da354084f6fc883ae5cf
4
+ data.tar.gz: 403339bc82d1c09823afc7a5c2b16199cafab92300a0e56eb446fb33e55e1407
5
5
  SHA512:
6
- metadata.gz: 48d509ee79d59085508bd591c051d7ba8cc33efc3e0cb1d64e8ad04f28ed60444fdd4f322e65d4e41ffc84c3d0e7c7770bf7f3cfe1d1076df692ba5dfb8dddcc
7
- data.tar.gz: 9c21c80065796cdadc5fb8aad7c4c1b810cff27a1581d5e83a21d4de920ff34f9318d52f39337c599da8148bbbb6f4f1ac6e365459373079d906cd6812397c77
6
+ metadata.gz: d3cc4c75562d9698c668b02e172d8eeb2c15de4233cb1ebe55607e6daeb18efe19df1bd20f2b0c586f79e07d63301bcf880221d904ebcf11c34047b7a00fd12d
7
+ data.tar.gz: 83d8d1e66e74c93a23f46d7580591b72d1bd3dfd064365ce262057890cb8aff0377cae4cf7c88ad810ed94842a5eb7c91e526109efd50fcff7d131c6afb4f3a7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.3] - 2026-06-25
4
+
5
+ Fixes:
6
+
7
+ - in_opentelemetry: enforce size limits on incoming payloads
8
+
3
9
  ## [0.5.2] - 2026-03-15
4
10
 
5
11
  Improvements:
data/README.md CHANGED
@@ -65,10 +65,12 @@ Example:
65
65
 
66
66
  This requires to receive data via HTTP/HTTPS.
67
67
 
68
- | parameter | type | description | default |
69
- |-----------|---------|------------------------|-----------|
70
- | bind | string | The address to bind to | `0.0.0.0` |
71
- | port | integer | The port to listen to | `4318` |
68
+ | parameter | type | description | default |
69
+ |--------------------------|---------|---------------------------------------------------------------------------------------------------------------------------|-----------|
70
+ | bind | string | The address to bind to | `0.0.0.0` |
71
+ | port | integer | The port to listen to | `4318` |
72
+ | body_size_limit | size | The size limit of the POSTed element. This value should be larger than the 'chunk_limit_size' in out_opentelemetry plugin | `32M` (32MiB) |
73
+ | decompression_size_limit | size | The size limit of the decompressed element | `256M` (256MiB) |
72
74
 
73
75
  #### `<grpc>` section
74
76
 
@@ -144,6 +146,19 @@ To output the data, it requires to use output `opentelemetry` plugin.
144
146
  >
145
147
  > **PromQL Example:** `rate(fluentd_process_cpu_time_seconds_total[$__rate_interval])`
146
148
 
149
+ > [!NOTE]
150
+ > **Process Metrics (CPU / Memory)**
151
+ >
152
+ > Fluentd operates on a multi-process architecture consisting of a Supervisor process and one or more Worker processes.
153
+ >
154
+ > Because this plugin runs inside a specific worker process, the process-level metrics it collects (such as CPU time and memory usage) represent **only the footprint of that single worker process**, not the total resource consumption of the entire Fluentd instance.
155
+ >
156
+ > If you are using a multi-worker configuration (`<system> workers N </system>`), be aware that the actual total CPU and memory usage of Fluentd will be higher than what this plugin reports.
157
+ >
158
+ > For accurate, instance-wide resource monitoring, we strongly recommend using external OS-level monitoring tools rather than relying on application-internal metrics:
159
+ > * Container Environments (Kubernetes/Docker): Use tools like `cAdvisor` or `kube-state-metrics`, etc.
160
+ > * VM/Bare-metal Environments: Use `node_exporter` combined with `process-exporter`, etc.
161
+
147
162
  ### Output `opentelemetry` plugin
148
163
 
149
164
  To send data, this plugin requires `<http>` or `<grpc>` section.
@@ -231,4 +246,3 @@ Refer [Config: Buffer Section](https://docs.fluentd.org/configuration/buffer-sec
231
246
  * Copyright(c) 2025- Shizuo Fujita
232
247
  * License
233
248
  * Apache License, Version 2.0
234
-
data/TODO.md CHANGED
@@ -8,10 +8,13 @@ Ref. https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specif
8
8
  - [x] [MUST] Gzip compression, denoted by gzip.
9
9
 
10
10
  ### OTLP/gRPC Concurrent Requests
11
- - [ ] [SHOULD] The implementations that need to achieve high throughput SHOULD support concurrent Unary calls to achieve higher throughput.
11
+ - [x] [SHOULD] The implementations that need to achieve high throughput SHOULD support concurrent Unary calls to achieve higher throughput.
12
+ * NOTE: Supported by `flush_thread_count` settings in `<buffer>`.
12
13
  - [ ] [SHOULD] The client SHOULD send new requests without waiting for the response to the earlier sent requests, essentially creating a pipeline of requests that are currently in flight that are not acknowledged.
13
- - [ ] [SHOULD] The number of concurrent requests SHOULD be configurable.
14
- - [ ] [SHOULD] The client implementation SHOULD expose an option to turn on and off the waiting during a shutdown.
14
+ - [x] [SHOULD] The number of concurrent requests SHOULD be configurable.
15
+ * NOTE: Supported by `flush_thread_count` settings in `<buffer>`.
16
+ - [x] [SHOULD] The client implementation SHOULD expose an option to turn on and off the waiting during a shutdown.
17
+ * NOTE: Supported by `flush_at_shutdown` settings in `<buffer>`.
15
18
 
16
19
  ### OTLP/gRPC Response
17
20
  - Full Success
@@ -30,7 +33,8 @@ Ref. https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specif
30
33
  - [ ] [SHOULD] Retryable errors indicate that telemetry data processing failed, and the client SHOULD record the error and may retry exporting the same data.
31
34
  - [ ] [SHOULD] The client SHOULD maintain a counter of such dropped data.
32
35
  - [ ] [SHOULD] The client SHOULD interpret gRPC status codes as retryable or not-retryable according to the following table.
33
- - [ ] [SHOULD] When retrying, the client SHOULD implement an exponential backoff strategy.
36
+ - [x] [SHOULD] When retrying, the client SHOULD implement an exponential backoff strategy.
37
+ * NOTE: Fluentd's retry mechanism has `retry_type: exponential_backoff` by default.
34
38
  - [ ] [SHOULD] The client SHOULD interpret RESOURCE_EXHAUSTED code as retryable only if the server signals that the recovery from resource exhaustion is possible.
35
39
 
36
40
  ### OTLP/gRPC Throttling
@@ -91,18 +95,21 @@ Ref. https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specif
91
95
  - OTLP/HTTP Throttling
92
96
  - [ ] [SHOULD] If the server receives more requests than the client is allowed or the server is overloaded, the server SHOULD respond with HTTP 429 Too Many Requests or HTTP 503 Service Unavailable.
93
97
  - [ ] [SHOULD] The client SHOULD honour the waiting interval specified in the "Retry-After" header if it is present.
94
- - [ ] [SHOULD] The "Retry-After" header is not present in the response, then the client SHOULD implement an exponential backoff strategy between retries.
98
+ - [x] [SHOULD] The "Retry-After" header is not present in the response, then the client SHOULD implement an exponential backoff strategy between retries.
99
+ * NOTE: Fluentd's retry mechanism has `retry_type: exponential_backoff` by default.
95
100
  - All Other Responses
96
101
  - [x] [SHOULD] If the server disconnects without returning a response, the client SHOULD retry and send the same request.
97
102
  - [x] [SHOULD] The client SHOULD implement an exponential backoff strategy between retries to avoid overwhelming the server.
98
103
 
99
104
  ### OTLP/HTTP Connection
100
- - [ ] [SHOULD] If the client cannot connect to the server, the client SHOULD retry the connection using an exponential backoff strategy between retries.
101
- - [ ] [SHOULD] The client SHOULD keep the connection alive between requests.
105
+ - [x] [SHOULD] If the client cannot connect to the server, the client SHOULD retry the connection using an exponential backoff strategy between retries.
106
+ * NOTE: Fluentd's retry mechanism has `retry_type: exponential_backoff` by default.
107
+ - [x] [SHOULD] The client SHOULD keep the connection alive between requests.
102
108
  - [ ] [SHOULD] Server implementations SHOULD accept OTLP/HTTP with binary-encoded Protobuf payload and OTLP/HTTP with JSON-encoded Protobuf payload requests on the same port and multiplex the requests to the corresponding payload decoder based on the "Content-Type" request header.
103
109
 
104
110
  ### OTLP/HTTP Concurrent Requests
105
- - [ ] [SHOULD] To achieve higher total throughput, the client MAY send requests using several parallel HTTP connections. In that case, the maximum number of parallel connections SHOULD be configurable.
111
+ - [x] [SHOULD] To achieve higher total throughput, the client MAY send requests using several parallel HTTP connections. In that case, the maximum number of parallel connections SHOULD be configurable.
112
+ * NOTE: Supported by `flush_thread_count` settings in `<buffer>`.
106
113
 
107
114
  # Future Versions and Interoperability
108
115
  - [ ] [MUST] When possible, the interoperability MUST be ensured between all versions of OTLP that are not declared obsolete.
@@ -27,6 +27,11 @@ module Fluent::Plugin
27
27
  config_param :bind, :string, default: "0.0.0.0"
28
28
  desc "The port to listen to."
29
29
  config_param :port, :integer, default: 4318
30
+
31
+ desc "The size limit of the POSTed element. This value should be larger than the 'chunk_limit_size' in out_opentelemetry plugin."
32
+ config_param :body_size_limit, :size, default: 32 * 1024 * 1024
33
+ desc "The size limit of the decompressed element."
34
+ config_param :decompression_size_limit, :size, default: 256 * 1024 * 1024
30
35
  end
31
36
 
32
37
  config_section :grpc, required: false, multi: false, init: false, param_name: :grpc_config do
@@ -58,7 +63,7 @@ module Fluent::Plugin
58
63
  super
59
64
 
60
65
  if @http_config
61
- http_handler = Opentelemetry::HttpInputHandler.new
66
+ http_handler = Opentelemetry::HttpInputHandler.new(@http_config, log)
62
67
  http_server_create_http_server(:in_opentelemetry_http_server, addr: @http_config.bind, port: @http_config.port, logger: log) do |serv|
63
68
  serv.post("/v1/logs") do |req|
64
69
  http_handler.logs(req) { |record| router.emit(tag_for(Opentelemetry::RECORD_TYPE_LOGS), Fluent::EventTime.now, { "type" => Opentelemetry::RECORD_TYPE_LOGS, "message" => record }) }
@@ -5,7 +5,7 @@ require "openssl"
5
5
 
6
6
  module Fluent::Plugin::Opentelemetry
7
7
  CONTENT_TYPE = "Content-Type"
8
- CONTENT_TYPE_PAIN = "text/plain"
8
+ CONTENT_TYPE_PLAIN = "text/plain"
9
9
  CONTENT_TYPE_PROTOBUF = "application/x-protobuf"
10
10
  CONTENT_TYPE_JSON = "application/json"
11
11
 
@@ -25,13 +25,26 @@ module Fluent::PluginHelper::HttpServer
25
25
  @request.body&.close
26
26
  end
27
27
  end
28
+
29
+ unless method_defined?(:body_stream)
30
+ def body_stream
31
+ @request.body
32
+ end
33
+ end
28
34
  end
29
35
  end
30
36
  end
31
37
 
32
38
  class Fluent::Plugin::Opentelemetry::HttpInputHandler
39
+ class SizeLimitError < StandardError; end
40
+
33
41
  using Fluent::PluginHelper::HttpServer::Extension
34
42
 
43
+ def initialize(http_config, logger)
44
+ @http_config = http_config
45
+ @logger = logger
46
+ end
47
+
35
48
  def logs(req, &block)
36
49
  common(req, Fluent::Plugin::Opentelemetry::Request::Logs, Fluent::Plugin::Opentelemetry::Response::Logs, &block)
37
50
  end
@@ -49,16 +62,40 @@ class Fluent::Plugin::Opentelemetry::HttpInputHandler
49
62
  def common(req, request_class, response_class)
50
63
  content_type = req.headers["content-type"]
51
64
  content_encoding = req.headers["content-encoding"]&.first
52
- body = req.body
65
+
66
+ content_length = req.headers["content-length"]&.first&.to_i
67
+ if content_length && content_length >= @http_config.body_size_limit
68
+ @logger.warn { "Received too big content length: #{content_length}" }
69
+ return response_payload_too_large
70
+ end
71
+
72
+ begin
73
+ body = read_body(req, limit: @http_config.body_size_limit)
74
+ rescue SizeLimitError
75
+ @logger.warn { "Received payload exceeding body_size_limit" }
76
+ return response_payload_too_large
77
+ end
78
+
53
79
  return response_unsupported_media_type unless valid_content_type?(content_type)
54
80
  return response_bad_request(content_type) unless valid_content_encoding?(content_encoding)
55
81
 
56
- body = Zlib::GzipReader.new(StringIO.new(body)).read if content_encoding == Fluent::Plugin::Opentelemetry::CONTENT_ENCODING_GZIP
82
+ if content_encoding == Fluent::Plugin::Opentelemetry::CONTENT_ENCODING_GZIP
83
+ begin
84
+ body = decompress(body, limit: @http_config.decompression_size_limit)
85
+ rescue SizeLimitError
86
+ @logger.warn { "Decompressed payload exceeding decompression_size_limit" }
87
+ return response_payload_too_large
88
+ rescue Zlib::Error => e
89
+ @logger.warn { "Failed to decompress gzip payload: #{e.message}" }
90
+ return response_bad_request(content_type)
91
+ end
92
+ end
57
93
 
58
94
  begin
59
95
  record = request_class.new(body).record
60
- rescue Google::Protobuf::ParseError
96
+ rescue Google::Protobuf::ParseError => e
61
97
  # The format in request body does not comply with the OpenTelemetry protocol.
98
+ @logger.warn { "Failed to parse OpenTelemetry payload: #{e.message}" }
62
99
  return response_bad_request(content_type)
63
100
  end
64
101
 
@@ -70,6 +107,42 @@ class Fluent::Plugin::Opentelemetry::HttpInputHandler
70
107
  req.close
71
108
  end
72
109
 
110
+ def read_body(request, limit:)
111
+ body = +""
112
+ while (chunk = request.body_stream&.read)
113
+ body << chunk
114
+ if body.bytesize > limit
115
+ raise SizeLimitError, "Too large payload"
116
+ end
117
+ end
118
+ body
119
+ end
120
+
121
+ BYTES_TO_READ = 64 * 1024
122
+
123
+ def decompress(compressed_data, limit:)
124
+ io = StringIO.new(compressed_data)
125
+ out = +""
126
+ loop do
127
+ reader = Zlib::GzipReader.new(io)
128
+ while (chunk = reader.read(BYTES_TO_READ))
129
+ out << chunk
130
+ if out.bytesize > limit
131
+ raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
132
+ end
133
+ end
134
+
135
+ unused = reader.unused
136
+ reader.finish
137
+ unless unused.nil?
138
+ adjust = unused.length
139
+ io.pos -= adjust
140
+ end
141
+ break if io.eof?
142
+ end
143
+ out
144
+ end
145
+
73
146
  def valid_content_type?(content_type)
74
147
  case content_type
75
148
  when Fluent::Plugin::Opentelemetry::CONTENT_TYPE_PROTOBUF, Fluent::Plugin::Opentelemetry::CONTENT_TYPE_JSON
@@ -90,7 +163,11 @@ class Fluent::Plugin::Opentelemetry::HttpInputHandler
90
163
  end
91
164
 
92
165
  def response_unsupported_media_type
93
- response(415, Fluent::Plugin::Opentelemetry::CONTENT_TYPE_PAIN, "415 unsupported media type, supported: [application/json, application/x-protobuf]")
166
+ response(415, Fluent::Plugin::Opentelemetry::CONTENT_TYPE_PLAIN, "415 unsupported media type, supported: [application/json, application/x-protobuf]")
167
+ end
168
+
169
+ def response_payload_too_large
170
+ response(413, Fluent::Plugin::Opentelemetry::CONTENT_TYPE_PLAIN, "413 Payload Too Large")
94
171
  end
95
172
 
96
173
  def response_bad_request(content_type)
@@ -3,7 +3,7 @@
3
3
  module Fluent
4
4
  module Plugin
5
5
  module Opentelemetry
6
- VERSION = "0.5.2"
6
+ VERSION = "0.5.3"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-opentelemetry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shizuo Fujita
@@ -138,6 +138,7 @@ licenses:
138
138
  metadata:
139
139
  homepage_uri: https://github.com/fluent-plugins-nursery/fluent-plugin-opentelemetry
140
140
  source_code_uri: https://github.com/fluent-plugins-nursery/fluent-plugin-opentelemetry
141
+ changelog_uri: https://github.com/fluent-plugins-nursery/fluent-plugin-opentelemetry/blob/main/CHANGELOG.md
141
142
  rubygems_mfa_required: 'true'
142
143
  rdoc_options: []
143
144
  require_paths:
@@ -153,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  - !ruby/object:Gem::Version
154
155
  version: '0'
155
156
  requirements: []
156
- rubygems_version: 4.0.6
157
+ rubygems_version: 4.0.10
157
158
  specification_version: 4
158
159
  summary: Fluentd input/output plugin to forward OpenTelemetry Protocol data.
159
160
  test_files: []