fluent-plugin-remote-syslog-cg 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e279be2ffb7abea3d88ceb3b3043882ccc49dce5
4
+ data.tar.gz: a0d594be3a4bd02c59cf6ddc4dc10b59dc98e09d
5
+ SHA512:
6
+ metadata.gz: 082b8195907ee98995ff34e4b757ee66b01204258c29c316286025e59fdf18ab5ec08f1487a6e3396669df5b09b31d62a718b6cb1e8ad5f4dd8f9f2cf322c28f
7
+ data.tar.gz: 22e0cfc1c2e35d48355e4a00b93459fef6e8e70694cb571407f13452e1f1c76bb548dc92276de181674769d51449aa1c8b19726e7440c9a5468556c66fcb49cf
@@ -0,0 +1,3 @@
1
+ .idea
2
+ *.gem
3
+ *.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,41 @@
1
+ fluent-plugin-remote-syslog-cg
2
+ ===========================
3
+
4
+ fluentd plugin for streaming logs out to a remote syslog server or syslog SaaS service (like Papertrail)
5
+
6
+ #Available Plugins:
7
+ * out_syslog: registers itself as "syslog-cg", and is the non-buffered implementation, communicating through UDP
8
+ * out_syslog_buffered: registers itself as "syslog_buffered-cg", and is the buffered implementation, communicating through TCP
9
+
10
+ #Plugin Settings:
11
+ Both plugins have the same configuration options:
12
+
13
+ * remote_syslog: fqdn or ip of the remote syslog instance
14
+ * port: the port, where the remote syslog instance is listening
15
+ * hostname: hostname to be set for syslog messages
16
+ * remove_tag_prefix: remove tag prefix for tag placeholder.
17
+ * tag_key: use the field specified in tag_key from record to set the syslog key
18
+ * facility: Syslog log facility
19
+ * severity: Syslog log severity
20
+ * use_record: Use severity and facility from record if available
21
+ * payload_key: Use the field specified in payload_key from record to set payload
22
+ * max_size: the max size of message to send defaults to 4096
23
+
24
+ #Configuration example:
25
+ ```
26
+ <match site.*>
27
+ type syslog_buffered-cg
28
+ remote_syslog your.syslog.host
29
+ port 25
30
+ hostname ${hostname}
31
+ facility local0
32
+ severity debug
33
+ </match>
34
+ ```
35
+
36
+
37
+ Contributors:
38
+
39
+ * CompareGroup
40
+ * Andrea Spoldi
41
+ * [deathowl](http://github.com/deathowl)
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "fluent-plugin-remote-syslog-cg"
6
+ gem.description = "Output plugin for streaming logs out to a remote syslog"
7
+ gem.homepage = "https://stash.comparegroup.eu/projects/IAC/repos/fluent-plugin-remote-syslog-cg/"
8
+ gem.summary = gem.description
9
+ gem.version = "1.0.0"
10
+ gem.authors = ["CompareGroup"]
11
+ gem.email = "itops-box@comparegroup.eu"
12
+ gem.has_rdoc = false
13
+ gem.license = 'MIT'
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ gem.require_paths = ['lib']
18
+
19
+ gem.add_dependency "fluentd", "~> 0.10.45"
20
+ gem.add_dependency "fluent-mixin-config-placeholders", "~> 0.2.0"
21
+ gem.add_dependency "syslog_protocol"
22
+ gem.add_development_dependency "rake", ">= 0.9.2"
23
+ end
@@ -0,0 +1,99 @@
1
+ require 'fluent/mixin/config_placeholders'
2
+ module Fluent
3
+
4
+ class SyslogOutputCG < Fluent::Output
5
+ # First, register the plugin. NAME is the name of this plugin
6
+ # and identifies the plugin in the configuration file.
7
+ # From configuration, fluentd knows only @type NAME information.
8
+ # So we write a same NAME both lib/fluent/plugin/<TYPE>_<NAME>.rb and
9
+ # Fluent::Plugin.register_input('NAME', self) in the plugin development article.
10
+ Fluent::Plugin.register_output('syslog-cg', self)
11
+
12
+ # This method is called before starting.
13
+
14
+ config_param :remote_syslog, :string, :default => nil
15
+ config_param :port, :integer, :default => 25
16
+ config_param :hostname, :string, :default => ""
17
+ config_param :remove_tag_prefix, :string, :default => nil
18
+ config_param :tag_key, :string, :default => nil
19
+ config_param :facility, :string, :default => 'user'
20
+ config_param :severity, :string, :default => 'debug'
21
+ config_param :use_record, :string, :default => nil
22
+ config_param :payload_key, :string, :default => 'message'
23
+ config_param :max_size, :integer, :default => 4096
24
+
25
+
26
+ def initialize
27
+ super
28
+ require 'socket'
29
+ require 'syslog_protocol'
30
+ end
31
+
32
+ def configure(conf)
33
+ super
34
+ if not conf['remote_syslog']
35
+ raise Fluent::ConfigError.new("remote syslog required")
36
+ end
37
+ @socket = UDPSocket.new
38
+ @packet = SyslogProtocol::Packet.new
39
+ if remove_tag_prefix = conf['remove_tag_prefix']
40
+ @remove_tag_prefix = Regexp.new('^' + Regexp.escape(remove_tag_prefix))
41
+ end
42
+ @facilty = conf['facility']
43
+ @severity = conf['severity']
44
+ @use_record = conf['use_record']
45
+ @payload_key = conf['payload_key']
46
+ if not @payload_key
47
+ @payload_key = "message"
48
+ end
49
+ if conf['max_size']
50
+ @max_size = conf['max_size'].to_i
51
+ end
52
+ end
53
+
54
+
55
+ # This method is called when starting.
56
+ def start
57
+ super
58
+ end
59
+
60
+ # This method is called when shutting down.
61
+ def shutdown
62
+ super
63
+ end
64
+
65
+ # This method is called when an event reaches Fluentd.
66
+ # 'es' is a Fluent::EventStream object that includes multiple events.
67
+ # You can use 'es.each {|time,record| ... }' to retrieve events.
68
+ # 'chain' is an object that manages transactions. Call 'chain.next' at
69
+ # appropriate points and rollback if it raises an exception.
70
+ def emit(tag, es, chain)
71
+ tag = tag.sub(@remove_tag_prefix, '') if @remove_tag_prefix
72
+ chain.next
73
+ es.each {|time,record|
74
+ @packet.hostname = hostname
75
+ if @use_record
76
+ @packet.facility = record['facility'] || @facilty
77
+ @packet.severity = record['severity'] || @severity
78
+ else
79
+ @packet.facility = @facilty
80
+ @packet.severity = @severity
81
+ end
82
+ if record['time']
83
+ time = Time.parse(record['time'])
84
+ else
85
+ time = Time.now
86
+ end
87
+ @packet.time = time
88
+ @packet.tag = if tag_key
89
+ record[tag_key][0..31].gsub(/[\[\]]/,'') # tag is trimmed to 32 chars for syslog_protocol gem compatibility
90
+ else
91
+ tag[0..31] # tag is trimmed to 32 chars for syslog_protocol gem compatibility
92
+ end
93
+ packet = @packet.dup
94
+ packet.content = record[@payload_key]
95
+ @socket.send(packet.assemble(@max_size), 0, @remote_syslog, @port)
96
+ }
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,142 @@
1
+ require 'fluent/mixin/config_placeholders'
2
+ module Fluent
3
+ class SyslogBufferedOutputCG < Fluent::BufferedOutput
4
+ # First, register the plugin. NAME is the name of this plugin
5
+ # and identifies the plugin in the configuration file.
6
+ # From configuration, fluentd knows only @type NAME information.
7
+ # So we write a same NAME both lib/fluent/plugin/<TYPE>_<NAME>.rb and
8
+ # Fluent::Plugin.register_input('NAME', self) in the plugin development article.
9
+ Fluent::Plugin.register_output('syslog_buffered-cg', self)
10
+
11
+ # This method is called before starting.
12
+
13
+ config_param :remote_syslog, :string, :default => ""
14
+ config_param :port, :integer, :default => 25
15
+ config_param :hostname, :string, :default => ""
16
+ config_param :remove_tag_prefix, :string, :default => nil
17
+ config_param :tag_key, :string, :default => nil
18
+ config_param :facility, :string, :default => 'user'
19
+ config_param :severity, :string, :default => 'debug'
20
+ config_param :use_record, :string, :default => nil
21
+ config_param :payload_key, :string, :default => 'message'
22
+ config_param :max_size, :integer, :default => 4096
23
+
24
+
25
+ def initialize
26
+ super
27
+ require 'socket'
28
+ require 'syslog_protocol'
29
+ require 'timeout'
30
+ end
31
+
32
+ def configure(conf)
33
+ super
34
+ if not conf['remote_syslog']
35
+ raise Fluent::ConfigError.new("remote syslog required")
36
+ end
37
+ @socket = create_tcp_socket(conf['remote_syslog'], conf['port'])
38
+ @packet = SyslogProtocol::Packet.new
39
+ if remove_tag_prefix = conf['remove_tag_prefix']
40
+ @remove_tag_prefix = Regexp.new('^' + Regexp.escape(remove_tag_prefix))
41
+ end
42
+ @facilty = conf['facility']
43
+ @severity = conf['severity']
44
+ @use_record = conf['use_record']
45
+ @payload_key = conf['payload_key']
46
+ if not @payload_key
47
+ @payload_key = "message"
48
+ end
49
+ if conf['max_size']
50
+ @max_size = conf['max_size'].to_i
51
+ end
52
+ end
53
+
54
+ def format(tag, time, record)
55
+ [tag, time, record].to_msgpack
56
+ end
57
+
58
+ def create_tcp_socket(host, port)
59
+ begin
60
+ Timeout.timeout(10) do
61
+ begin
62
+ socket = TCPSocket.new(host, port)
63
+ rescue Errno::ENETUNREACH
64
+ retry
65
+ end
66
+ end
67
+ socket = TCPSocket.new(host, port)
68
+ secs = Integer(1)
69
+ usecs = Integer((1 - secs) * 1_000_000)
70
+ optval = [secs, usecs].pack("l_2")
71
+ socket.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
72
+ rescue SocketError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EPIPE, Timeout::Error, OpenSSL::SSL::SSLError, Timeout::Error => e
73
+ log.warn "out:syslog: failed to open tcp socket #{@remote_syslog}:#{@port} :#{e}"
74
+ socket = nil
75
+ end
76
+ socket
77
+ end
78
+
79
+ # This method is called when starting.
80
+ def start
81
+ super
82
+ end
83
+
84
+ # This method is called when shutting down.
85
+ def shutdown
86
+ super
87
+ end
88
+
89
+
90
+ def write(chunk)
91
+ chunk.msgpack_each {|(tag,time,record)|
92
+ send_to_syslog(tag, time, record)
93
+ }
94
+ end
95
+
96
+ def send_to_syslog(tag, time, record)
97
+ tag = tag.sub(@remove_tag_prefix, '') if @remove_tag_prefix
98
+ @packet.hostname = hostname
99
+ if @use_record
100
+ @packet.facility = record['facility'] || @facilty
101
+ @packet.severity = record['severity'] || @severity
102
+ else
103
+ @packet.facility = @facilty
104
+ @packet.severity = @severity
105
+ end
106
+ if record['time']
107
+ time = Time.parse(record['time'])
108
+ else
109
+ time = Time.now
110
+ end
111
+ @packet.time = time
112
+ @packet.tag = if tag_key
113
+ record[tag_key][0..31].gsub(/[\[\]]/,'') # tag is trimmed to 32 chars for syslog_protocol gem compatibility
114
+ else
115
+ tag[0..31] # tag is trimmed to 32 chars for syslog_protocol gem compatibility
116
+ end
117
+ packet = @packet.dup
118
+ packet.content = record[@payload_key]
119
+ begin
120
+ if not @socket
121
+ @socket = create_tcp_socket(@remote_syslog, @port)
122
+ end
123
+ if @socket
124
+ begin
125
+ @socket.write packet.assemble(@max_size) + "\n"
126
+ @socket.flush
127
+ rescue SocketError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EPIPE, Timeout::Error, OpenSSL::SSL::SSLError => e
128
+ log.warn "out:syslog: connection error by #{@remote_syslog}:#{@port} :#{e}"
129
+ @socket = nil
130
+ raise #{e}
131
+ end
132
+ else
133
+ log.warn "out:syslog: Socket connection couldn't be reestablished"
134
+ raise #{e}
135
+ end
136
+ end
137
+ end
138
+
139
+
140
+ end
141
+ end
142
+
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ unless ENV.has_key?('VERBOSE')
16
+ nulllogger = Object.new
17
+ nulllogger.instance_eval {|obj|
18
+ def method_missing(method, *args)
19
+ # pass
20
+ end
21
+ }
22
+ $log = nulllogger
23
+ end
24
+
25
+ require 'fluentd/plugin/out_syslog-cg'
26
+ require 'fluentd/plugin/out_syslog_buffered-cg'
27
+
28
+
29
+ class Test::Unit::TestCase
30
+ end
@@ -0,0 +1,138 @@
1
+ require 'helper'
2
+
3
+ class SyslogOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ remote_syslog 127.0.0.1
10
+ port 25
11
+ hostname testhost
12
+ remove_tag_prefix test
13
+ severity debug
14
+ facility user
15
+ payload_key message
16
+ ]
17
+
18
+ def create_driver(conf=CONFIG,tag='test')
19
+ Fluent::Test::OutputTestDriver.new(Fluent::SyslogOutputCG, tag).configure(conf)
20
+ end
21
+
22
+ def test_configure
23
+ assert_raise(Fluent::ConfigError) {
24
+ d = create_driver('')
25
+ }
26
+ assert_raise(Fluent::ConfigError) {
27
+ d = create_driver %[
28
+ hostname testhost
29
+ remove_tag_prefix test
30
+ ]
31
+ }
32
+ assert_nothing_raised {
33
+ d = create_driver %[
34
+ remote_syslog 127.0.0.1
35
+ ]
36
+ }
37
+ assert_nothing_raised {
38
+ d = create_driver %[
39
+ remote_syslog 127.0.0.1
40
+ port 639
41
+ ]
42
+ }
43
+ assert_nothing_raised {
44
+ d = create_driver %[
45
+ remote_syslog 127.0.0.1
46
+ port 25
47
+ hostname deathstar
48
+ ]
49
+ }
50
+ assert_nothing_raised {
51
+ d = create_driver %[
52
+ remote_syslog 127.0.0.1
53
+ port 25
54
+ hostname testhost
55
+ remove_tag_prefix test123
56
+ ]
57
+ }
58
+ assert_nothing_raised {
59
+ d = create_driver %[
60
+ remote_syslog 127.0.0.1
61
+ port 25
62
+ hostname testhost
63
+ remove_tag_prefix test
64
+ tag_key tagtag
65
+ severity debug
66
+ ]
67
+ }
68
+ assert_nothing_raised {
69
+ d = create_driver %[
70
+ remote_syslog 127.0.0.1
71
+ port 25
72
+ hostname testhost
73
+ remove_tag_prefix test
74
+ tag_key tagtag
75
+ severity debug
76
+ facility user
77
+ ]
78
+ }
79
+ assert_nothing_raised {
80
+ d = create_driver %[
81
+ remote_syslog 127.0.0.1
82
+ port 25
83
+ hostname testhost
84
+ remove_tag_prefix test
85
+ tag_key tagtag
86
+ severity debug
87
+ facility user
88
+ payload_key message
89
+ ]
90
+ }
91
+ d = create_driver %[
92
+ remote_syslog 127.0.0.1
93
+ port 25
94
+ hostname testhost
95
+ remove_tag_prefix test
96
+ tag_key tagtag
97
+ severity debug
98
+ facility user
99
+ payload_key message
100
+ ]
101
+ assert_equal 25, d.instance.port
102
+ assert_equal "127.0.0.1", d.instance.remote_syslog
103
+ assert_equal "testhost", d.instance.hostname
104
+ assert_equal Regexp.new('^' + Regexp.escape("test")), d.instance.remove_tag_prefix
105
+ assert_equal "tagtag", d.instance.tag_key
106
+ assert_equal "debug", d.instance.severity
107
+ assert_equal "user", d.instance.facility
108
+ assert_equal "message", d.instance.payload_key
109
+
110
+ end
111
+ def test_emit
112
+ d1 = create_driver(CONFIG, 'test.in')
113
+ d1.run do
114
+ d1.emit({'message' => 'asd asd'})
115
+ d1.emit({'message' => 'dsa xasd'})
116
+ d1.emit({'message' => 'ddd ddddd'})
117
+ d1.emit({'message' => '7sssss8 ssssdasd'})
118
+ d1.emit({'message' => 'aaassddffg asdasdasfasf'})
119
+ end
120
+ assert_equal 0, d1.emits.size
121
+
122
+ end
123
+
124
+ def test_emit_with_time_and_without_time
125
+ d1 = create_driver(CONFIG, 'test.in')
126
+ d1.run do
127
+ d1.emit({'message' => 'asd asd', 'time' => '2007-01-31 12:22:26'})
128
+ d1.emit({'message' => 'dsa xasd'})
129
+ d1.emit({'message' => 'ddd ddddd', 'time' => '2007-03-01 12:22:26'})
130
+ d1.emit({'message' => '7sssss8 ssssdasd', 'time' => '2011-03-01 12:22:26'})
131
+ d1.emit({'message' => 'aaassddffg asdasdasfasf', 'time' => '2016-03-01 12:22:26'})
132
+ end
133
+ assert_equal 0, d1.emits.size
134
+
135
+ end
136
+
137
+
138
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-remote-syslog-cg
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - CompareGroup
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-07-18 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.10.45
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.45
27
+ - !ruby/object:Gem::Dependency
28
+ name: fluent-mixin-config-placeholders
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: syslog_protocol
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.2
69
+ description: Output plugin for streaming logs out to a remote syslog
70
+ email: itops-box@comparegroup.eu
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".gitignore"
76
+ - Gemfile
77
+ - README.md
78
+ - Rakefile
79
+ - fluent-plugin-remote-syslog-cg.gemspec
80
+ - lib/fluentd/plugin/out_syslog-cg.rb
81
+ - lib/fluentd/plugin/out_syslog_buffered-cg.rb
82
+ - test/helper.rb
83
+ - test/plugin/test_out_syslog.rb
84
+ homepage: https://stash.comparegroup.eu/projects/IAC/repos/fluent-plugin-remote-syslog-cg/
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.6.14
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Output plugin for streaming logs out to a remote syslog
108
+ test_files:
109
+ - test/helper.rb
110
+ - test/plugin/test_out_syslog.rb