logstash-output-splunk_hec 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9acf5738a6f95a638b41287b71bcaec122a713a144ddfdbe4e8eacb58bfd95ca
4
+ data.tar.gz: 050a2753e156c7cb195701b1460605f767e6351bfedaacd56214f27b955b4a43
5
+ SHA512:
6
+ metadata.gz: 7c0cc2d47d092a10fedf6ad8831be42eb3fd84ee173f871d6eb5dc5d546d6015539763f56f908b2e0bbe96082f5f9fedda5a6c54d8584a99611f00fe86392a49
7
+ data.tar.gz: cd7d3d98d661ee1da85893c8444a0df15da2504c9ce52d70ada5357e8da458e3fa3c8bed85c6afaaee7af91a05ffe9bf8a389e4d99a69b4f6f6f49eff084df99
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ - Initial release, includes basic batching functionality
data/CONTRIBUTORS ADDED
@@ -0,0 +1,10 @@
1
+ The following is a list of people who have contributed ideas, code, bug
2
+ reports, or in general have helped logstash along its way.
3
+
4
+ Contributors:
5
+ * Elisha Mawson - elisha.mawson@origin.com.au
6
+
7
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
8
+ Logstash, and you aren't on the list above and want to be, please let us know
9
+ and we'll make sure you're here. Contributions from folks like you are what make
10
+ open source awesome.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ logstash_path = ENV['LOGSTASH_PATH'] || 'C:/Users/mawsone/logstash-8.15.0'
5
+
6
+ if Dir.exist?(logstash_path)
7
+ gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
8
+ gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
9
+ end
10
+
data/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # logstash_splunk_http_event_collector
@@ -0,0 +1,112 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "net/http"
5
+ require "uri"
6
+ require "json"
7
+ require "concurrent"
8
+
9
+ class LogStash::Outputs::SplunkHec < LogStash::Outputs::Base
10
+ config_name "splunk_hec"
11
+
12
+ concurrency :shared
13
+
14
+ config :token, :validate => :string, :required => true
15
+ config :host, :validate => :string, :required => true
16
+ config :port, :validate => :number, :default => 443
17
+ config :index, :validate => :string, :default => "main"
18
+ config :sourcetype, :validate => :string, :default => "_json"
19
+ config :batch_size, :validate => :number, :default => 100
20
+ config :flush_interval, :validate => :number, :default => 5
21
+ config :retry_count, :validate => :number, :default => 3
22
+
23
+ public
24
+ def register
25
+ @http = Net::HTTP.new(@host, @port)
26
+ @http.use_ssl = true
27
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
28
+ @uri = URI.parse("https://#{@host}:#{@port}/services/collector/event")
29
+
30
+ @event_batch = Concurrent::Array.new
31
+ @last_flush = Concurrent::AtomicReference.new(Time.now)
32
+ end
33
+
34
+ public
35
+ def receive(event)
36
+ format_and_add_to_batch(event)
37
+
38
+ if batch_full? || time_to_flush?
39
+ flush_batch
40
+ end
41
+ end
42
+
43
+ public
44
+ def close
45
+ flush_batch if @event_batch.any?
46
+ end
47
+
48
+ private
49
+ def format_and_add_to_batch(event)
50
+ event_data = event.to_hash
51
+ event_data.delete("@version")
52
+
53
+ hec_event = {
54
+ "time" => event.get("@timestamp").to_i,
55
+ "host" => event.get("host")&.fetch("name") { Socket.gethostname },
56
+ "source" => event.get("source") { "logstash" },
57
+ "sourcetype" => @sourcetype,
58
+ "index" => @index,
59
+ "event" => event_data
60
+ }
61
+
62
+ @event_batch << hec_event
63
+ end
64
+
65
+ private
66
+ def batch_full?
67
+ @event_batch.size >= @batch_size
68
+ end
69
+
70
+ private
71
+ def time_to_flush?
72
+ Time.now - @last_flush.get >= @flush_interval
73
+ end
74
+
75
+ private
76
+ def flush_batch
77
+ return if @event_batch.empty?
78
+
79
+ batch_to_send = @event_batch.slice!(0, @batch_size)
80
+ request = Net::HTTP::Post.new(@uri.request_uri)
81
+ request["Authorization"] = "Splunk #{@token}"
82
+ request["Content-Type"] = "application/json"
83
+ request.body = batch_to_send.map(&:to_json).join("\n")
84
+
85
+ @retry_count.times do |attempt|
86
+ begin
87
+ response = @http.request(request)
88
+ if response.code == "200"
89
+ @logger.debug("Successfully sent batch to Splunk", :batch_size => batch_to_send.size)
90
+ @last_flush.set(Time.now)
91
+ return
92
+ else
93
+ @logger.warn("Failed to send batch to Splunk, will retry",
94
+ :response_code => response.code,
95
+ :response_body => response.body,
96
+ :attempt => attempt + 1,
97
+ :batch_size => batch_to_send.size)
98
+ end
99
+ rescue StandardError => e
100
+ @logger.error("Error sending batch to Splunk, will retry",
101
+ :error => e.message,
102
+ :attempt => attempt + 1,
103
+ :batch_size => batch_to_send.size)
104
+ end
105
+ sleep(1)
106
+ end
107
+
108
+ @logger.error("Failed to send batch to Splunk after #{@retry_count} attempts",
109
+ :batch_size => batch_to_send.size)
110
+ @event_batch.concat(batch_to_send)
111
+ end
112
+ end
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-output-splunk_hec'
3
+ s.version = '0.1.0'
4
+ s.licenses = ['Apache-2.0']
5
+ s.summary = 'Logstash Output Plugin for SplunkHec'
6
+ s.authors = ['Elisha Mawson']
7
+ s.email = 'elisha.mawson@origin.com.au'
8
+ s.require_paths = ['lib']
9
+
10
+ # Files
11
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
12
+ # Tests
13
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
14
+
15
+ # Special flag to let us know this is actually a logstash plugin
16
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
17
+
18
+ # Gem dependencies
19
+ s.add_runtime_dependency "logstash-core-plugin-api", "~> 2.0"
20
+ s.add_runtime_dependency "logstash-codec-plain"
21
+ s.add_development_dependency "logstash-devutils"
22
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/outputs/splunk_hec"
4
+ require "logstash/codecs/plain"
5
+
6
+
7
+ describe LogStash::Outputs::SplunkHec do
8
+ let(:sample_event) { LogStash::Event.new }
9
+ let(:output) { LogStash::Outputs::SplunkHec.new }
10
+
11
+ before do
12
+ output.register
13
+ end
14
+
15
+ describe "receive message" do
16
+ subject { output.receive(sample_event) }
17
+
18
+ it "returns a string" do
19
+ expect(subject).to eq("Event received")
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-splunk_hec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Elisha Mawson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash-core-plugin-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: logstash-codec-plain
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: logstash-devutils
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
+ description:
56
+ email: elisha.mawson@origin.com.au
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - CHANGELOG.md
62
+ - CONTRIBUTORS
63
+ - Gemfile
64
+ - LICENSE
65
+ - README.md
66
+ - lib/logstash/outputs/splunk_hec.rb
67
+ - logstash-output-splunk_hec.gemspec
68
+ - spec/outputs/splunk_hec_spec.rb
69
+ homepage:
70
+ licenses:
71
+ - Apache-2.0
72
+ metadata:
73
+ logstash_plugin: 'true'
74
+ logstash_group: output
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.3.5
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Logstash Output Plugin for SplunkHec
94
+ test_files:
95
+ - spec/outputs/splunk_hec_spec.rb