fluent-plugin-newsyslog 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b2f88ad81aa87528440228c6f20196250b0e3ba1
4
+ data.tar.gz: 5ff2e7de0a8b987e692667f98fc206d235315655
5
+ SHA512:
6
+ metadata.gz: 0d0db0f3ec65e44cf136f4d95b83d51343db8794b62afd659265b15029d5de2c9cef76e1c080759101dee423ee6172481b7f696093786f353f777f0dc8de2b59
7
+ data.tar.gz: c8a934ca856137097371aa02f2e5948b9ede3f028142384f2bab7863b4e2c849c365516676259c0d3ea6514652aa850b5cc1c699b4cf0489ce97f9e1b7677170
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1 @@
1
+ 2.1.5@fluent-plugin-newsyslog
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-newsyslog.gemspec
4
+ gemspec
@@ -0,0 +1,96 @@
1
+ # Fluent::Plugin::NewSyslog
2
+
3
+ This is a new syslog input and parser plugins for Fluentd.
4
+ It supports the newer rfc5424 syslog format along with the older rfc3164 format.
5
+ It also automatically parse the time formats using the build in
6
+ ruby time parser rather than specifying the expected format from the syslog message.
7
+ The parser plugin is backwards compatible with the built in syslog parser.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'fluent-plugin-newsyslog'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install fluent-plugin-newsyslog
24
+
25
+ ## Usage
26
+
27
+ ### `in_newsyslog` Input plugin
28
+
29
+ The `in_newsyslog` Input plugin enables Fluentd to retrieve records via the syslog protocol on UDP or TCP.
30
+ The default parser is the `parser_newsyslog` plugin.
31
+
32
+ #### Example Configuration
33
+ ```
34
+ <source>
35
+ type newsyslog
36
+ port 5140
37
+ bind 0.0.0.0
38
+ tag system
39
+ </source>
40
+ ```
41
+ #### Parameters
42
+ **type (required)**
43
+ The value must be newsyslog.
44
+
45
+ **port**
46
+ The port to listen to. Default Value = 5140
47
+
48
+ **bind**
49
+ The bind address to listen to. Default Value = 0.0.0.0 (all addresses)
50
+
51
+ **protocol_type**
52
+ The transport protocol used to receive logs. “udp” and “tcp” are supported. “udp” by default.
53
+
54
+ **tag (required)**
55
+ The prefix of the tag. The tag itself is generated by the tag prefix, facility level, and priority.
56
+
57
+ ### `parser_newsyslog` Parser plugin
58
+
59
+ The `parser_newsyslog` Parser plugin enables Fluentd to parse syslog records in either rfc5424 or rfc3164 format.
60
+
61
+ #### Example Configuration
62
+ This is an example to use this parser with the syslog plugin.
63
+ ```
64
+ <source>
65
+ type syslog
66
+ port 5140
67
+ bind 0.0.0.0
68
+ format newsyslog
69
+ tag system
70
+ </source>
71
+ ```
72
+ #### Parameters
73
+
74
+ **payload_message**
75
+ When set to true, it will output the entire syslog message into the message field rather than the parsed message field.
76
+ Default Value = false, send the parsed syslog message field.
77
+
78
+ ## Development
79
+
80
+ After checking out the repo, run `bundle` to install dependencies.
81
+
82
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `fluent-plugin-newsyslog.gemspec`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
83
+
84
+ ### Running unit tests
85
+ This gem is using both rspec and test::unit
86
+
87
+ execute `bundle exec rspec` to run the rspec tests
88
+ execute `bundle exec rake test` to run test::unit tests
89
+
90
+ ## Contributing
91
+
92
+ 1. Fork it ( https://github.com/athenahealth/fluent-plugin-newsyslog/fork )
93
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
94
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
95
+ 4. Push to the branch (`git push origin my-new-feature`)
96
+ 5. Create a new Pull Request
@@ -0,0 +1,26 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ desc 'Run test_unit based test'
10
+ Rake::TestTask.new(:test) do |t|
11
+ # To run test for only one file (or file path pattern)
12
+ # $ bundle exec rake base_test TEST=test/test_specified_path.rb
13
+ # $ bundle exec rake base_test TEST=test/test_*.rb
14
+ t.libs << "test"
15
+ t.test_files = Dir["test/**/test_*.rb"].sort
16
+ t.verbose = true
17
+ #t.warning = true
18
+ end
19
+
20
+ desc 'Run test with simplecov'
21
+ task :coverage do |t|
22
+ ENV['SIMPLE_COV'] = '1'
23
+ Rake::Task["test"].invoke
24
+ end
25
+
26
+ task :default => [:test, :build]
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-newsyslog"
7
+ spec.version = "0.1.0"
8
+ spec.authors = ["Kevin Scheunemann"]
9
+ spec.email = ["kscheunemann@athenahealth.com"]
10
+
11
+ spec.summary = %q{A better fluentd syslog input and parser}
12
+ spec.description = %q{A fluentd syslog parser that handles multiple formats }
13
+ spec.homepage = "https://github.com/athenahealth/fluent-plugin-newsyslog"
14
+
15
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
16
+ # delete this section to allow pushing this gem to any host.
17
+ # if spec.respond_to?(:metadata)
18
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
19
+ # else
20
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
21
+ # end
22
+
23
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_runtime_dependency 'fluentd', '>= 0.10.59'
29
+ spec.add_development_dependency 'bundler', '~> 1.9'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rspec'
32
+ spec.add_development_dependency 'flexmock'
33
+ spec.add_development_dependency 'simplecov', '~> 0.6.4'
34
+ spec.add_development_dependency 'rr', '>= 1.0.0'
35
+ spec.add_development_dependency 'timecop', '>= 0.3.0'
36
+ spec.add_development_dependency 'test-unit', '~> 3.0.2'
37
+ spec.add_development_dependency 'test-unit-rr', '~> 1.0.3'
38
+
39
+ end
@@ -0,0 +1,139 @@
1
+ module Fluent
2
+ class NewSyslogInput < Input
3
+ Plugin.register_input('newsyslog', self)
4
+
5
+ FACILITY_MAP = {
6
+ 0 => 'kern',
7
+ 1 => 'user',
8
+ 2 => 'mail',
9
+ 3 => 'daemon',
10
+ 4 => 'auth',
11
+ 5 => 'syslog',
12
+ 6 => 'lpr',
13
+ 7 => 'news',
14
+ 8 => 'uucp',
15
+ 9 => 'cron',
16
+ 10 => 'authpriv',
17
+ 11 => 'ftp',
18
+ 12 => 'ntp',
19
+ 13 => 'audit',
20
+ 14 => 'alert',
21
+ 15 => 'at',
22
+ 16 => 'local0',
23
+ 17 => 'local1',
24
+ 18 => 'local2',
25
+ 19 => 'local3',
26
+ 20 => 'local4',
27
+ 21 => 'local5',
28
+ 22 => 'local6',
29
+ 23 => 'local7'
30
+ }
31
+
32
+ PRIORITY_MAP = {
33
+ 0 => 'emerg',
34
+ 1 => 'alert',
35
+ 2 => 'crit',
36
+ 3 => 'err',
37
+ 4 => 'warn',
38
+ 5 => 'notice',
39
+ 6 => 'info',
40
+ 7 => 'debug'
41
+ }
42
+
43
+ def initialize
44
+ super
45
+ require 'cool.io'
46
+ require 'fluent/plugin/socket_util'
47
+ end
48
+
49
+ config_param :port, :integer, :default => 5140
50
+ config_param :bind, :string, :default => '0.0.0.0'
51
+ config_param :tag, :string
52
+ config_param :protocol_type, :default => :udp do |val|
53
+ case val.downcase
54
+ when 'tcp'
55
+ :tcp
56
+ when 'udp'
57
+ :udp
58
+ else
59
+ raise ConfigError, "syslog input protocol type should be 'tcp' or 'udp'"
60
+ end
61
+ end
62
+ config_param :include_source_host, :bool, :default => false
63
+ config_param :source_host_key, :string, :default => 'source_host'.freeze
64
+ config_param :blocking_timeout, :time, :default => 0.5
65
+
66
+ def configure(conf)
67
+ super
68
+ conf['with_priority'] = true
69
+ @parser = TextParser::NewSyslogParser.new
70
+ @parser.configure(conf)
71
+ end
72
+
73
+ def start
74
+ @loop = Coolio::Loop.new
75
+ @handler = listen(method(:receive_data))
76
+ @loop.attach(@handler)
77
+
78
+ @thread = Thread.new(&method(:run))
79
+ end
80
+
81
+ def shutdown
82
+ @loop.watchers.each {|w| w.detach }
83
+ @loop.stop
84
+ @handler.close
85
+ @thread.join
86
+ end
87
+
88
+ def run
89
+ @loop.run(@blocking_timeout)
90
+ rescue
91
+ log.error "unexpected error", :error=>$!.to_s
92
+ log.error_backtrace
93
+ end
94
+
95
+ private
96
+
97
+ def receive_data(data, addr)
98
+ @parser.parse(data) { |time, record|
99
+ unless time && record
100
+ log.warn "invalid syslog message", :data => data
101
+ return
102
+ end
103
+
104
+ pri = record.delete('pri')
105
+ record[@source_host_key] = addr[2] if @include_source_host
106
+ emit(pri, time, record)
107
+ }
108
+ rescue => e
109
+ log.error data.dump, :error => e.to_s
110
+ log.error_backtrace
111
+ end
112
+
113
+ private
114
+
115
+ def listen(callback)
116
+ log.debug "listening syslog socket on #{@bind}:#{@port} with #{@protocol_type}"
117
+ if @protocol_type == :udp
118
+ @usock = SocketUtil.create_udp_socket(@bind)
119
+ @usock.bind(@bind, @port)
120
+ SocketUtil::UdpHandler.new(@usock, log, 2048, callback)
121
+ else
122
+ # syslog family add "\n" to each message and this seems only way to split messages in tcp stream
123
+ Coolio::TCPServer.new(@bind, @port, SocketUtil::TcpHandler, log, "\n", callback)
124
+ end
125
+ end
126
+
127
+ def emit(pri, time, record)
128
+ facility = FACILITY_MAP[pri >> 3]
129
+ priority = PRIORITY_MAP[pri & 0b111]
130
+
131
+ tag = "#{@tag}.#{facility}.#{priority}"
132
+
133
+ router.emit(tag, time, record)
134
+ rescue => e
135
+ log.error "syslog failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
136
+ end
137
+
138
+ end
139
+ end
@@ -0,0 +1,88 @@
1
+ require 'fluent/parser'
2
+
3
+ module Fluent
4
+ class TextParser
5
+ class NewSyslogParser < Parser
6
+ # register as newsyslog parser
7
+ Plugin.register_parser("newsyslog", self)
8
+
9
+ # default to using the built in ruby time parser rather than specifying a time format
10
+ config_param :time_format, :string, :default => nil #"%b %d %H:%M:%S"
11
+ config_param :payload_message, :bool, :default => false
12
+ config_param :with_priority, :bool, :default => false
13
+
14
+ def initialize
15
+ super
16
+ @mutex = Mutex.new
17
+ end
18
+
19
+ def configure(conf)
20
+ super
21
+ @time_parser = TimeParser.new(@time_format)
22
+ end
23
+
24
+ def parse(text)
25
+
26
+ if @with_priority
27
+ if /^\<.*\>\d/.match(text)
28
+ #match rfc5424 syslog format
29
+ regex = /^\<(?<pri>[0-9]+)\>(1)(?<time>[^ ]* {1,2}[^ ]*) (?<host>[^ ]*) (?<ident>[^ ]*) (?<pid>[^ ]*) (?<msgid>[^ ]*) (-|) *(?<message>.*)$/
30
+ elsif /^\<.*>/.match(text)
31
+ #match rfc3164 syslog format
32
+ regex = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
33
+ else
34
+ #set an impossible regex match if not matching a the start of a syslog message above
35
+ regex = /a^/
36
+ end
37
+ else
38
+ # with_priorty = false to support in_syslog plugin
39
+ regex = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
40
+ end
41
+
42
+
43
+ m = regex.match(text)
44
+ unless m
45
+ if block_given?
46
+ yield nil, nil
47
+ return
48
+ else
49
+ return nil, nil
50
+ end
51
+ end
52
+
53
+ Regexp.union
54
+
55
+ time = nil
56
+ record = {}
57
+
58
+ m.names.each { |name|
59
+ if value = m[name]
60
+ case name
61
+ when 'pri'
62
+ record['pri'] = value.to_i
63
+ when 'time'
64
+ time = @mutex.synchronize { @time_parser.parse(value.gsub(/ +/, ' ')) }
65
+ when 'message'
66
+ record['message'] = @payload_message? text : value
67
+ else
68
+ record[name] = value
69
+ end
70
+ end
71
+ }
72
+
73
+ if @estimate_current_event
74
+ time ||= Engine.now
75
+ end
76
+
77
+ if block_given?
78
+ yield time, record
79
+ else
80
+ return time, record
81
+ end
82
+
83
+
84
+ end
85
+
86
+ end
87
+ end
88
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-newsyslog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Scheunemann
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-05 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.59
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.59
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: flexmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.6.4
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.6.4
97
+ - !ruby/object:Gem::Dependency
98
+ name: rr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.0.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: timecop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 0.3.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 0.3.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: test-unit
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.0.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.0.2
139
+ - !ruby/object:Gem::Dependency
140
+ name: test-unit-rr
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.0.3
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.0.3
153
+ description: 'A fluentd syslog parser that handles multiple formats '
154
+ email:
155
+ - kscheunemann@athenahealth.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - ".gitignore"
161
+ - ".rspec"
162
+ - ".ruby-version"
163
+ - ".travis.yml"
164
+ - Gemfile
165
+ - README.md
166
+ - Rakefile
167
+ - fluent-plugin-newsyslog.gemspec
168
+ - lib/fluent/plugin/in_newsyslog.rb
169
+ - lib/fluent/plugin/parser_newsyslog.rb
170
+ homepage: https://github.com/athenahealth/fluent-plugin-newsyslog
171
+ licenses: []
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 2.4.3
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: A better fluentd syslog input and parser
193
+ test_files: []