fluent-plugin-splunk-ex-logentries 1.0.1.logentries

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: df18337f5895e02bcafd8d9926082575d6ba5234a4b343db4da3bff10efa7678
4
+ data.tar.gz: 6f7e8e2b4c06a27e04c7fc7bb0d62a6c4fab71b483cfa72663b2e12c5f418440
5
+ SHA512:
6
+ metadata.gz: 591ca52932934d84a350f5b90f3a358e6250777ea798b79cc15107a81d1146de283419d89243c64a2428c78c85f0e813748a88e25b3e86327d552586658ac4f1
7
+ data.tar.gz: cac585a169d1b687e96914dbe320e65106814637681ea78d6a2199b8996e95208790f0cbef3d7c41d3cb3591730b4b64b8ad7cd99a202eb64f2def2630943189
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.*
5
+ gemfile:
6
+ - Gemfile
7
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'coveralls', require: false
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ [![Build Status](https://travis-ci.org/gtrevg/fluent-plugin-splunk-ex.svg?branch=master)](https://travis-ci.org/gtrevg/fluent-plugin-splunk-ex) [![Code Climate](https://codeclimate.com/github/gtrevg/fluent-plugin-splunk-ex.png)](https://codeclimate.com/github/gtrevg/fluent-plugin-splunk-ex) [![Coverage Status](https://coveralls.io/repos/gtrevg/fluent-plugin-splunk-ex/badge.png)](https://coveralls.io/r/gtrevg/fluent-plugin-splunk-ex)
2
+
3
+ ## Overview
4
+
5
+ This plugin will send your fluentd logs to a splunk server. It can send the data in either
6
+ key/value (k1=v1 k2=v2) or json format for easy splunk parsing.
7
+
8
+
9
+ ## Installation
10
+
11
+ gem install fluent-plugin-splunk-ex
12
+
13
+ ## Configuration
14
+
15
+ ### Plugin
16
+
17
+ <match pattern>
18
+ type splunk_ex
19
+ host <splunk_host> # default: localhost
20
+ port <splunk_port> # default: 9997 - but you'll want to change this
21
+ output_format json|kv # default: json
22
+ </match>
23
+
24
+ ### Splunk
25
+
26
+ You may need to open up a special TCP port just for the fluentd logs. To do that, go to
27
+ `Manager -> Data Inputs -> TCP -> New`. Then decide the following:
28
+
29
+ * Port
30
+ * Source Name
31
+ * Source Type
32
+ * Index ( default works well )
33
+
34
+ After enabling these settings, you'll be able to see your fluentd logs appear in your Splunk search interface.
35
+ The JSON format will be automagically parsed and indexed based on the keys passed in.
36
+
37
+ Because the plugin batch sends data to Splunk, you'll want to update your `apps/search/local/props.conf`
38
+ file to specify that Splunk should split on newlines. If you do not update this setting, you find that
39
+ all logs from a similar time slice will be stacked upon each other. Because the kv & json formats do
40
+ not contain any newline characters, splitting on the newline will solve this problem. The values to
41
+ add to this file are:
42
+
43
+ [<source_type_here>]
44
+ SHOULD_LINEMERGE = false
45
+
46
+ This will make sure that the new source type you just set up for fluentd will always split on the newline character.
47
+
48
+ ## Copyright
49
+
50
+ Copyright (c) 2014 Trevor Gattis
51
+
52
+ ## License
53
+
54
+ Apache License, Version 2.0
55
+
56
+
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+ task :default => :spec
10
+
11
+ desc 'Open an irb session preloaded with the gem library'
12
+ task :console do
13
+ sh 'irb -rubygems -I lib'
14
+ end
15
+ task :c => :console
16
+
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "fluent-plugin-splunk-ex-logentries"
5
+ gem.version = "1.0.1.logentries"
6
+
7
+ gem.authors = ["Trevor Gattis"]
8
+ gem.email = "github@trevorgattis.com"
9
+ gem.description = "Splunk output plugin for Fluent event collector. It supports reconnecting on socket failure as well as exporting the data as json or in key/value pairs. Modified to produce output format fit for Logentries."
10
+ gem.homepage = "https://github.com/Indrius/fluent-plugin-splunk-ex"
11
+ gem.summary = gem.description
12
+ gem.license = "APLv2"
13
+ gem.has_rdoc = false
14
+
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_dependency "fluentd", "~> 0.10.17"
21
+ gem.add_runtime_dependency "json"
22
+
23
+ gem.add_development_dependency "rake"
24
+ gem.add_development_dependency "rspec"
25
+ gem.add_development_dependency "pry"
26
+ gem.add_development_dependency "pry-nav"
27
+ end
28
+
@@ -0,0 +1,145 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+ require 'open-uri'
15
+ require 'json'
16
+
17
+ class Fluent::SplunkExOutput < Fluent::Output
18
+
19
+ SOCKET_TRY_MAX = 3
20
+
21
+ Fluent::Plugin.register_output('splunk_ex', self)
22
+
23
+ include Fluent::SetTagKeyMixin
24
+ config_set_default :include_tag_key, false
25
+
26
+ include Fluent::SetTimeKeyMixin
27
+ config_set_default :include_time_key, false
28
+
29
+ config_param :host, :string, :default => 'localhost'
30
+ config_param :port, :string, :default => 9997
31
+ config_param :output_format, :string, :default => 'json'
32
+
33
+ config_param :test_mode, :bool, :default => false
34
+
35
+ # To support log_level option implemented by Fluentd v0.10.43
36
+ unless method_defined?(:log)
37
+ define_method(:log) { $log }
38
+ end
39
+
40
+
41
+ def configure(conf)
42
+ super
43
+ end
44
+
45
+ def start
46
+ super
47
+
48
+ if @output_format == 'kv'
49
+ @format_fn = self.class.method(:format_kv)
50
+ elsif @output_format == 'logentries'
51
+ @format_fn = self.class.method(:format_logentries)
52
+ else
53
+ @format_fn = self.class.method(:format_json)
54
+ end
55
+
56
+ if @test_mode
57
+ @send_data = proc { |text| log.trace("test mode text: #{text}") }
58
+ else
59
+ begin
60
+ @splunk_connection = TCPSocket.open(@host, @port)
61
+ rescue Errno::ECONNREFUSED
62
+ # we'll try again when data is sent
63
+ end
64
+ @send_data = self.method(:splunk_send)
65
+ end
66
+
67
+ end
68
+
69
+
70
+ def shutdown
71
+ super
72
+ if !@test_mode && @splunk_connection.respond_to?(:close)
73
+ @splunk_connection.close
74
+ end
75
+ end
76
+
77
+
78
+ def emit(tag, es, chain)
79
+ chain.next
80
+ es.each {|time,record|
81
+ @send_data.call( @format_fn.call(record) )
82
+ }
83
+ end
84
+
85
+ # =================================================================
86
+
87
+ protected
88
+
89
+ def self.format_kv(record)
90
+ kv_out_str = ''
91
+ record.each { |k, v|
92
+ kv_out_str << sprintf('%s=%s ', URI::encode(k), URI::encode(v.to_s))
93
+ }
94
+ kv_out_str
95
+ end
96
+
97
+ def self.format_logentries(record)
98
+ label = record["kubernetes"]["labels"]["logentries"]
99
+ message = record["message"]
100
+ le_out_str = label + " " + message
101
+ end
102
+
103
+ def self.format_json(record)
104
+ json_str = record.to_json
105
+ end
106
+
107
+ def splunk_send(text, try_count=0)
108
+ log.debug("splunk_send: #{text}")
109
+
110
+ successful_send = false
111
+ try_count = 0
112
+
113
+ while (!successful_send && try_count < SOCKET_TRY_MAX)
114
+ begin
115
+ @splunk_connection.puts(text)
116
+ successful_send = true
117
+
118
+ rescue NoMethodError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EPIPE => se
119
+ log.error("splunk_send - socket send retry (#{try_count}) failed: #{se}")
120
+ try_count = try_count + 1
121
+
122
+ successful_reopen = false
123
+ while (!successful_reopen && try_count < SOCKET_TRY_MAX)
124
+ begin
125
+ # Try reopening
126
+ @splunk_connection = TCPSocket.open(@host, @port)
127
+ successful_reopen = true
128
+ rescue Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EPIPE => se
129
+ log.error("splunk_send - socket open retry (#{try_count}) failed: #{se}")
130
+ try_count = try_count + 1
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ if !successful_send
137
+ log.fatal("splunk_send - retry of sending data failed after #{SOCKET_TRY_MAX} chances.")
138
+ log.warn(text)
139
+ end
140
+
141
+ end
142
+
143
+
144
+ end
145
+
@@ -0,0 +1,74 @@
1
+ # encoding: UTF-8
2
+ require_relative 'spec_helper'
3
+ require 'benchmark'
4
+ Fluent::Test.setup
5
+
6
+ def create_driver(config, tag = 'foo.bar')
7
+ Fluent::Test::OutputTestDriver.new(Fluent::SplunkExOutput, tag).configure(config)
8
+ end
9
+
10
+ # setup
11
+ single_key_message = {
12
+ 'msg' => 'testing some data'
13
+ }
14
+
15
+ multi_key_message = {
16
+ 'msg' => 'testing some data',
17
+ 'chars' => 'let"s put !@#$%^&*()-= some weird :\'?><,./ characters',
18
+ 'dt' => '2014/04/03T07:02:11.124202',
19
+ 'debug_line' => 24,
20
+ 'debug_file' => '/some/path/to/myFile.py',
21
+ 'statsd_key' => 'fluent_plugin_splunk_ex',
22
+ 'statsd_timing' => 0.234,
23
+ 'statsd_type' => 'timing',
24
+ 'tx' => '280c3e80-bb6c-11e3-a5e2-0800200c9a66',
25
+ 'host' => 'my01.cool.server.com'
26
+ }
27
+
28
+ time = Time.now.to_i
29
+
30
+ driver_kv = create_driver(%[
31
+ log_level fatal
32
+ test_mode true
33
+ output_format kv
34
+ ])
35
+
36
+ driver_json = create_driver(%[
37
+ log_level fatal
38
+ test_mode true
39
+ output_format json
40
+ ])
41
+
42
+ driver_kv_time = create_driver(%[
43
+ log_level fatal
44
+ test_mode true
45
+ output_format kv
46
+ time_key myKey
47
+ include_time_key true
48
+ ])
49
+
50
+ driver_json_time = create_driver(%[
51
+ log_level fatal
52
+ test_mode true
53
+ output_format json
54
+ time_key myKey
55
+ include_time_key true
56
+ ])
57
+
58
+
59
+
60
+ # bench
61
+ n = 10000
62
+ Benchmark.bm(7) do |x|
63
+ x.report("single_kv ") { driver_kv.run { n.times { driver_kv.emit( single_key_message, time) } } }
64
+ x.report("single_kv_time ") { driver_kv_time.run { n.times { driver_kv_time.emit( single_key_message, time) } } }
65
+ x.report("single_json ") { driver_json.run { n.times { driver_json.emit( single_key_message, time) } } }
66
+ x.report("single_json_time") { driver_json_time.run { n.times { driver_json_time.emit(single_key_message, time) } } }
67
+
68
+ x.report("multi_kv ") { driver_kv.run { n.times { driver_kv.emit( multi_key_message, time ) } } }
69
+ x.report("multi_kv_time ") { driver_kv_time.run { n.times { driver_kv_time.emit( multi_key_message, time ) } } }
70
+ x.report("multi_json ") { driver_json.run { n.times { driver_json.emit( multi_key_message, time ) } } }
71
+ x.report("multi_json_time ") { driver_json_time.run { n.times { driver_json_time.emit(multi_key_message, time ) } } }
72
+
73
+ end
74
+
@@ -0,0 +1,25 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ # This file was generated by the `rspec --init` command. Conventionally, all
5
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
6
+ # Require this file using `require "spec_helper"` to ensure that it is only
7
+ # loaded once.
8
+ #
9
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+
15
+ # Run specs in random order to surface order dependencies. If you find an
16
+ # order dependency and want to debug it, you can fix the order by providing
17
+ # the seed, which is printed after each run.
18
+ # --seed 1234
19
+ config.order = 'random'
20
+ end
21
+
22
+ require 'fluent/test'
23
+
24
+ require 'fluent/plugin/out_splunk_ex'
25
+
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-splunk-ex-logentries
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1.logentries
5
+ platform: ruby
6
+ authors:
7
+ - Trevor Gattis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-15 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.17
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.17
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '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'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
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: 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: pry
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: pry-nav
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Splunk output plugin for Fluent event collector. It supports reconnecting
98
+ on socket failure as well as exporting the data as json or in key/value pairs. Modified
99
+ to produce output format fit for Logentries.
100
+ email: github@trevorgattis.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - README.md
108
+ - Rakefile
109
+ - fluent-plugin-splunk-ex.gemspec
110
+ - lib/fluent/plugin/out_splunk_ex.rb
111
+ - spec/out_splunk_ex_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/Indrius/fluent-plugin-splunk-ex
114
+ licenses:
115
+ - APLv2
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">"
129
+ - !ruby/object:Gem::Version
130
+ version: 1.3.1
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.7.3
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Splunk output plugin for Fluent event collector. It supports reconnecting
137
+ on socket failure as well as exporting the data as json or in key/value pairs. Modified
138
+ to produce output format fit for Logentries.
139
+ test_files: []