fluent-plugin-time-cutoff 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5eddac80384bc759095b8ead85af572e50aafb3d0820b8f87b46b8fbc7aa6361
4
- data.tar.gz: 2df3ffbc38531125d8b893eec4a144ffda0348505efa46a9d9a29412a5da1505
3
+ metadata.gz: a52993553c1cdc40bb6800791120e5248662a1f84546bf13b686c90c16f5c35d
4
+ data.tar.gz: c58051186b9056ee4fe0b6aa25850e11d1013de01038cca983323e525e551bdd
5
5
  SHA512:
6
- metadata.gz: 3bb580a34a68cd2859431f64cb034046b7ffaee4680241617d9f279ed0eb2140b55a1b610dccbf7b35558c1e1b92e3f39b42e9f5db35eab5334cbe1e6dd64918
7
- data.tar.gz: ff4f97ac6abec3a87807cee266cbf1597dfeb8dae566ff742ba797aef4946238ec89ecdc89374be259dfaea1ae4730e476cdb0dfc46369c2b7023b63abe173f8
6
+ metadata.gz: 7b2c8c998860001c4142850878506fa29978fd996049019babdc7331dc74b6889c90a1caa55344075c4d399e883cdf384e9e7f2f3f9b8f3c7ba07c38c181a45c
7
+ data.tar.gz: 1be548ff25ac8d3e9db3314a3c01a36404c7c77cae535f1857366deb87ce2b62199913b84ffd3ffbf88c2de86a421c0cb5f4f936b722f8835d13cbda2064982b
data/README.md CHANGED
@@ -104,20 +104,22 @@ $ bundle
104
104
 
105
105
  old_cutoff 24h
106
106
  old_action pass
107
- old_log true
107
+ old_log full
108
108
 
109
109
  new_cutoff 24h
110
110
  new_action pass
111
- new_log true
111
+ new_log full
112
112
 
113
113
  source_time_key source_time
114
114
  source_time_format iso8601
115
115
 
116
116
  bad_time_action replace_timestamp
117
- bad_time_log true
117
+ bad_time_log full
118
118
  bad_time_key source_time_raw
119
119
 
120
120
  time_key_conflict skip
121
+
122
+ metrics false
121
123
  </filter>
122
124
 
123
125
  ```
@@ -138,11 +140,15 @@ Available values: pass, replace_timestamp, drop
138
140
 
139
141
  Default value: `pass`.
140
142
 
141
- ### old_log (bool) (optional)
143
+ ### old_log (enum) (optional)
144
+
145
+ Log the "old" messages to Fluentd's own log. Defaults to "full".
146
+
147
+ Available values: none (or false/no), metadata, full (or true/yes)
142
148
 
143
- Log the "old" messages to Fluentd's own log. Defaults to "true".
149
+ See [Logging](#logging) for what each mode logs.
144
150
 
145
- Default value: `true`.
151
+ Default value: `full`.
146
152
 
147
153
  ### new_cutoff (time) (optional)
148
154
 
@@ -160,11 +166,15 @@ Available values: pass, replace_timestamp, drop
160
166
 
161
167
  Default value: `pass`.
162
168
 
163
- ### new_log (bool) (optional)
169
+ ### new_log (enum) (optional)
170
+
171
+ Log the "new" messages to Fluentd's own log. Defaults to "full".
172
+
173
+ Available values: none (or false/no), metadata, full (or true/yes)
164
174
 
165
- Log the "new" messages to Fluentd's own log. Defaults to "true".
175
+ See [Logging](#logging) for what each mode logs.
166
176
 
167
- Default value: `true`.
177
+ Default value: `full`.
168
178
 
169
179
  ### source_time_key (string) (optional)
170
180
 
@@ -186,17 +196,21 @@ Default value: `iso8601`.
186
196
 
187
197
  The action that will be performed to all messages with an unparseable time. Defaults to replacing it with current time.
188
198
 
189
- Event times that aren't a `Fluent::EventTime` are parsed before the age check. Integers, floats, numeric strings and ISO 8601 datetime strings are accepted. ISO 8601 strings may use a space instead of `T` and may have a space before the timezone (e.g. `2025-04-08 14:43:14 +0300` or `2025-04-08 11:43:14 UTC`, as produced by Ruby's `Time#to_s`). Strings without a timezone are treated as local time. Any other time is deemed unparseable and is handled according to this action (and logged, unless `bad_time_log` is disabled).
199
+ Event times that aren't a `Fluent::EventTime` are parsed before the age check. Integers, floats, numeric strings and ISO 8601 datetime strings are accepted. ISO 8601 strings may use a space instead of `T` and may have a space before the timezone (e.g. `2025-04-08 14:43:14 +0300` or `2025-04-08 11:43:14 UTC`, as produced by Ruby's `Time#to_s`). Strings without a timezone are treated as local time. Any other time is deemed unparseable and is handled according to this action (and logged, unless `bad_time_log` is `none`).
190
200
 
