fluent-plugin-systemd 0.3.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c2cebb67ce9b89e20f0354bdbb45f7f3c8f1c817
4
- data.tar.gz: b59f85ccd7e8550cdf7835c2fa3449406e9c0769
3
+ metadata.gz: 13f78fa020542fb3c022c6d0870ecf1ec2d307ae
4
+ data.tar.gz: 5cac751f2b33bc5783bf3a721999890e9f2c51ba
5
5
  SHA512:
6
- metadata.gz: 8a115c1eb388b1263f933d1f3283c84b6dbbfc4093756842095879c7f07312c0562ccbf87093fb4defd643e17cc5219569c795a48e82f3e79200990d8b22360f
7
- data.tar.gz: ba30dc865abe28b552379c7a680f6ffff3303990d98eea0747d4bda5810a585cbb866c9410a57302e6f4e9e5385d33894c0dacaca192fec4c207f5dc2e17917c
6
+ metadata.gz: 89677dd5dbf1c6648e37ec969590392cf54a929ae15d30a64824df1b3a93f1a7ea54f71c83839f484bcc914f5ffbaf8b2b32c05320e1dc45084ea30ec48afdae
7
+ data.tar.gz: dcd1c5f2eaac7c766344bbbae29d7fc8fb10cc951cc7dfbb07982ae5946dc8eef6ec26593b8ade6bac1c8fe981b78bb5f291982b9941a6ef02a85801919893c8
data/README.md CHANGED
@@ -44,7 +44,7 @@ or
44
44
  read_from_head true
45
45
  <storage>
46
46
  @type local
47
- persistent true
47
+ persistent false
48
48
  path kube-proxy.pos
49
49
  </storage>
50
50
  <entry>
@@ -196,7 +196,7 @@ For systems with systemd installed you can run the tests against your installed
196
196
 
197
197
  Issues and pull requests are very welcome.
198
198
 
