fluent-plugin-time-cutoff 0.1.1 → 0.1.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 +4 -4
- data/README.md +139 -5
- data/fluent-plugin-time-cutoff.gemspec +1 -1
- data/lib/fluent/plugin/filter_time_cutoff.rb +65 -9
- metadata +6 -4
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ced312074114226376fedaf33671d11804667825d8a50430c1ac54137aac535
|
|
4
|
+
data.tar.gz: c11dc8c0510a8adec9475bac1382a003255bdb8e3af7de6f8aba46defa60ff16
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd2ea5a6907c0b27e95580c0081030de242dcd3cb85ef4bbd79a99918c369ee53680187a866c78e12016ae47d1d534c2b4461a5b6bd522e3f0b2ef691a3c1fb2
|
|
7
|
+
data.tar.gz: 6d39a4673c35dac85aff1e96d4575e87c03f807973acdaa86dca01b6e729f587fbeeec8939a4683e7491ebf0d5cef86fbb0e38f65b70aa90d259db5347188b98
|
data/README.md
CHANGED
|
@@ -2,7 +2,76 @@
|
|
|
2
2
|
|
|
3
3
|
[Fluentd](https://fluentd.org/) filter plugin to cut off log records with a timestamp outside of given window.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### Example 1: Delete all logs older than 12 hours, pass through records from the future
|
|
8
|
+
|
|
9
|
+
**Configuration**
|
|
10
|
+
|
|
11
|
+
``` xml
|
|
12
|
+
<filter **>
|
|
13
|
+
@type time_cutoff
|
|
14
|
+
@id time_cutoff
|
|
15
|
+
|
|
16
|
+
old_cutoff 12h
|
|
17
|
+
old_action drop
|
|
18
|
+
|
|
19
|
+
new_action pass
|
|
20
|
+
new_log false
|
|
21
|
+
</filter>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Input**
|
|
25
|
+
|
|
26
|
+
``` bash
|
|
27
|
+
# Local time is 2025-04-08T14:43:14+03:00
|
|
28
|
+
fluent-cat --event-time '2025-04-08T02:42:00+03:00' test.cutoff <<< '{"message": "hello"}'
|
|
29
|
+
fluent-cat --event-time '2025-04-08T12:42:00+03:00' test.cutoff <<< '{"message": "hello"}'
|
|
30
|
+
fluent-cat --event-time '2025-04-09T14:42:00+03:00' test.cutoff <<< '{"message": "hello"}'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Output**
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
2025-04-08 14:43:24 +0300 [warn]: [time_cutoff] Record caught [old, drop]: "test.cutoff: 2025-04-08T02:42:00+03:00 {"message":"hello"}".
|
|
37
|
+
2025-04-08 12:42:00.000000000 +0300 test.cutoff: {"message":"hello"}
|
|
38
|
+
2025-04-09 14:42:00.000000000 +0300 test.cutoff: {"message":"hello"}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Example 2: Delete all logs older than 24 hours (omit log), rewrite timestamps for all records newer than 3 hours:
|
|
42
|
+
|
|
43
|
+
**Configuration**
|
|
44
|
+
|
|
45
|
+
``` xml
|
|
46
|
+
<filter **>
|
|
47
|
+
@type time_cutoff
|
|
48
|
+
@id time_cutoff
|
|
49
|
+
|
|
50
|
+
old_cutoff 24h
|
|
51
|
+
old_action drop
|
|
52
|
+
old_log false
|
|
53
|
+
|
|
54
|
+
new_cutoff 3h
|
|
55
|
+
new_action replace_timestamp
|
|
56
|
+
</filter>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Input**
|
|
60
|
+
|
|
61
|
+
``` bash
|
|
62
|
+
# Local time is 2025-04-08T14:48:42+03:00
|
|
63
|
+
fluent-cat --event-time '2025-04-07T14:48:00+03:00' test.cutoff <<< '{"message": "hello"}'
|
|
64
|
+
fluent-cat --event-time '2025-04-08T14:48:00+03:00' test.cutoff <<< '{"message": "hello"}'
|
|
65
|
+
fluent-cat --event-time '2025-04-08T18:48:00+03:00' test.cutoff <<< '{"message": "hello"}'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Output**
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
2025-04-08 14:48:00.000000000 +0300 test.cutoff: {"message":"hello"}
|
|
72
|
+
2025-04-08 14:49:13 +0300 [warn]: [time_cutoff] Record caught [new, replace_timestamp]: "test.cutoff: 2025-04-08T18:48:00+03:00 {"message":"hello"}".
|
|
73
|
+
2025-04-08 14:49:13.090783000 +0300 test.cutoff: {"message":"hello","source_time":"2025-04-08T18:48:00+03:00"}
|
|
74
|
+
```
|
|
6
75
|
|
|
7
76
|
## Installation
|
|
8
77
|
|
|
@@ -28,13 +97,78 @@ $ bundle
|
|
|
28
97
|
|
|
29
98
|
## Configuration
|
|
30
99
|
|
|
31
|
-
|
|
100
|
+
``` xml
|
|
101
|
+
<filter **>
|
|
102
|
+
@type time_cutoff
|
|
103
|
+
@id time_cutoff
|
|
104
|
+
|
|
105
|
+
old_cutoff 24h
|
|
106
|
+
old_action pass
|
|
107
|
+
old_log true
|
|
108
|
+
|
|
109
|
+
new_cutoff 24h
|
|
110
|
+
new_action pass
|
|
111
|
+
new_log true
|
|
112
|
+
|
|
113
|
+
source_time_key source_time
|
|
114
|
+
source_time_format iso8601
|
|
115
|
+
</filter>
|
|
32
116
|
|
|
33
117
|
```
|
|
34
|
-
$ fluent-plugin-config-format filter time-cutoff
|
|
35
|
-
```
|
|
36
118
|
|
|
37
|
-
|
|
119
|
+
### old_cutoff (time) (optional)
|
|
120
|
+
|
|
121
|
+
Records older than this amount of time are deemed "old". Defaults to 24 hours.
|
|
122
|
+
|
|
123
|
+
Default value: `86400`.
|
|
124
|
+
|
|
125
|
+
### old_action (enum) (optional)
|
|
126
|
+
|
|
127
|
+
The action that will be performed to all "old" messages. Defaults to passthrough.
|
|
128
|
+
|
|
129
|
+
Available values: pass, replace_timestamp, drop
|
|
130
|
+
|
|
131
|
+
Default value: `pass`.
|
|
132
|
+
|
|
133
|
+
### old_log (bool) (optional)
|
|
134
|
+
|
|
135
|
+
Log the "old" messages to Fluentd's own log. Defaults to "true".
|
|
136
|
+
|
|
137
|
+
Default value: `true`.
|
|
138
|
+
|
|
139
|
+
### new_cutoff (time) (optional)
|
|
140
|
+
|
|
141
|
+
Records newer than this amount of time are deemed "new". Defaults to 24 hours.
|
|
142
|
+
|
|
143
|
+
Default value: `86400`.
|
|
144
|
+
|
|
145
|
+
### new_action (enum) (optional)
|
|
146
|
+
|
|
147
|
+
The action that will be performed to all "new" messages. Defaults to passthrough.
|
|
148
|
+
|
|
149
|
+
Available values: pass, replace_timestamp, drop
|
|
150
|
+
|
|
151
|
+
Default value: `pass`.
|
|
152
|
+
|
|
153
|
+
### new_log (bool) (optional)
|
|
154
|
+
|
|
155
|
+
Log the "new" messages to Fluentd's own log. Defaults to "true".
|
|
156
|
+
|
|
157
|
+
Default value: `true`.
|
|
158
|
+
|
|
159
|
+
### source_time_key (string) (optional)
|
|
160
|
+
|
|
161
|
+
The key that will hold the original time (for :replace_timestamp action). Defaults to "source_time".
|
|
162
|
+
|
|
163
|
+
Default value: `source_time`.
|
|
164
|
+
|
|
165
|
+
### source_time_format (enum) (optional)
|
|
166
|
+
|
|
167
|
+
Time format for the original timestamp field. Defaults to ISO8601-formatted string.
|
|
168
|
+
|
|
169
|
+
Available values: epoch, epoch_float, iso8601
|
|
170
|
+
|
|
171
|
+
Default value: `iso8601`.
|
|
38
172
|
|
|
39
173
|
## Copyright
|
|
40
174
|
|
|
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = 'fluent-plugin-time-cutoff'
|
|
8
|
-
spec.version = '0.1.
|
|
8
|
+
spec.version = '0.1.3'
|
|
9
9
|
spec.authors = ['Qrator Labs', 'Serge Tkatchouk']
|
|
10
10
|
spec.email = ['devops@qrator.net', 'st@qrator.net']
|
|
11
11
|
|
|
@@ -6,7 +6,12 @@ require 'time'
|
|
|
6
6
|
|
|
7
7
|
module Fluent
|
|
8
8
|
module Plugin
|
|
9
|
+
# A filter plugin that allows Fluentd to modify or drop messages that are
|
|
10
|
+
# newer or older than a set threshold. By default this filter will not
|
|
11
|
+
# modify or drop any messages, but it will log all messages that are 24
|
|
12
|
+
# hours older or newer than current time.
|
|
9
13
|
class TimeCutoffFilter < Fluent::Plugin::Filter
|
|
14
|
+
# Available actions for messages.
|
|
10
15
|
CUTOFF_ACTIONS = [
|
|
11
16
|
# Pass record as is:
|
|
12
17
|
:pass,
|
|
@@ -16,6 +21,7 @@ module Fluent
|
|
|
16
21
|
:drop
|
|
17
22
|
].freeze
|
|
18
23
|
|
|
24
|
+
# Available time formats for :replace_timestamp action.
|
|
19
25
|
TIME_FORMATS = [
|
|
20
26
|
# UNIX time (integer)
|
|
21
27
|
:epoch,
|
|
@@ -25,25 +31,26 @@ module Fluent
|
|
|
25
31
|
:iso8601
|
|
26
32
|
].freeze
|
|
27
33
|
|
|
34
|
+
# strftime() format string for :iso8601 time format.
|
|
28
35
|
TIME_ISO8601 = '%FT%T%:z'
|
|
29
36
|
|
|
30
37
|
Fluent::Plugin.register_filter('time_cutoff', self)
|
|
31
|
-
|
|
38
|
+
|
|
39
|
+
desc 'Records older than this amount of time are deemed "old". Defaults to 24 hours.'
|
|
32
40
|
config_param :old_cutoff, :time, default: 86_400 # 24 hours
|
|
33
|
-
|
|
41
|
+
desc 'The action that will be performed to all "old" messages. Defaults to passthrough.'
|
|
34
42
|
config_param :old_action, :enum, list: CUTOFF_ACTIONS, default: :pass
|
|
35
|
-
|
|
43
|
+
desc 'Log the "old" messages to Fluentd\'s own log. Defaults to "true".'
|
|
36
44
|
config_param :old_log, :bool, default: true
|
|
37
|
-
|
|
45
|
+
desc 'Records newer than this amount of time are deemed "new". Defaults to 24 hours.'
|
|
38
46
|
config_param :new_cutoff, :time, default: 86_400 # 24 hours
|
|
39
|
-
|
|
47
|
+
desc 'The action that will be performed to all "new" messages. Defaults to passthrough.'
|
|
40
48
|
config_param :new_action, :enum, list: CUTOFF_ACTIONS, default: :pass
|
|
41
|
-
|
|
49
|
+
desc 'Log the "new" messages to Fluentd\'s own log. Defaults to "true".'
|
|
42
50
|
config_param :new_log, :bool, default: true
|
|
43
|
-
|
|
44
|
-
# (for action = :replace_timestamp):
|
|
51
|
+
desc 'The key that will hold the original time (for :replace_timestamp action). Defaults to "source_time".'
|
|
45
52
|
config_param :source_time_key, :string, default: 'source_time'
|
|
46
|
-
|
|
53
|
+
desc 'Time format for the original timestamp field. Defaults to ISO8601-formatted string.'
|
|
47
54
|
config_param :source_time_format, :enum, list: TIME_FORMATS, default: :iso8601
|
|
48
55
|
|
|
49
56
|
def filter_with_time(tag, time, record)
|
|
@@ -64,6 +71,10 @@ module Fluent
|
|
|
64
71
|
|
|
65
72
|
private
|
|
66
73
|
|
|
74
|
+
# Format the event time to a given type/format.
|
|
75
|
+
# @param time [Fluent::EventTime] the original event time
|
|
76
|
+
# @param @source_time_format [Symbol] the target format
|
|
77
|
+
# @return [Integer,Float,String] formatted time as an integer, float (with microseconds), or an ISO8601-formatted datetime string.
|
|
67
78
|
def format_time(time)
|
|
68
79
|
case @source_time_format
|
|
69
80
|
when :epoch
|
|
@@ -75,6 +86,11 @@ module Fluent
|
|
|
75
86
|
end
|
|
76
87
|
end
|
|
77
88
|
|
|
89
|
+
# Replace event time and put the old time into a specified field.
|
|
90
|
+
# @param time [Fluent::EventTime] the original event time
|
|
91
|
+
# @param record [Hash] the original record contents
|
|
92
|
+
# @param @source_time_key [String] name of the field to put the old timestamp to.
|
|
93
|
+
# @return [Array] new event time and a modified record.
|
|
78
94
|
def do_replace_timestamp(time, record)
|
|
79
95
|
new_time = Fluent::EventTime.now
|
|
80
96
|
new_record = record.dup
|
|
@@ -84,6 +100,12 @@ module Fluent
|
|
|
84
100
|
[new_time, new_record]
|
|
85
101
|
end
|
|
86
102
|
|
|
103
|
+
# Log the caught event to Fluentd's log.
|
|
104
|
+
# @param tag [String] log/stream's tag name
|
|
105
|
+
# @param time [Fluent::EventTime] the original event time
|
|
106
|
+
# @param record [Hash] the original record contents
|
|
107
|
+
# @param action [Symbol] determined action for this record
|
|
108
|
+
# @param age [Symbol] detemined age for this record (:old or :new)
|
|
87
109
|
def log_record(tag, time, record, action, age)
|
|
88
110
|
fmt_time = Time.at(time).strftime(TIME_ISO8601)
|
|
89
111
|
log_line = format(
|
|
@@ -93,7 +115,33 @@ module Fluent
|
|
|
93
115
|
log.warn log_line
|
|
94
116
|
end
|
|
95
117
|
|
|
118
|
+
# Normalize time to Fluent::EventTime if it's plain int or float.
|
|
119
|
+
# @param time [Integer|Float] incoming event time
|
|
120
|
+
# @return [Fluent::EventTime] event time normalized to Fluentd's internal format
|
|
121
|
+
def normalize_time(time)
|
|
122
|
+
case time.class
|
|
123
|
+
when Integer
|
|
124
|
+
Fluent::EventTime.new(time)
|
|
125
|
+
when Float
|
|
126
|
+
time_int, time_frac = time.divmod(1)
|
|
127
|
+
Fluent::EventTime.new(time_int, (time_frac * 10**9).to_i)
|
|
128
|
+
else
|
|
129
|
+
log.warn "Unknown time format given: \"#{time.inspect}\"."
|
|
130
|
+
Fluent::EventTime.new(time.to_i) || Fluent::EventTime.now
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Process the record according to its determined "age"
|
|
135
|
+
# @param tag [String] log/stream's tag name
|
|
136
|
+
# @param time [Fluent::EventTime] the original event time
|
|
137
|
+
# @param record [Hash] the original record contents
|
|
138
|
+
# @param do_log [Boolean] should we log this record or not
|
|
139
|
+
# @param action [Symbol] determined action for this record
|
|
140
|
+
# @param age [Symbol] detemined age for this record (:old or :new)
|
|
96
141
|
def process_record(tag, time, record, do_log, action, age) # rubocop:disable Metrics/ParameterLists
|
|
142
|
+
## Safeguard against rogue integer time.
|
|
143
|
+
time = normalize_time(time) unless time.is_a?(Fluent::EventTime)
|
|
144
|
+
|
|
97
145
|
log_record(tag, time, record, action, age) if do_log
|
|
98
146
|
|
|
99
147
|
case action
|
|
@@ -106,10 +154,18 @@ module Fluent
|
|
|
106
154
|
end
|
|
107
155
|
end
|
|
108
156
|
|
|
157
|
+
# Process the "old" record according to the configuration
|
|
158
|
+
# @param tag [String] log/stream's tag name
|
|
159
|
+
# @param time [Fluent::EventTime] the original event time
|
|
160
|
+
# @param record [Hash] the original record contents
|
|
109
161
|
def process_old_record(tag, time, record)
|
|
110
162
|
process_record(tag, time, record, @old_log, @old_action, :old)
|
|
111
163
|
end
|
|
112
164
|
|
|
165
|
+
# Process the "new" record according to the configuration
|
|
166
|
+
# @param tag [String] log/stream's tag name
|
|
167
|
+
# @param time [Fluent::EventTime] the original event time
|
|
168
|
+
# @param record [Hash] the original record contents
|
|
113
169
|
def process_new_record(tag, time, record)
|
|
114
170
|
process_record(tag, time, record, @new_log, @new_action, :new)
|
|
115
171
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fluent-plugin-time-cutoff
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Qrator Labs
|
|
8
8
|
- Serge Tkatchouk
|
|
9
|
+
autorequire:
|
|
9
10
|
bindir: bin
|
|
10
11
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
12
|
+
date: 2025-11-24 00:00:00.000000000 Z
|
|
12
13
|
dependencies:
|
|
13
14
|
- !ruby/object:Gem::Dependency
|
|
14
15
|
name: fluentd
|
|
@@ -82,7 +83,6 @@ extensions: []
|
|
|
82
83
|
extra_rdoc_files: []
|
|
83
84
|
files:
|
|
84
85
|
- ".rubocop.yml"
|
|
85
|
-
- ".ruby-version"
|
|
86
86
|
- LICENSE.txt
|
|
87
87
|
- README.md
|
|
88
88
|
- Rakefile
|
|
@@ -92,6 +92,7 @@ homepage: https://github.com/QratorLabs/fluent-plugin-time-cutoff
|
|
|
92
92
|
licenses:
|
|
93
93
|
- MIT
|
|
94
94
|
metadata: {}
|
|
95
|
+
post_install_message:
|
|
95
96
|
rdoc_options: []
|
|
96
97
|
require_paths:
|
|
97
98
|
- lib
|
|
@@ -106,7 +107,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
106
107
|
- !ruby/object:Gem::Version
|
|
107
108
|
version: '0'
|
|
108
109
|
requirements: []
|
|
109
|
-
rubygems_version: 3.
|
|
110
|
+
rubygems_version: 3.3.27
|
|
111
|
+
signing_key:
|
|
110
112
|
specification_version: 4
|
|
111
113
|
summary: Fluentd time-based filter plugin.
|
|
112
114
|
test_files: []
|
data/.ruby-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3.3.7
|