191
201
  Available values: replace_timestamp, drop
192
202
 
193
203
  Default value: `replace_timestamp`.
194
204
 
195
- ### bad_time_log (bool) (optional)
205
+ ### bad_time_log (enum) (optional)
196
206
 
197
- Log the messages with an unparseable time to Fluentd's own log. Defaults to "true".
207
+ Log the messages with an unparseable time to Fluentd's own log. Defaults to "full".
198
208
 
199
- Default value: `true`.
209
+ Available values: none (or false/no), metadata, full (or true/yes)
210
+
211
+ See [Logging](#logging) for what each mode logs.
212
+
213
+ Default value: `full`.
200
214
 
201
215
  ### bad_time_key (string) (optional)
202
216
 
@@ -215,13 +229,78 @@ The action that will be performed when the record already has source_time_key or
215
229
  This happens e.g. when a record passes through more than one `time_cutoff` filter, in which case the existing value is the true original time. The event time itself is replaced with current time in any case.
216
230
 
217
231
  * `skip`: keep the existing value.
218
- * `warn`: keep the existing value and log a warning to Fluentd's own log.
232
+ * `warn`: keep the existing value and log a warning to Fluentd's own log. The warning is logged even if the record's log mode is `none`, but includes the record only in `full` mode.
219
233
  * `overwrite`: replace the existing value.
220
234
 
221
235
  Available values: skip, warn, overwrite
222
236
 
223
237
  Default value: `skip`.
224
238
 
239
+ ### metrics (bool) (optional)
240
+
241
+ Count caught records in a Prometheus counter (needs the prometheus-client gem). Defaults to "false".
242
+
243
+ See [Metrics](#metrics) for details.
244
+
245
+ Default value: `false`.
246
+
247
+ ## Logging
248
+
249
+ Each caught record is logged as a warning to Fluentd's own log, according to the `old_log`, `new_log` or `bad_time_log` mode:
250
+
251
+ * `none` (or `false`/`no`): nothing is logged.
252
+ * `metadata`: only the tag, the event time and its age (or the raw unparseable time) are logged, but not the record itself. Use it for records that may hold sensitive data, e.g. audit logs.
253
+ * `full` (or `true`/`yes`): the whole record is logged as well.
254
+
255
+ ```
256
+ # metadata
257
+ [warn]: [time_cutoff] Record caught [old, drop]: "vault.audit: 2025-04-07T14:43:24+03:00 (age 1d 0h 0m 0s)".
258
+ [warn]: [time_cutoff] Record caught [new, pass]: "vault.audit: 2025-04-08T16:43:29+03:00 (age -2h 0m 5s)".
259
+ [warn]: [time_cutoff] Record caught [bad_time, drop]: "vault.audit: "not-a-time"".
260
+
261
+ # full
262
+ [warn]: [time_cutoff] Record caught [old, drop]: "vault.audit: 2025-04-07T14:43:24+03:00 {"message":"hello"}".
263
+ [warn]: [time_cutoff] Record caught [bad_time, drop]: "vault.audit: "not-a-time" {"message":"hello"}".
264
+ ```
265
+
266
+ ## Metrics
267
+
268
+ With `metrics true`, caught records are counted in a Prometheus counter:
269
+
270
+ ```
271
+ fluentd_time_cutoff_records_total{plugin_id, worker_id, hostname, tag, reason, action}
272
+ ```
273
+
274
+ * `plugin_id`: the filter's `@id`. Give each `time_cutoff` filter a stable `@id` to tell them apart.
275
+ * `worker_id`, `hostname`: the Fluentd worker and host, so that series from multiple workers (e.g. on fluent-plugin-prometheus's `/aggregated_metrics` endpoint) and hosts don't collide.
276
+ * `tag`: the record's tag.
277
+ * `reason`: why the record was caught: `old`, `new` or `bad_time`.
278
+ * `action`: what was done to it: `pass`, `replace_timestamp` or `drop`.
279
+
280
+ Records inside the time window aren't counted. Records are counted regardless of their log mode, so the counter can replace per-record logging.
281
+
282
+ The counter is registered in the default registry of the [prometheus-client](https://github.com/prometheus/client_ruby) gem (version 2.1 or newer), which is what [fluent-plugin-prometheus](https://github.com/fluent/fluent-plugin-prometheus) serves, so adding its `prometheus` input is enough to expose it:
283
+
284
+ ``` xml
285
+ <source>
286
+ @type prometheus
287
+ </source>
288
+
289
+ <filter **>
290
+ @type time_cutoff
291
+ @id cutoff_main
292
+ metrics true
293
+ </filter>
294
+ ```
295
+
296
+ The prometheus-client gem is an optional dependency of this plugin. If it's not installed, enabling `metrics` only logs a warning on startup. Errors while updating the counter are logged once and never affect how records are processed.
297
+
298
+ Example query, records dropped per second for being too old, by tag:
299
+
300
+ ```
301
+ sum by (tag) (rate(fluentd_time_cutoff_records_total{reason="old", action="drop"}[5m]))
302
+ ```
303
+
225
304
  ## Copyright
226
305
 
227
306
  * Copyright(c) 2025-2026 Qrator Labs and Serge Tkatchouk
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'fluent/plugin/filter'
4
4
  require 'json'
5
+ require 'socket'
5
6
  require 'time'
6
7
 
7
8
  module Fluent
@@ -50,6 +51,29 @@ module Fluent
50
51
  :overwrite
51
52
  ].freeze
52
53
 
54
+ # Available log modes for caught records.
55
+ LOG_MODES = [
56
+ # Do not log:
57
+ :none,
58
+ # Log tag, time and age (or the raw unparseable time) only:
59
+ :metadata,
60
+ # Log the whole record:
61
+ :full,
62
+ # Aliases for :none and :full, kept for compatibility with the
63
+ # boolean *_log options of earlier versions:
64
+ :false,
65
+ :no,
66
+ :true,
67
+ :yes
68
+ ].freeze
69
+
70
+ # Log modes the boolean aliases stand for.
71
+ LOG_MODE_ALIASES = { false: :none, no: :none, true: :full, yes: :full }.freeze
72
+
73
+ # Name and label names of the Prometheus counter for caught records.
74
+ METRIC_NAME = :fluentd_time_cutoff_records_total
75
+ METRIC_LABELS = %i[plugin_id worker_id hostname tag reason action].freeze
76
+
53
77
  # strftime() format string for :iso8601 time format.
54
78
  TIME_ISO8601 = '%FT%T%:z'
55
79
 
@@ -72,26 +96,28 @@ module Fluent
72
96
  config_param :old_cutoff, :time, default: 86_400 # 24 hours
73
97
  desc 'The action that will be performed to all "old" messages. Defaults to passthrough.'
74
98
  config_param :old_action, :enum, list: CUTOFF_ACTIONS, default: :pass
75
- desc 'Log the "old" messages to Fluentd\'s own log. Defaults to "true".'
76
- config_param :old_log, :bool, default: true
99
+ desc 'Log the "old" messages to Fluentd\'s own log: none (false/no), metadata or full (true/yes). Defaults to "full".'
100
+ config_param :old_log, :enum, list: LOG_MODES, default: :full
77
101
  desc 'Records newer than this amount of time are deemed "new". Defaults to 24 hours.'
78
102
  config_param :new_cutoff, :time, default: 86_400 # 24 hours
79
103
  desc 'The action that will be performed to all "new" messages. Defaults to passthrough.'
80
104
  config_param :new_action, :enum, list: CUTOFF_ACTIONS, default: :pass
81
- desc 'Log the "new" messages to Fluentd\'s own log. Defaults to "true".'
82
- config_param :new_log, :bool, default: true
105
+ desc 'Log the "new" messages to Fluentd\'s own log: none (false/no), metadata or full (true/yes). Defaults to "full".'
106
+ config_param :new_log, :enum, list: LOG_MODES, default: :full
83
107
  desc 'The key that will hold the original time (for :replace_timestamp action). Defaults to "source_time".'
84
108
  config_param :source_time_key, :string, default: 'source_time'
85
109
  desc 'Time format for the original timestamp field. Defaults to ISO8601-formatted string.'
86
110
  config_param :source_time_format, :enum, list: TIME_FORMATS, default: :iso8601
87
111
  desc 'The action that will be performed to all messages with an unparseable time. Defaults to replacing it with current time.'
88
112
  config_param :bad_time_action, :enum, list: BAD_TIME_ACTIONS, default: :replace_timestamp
89
- desc 'Log the messages with an unparseable time to Fluentd\'s own log. Defaults to "true".'
90
- config_param :bad_time_log, :bool, default: true
113
+ desc 'Log the messages with an unparseable time to Fluentd\'s own log: none (false/no), metadata or full (true/yes). Defaults to "full".'
114
+ config_param :bad_time_log, :enum, list: LOG_MODES, default: :full
91
115
  desc 'The key that will hold the original unparseable time (for :replace_timestamp action). Defaults to "source_time_raw".'
92
116
  config_param :bad_time_key, :string, default: 'source_time_raw'
93
117
  desc 'The action that will be performed when the record already has source_time_key or bad_time_key. Defaults to keeping the existing value.'
94
118
  config_param :time_key_conflict, :enum, list: TIME_KEY_CONFLICT_ACTIONS, default: :skip
119
+ desc 'Count caught records in a Prometheus counter (needs the prometheus-client gem). Defaults to "false".'
120
+ config_param :metrics, :bool, default: false
95
121
 
96
122
  def configure(conf)
97
123
  super
@@ -107,9 +133,16 @@ module Fluent
107
133
  %i[source_time_key bad_time_key].each do |param|
108
134
  raise Fluent::ConfigError, "#{param} must not be empty" if instance_variable_get("@#{param}").empty?
109
135
  end
110
- return unless @source_time_key == @bad_time_key
136
+ if @source_time_key == @bad_time_key
137
+ raise Fluent::ConfigError, "source_time_key and bad_time_key must differ, both are \"#{@source_time_key}\""
138
+ end
111
139
 
112
- raise Fluent::ConfigError, "source_time_key and bad_time_key must differ, both are \"#{@source_time_key}\""
140
+ %i[old_log new_log bad_time_log].each do |param|
141
+ mode = instance_variable_get("@#{param}")
142
+ instance_variable_set("@#{param}", LOG_MODE_ALIASES.fetch(mode, mode))
143
+ end
144
+
145
+ setup_metrics
113
146
  end
114
147
 
115
148
  def filter_with_time(tag, time, record)
@@ -139,6 +172,67 @@ module Fluent
139
172
 
140
173
  private
141
174
 
175
+ # Set up the Prometheus counter for caught records, if enabled. The
176
+ # counter is shared by all time_cutoff filters in the process.
177
+ def setup_metrics
178
+ return unless @metrics
179
+
180
+ unless load_prometheus_client
181
+ log.warn 'Metrics are enabled, but the prometheus-client gem is not installed, so caught records will not be counted.'
182
+ return
183
+ end
184
+
185
+ registry = prometheus_registry
186
+ @records_counter = registry.get(METRIC_NAME) || registry.counter(
187
+ METRIC_NAME,
188
+ docstring: 'Number of records caught by the time_cutoff filter.',
189
+ labels: METRIC_LABELS
190
+ )
191
+ @metric_labels = { plugin_id: plugin_id, worker_id: worker_id.to_s, hostname: Socket.gethostname }
192
+ end
193
+
194
+ # Load the prometheus-client gem, which is an optional dependency.
195
+ # @return [Boolean] whether the gem could be loaded
196
+ def load_prometheus_client
197
+ require 'prometheus/client'
198
+ true
199
+ rescue LoadError
200
+ false
201
+ end
202
+
203
+ # The Prometheus registry to register the counter in. This is the one
204
+ # fluent-plugin-prometheus serves on its /metrics endpoints.
205
+ def prometheus_registry
206
+ ::Prometheus::Client.registry
207
+ end
208
+
209
+ # ID of the Fluentd worker this plugin runs in.
210
+ # NOTE: Plugin::Base#fluentd_worker_id isn't available in the oldest
211
+ # Fluentd releases declared in the gemspec, so fall back to the env var
212
+ # it reads.
213
+ # @return [Integer] worker ID
214
+ def worker_id
215
+ return fluentd_worker_id if respond_to?(:fluentd_worker_id, true)
216
+
217
+ (ENV['SERVERENGINE_WORKER_ID'] || 0).to_i
218
+ end
219
+
220
+ # Count a caught record. Errors are logged once and never affect how
221
+ # the record is processed.
222
+ # @param tag [String] log/stream's tag name
223
+ # @param reason [Symbol] why the record was caught (:old, :new or :bad_time)
224
+ # @param action [Symbol] determined action for this record
225
+ def count_record(tag, reason, action)
226
+ return unless @records_counter
227
+
228
+ @records_counter.increment(labels: @metric_labels.merge(tag: tag, reason: reason.to_s, action: action.to_s))
229
+ rescue StandardError => e
230
+ return if @metrics_error_logged
231
+
232
+ @metrics_error_logged = true
233
+ log.warn "Failed to update metrics, further errors will not be logged: #{e.class}: #{e.message}"
234
+ end
235
+
142
236
  # Current UNIX time, used as the reference point for the age check.
143
237
  # Kept as a separate method so that tests can freeze the clock.
144
238
  # @return [Integer] current time in seconds
@@ -176,10 +270,11 @@ module Fluent
176
270
  # @param tag [String] log/stream's tag name
177
271
  # @param time [Fluent::EventTime] the original event time
178
272
  # @param record [Hash] the original record contents
273
+ # @param log_mode [Symbol] log mode for this record
179
274
  # @param @source_time_key [String] name of the field to put the old timestamp to.
180
275
  # @return [Array] new event time and a modified record.
181
- def do_replace_timestamp(tag, time, record)
182
- [Fluent::EventTime.now, put_time_key(tag, record, @source_time_key, format_time(time))]
276
+ def do_replace_timestamp(tag, time, record, log_mode)
277
+ [Fluent::EventTime.now, put_time_key(tag, record, @source_time_key, format_time(time), log_mode)]
183
278
  end
184
279
 
185
280
  # Put the original time into the given field of a copy of the record,
@@ -189,10 +284,11 @@ module Fluent
189
284
  # @param record [Hash] the original record contents
190
285
  # @param key [String] name of the field to put the time to
191
286
  # @param value the time value to put into the field
287
+ # @param log_mode [Symbol] log mode for this record
192
288
  # @return [Hash] the modified copy of the record, or the original record if kept as is
193
- def put_time_key(tag, record, key, value)
289
+ def put_time_key(tag, record, key, value, log_mode) # rubocop:disable Metrics/ParameterLists
194
290
  if record.key?(key) && @time_key_conflict != :overwrite
195
- log_time_key_conflict(tag, record, key, value) if @time_key_conflict == :warn
291
+ log_time_key_conflict(tag, record, key, value, log_mode) if @time_key_conflict == :warn
196
292
  return record
197
293
  end
198
294
 
@@ -201,44 +297,57 @@ module Fluent
201
297
  new_record
202
298
  end
203
299
 
204
- # Log a time key conflict to Fluentd's log.
300
+ # Log a time key conflict to Fluentd's log. It is logged even if the
301
+ # record's log mode is :none, since it was asked for explicitly, but the
302
+ # record itself is only included in :full mode.
205
303
  # @param tag [String] log/stream's tag name
206
304
  # @param record [Hash] the original record contents
207
305
  # @param key [String] name of the conflicting field
208
306
  # @param value the time value that was not put into the field
209
- def log_time_key_conflict(tag, record, key, value)
210
- log_line = format(
211
- 'Record already has the "%<key>s" key, keeping its existing value instead of %<val>s: "%<tag>s: %<msg>s".',
212
- key: key, val: value.inspect, tag: tag, msg: dump_record(record)
307
+ # @param log_mode [Symbol] log mode for this record
308
+ def log_time_key_conflict(tag, record, key, value, log_mode) # rubocop:disable Metrics/ParameterLists
309
+ subject = log_mode == :full ? "#{tag}: #{dump_record(record)}" : tag
310
+ log.warn format(
311
+ 'Record already has the "%<key>s" key, keeping its existing value instead of %<val>s: "%<subject>s".',
312
+ key: key, val: value.inspect, subject: subject
213
313
  )
214
- log.warn log_line
215
314
  end
216
315
 
217
316
  # Log the caught event to Fluentd's log.
218
317
  # @param tag [String] log/stream's tag name
219
- # @param time [Fluent::EventTime] the original event time
318
+ # @param time [Fluent::EventTime] the original event time, or the raw
319
+ # time for :bad_time records
220
320
  # @param record [Hash] the original record contents
221
321
  # @param action [Symbol] determined action for this record
222
- # @param age [Symbol] detemined age for this record (:old or :new)
223
- def log_record(tag, time, record, action, age)
224
- log_line = format(
225
- 'Record caught [%<age>s, %<act>s]: "%<tag>s: %<time>s %<msg>s".',
226
- age: age, act: action, tag: tag, time: iso8601(time), msg: dump_record(record)
322
+ # @param reason [Symbol] why the record was caught (:old, :new or :bad_time)
323
+ # @param log_mode [Symbol] :none, :metadata (no record contents) or :full
324
+ def log_record(tag, time, record, action, reason, log_mode) # rubocop:disable Metrics/ParameterLists
325
+ return if log_mode == :none
326
+
327
+ details = reason == :bad_time ? time.inspect : iso8601(time)
328
+ if log_mode == :full
329
+ details = "#{details} #{dump_record(record)}"
330
+ elsif reason != :bad_time
331
+ details = "#{details} (age #{format_age(current_time - time.to_i)})"
332
+ end
333
+ log.warn format(
334
+ 'Record caught [%<reason>s, %<act>s]: "%<tag>s: %<details>s".',
335
+ reason: reason, act: action, tag: tag, details: details
227
336
  )
228
- log.warn log_line
229
337
  end
230
338
 
231
- # Log the caught event with an unparseable time to Fluentd's log.
232
- # @param tag [String] log/stream's tag name
233
- # @param time the original (unparseable) event time
234
- # @param record [Hash] the original record contents
235
- # @param action [Symbol] determined action for this record
236
- def log_bad_time_record(tag, time, record, action)
237
- log_line = format(
238
- 'Record caught [unparseable, %<act>s]: "%<tag>s: %<time>s %<msg>s".',
239
- act: action, tag: tag, time: time.inspect, msg: dump_record(record)
240
- )
241
- log.warn log_line
339
+ # Format an age in seconds as a compact human-readable string, e.g.
340
+ # "1d 2h 3m 4s", "5m 0s" or "-2h 0m 5s" for times in the future.
341
+ # @param seconds [Integer] the age in seconds
342
+ # @return [String] the formatted age
343
+ def format_age(seconds)
344
+ rest = seconds.abs
345
+ parts = [[86_400, 'd'], [3600, 'h'], [60, 'm'], [1, 's']].map do |size, unit|
346
+ value, rest = rest.divmod(size)
347
+ "#{value}#{unit}"
348
+ end
349
+ parts.shift while parts.size > 1 && parts.first.start_with?('0')
350
+ "#{'-' if seconds.negative?}#{parts.join(' ')}"
242
351
  end
243
352
 
244
353
  # Serialize the record for logging. Falls back to #inspect when the
@@ -304,17 +413,18 @@ module Fluent
304
413
  # @param tag [String] log/stream's tag name
305
414
  # @param time [Fluent::EventTime] the original event time
306
415
  # @param record [Hash] the original record contents
307
- # @param do_log [Boolean] should we log this record or not
416
+ # @param log_mode [Symbol] log mode for this record
308
417
  # @param action [Symbol] determined action for this record
309
- # @param age [Symbol] detemined age for this record (:old or :new)
310
- def process_record(tag, time, record, do_log, action, age) # rubocop:disable Metrics/ParameterLists
311
- log_record(tag, time, record, action, age) if do_log
418
+ # @param reason [Symbol] why the record was caught (:old or :new)
419
+ def process_record(tag, time, record, log_mode, action, reason) # rubocop:disable Metrics/ParameterLists
420
+ count_record(tag, reason, action)
421
+ log_record(tag, time, record, action, reason, log_mode)
312
422
 
313
423
  case action
314
424
  when :pass
315
425
  [time, record]
316
426
  when :replace_timestamp
317
- do_replace_timestamp(tag, time, record)
427
+ do_replace_timestamp(tag, time, record, log_mode)
318
428
  when :drop
319
429
  nil
320
430
  end
@@ -326,7 +436,8 @@ module Fluent
326
436
  # @param record [Hash] the original record contents
327
437
  # @return [Array,nil] current time and the record, or nil if dropped.
328
438
  def process_bad_time_record(tag, time, record)
329
- log_bad_time_record(tag, time, record, @bad_time_action) if @bad_time_log
439
+ count_record(tag, :bad_time, @bad_time_action)
440
+ log_record(tag, time, record, @bad_time_action, :bad_time, @bad_time_log)
330
441
 
331
442
  case @bad_time_action
332
443
  when :replace_timestamp
@@ -347,7 +458,7 @@ module Fluent
347
458
  # @return [Array] new event time and a modified record.
348
459
  def do_replace_bad_timestamp(tag, time, record)
349
460
  raw_time = time.is_a?(String) ? time : time.inspect
350
- [Fluent::EventTime.now, put_time_key(tag, record, @bad_time_key, raw_time)]
461
+ [Fluent::EventTime.now, put_time_key(tag, record, @bad_time_key, raw_time, @bad_time_log)]
351
462
  end
352
463
 
353
464
  # Process the "old" record according to the configuration
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-time-cutoff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Qrator Labs
@@ -30,6 +30,26 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: prometheus-client
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2.1'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '6'
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '2.1'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '6'
33
53
  - !ruby/object:Gem::Dependency
34
54
  name: rake
35
55
  requirement: !ruby/object:Gem::Requirement