logstash-output-json_batch 0.2.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: ee4f16aca346581c664061bb54a8277e221e5202
4
+ data.tar.gz: 12cba94b51e576e5f255b2cb3b6bd7aa80784325
5
+ SHA512:
6
+ metadata.gz: 4558c603e114ef0b404ff6e92074aede6a0c646a713f78890f5e65b9cc8df533a51dd9fdcb10a0184dfeb3ed112a5ccd6119ca7334b70984befbfd0a0fb78455
7
+ data.tar.gz: 3a6771048a1366e45acc1c252f4ca6cb66481539d1c75ce6fa2c468e771623dada1abd2deac0ba354ca52101c4ee3a6f22f40b71c6e7bde6cd53d83eb45dac6d
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2016 Lucidworks
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.
@@ -0,0 +1,26 @@
1
+ # Logstash Plugin
2
+
3
+ This plugin is a heavily butchered and modified version of the standard logstash http output plugin. That plugin is available [here](https://github.com/logstash-plugins/logstash-output-http).
4
+
5
+ It has been modified to only support JSON, but also supports batching of messages into JSON lists.
6
+
7
+ # Usage
8
+
9
+ Please note that the name of the plugin when used is `json_batch`, since it only supports json in its current form. If further output formats are added in the future, this might change back to http_batch.
10
+
11
+ output {
12
+ json_batch {
13
+ headers => ["Authorization", "Basic YWRtaW46cGFzc3dvcmQxMjM="]
14
+ url => "http://your.site/your/json/update/endpoint"
15
+ }
16
+ }
17
+
18
+ Default batch size is 50, with a wait of at most 5 seconds per send. These can be tweaked with the parameters `flush_size` and `idle_flush_time` respectively.
19
+
20
+ # Installation & build
21
+
22
+ To build the gem yourself, use `gem build logstash-output-json_batch.gemspec` in the root of this repository. Alternatively, you can download a built version of the gem from the `dist` branch of this repository.
23
+
24
+ To install, run the following command, assuming the gem is in the local directory: `$LOGSTASH_HOME/bin/plugin install logstash-output-json_batch-X.Y.Z.gem`
25
+
26
+ Direct links to the built versions of the gems are available on the [releases page](https://github.com/jwestberg/logstash-output-http_batch/releases)
@@ -0,0 +1,158 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "logstash/json"
5
+ require "uri"
6
+ require "stud/buffer"
7
+ require "logstash/plugin_mixins/http_client"
8
+
9
+ class LogStash::Outputs::JSONBatch < LogStash::Outputs::Base
10
+ include LogStash::PluginMixins::HttpClient
11
+ include Stud::Buffer
12
+
13
+ config_name "json_batch"
14
+
15
+ # URL to use
16
+ config :url, :validate => :string, :required => true
17
+
18
+ # Custom headers to use
19
+ # format is `headers => ["X-My-Header", "%{host}"]`
20
+ config :headers, :validate => :hash
21
+
22
+ config :flush_size, :validate => :number, :default => 50
23
+
24
+ config :idle_flush_time, :validate => :number, :default => 5
25
+
26
+ config :retry_individual, :validate => :boolean, :default => true
27
+
28
+ config :pool_max, :validate => :number, :default => 50
29
+
30
+ def register
31
+ # Handle this deprecated option. TODO: remove the option
32
+ #@ssl_certificate_validation = @verify_ssl if @verify_ssl
33
+
34
+ # We count outstanding requests with this queue
35
+ # This queue tracks the requests to create backpressure
36
+ # When this queue is empty no new requests may be sent,
37
+ # tokens must be added back by the client on success
38
+ @request_tokens = SizedQueue.new(@pool_max)
39
+ @pool_max.times {|t| @request_tokens << true }
40
+ @total = 0
41
+ @total_failed = 0
42
+ @requests = Array.new
43
+
44
+ buffer_initialize(
45
+ :max_items => @flush_size,
46
+ :max_interval => @idle_flush_time,
47
+ :logger => @logger
48
+ )
49
+ logger.info("Initialized json_batch with settings",
50
+ :flush_size => @flush_size,
51
+ :idle_flush_time => @idle_flush_time,
52
+ :request_tokens => @pool_max,
53
+ :url => @url,
54
+ :headers => request_headers,
55
+ :retry_individual => @retry_individual)
56
+
57
+ end # def register
58
+
59
+ # This module currently does not support parallel requests as that would circumvent the batching
60
+ def receive(event, async_type=:background)
61
+ buffer_receive(event)
62
+ end #def event
63
+
64
+ public
65
+ def flush(events, close=false)
66
+ documents = [] #this is the array of hashes that we push to Fusion as documents
67
+
68
+ events.each do |event|
69
+ document = event.to_hash()
70
+ documents.push(document)
71
+ end
72
+
73
+ make_request(documents)
74
+ end
75
+
76
+ def multi_receive(events)
77
+ events.each {|event| buffer_receive(event)}
78
+ end
79
+
80
+ private
81
+
82
+ def make_request(documents)
83
+ body = LogStash::Json.dump(documents)
84
+ # Block waiting for a token
85
+ #@logger.info("Requesting token ", :tokens => request_tokens.length())
86
+ token = @request_tokens.pop
87
+ @logger.debug("Got token", :tokens => @request_tokens.length)
88
+
89
+ # Create an async request
90
+ begin
91
+ request = client.send(:post, @url, :body => body, :headers => request_headers, :async => true)
92
+ rescue Exception => e
93
+ @logger.warn("An error occurred while indexing: #{e.message}")
94
+ end
95
+
96
+ # attach handlers before performing request
97
+ request.on_complete do
98
+ # Make sure we return the token to the pool
99
+ @request_tokens << token
100
+ end
101
+
102
+ request.on_success do |response|
103
+ if response.code >= 200 && response.code < 300
104
+ @total = @total + documents.length
105
+ @logger.debug("Successfully submitted",
106
+ :docs => documents.length,
107
+ :response_code => response.code,
108
+ :total => @total)
109
+ else
110
+ if documents.length > 1 && @retry_individual
111
+ documents.each do |doc|
112
+ make_request([doc])
113
+ end
114
+ else
115
+ @total_failed += documents.length
116
+ log_failure(
117
+ "Encountered non-200 HTTP code #{response.code}",
118
+ :response_code => response.code,
119
+ :url => url,
120
+ :response_body => response.body,
121
+ :num_docs => documents.length,
122
+ :retry_individual => @retry_individual,
123
+ :total_failed => @total_failed)
124
+ end
125
+ end
126
+ end
127
+
128
+ request.on_failure do |exception|
129
+ @total_failed += documents.length
130
+ log_failure("Could not access URL",
131
+ :url => url,
132
+ :method => @http_method,
133
+ :body => body,
134
+ :headers => headers,
135
+ :message => exception.message,
136
+ :class => exception.class.name,
137
+ :backtrace => exception.backtrace,
138
+ :total_failed => @total_failed
139
+ )
140
+ end
141
+
142
+ Thread.new do
143
+ client.execute!
144
+ end
145
+ end
146
+
147
+ # This is split into a separate method mostly to help testing
148
+ def log_failure(message, opts)
149
+ @logger.error("[HTTP Output Failure] #{message}", opts)
150
+ end
151
+
152
+ def request_headers()
153
+ headers = @headers || {}
154
+ headers["Content-Type"] ||= "application/json"
155
+ headers
156
+ end
157
+
158
+ end
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-output-json_batch'
3
+ s.version = '0.2.0'
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = "This output lets you `POST` messages as JSON in a batched fashion to a HTTP endpoint"
6
+ s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
7
+ s.authors = ["jwestberg"]
8
+ s.email = 'joel.westberg@lucidworks.com'
9
+ s.homepage = "http://lucidworks.com"
10
+ s.require_paths = ["lib"]
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','*.gemspec','*.md','Gemfile','LICENSE' ]
14
+
15
+ # Tests
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+
18
+ # Special flag to let us know this is actually a logstash plugin
19
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
20
+
21
+ # Gem dependencies
22
+ s.add_runtime_dependency "logstash-core-plugin-api", "~> 1.0"
23
+ s.add_runtime_dependency "logstash-mixin-http_client", ">= 2.2.1", "< 3.0.0"
24
+
25
+ s.add_development_dependency 'logstash-devutils'
26
+ s.add_development_dependency 'sinatra'
27
+ s.add_development_dependency 'webrick'
28
+ end
29
+
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-json_batch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - jwestberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ name: logstash-core-plugin-api
20
+ prerelease: false
21
+ type: :runtime
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.2.1
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: 3.0.0
36
+ name: logstash-mixin-http_client
37
+ prerelease: false
38
+ type: :runtime
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.2.1
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: 3.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ name: logstash-devutils
54
+ prerelease: false
55
+ type: :development
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ name: sinatra
68
+ prerelease: false
69
+ type: :development
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ name: webrick
82
+ prerelease: false
83
+ type: :development
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
90
+ email: joel.westberg@lucidworks.com
91
+ executables: []
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - Gemfile
96
+ - LICENSE
97
+ - README.md
98
+ - lib/logstash/outputs/json_batch.rb
99
+ - logstash-output-json_batch.gemspec
100
+ homepage: http://lucidworks.com
101
+ licenses:
102
+ - Apache License (2.0)
103
+ metadata:
104
+ logstash_plugin: 'true'
105
+ logstash_group: output
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.4.8
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: This output lets you `POST` messages as JSON in a batched fashion to a HTTP endpoint
126
+ test_files: []