fluent-plugin-sumologic-cloud-syslog 0.1.2

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.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ # Copyright 2016 Acquia, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'bundler/gem_tasks'
16
+ require 'rake/testtask'
17
+
18
+ Rake::TestTask.new(:test) do |test|
19
+ test.libs << 'test'
20
+ test.pattern = 'test/**/test_*.rb'
21
+ test.verbose = true
22
+ end
23
+
24
+ task :default => :test
@@ -0,0 +1,119 @@
1
+ # Configuration
2
+
3
+ This plugin allows to configure all syslog message attributes.
4
+
5
+ ## Static configuration
6
+
7
+ Static configuration allow to define connection details, facility and hostname that will
8
+ apply to all messages.
9
+
10
+ ### host
11
+
12
+ Host represents DNS name of endpoint where should be data sent. Example: `syslog.collection.us1.sumologic.com`
13
+
14
+ ### port
15
+
16
+ Example: `6514`
17
+
18
+ ### token
19
+
20
+ Private token that is unique per account. Example: `ABABABABABABA@99999`
21
+
22
+ ### cert
23
+
24
+ Optionally path to private certificate for TLS connection. Example: `/path/to/crt/file.crt`
25
+
26
+ ### key
27
+
28
+ Optionally path to key for TLS connection. Example: `/path/to/key/file.key`
29
+
30
+ ### hostname
31
+
32
+ Default hostname that is going to be sent in syslog message. Example: `ip-10-0-0-10`
33
+
34
+ ### facility
35
+
36
+ Default syslog facility for all records. Example: `LOCAL0`
37
+
38
+ ## Per message configuration
39
+
40
+ Its possible to configure the plugin to extract various parts of syslog message header
41
+ from processed record itself. That allows to dynamically set app_name, procid, msgid from
42
+ records if single match is being used to log messages from multiple sources.
43
+
44
+ ### severity_key
45
+
46
+ Optionally record key where to get severity from the record. If not provided default `INFO` will be used.
47
+
48
+ ### facility_key
49
+
50
+ Optionally record key where to get syslog facility from the record. If not provided default `LOCAL0` will be used.
51
+
52
+ ### hostname_key
53
+
54
+ Optionally record key where to get hostname from the record. If not provided hostname is determined by system hostname.
55
+
56
+ ### app_name_key
57
+
58
+ Optionally record key where to get app_name from the record. If not provided nil value will be sent.
59
+
60
+ ### procid_key
61
+
62
+ Optionally record key where to get procid from the record. If not provided nil value will be sent.
63
+
64
+ ### msgid_key
65
+
66
+ Optionally record key where to get msgid from the record. If not provided nil value will be sent.
67
+
68
+ ## Additional configuration
69
+
70
+ This plugin makes use of [Fluent::Mixin::PlainTextFormatter](https://github.com/tagomoris/fluent-mixin-plaintextformatter) please check out its documentation for more configuration options.
71
+
72
+ ## Puppet
73
+
74
+ If you are using Puppet for configuration management then an example configuration
75
+ using the [wywygmbh/puppet-fluentd](http://github.com/wywygmbh/puppet-fluentd) puppet module would be:
76
+
77
+ ```
78
+ ::fluentd::plugin { 'fluent-plugin-sumologic-cloud-syslog':
79
+ type => 'gem',
80
+ }
81
+
82
+ ::fluentd::match { 'sumologic_cloud_syslog':
83
+ priority => 10,
84
+ pattern => '**',
85
+ config => {
86
+ 'type' => 'sumologic_cloud_syslog',
87
+ 'host' => 'syslog.collection.us1.sumologic.com',
88
+ 'port' => 6514,
89
+ 'token' => $token,
90
+ 'cert' => $cert,
91
+ 'key' => $key,
92
+ },
93
+ }
94
+ ```
95
+
96
+ ## Example
97
+
98
+ ```
99
+ <match>
100
+ host syslog.collection.us1.sumologic.com
101
+ port 6514
102
+ token [token]@[iana-id]
103
+ cert /path/to/cert/file.crt
104
+ key /path/to/key/file.key
105
+
106
+ hostname static-hostname
107
+ facility SYSLOG
108
+
109
+ # You can configure syslog headers to be picked from actual message
110
+ # processed by plugin. If key is not provided '-' value will be sent
111
+ # which is NIL by syslog specification.
112
+ severity_key RECORD_SEVERITY_KEY
113
+ facility_key RECORD_FACILITY_KEY
114
+ hostname_key ...
115
+ app_name_key ...
116
+ procid_key ...
117
+ msgid_key ...
118
+ </match>
119
+ ```
@@ -0,0 +1,43 @@
1
+ # Copyright 2016 Acquia, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ lib = File.expand_path('../lib', __FILE__)
16
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
17
+ require 'sumologic_cloud_syslog/version'
18
+
19
+ Gem::Specification.new do |s|
20
+ s.name = 'fluent-plugin-sumologic-cloud-syslog'
21
+ s.version = SumologicCloudSyslog::VERSION
22
+ s.authors = ['Acquia Engineering']
23
+ s.email = ['engineering@acquia.com']
24
+ s.summary = %q{Fluent Sumologic Cloud Syslog plugin}
25
+ s.description = %q{Sumologic Cloud Syslog output plugin for Fluent event collector}
26
+ s.homepage = 'https://github.com/acquia/fluent-plugin-sumologic-cloud-syslog'
27
+ s.license = 'Apache v2'
28
+ s.files = `git ls-files`.split($/)
29
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
30
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
31
+ s.require_paths = ['lib']
32
+ s.required_ruby_version = '>= 2.0.0'
33
+
34
+ s.add_runtime_dependency 'fluentd', '~> 0.12'
35
+ s.add_runtime_dependency 'fluent-mixin-config-placeholders', '~> 0.3'
36
+ s.add_runtime_dependency 'fluent-mixin-plaintextformatter', '~> 0.2'
37
+
38
+ s.add_development_dependency 'minitest', '~> 5.8'
39
+ s.add_development_dependency 'rake', '~> 10.5'
40
+ s.add_development_dependency 'test-unit', '~> 3.1'
41
+ s.add_development_dependency 'webmock', '~> 2.0'
42
+ s.add_development_dependency 'simplecov', '~> 0.11'
43
+ end
@@ -0,0 +1,118 @@
1
+ # Copyright 2016 Acquia, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'fluent/mixin/config_placeholders'
16
+ require 'fluent/mixin/plaintextformatter'
17
+ require 'socket'
18
+
19
+ module Fluent
20
+ class SumologicCloudSyslogOutput < Fluent::Output
21
+ Fluent::Plugin.register_output('sumologic_cloud_syslog', self)
22
+
23
+ include Fluent::Mixin::PlainTextFormatter
24
+ include Fluent::Mixin::ConfigPlaceholders
25
+ include Fluent::HandleTagNameMixin
26
+
27
+ config_param :host, :string
28
+ config_param :port, :integer
29
+ config_param :token, :string
30
+ config_param :cert, :string, :default => nil
31
+ config_param :key, :string, :default => nil
32
+ config_param :hostname, :string, :default => nil
33
+ config_param :facility, :string, :default => 'LOCAL0'
34
+
35
+ # Allow to map keys from record to syslog message headers
36
+ SYSLOG_HEADERS = [
37
+ :severity, :facility, :hostname, :app_name, :procid, :msgid
38
+ ]
39
+
40
+ SYSLOG_HEADERS.each do |key_name|
41
+ config_param "#{key_name}_key".to_sym, :string, :default => nil
42
+ end
43
+
44
+ def initialize
45
+ super
46
+ require 'sumologic_cloud_syslog/logger'
47
+ @loggers = {}
48
+ end
49
+
50
+ def shutdown
51
+ super
52
+ @loggers.values.each(&:close)
53
+ end
54
+
55
+ # This method is called before starting.
56
+ def configure(conf)
57
+ super
58
+ @host = conf['host']
59
+ @port = conf['port']
60
+ @token = conf['token']
61
+ @hostname = conf['hostname'] || Socket.gethostname.split('.').first
62
+
63
+ # Determine mapping of record keys to syslog keys
64
+ @mappings = {}
65
+ SYSLOG_HEADERS.each do |key_name|
66
+ conf_key = "#{key_name}_key"
67
+ @mappings[key_name] = conf[conf_key] if conf.key?(conf_key)
68
+ end
69
+ end
70
+
71
+ # Get logger for given tag
72
+ def logger(tag)
73
+ # Try to reuse existing logger
74
+ @loggers[tag] ||= new_logger(tag)
75
+
76
+ # Create new logger if old one is closed
77
+ if @loggers[tag].closed?
78
+ @loggers[tag] = new_logger(tag)
79
+ end
80
+
81
+ @loggers[tag]
82
+ end
83
+
84
+ def new_logger(tag)
85
+ transport = ::SumologicCloudSyslog::SSLTransport.new(host, port, cert: cert, key: key)
86
+ logger = ::SumologicCloudSyslog::Logger.new(transport, token)
87
+ logger.facility(facility)
88
+ logger.hostname(hostname)
89
+ logger.app_name(tag)
90
+ logger
91
+ end
92
+
93
+ def emit(tag, es, chain)
94
+ chain.next
95
+ es.each do |time, record|
96
+ record.each_pair do |_, v|
97
+ v.force_encoding('utf-8') if v.is_a?(String)
98
+ end
99
+
100
+ # Check if severity has been provided in record otherwise use INFO
101
+ # by default.
102
+ severity = if @mappings.key?(:severity)
103
+ record[@mappings[:severity]] || 'INFO'
104
+ else
105
+ 'INFO'
106
+ end
107
+
108
+ # Send message to Sumo
109
+ logger(tag).log(severity, format(tag, time, record), time: Time.at(time)) { |header|
110
+ # Map syslog headers from record
111
+ @mappings.each do |name, record_key|
112
+ header.send("#{name}=", record[record_key]) unless record[record_key].nil?
113
+ end
114
+ }
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright 2016 Acquia, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative 'lookup_from_const'
16
+
17
+ module SumologicCloudSyslog
18
+ module Facility
19
+ extend LookupFromConst
20
+ KERN = 0
21
+ USER = 1
22
+ MAIL = 2
23
+ DAEMON = 3
24
+ AUTH = 4
25
+ SYSLOG = 5
26
+ LPR = 6
27
+ NEWS = 7
28
+ UUCP = 8
29
+ CRON = 9
30
+ AUTHPRIV = 10
31
+ FTP = 11
32
+ NTP = 12
33
+ SECURITY = 13
34
+ CONSOLE = 14
35
+ RAS = 15
36
+ LOCAL0 = 16
37
+ LOCAL1 = 17
38
+ LOCAL2 = 18
39
+ LOCAL3 = 19
40
+ LOCAL4 = 20
41
+ LOCAL5 = 21
42
+ LOCAL6 = 22
43
+ LOCAL7 = 23
44
+ NONE = SYSLOG
45
+ end
46
+ end
@@ -0,0 +1,81 @@
1
+ # Copyright 2016 Acquia, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative 'protocol'
16
+ require_relative 'ssl_transport'
17
+
18
+ module SumologicCloudSyslog
19
+ class Logger
20
+ attr_reader :token
21
+ attr_accessor :transport
22
+
23
+ # Logger accepts transport which should implement IO methods
24
+ # close, closed? and write
25
+ def initialize(transport, token)
26
+ @transport = transport
27
+ @default_header = SumologicCloudSyslog::Header.new
28
+ @default_structured_data = SumologicCloudSyslog::StructuredData.new(token)
29
+ end
30
+
31
+ # Sets default facility for each message
32
+ def facility(val)
33
+ @default_header.facility = val
34
+ end
35
+
36
+ # Sets default hostname for each message
37
+ def hostname(val)
38
+ @default_header.hostname = val
39
+ end
40
+
41
+ # Sets default app_name for each message
42
+ def app_name(val)
43
+ @default_header.app_name = val
44
+ end
45
+
46
+ # Sets default procid for message
47
+ def procid(val)
48
+ @default_header.procid = val
49
+ end
50
+
51
+ # Check if IO is closed
52
+ def closed?
53
+ transport && transport.closed?
54
+ end
55
+
56
+ def close
57
+ transport.close
58
+ end
59
+
60
+ # Send log message with severity to Sumologic
61
+ def log(severity, message, time: nil)
62
+ time ||= Time.now
63
+
64
+ m = SumologicCloudSyslog::Message.new
65
+
66
+ # Include authentication header
67
+ m.structured_data << @default_structured_data
68
+
69
+ # Adjust header with current timestamp and severity
70
+ m.header = @default_header.dup
71
+ m.header.severity = severity
72
+ m.header.timestamp = time
73
+
74
+ yield m.header if block_given?
75
+
76
+ m.msg = message
77
+
78
+ transport.write(m.to_s)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright 2016 Acquia, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module SumologicCloudSyslog
16
+ module LookupFromConst
17
+ def setup_constants(dst)
18
+ constants.each do |pri|
19
+ cval = const_get pri
20
+
21
+ dst[pri] = cval
22
+ dst[pri.downcase] = cval
23
+
24
+ dst[:"LOG_#{pri.to_s}"] = cval
25
+ dst[:"LOG_#{pri.downcase.to_s}"] = cval
26
+ const_set :"LOG_#{pri.to_s}", cval
27
+
28
+ dst[pri.to_s] = cval
29
+ dst[pri.downcase.to_s] = cval
30
+
31
+ dst[cval] = cval
32
+ dst[cval.to_s] = cval
33
+ end
34
+ end
35
+ end
36
+ end