199
- If you want to make a contribution but need some help or advice feel free to message me @errm on the [Fluentd Slack](http://slack.fluentd.org/), or send me an email ed@reevoo.com.
199
+ If you want to make a contribution but need some help or advice feel free to message me @errm on the [Fluentd Slack](http://slack.fluentd.org/), or send me an email edward-robinson@cookpad.com
200
200
 
201
201
  We have adopted the [Contributor Covenant](CODE_OF_CONDUCT.md) and thus expect anyone interacting with contributors, maintainers and users of this project to abide by it.
202
202
 
@@ -216,3 +216,5 @@ Many thanks to our fantastic contributors
216
216
  * [neko-neko](https://github.com/neko-neko)
217
217
  * [Sadayuki Furuhashi](https://github.com/frsyuki)
218
218
  * [Jesus Rafael Carrillo](https://github.com/jescarri)
219
+ * [John Thomas Wile II](https://github.com/jtwile2)
220
+ * [Kazuhiro Suzuki](https://github.com/ksauzz)
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
- require "fluent/plugin/filter"
3
- require "fluent/plugin/systemd/entry_mutator"
2
+
3
+ require 'fluent/plugin/filter'
4
+ require 'fluent/plugin/systemd/entry_mutator'
4
5
 
5
6
  module Fluent
6
7
  module Plugin
7
8
  # Fluentd systemd/journal filter plugin
8
9
  class SystemdEntryFilter < Filter
9
- Fluent::Plugin.register_filter("systemd_entry", self)
10
+ Fluent::Plugin.register_filter('systemd_entry', self)
10
11
 
11
12
  config_param :field_map, :hash, default: {}
12
13
  config_param :field_map_strict, :bool, default: false
@@ -16,9 +17,7 @@ module Fluent
16
17
  def configure(conf)
17
18
  super
18
19
  @mutator = SystemdEntryMutator.new(**@config_root_section.to_h)
19
- if @mutator.field_map_strict && @mutator.field_map.empty?
20
- log.warn("`field_map_strict` set to true with empty `field_map`, expect no fields")
21
- end
20
+ @mutator.warnings.each { |warning| log.warn(warning) }
22
21
  end
23
22
 
24
23
  def filter(_tag, _time, entry)
@@ -1,33 +1,31 @@
1
1
  # frozen_string_literal: true
2
- require "systemd/journal"
3
- require "fluent/plugin/input"
4
- require "fluent/plugin/systemd/pos_writer"
5
- require "fluent/plugin/systemd/entry_mutator"
2
+
3
+ require 'systemd/journal'
4
+ require 'fluent/plugin/input'
5
+ require 'fluent/plugin/systemd/entry_mutator'
6
6
 
7
7
  module Fluent
8
8
  module Plugin
9
- class SystemdInput < Input # rubocop:disable Metrics/ClassLength
10
- Fluent::Plugin.register_input("systemd", self)
9
+ # Fluentd plugin for reading from the systemd journal
10
+ class SystemdInput < Input
11
+ Fluent::Plugin.register_input('systemd', self)
11
12
 
12
13
  helpers :timer, :storage
13
14
 
14
- DEFAULT_STORAGE_TYPE = "local"
15
+ DEFAULT_STORAGE_TYPE = 'local'
15
16
 
16
- config_param :path, :string, default: "/var/log/journal"
17
+ config_param :path, :string, default: '/var/log/journal'
17
18
  config_param :filters, :array, default: []
18
- config_param :pos_file, :string, default: nil, deprecated: "Use <storage> section with `persistent: true' instead"
19
19
  config_param :read_from_head, :bool, default: false
20
- config_param :strip_underscores, :bool, default: false, deprecated: "Use <entry> section or `systemd_entry` " \
21
- "filter plugin instead"
22
20
  config_param :tag, :string
23
21
 
24
22
  config_section :storage do
25
- config_set_default :usage, "positions"
23
+ config_set_default :usage, 'positions'
26
24
  config_set_default :@type, DEFAULT_STORAGE_TYPE
27
25
  config_set_default :persistent, false
28
26
  end
29
27
 
30
- config_section :entry, param_name: "entry_opts", required: false, multi: false do
28
+ config_section :entry, param_name: 'entry_opts', required: false, multi: false do
31
29
  config_param :field_map, :hash, default: {}
32
30
  config_param :field_map_strict, :bool, default: false
33
31
  config_param :fields_strip_underscores, :bool, default: false
@@ -37,27 +35,16 @@ module Fluent
37
35
  def configure(conf)
38
36
  super
39
37
  @journal = nil
40
- @pos_storage = PosWriter.new(@pos_file, storage_create(usage: "positions"))
41
- # legacy strip_underscores backwards compatibility (legacy takes
42
- # precedence and is mutually exclusive with the entry block)
43
- mut_opts = @strip_underscores ? { fields_strip_underscores: true } : @entry_opts.to_h
44
- @mutator = SystemdEntryMutator.new(**mut_opts)
45
- if @mutator.field_map_strict && @mutator.field_map.empty?
46
- log.warn("`field_map_strict` set to true with empty `field_map`, expect no fields")
47
- end
38
+ @pos_storage = storage_create(usage: 'positions')
39
+ @mutator = SystemdEntryMutator.new(**@entry_opts.to_h)
40
+ @mutator.warnings.each { |warning| log.warn(warning) }
48
41
  end
49
42
 
50
43
  def start
51
44
  super
52
- @pos_storage.start
53
45
  timer_execute(:in_systemd_emit_worker, 1, &method(:run))
54
46
  end
55
47
 
56
- def shutdown
57
- @pos_storage.shutdown
58
- super
59
- end
60
-
61
48
  private
62
49
 
63
50
  def init_journal
@@ -80,8 +67,8 @@ module Fluent
80
67
  seek_to(cursor || read_from)
81
68
  rescue Systemd::JournalError
82
69
  log.warn(
83
- "Could not seek to cursor #{cursor} found in pos file: #{@pos_storage.path}, " \
84
- "falling back to reading from #{read_from}",
70
+ "Could not seek to cursor #{cursor} found in position file: #{@pos_storage.path}, " \
71
+ "falling back to reading from #{read_from}"
85
72
  )
86
73
  seek_to(read_from)
87
74
  end
@@ -120,7 +107,7 @@ module Fluent
120
107
  retries += 1
121
108
  sleep 1.5**retries + rand(0..3)
122
109
  retry
123
- rescue => e
110
+ rescue => e # rubocop:disable Style/RescueStandardError
124
111
  log.error("Exception emitting record: #{e}")
125
112
  end
126
113
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require "fluent/config/error"
2
+
3
+ require 'fluent/config/error'
3
4
 
4
5
  module Fluent
5
6
  module Plugin
@@ -19,12 +20,11 @@ module Fluent
19
20
  # "<new_field2>" => ["<source_field2>"]
20
21
  # }
21
22
  class SystemdEntryMutator
22
-
23
23
  Options = Struct.new(
24
24
  :field_map,
25
25
  :field_map_strict,
26
26
  :fields_lowercase,
27
- :fields_strip_underscores,
27
+ :fields_strip_underscores
28
28
  )
29
29
 
30
30
  def self.default_opts
@@ -56,6 +56,10 @@ module Fluent
56
56
  super
57
57
  end
58
58
 
59
+ def respond_to_missing?(sym, include_private = false)
60
+ @opts.members.include?(sym) || super
61
+ end
62
+
59
63
  # The main run method that performs all configured mutations, if any,
60
64
  # against a single journal entry. Returns the mutated entry hash.
61
65
  # entry - hash or `Systemd::Journal:Entry`
@@ -69,13 +73,11 @@ module Fluent
69
73
  # entry hash.
70
74
  # entry - hash or `Systemd::Journal:Entry`
71
75
  def map_fields(entry)
72
- mapped = {}
73
- @map.each do |cstm, sysds|
76
+ @map.each_with_object({}) do |(cstm, sysds), mapped|
74
77
  vals = sysds.collect { |fld| entry[fld] }.compact
75
78
  next if vals.empty? # systemd field does not exist in source entry
76
- mapped[cstm] = vals.length == 1 ? vals[0] : vals.join(" ")
79
+ mapped[cstm] = join_if_needed(vals)
77
80
  end
78
- mapped
79
81
  end
80
82
 
81
83
  # Run field formatting (mutations applied to all non-mapped fields)
@@ -84,20 +86,34 @@ module Fluent
84
86
  # mapped - Optional hash that represents a previously mapped entry to
85
87
  # which the formatted fields will be added
86
88
  def format_fields(entry, mapped = nil)
87
- mapped ||= {}
88
- entry.each do |fld, val|
89
+ entry.each_with_object(mapped || {}) do |(fld, val), formatted_entry|
89
90
  # don't mess with explicitly mapped fields
90
91
  next if @map_src_fields.include?(fld)
91
- fld = fld.gsub(/\A_+/, "") if @opts.fields_strip_underscores
92
- fld = fld.downcase if @opts.fields_lowercase
92
+ fld = format_field_name(fld)
93
93
  # account for mapping (appending) to an existing systemd field
94
- mapped[fld] = mapped.key?(fld) ? [val, mapped[fld]].join(" ") : val
94
+ formatted_entry[fld] = join_if_needed([val, mapped[fld]])
95
95
  end
96
- mapped
96
+ end
97
+
98
+ def warnings
99
+ return [] unless field_map_strict && field_map.empty?
100
+ '`field_map_strict` set to true with empty `field_map`, expect no fields'
97
101
  end
98
102
 
99
103
  private
100
104
 
105
+ def join_if_needed(values)
106
+ values.compact!
107
+ return values.first if values.length == 1
108
+ values.join(' ')
109
+ end
110
+
111
+ def format_field_name(name)
112
+ name = name.gsub(/\A_+/, '') if @opts.fields_strip_underscores
113
+ name = name.downcase if @opts.fields_lowercase
114
+ name
115
+ end
116
+
101
117
  # Returns a `SystemdEntryMutator::Options` struct derived from the
102
118
  # elements in the supplied hash merged with the option defaults
103
119
  def options_from_hash(opts)
@@ -109,39 +125,32 @@ module Fluent
109
125
  end
110
126
 
111
127
  def validate_options(opts)
112
- unless validate_strings_or_empty(opts[:field_map].keys)
113
- err = "`field_map` keys must be strings"
114
- end
115
- unless validate_strings_or_empty(opts[:field_map].values, true)
116
- err = "`field_map` values must be strings or array of strings"
117
- end
128
+ validate_all_strings opts[:field_map].keys, '`field_map` keys must be strings'
129
+ validate_all_strings opts[:field_map].values, '`field_map` values must be strings or an array of strings', true
118
130
  %i[field_map_strict fields_strip_underscores fields_lowercase].each do |opt|
119
- err = "`#{opt}` must be boolean" unless [true, false].include?(opts[opt])
131
+ validate_boolean opts[opt], opt
120
132
  end
121
- fail Fluent::ConfigError, err unless err.nil?
122
133
  end
123
134
 
124
- # Validates that values in array `arr` are strings. If `nested` is true
125
- # also allow and validate that `arr` values can be an array of strings
126
- def validate_strings_or_empty(arr, nested = false)
127
- return true if arr.empty?
128
- arr.each do |v|
129
- return true if v.is_a?(String)
130
- if v.is_a?(Array) && nested
131
- v.each { |nstd| return false unless nstd.is_a?(String) }
132
- end
135
+ def validate_all_strings(arr, message, allow_nesting = false)
136
+ valid = arr.all? do |value|
137
+ value.is_a?(String) || allow_nesting && value.is_a?(Array) && value.all? { |key| key.is_a?(String) }
133
138
  end
134
- false
139
+ raise Fluent::ConfigError, message unless valid
140
+ end
141
+
142
+ def validate_boolean(value, name)
143
+ raise Fluent::ConfigError, "`#{name}` must be boolean" unless [true, false].include?(value)
135
144
  end
136
145
 
137
- # Compute the inverse of a human friendly field map `fm` which is what
146
+ # Compute the inverse of a human friendly field map `field_map` which is what
138
147
  # the mutator uses for the actual mapping. The resulting structure for
139
148
  # the inverse field map hash is:
140
149
  # {"<new_field_name>" => ["<source_field_name>", ...], ...}
141
- def invert_field_map(fm)
150
+ def invert_field_map(field_map)
142
151
  invs = {}
143
- fm.values.flatten.uniq.each do |cstm|
144
- sysds = fm.select { |_, v| (v == cstm || v.include?(cstm)) }
152
+ field_map.values.flatten.uniq.each do |cstm|
153
+ sysds = field_map.select { |_, v| (v == cstm || v.include?(cstm)) }
145
154
  invs[cstm] = sysds.keys
146
155
  end
147
156
  invs
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-systemd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ed Robinson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-03 00:00:00.000000000 Z
11
+ date: 2018-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.5'
55
55
  - !ruby/object:Gem::Dependency
56
- name: reevoocop
56
+ name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 0.53.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 0.53.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: fluentd
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -102,7 +102,7 @@ dependencies:
102
102
  version: '1.3'
103
103
  description: This is a fluentd input plugin. It reads logs from the systemd journal.
104
104
  email:
105
- - ed@reevoo.com
105
+ - edward-robinson@cookpad.com
106
106
  executables: []
107
107
  extensions: []
108
108
  extra_rdoc_files: []
@@ -112,7 +112,6 @@ files:
112
112
  - lib/fluent/plugin/filter_systemd_entry.rb
113
113
  - lib/fluent/plugin/in_systemd.rb
114
114
  - lib/fluent/plugin/systemd/entry_mutator.rb
115
- - lib/fluent/plugin/systemd/pos_writer.rb
116
115
  homepage: https://github.com/reevoo/fluent-plugin-systemd
117
116
  licenses:
118
117
  - MIT
@@ -128,12 +127,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
128
127
  version: '0'
129
128
  required_rubygems_version: !ruby/object:Gem::Requirement
130
129
  requirements:
131
- - - ">="
130
+ - - ">"
132
131
  - !ruby/object:Gem::Version
133
- version: '0'
132
+ version: 1.3.1
134
133
  requirements: []
135
134
  rubyforge_project:
136
- rubygems_version: 2.6.11
135
+ rubygems_version: 2.6.13
137
136
  signing_key:
138
137
  specification_version: 4
139
138
  summary: Input plugin to read from systemd journal.
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
- require "fluent/plugin/input"
3
-
4
- module Fluent
5
- module Plugin
6
- class SystemdInput < Input
7
- class PosWriter
8
- def initialize(pos_file, storage)
9
- @path = pos_file
10
- @lock = Mutex.new
11
- @storage = storage
12
- @cursor = nil
13
- @written_cursor = nil
14
- setup
15
- end
16
-
17
- def get(key)
18
- @storage ? @storage.get(key) : @cursor
19
- end
20
-
21
- def put(key, cursor)
22
- return @storage.put(key, cursor) if @storage
23
- @lock.synchronize { @cursor = cursor }
24
- end
25
-
26
- def path
27
- @path || @storage.path
28
- end
29
-
30
- def start
31
- return unless @path
32
- @running = true
33
- @thread = Thread.new(&method(:work))
34
- end
35
-
36
- def shutdown
37
- return unless @path
38
- @running = false
39
- @thread.join
40
- write_pos
41
- end
42
-
43
- private
44
-
45
- def setup
46
- if @storage.persistent
47
- migrate_to_storage if @path && File.exist?(@path)
48
- elsif @path
49
- @cursor = IO.read(@path).chomp if File.exist?(@path)
50
- @storage = nil
51
- end
52
- end
53
-
54
- def migrate_to_storage
55
- @storage.put(:journal, IO.read(@path).chomp)
56
- File.delete(@path)
57
- @path = nil
58
- end
59
-
60
- def work
61
- while @running
62
- write_pos
63
- sleep 1
64
- end
65
- end
66
-
67
- def write_pos
68
- @lock.synchronize do
69
- if @written_cursor != @cursor
70
- file = File.open(@path, "w+", 0o644)
71
- file.print @cursor
72
- file.close
73
- @written_cursor = @cursor
74
- end
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end