fluent-plugin-time-cutoff 0.1.1

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: b8e038b330cfb51044909264e92646dfef5dbd368f5cec0db66952d816375c34
4
+ data.tar.gz: 2e16bc7505e8bb78c8d83ae0eb5425bab1dc7f5b6081d00f253a2534713f9e6d
5
+ SHA512:
6
+ metadata.gz: 12af52a9288c7468e33e5a7c4f617b2ac55cad85092ea701ade19305a16dfc49d86452093a179eec8adeeaf01d3445339e57b24b62ad4bcfb2706b1e0d73154d
7
+ data.tar.gz: fe9b813a02d46ede91152758c64a6b0ee2d809c530e37540c7dec4ce738c130381c9425030c80cbd2de6df8dffbc360ba4be0e2ef58c6a450047cbd0b963637d
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.7
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Qrator Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # fluent-plugin-time-cutoff
2
+
3
+ [Fluentd](https://fluentd.org/) filter plugin to cut off log records with a timestamp outside of given window.
4
+
5
+ TODO: write description for you plugin.
6
+
7
+ ## Installation
8
+
9
+ ### RubyGems
10
+
11
+ ```
12
+ $ gem install fluent-plugin-time-cutoff
13
+ ```
14
+
15
+ ### Bundler
16
+
17
+ Add following line to your Gemfile:
18
+
19
+ ```ruby
20
+ gem "fluent-plugin-time-cutoff"
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ ```
26
+ $ bundle
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ You can generate configuration template:
32
+
33
+ ```
34
+ $ fluent-plugin-config-format filter time-cutoff
35
+ ```
36
+
37
+ You can copy and paste generated documents here.
38
+
39
+ ## Copyright
40
+
41
+ * Copyright(c) 2025 Qrator Labs and Serge Tkatchouk
42
+ * License: MIT
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs.push('lib', 'test')
8
+ t.test_files = FileList['test/**/test_*.rb']
9
+ t.verbose = true
10
+ t.warning = true
11
+ end
12
+
13
+ task default: [:test]
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'fluent-plugin-time-cutoff'
8
+ spec.version = '0.1.1'
9
+ spec.authors = ['Qrator Labs', 'Serge Tkatchouk']
10
+ spec.email = ['devops@qrator.net', 'st@qrator.net']
11
+
12
+ spec.summary = 'Fluentd time-based filter plugin.'
13
+ spec.description = 'A plugin that lets Fluentd to prune/rewrite messages '\
14
+ 'that have a timestamp that is too old or too new.'
15
+ spec.homepage = 'https://github.com/QratorLabs/fluent-plugin-time-cutoff'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = Dir.chdir(__dir__) do
19
+ `git ls-files -z`.split("\x0").reject do |f|
20
+ (File.expand_path(f) == __FILE__) ||
21
+ f.start_with?(*%w[test/ testbed/ spec/ features/ .git .circleci appveyor Gemfile])
22
+ end
23
+ end
24
+
25
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
26
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.platform = Gem::Platform::RUBY
30
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3')
31
+
32
+ spec.add_runtime_dependency 'fluentd', ['>= 0.14.10', '< 2']
33
+
34
+ spec.add_development_dependency 'bundler', '~> 2.6.3'
35
+ spec.add_development_dependency 'rake', '~> 13.1.0'
36
+ spec.add_development_dependency 'test-unit', '~> 3.6.1'
37
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fluent/plugin/filter'
4
+ require 'json'
5
+ require 'time'
6
+
7
+ module Fluent
8
+ module Plugin
9
+ class TimeCutoffFilter < Fluent::Plugin::Filter
10
+ CUTOFF_ACTIONS = [
11
+ # Pass record as is:
12
+ :pass,
13
+ # Replace time with "now" and pass:
14
+ :replace_timestamp,
15
+ # Drop record as invalid:
16
+ :drop
17
+ ].freeze
18
+
19
+ TIME_FORMATS = [
20
+ # UNIX time (integer)
21
+ :epoch,
22
+ # UNIX time (float)
23
+ :epoch_float,
24
+ # ISO 8601 datetime (string)
25
+ :iso8601
26
+ ].freeze
27
+
28
+ TIME_ISO8601 = '%FT%T%:z'
29
+
30
+ Fluent::Plugin.register_filter('time_cutoff', self)
31
+ ## Records older than this are deemed "old":
32
+ config_param :old_cutoff, :time, default: 86_400 # 24 hours
33
+ ## What to do with "old" records:
34
+ config_param :old_action, :enum, list: CUTOFF_ACTIONS, default: :pass
35
+ ## Print the "old" records to Fluentd's log:
36
+ config_param :old_log, :bool, default: true
37
+ ## Records newer than this are deemed "new":
38
+ config_param :new_cutoff, :time, default: 86_400 # 24 hours
39
+ ## What to do with "new" records:
40
+ config_param :new_action, :enum, list: CUTOFF_ACTIONS, default: :pass
41
+ ## Print the "new" records to Fluentd's log:
42
+ config_param :new_log, :bool, default: true
43
+ ## Name of the key that will hold original timestamp
44
+ # (for action = :replace_timestamp):
45
+ config_param :source_time_key, :string, default: 'source_time'
46
+ ## How to format the original time (for action = :replace_timestamp):
47
+ config_param :source_time_format, :enum, list: TIME_FORMATS, default: :iso8601
48
+
49
+ def filter_with_time(tag, time, record)
50
+ event_time = time.to_i
51
+ current_time = Time.now.to_i
52
+
53
+ if event_time < current_time - @old_cutoff
54
+ # Too old
55
+ process_old_record(tag, time, record)
56
+ elsif event_time > current_time + @new_cutoff
57
+ # Too new
58
+ process_new_record(tag, time, record)
59
+ else
60
+ # OK
61
+ [time, record]
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def format_time(time)
68
+ case @source_time_format
69
+ when :epoch
70
+ time.to_i
71
+ when :epoch_float
72
+ time.to_f
73
+ when :iso8601
74
+ time.to_time.strftime(TIME_ISO8601)
75
+ end
76
+ end
77
+
78
+ def do_replace_timestamp(time, record)
79
+ new_time = Fluent::EventTime.now
80
+ new_record = record.dup
81
+ old_time = format_time(time)
82
+ new_record[@source_time_key] = old_time
83
+
84
+ [new_time, new_record]
85
+ end
86
+
87
+ def log_record(tag, time, record, action, age)
88
+ fmt_time = Time.at(time).strftime(TIME_ISO8601)
89
+ log_line = format(
90
+ 'Record caught [%<age>s, %<act>s]: "%<tag>s: %<time>s %<msg>s".',
91
+ age: age, act: action, tag: tag, time: fmt_time, msg: record.to_json
92
+ )
93
+ log.warn log_line
94
+ end
95
+
96
+ def process_record(tag, time, record, do_log, action, age) # rubocop:disable Metrics/ParameterLists
97
+ log_record(tag, time, record, action, age) if do_log
98
+
99
+ case action
100
+ when :pass
101
+ [time, record]
102
+ when :replace_timestamp
103
+ do_replace_timestamp(time, record)
104
+ when :drop
105
+ nil
106
+ end
107
+ end
108
+
109
+ def process_old_record(tag, time, record)
110
+ process_record(tag, time, record, @old_log, @old_action, :old)
111
+ end
112
+
113
+ def process_new_record(tag, time, record)
114
+ process_record(tag, time, record, @new_log, @new_action, :new)
115
+ end
116
+ end
117
+ end
118
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-time-cutoff
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Qrator Labs
8
+ - Serge Tkatchouk
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.10
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.10
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.6.3
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.6.3
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 13.1.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 13.1.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: test-unit
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 3.6.1
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 3.6.1
75
+ description: A plugin that lets Fluentd to prune/rewrite messages that have a timestamp
76
+ that is too old or too new.
77
+ email:
78
+ - devops@qrator.net
79
+ - st@qrator.net
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - ".rubocop.yml"
85
+ - ".ruby-version"
86
+ - LICENSE.txt
87
+ - README.md
88
+ - Rakefile
89
+ - fluent-plugin-time-cutoff.gemspec
90
+ - lib/fluent/plugin/filter_time_cutoff.rb
91
+ homepage: https://github.com/QratorLabs/fluent-plugin-time-cutoff
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '2.3'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.6.3
110
+ specification_version: 4
111
+ summary: Fluentd time-based filter plugin.
112
+ test_files: []