mrcooper-logstash-output-azuresearch 0.2.1

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
+ SHA1:
3
+ metadata.gz: 51965d9b889d6a7b66993d69f261ae5a0665947c
4
+ data.tar.gz: 82557a194de1f85a3c26d3e3bbb8a6919ae19d0d
5
+ SHA512:
6
+ metadata.gz: ac6d1f3247d38ab7bb4f97f78263ec42adb8dce49ad3cdac350c254bf5170b0ab109da3d19b07aa1731e3aac8d549ac1e203a81f1d035a5b6815887af129625a
7
+ data.tar.gz: 7f29bf99a287c387c5eebe5b450d04529bef785002a96ab2c218c6b0f1f31a64c0ed1c6d9c7716ccac65a7fdf77acf821697de5ea123aae04ab31794376f96e5
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## 0.1.1
2
+
3
+ * Fixed up [Issue#1](https://github.com/yokawasa/logstash-output-azuresearch/issues/1)
4
+
5
+ ## 0.1.0
6
+
7
+ * Inital Release
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
+ * Yoichi Kawasaki (yokawasa)
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,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012–2015 Elasticsearch <http://www.elastic.co>
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.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Azure Search output plugin for Logstash
2
+
3
+ logstash-output-azuresearch is a logstash plugin to output to Azure Search. [Logstash](https://www.elastic.co/products/logstash) is an open source, server-side data processing pipeline that ingests data from a multitude of sources simultaneously, transforms it, and then sends it to your favorite [destinations](https://www.elastic.co/products/logstash). [Azure Search](https://docs.microsoft.com/en-us/azure/search/search-what-is-azure-search) is a managed cloud search service provided in Microsoft Azure.
4
+
5
+ ## Installation
6
+
7
+ You can install this plugin using the Logstash "plugin" or "logstash-plugin" (for newer versions of Logstash) command:
8
+ ```
9
+ bin/plugin install logstash-output-azuresearch
10
+ # or
11
+ bin/logstash-plugin install logstash-output-azuresearch (Newer versions of Logstash)
12
+ ```
13
+ Please see [Logstash reference](https://www.elastic.co/guide/en/logstash/current/offline-plugins.html) for more information.
14
+
15
+ ## Configuration
16
+
17
+ ```
18
+ output {
19
+ azuresearch {
20
+ endpoint => "https://<YOUR ACCOUNT>.search.windows.net"
21
+ api_key => "<AZURESEARCH API KEY>"
22
+ search_index => "<SEARCH INDEX NAME>"
23
+ column_names => ['col1','col2','col3'..] ## ## list of column names (array)
24
+ key_names => ['key1','key2','key3'..] ## list of Key names (array)
25
+ flush_items => <FLUSH_ITEMS_NUM>
26
+ flush_interval_time => <FLUSH INTERVAL TIME(sec)>
27
+ }
28
+ }
29
+ ```
30
+
31
+ * **endpoint (required)** - Azure Search service endpoint URI
32
+ * **api\_key (required)** - Azure Search API key
33
+ * **search\_index (required)** - Azure Search Index name to insert records
34
+ * **column\_names (required)** - List of column names (array) in a target Azure search index. 1st item in column_names should be primary key
35
+ * **key\_names (optional)** - Default:[] (empty array). List of key names (array) in in-coming record to insert. The number of keys in key_names must be equal to the one of columns in column_names. Also the order or each item in key_names must match the one of each items in column_names.
36
+ * **flush_items (optional)** - Default 50. Max number of items to buffer before flushing (1 - 1000).
37
+ * **flush_interval_time (optional)** - Default 5. Max number of seconds to wait between flushes.
38
+
39
+ ## Tests
40
+
41
+ Here is an example configuration where Logstash's event source and destination are configured as standard input and Azure Search respectively.
42
+
43
+ ### Example Configuration
44
+ ```
45
+ input {
46
+ stdin {
47
+ codec => json_lines
48
+ }
49
+ }
50
+
51
+ output {
52
+ azuresearch {
53
+ endpoint => "https://<YOUR ACCOUNT>.search.windows.net"
54
+ api_key => "<AZURESEARCH API KEY>"
55
+ search_index => "<SEARCH INDEX NAME>"
56
+ column_names => ['id','user_name','message','created_at']
57
+ key_names => ['postid','user','content','posttime']
58
+ flush_items => 100
59
+ flush_interval_time => 5
60
+ }
61
+ }
62
+ ```
63
+ You can find example configuration files in logstash-output-azuresearch/examples.
64
+
65
+ ### Run the plugin with the example configuration
66
+
67
+ Now you run logstash with the the example configuration like this:
68
+ ```
69
+ # Test your logstash configuration before actually running the logstash
70
+ bin/logstash -f logstash-stdin-json-to-azuresearch.conf --configtest
71
+ # run
72
+ bin/logstash -f logstash-stdin-json-to-azuresearch.conf
73
+ ```
74
+
75
+ Here is an expected output for sample input (JSON Lines):
76
+
77
+ <u>JSON Lines</u>
78
+ ```
79
+ { "id": "a001", "user_name": "user001", "message":"msg001", "created_at":"2016-12-28T00:01:00Z" },
80
+ { "id": "a002", "user_name": "user002", "message":"msg002", "created_at":"2016-12-28T00:02:00Z" },
81
+ { "id": "a003", "user_name": "user003", "message":"msg003", "created_at":"2016-12-28T00:03:00Z" },
82
+ ```
83
+ <u>Output (Azure Search POST message)</u>
84
+ ```
85
+ "value": [
86
+ { "@search.score": 1, "id": "a001", "user_name": "user001", "message": "msg001", "created_at": "2016-12-28T00:01:00Z" },
87
+ { "@search.score": 1, "id": "a002", "user_name": "user002", "message": "msg002", "created_at": "2016-12-28T00:02:00Z" },
88
+ { "@search.score": 1, "id": "a003", "user_name": "user003", "message": "msg003", "created_at": "2016-12-28T00:03:00Z" }
89
+ ]
90
+ ```
91
+
92
+ ## Contributing
93
+
94
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yokawasa/logstash-output-azuresearch.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.1
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+ require "stud/buffer"
5
+
6
+ class LogStash::Outputs::Azuresearch < LogStash::Outputs::Base
7
+ include Stud::Buffer
8
+
9
+ config_name "azuresearch"
10
+
11
+ # Azure Search Endpoint URL
12
+ config :endpoint, :validate => :string, :required => true
13
+
14
+ # zure Search API key
15
+ config :api_key, :validate => :string, :required => true
16
+
17
+ # Azure Search Index name to insert records
18
+ config :search_index, :validate => :string, :required => true
19
+
20
+ # Column names in a target Azure search index.
21
+ # 1st item in column_names should be primary key
22
+ config :column_names, :validate => :array, :required => true
23
+
24
+ # Key names in incomming record to insert.
25
+ # The number of keys in key_names must be equal to the one of columns in column_names.
26
+ # Also the order or each item in key_names must match the one of each items in column_names.
27
+ config :key_names, :validate => :array, :default => []
28
+
29
+ # Max number of items to buffer before flushing (1 - 1000). Default 50.
30
+ config :flush_items, :validate => :number, :default => 50
31
+
32
+ # Max number of seconds to wait between flushes. Default 5
33
+ config :flush_interval_time, :validate => :number, :default => 5
34
+
35
+
36
+ public
37
+ def register
38
+ require_relative 'azuresearch/client'
39
+
40
+ ## Configure
41
+ if @key_names.length < 1
42
+ @key_names = @column_names
43
+ end
44
+ raise ArgumentError, 'NOT match keys number: column_names and key_names' \
45
+ if @key_names.length != @column_names.length
46
+
47
+ @primary_key_in_event = @key_names[0]
48
+ ## Initialize Azure Search client Instance
49
+ @client=AzureSearch::Client::new( @endpoint, @api_key )
50
+
51
+ buffer_initialize(
52
+ :max_items => @flush_items,
53
+ :max_interval => @flush_interval_time,
54
+ :logger => @logger
55
+ )
56
+
57
+ end # def register
58
+
59
+ public
60
+ def receive(event)
61
+ # Simply save an event for later delivery
62
+ buffer_receive(event)
63
+ end # def event
64
+
65
+ # called from Stud::Buffer#buffer_flush when there are events to flush
66
+ public
67
+ def flush (events, close=false)
68
+
69
+ documents = [] #this is the array of hashes to add Azure search
70
+ events.each do |event|
71
+ document = {}
72
+ event_hash = event.to_hash()
73
+
74
+ ## Check if event contains primary item that should be stored as
75
+ ## primary key in Azure Search
76
+ if not event_hash.include?(@primary_key_in_event)
77
+ $logger.warn( "The event does not contain primary item!!: " + (event_hash.to_json).to_s)
78
+ next
79
+ end
80
+
81
+ @column_names.each_with_index do|k, i|
82
+ ikey = @key_names[i]
83
+ ival = event_hash.include?(ikey) ? event_hash[ikey] : ''
84
+ document[k] = ival
85
+ end
86
+ documents.push(document)
87
+ end
88
+
89
+ ## Skip in case there are no candidate documents to deliver
90
+ if documents.length < 1
91
+ return
92
+ end
93
+
94
+ begin
95
+ @client.add_documents(@search_index, documents)
96
+ rescue RestClient::ExceptionWithResponse => rcex
97
+ exdict = JSON.parse(rcex.response)
98
+ $logger.error("RestClient Error: '#{rcex.response}', data=>" + (documents.to_json).to_s)
99
+ rescue => ex
100
+ $logger.error( "Error: '#{ex}'" + ", data=>" + (documents.to_json).to_s)
101
+ end
102
+
103
+ end # def flush
104
+
105
+ end # class LogStash::Outputs::AzureSearch
@@ -0,0 +1,37 @@
1
+ require_relative 'constants'
2
+
3
+ module AzureSearch
4
+ class Client
5
+ def initialize (api_url, api_key, api_version=AzureSearch::API_VERSION)
6
+ require 'rest-client'
7
+ require 'json'
8
+ @api_url = api_url
9
+ @api_version = api_version
10
+ @headers = {
11
+ 'Content-Type' => "application/json; charset=UTF-8",
12
+ 'Api-Key' => api_key,
13
+ 'Accept' => "application/json",
14
+ 'Accept-Charset' => "UTF-8"
15
+ }
16
+ end
17
+
18
+ def add_documents(index_name, documents, merge=true)
19
+ raise ConfigError, 'no index_name' if index_name.empty?
20
+ raise ConfigError, 'no documents' if documents.empty?
21
+ action = merge ? 'mergeOrUpload' : 'upload'
22
+ for document in documents
23
+ document['@search.action'] = action
24
+ end
25
+ req_body = { :value => documents }.to_json
26
+ # p "REQ_BODY= #{req_body}"
27
+ # p "URI= #{@api_url}/indexes/#{index_name}/docs/index?api-version=#{@api_version}"
28
+ res = RestClient.post(
29
+ "#{@api_url}/indexes/#{index_name}/docs/index?api-version=#{@api_version}",
30
+ req_body,
31
+ @headers)
32
+ res
33
+ end
34
+
35
+ end
36
+ end
37
+
@@ -0,0 +1,5 @@
1
+ module AzureSearch
2
+ API_VERSION = '2015-02-28'.freeze
3
+ MAX_DOCS_PER_INDEX_UPLOAD = 1000.freeze
4
+ end
5
+
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'mrcooper-logstash-output-azuresearch'
3
+ s.version = File.read("VERSION").strip
4
+ s.authors = ["Yoichi Kawasaki", "Dwight Spencer"]
5
+ s.email = "dwightaspencer@gmail.com"
6
+ s.summary = %q{logstash output plugin to store events into Azure Search}
7
+ s.description = s.summary
8
+ s.homepage = "http://github.com/denzuko/logstash-output-azuresearch"
9
+ s.licenses = ["Apache License (2.0)"]
10
+ s.require_paths = ["lib"]
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT', 'VERSION']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
19
+
20
+ # Gem dependencies
21
+ s.add_runtime_dependency "rest-client", "1.8.0"
22
+ s.add_runtime_dependency "logstash-core", ">= 2.0.0", "< 3.0.0"
23
+ s.add_runtime_dependency "logstash-codec-plain", "~> 0"
24
+ s.add_development_dependency "logstash-devutils", "~> 0"
25
+
26
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/outputs/azuresearch"
4
+ require "logstash/codecs/plain"
5
+ require "logstash/event"
6
+
7
+ describe LogStash::Outputs::Azuresearch do
8
+
9
+ let(:endpoint) { 'https://<YOUR ACCOUNT>.search.windows.net' }
10
+ let(:api_key) { '<AZURESEARCH API KEY>' }
11
+ let(:search_index) { '<SEARCH INDEX NAME>' }
12
+ let(:column_names) { ['id','user_name','message','created_at'] }
13
+ let(:key_names) { ['postid','user','content','posttime'] }
14
+
15
+ let(:azuresearch_config) {
16
+ {
17
+ "endpoint" => endpoint,
18
+ "api_key" => api_key,
19
+ "search_index" => search_index,
20
+ "column_names" => column_names,
21
+ "key_names" => key_names
22
+ }
23
+ }
24
+
25
+ let(:azuresearch_output) { LogStash::Outputs::Azuresearch.new(azuresearch_config) }
26
+
27
+ before do
28
+ azuresearch_output.register
29
+ end
30
+
31
+ describe "#flush" do
32
+ it "Should successfully send the event to azuresearch" do
33
+ events = []
34
+ properties1 = { "postid" => "a0001", "user" => "foo", "content" => "msg0001", "posttime"=>"2016-12-27T00:01:00Z" }
35
+ properties2 = { "postid" => "a0002", "user" => "bar", "content" => "msg0002", "posttime"=>"2016-12-27T00:02:00Z" }
36
+ event1 = LogStash::Event.new(properties1)
37
+ event2 = LogStash::Event.new(properties2)
38
+ azuresearch_output.receive(event1)
39
+ azuresearch_output.receive(event2)
40
+ events.push(event1)
41
+ events.push(event2)
42
+ expect {azuresearch_output.flush(events)}.to_not raise_error
43
+ end
44
+ end
45
+
46
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mrcooper-logstash-output-azuresearch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Yoichi Kawasaki
8
+ - Dwight Spencer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-05-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '='
19
+ - !ruby/object:Gem::Version
20
+ version: 1.8.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '='
26
+ - !ruby/object:Gem::Version
27
+ version: 1.8.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: logstash-core
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 2.0.0
35
+ - - "<"
36
+ - !ruby/object:Gem::Version
37
+ version: 3.0.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.0.0
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ - !ruby/object:Gem::Dependency
49
+ name: logstash-codec-plain
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: logstash-devutils
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ description: logstash output plugin to store events into Azure Search
77
+ email: dwightaspencer@gmail.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - CHANGELOG.md
83
+ - CONTRIBUTORS
84
+ - Gemfile
85
+ - LICENSE
86
+ - README.md
87
+ - VERSION
88
+ - lib/logstash/outputs/azuresearch.rb
89
+ - lib/logstash/outputs/azuresearch/client.rb
90
+ - lib/logstash/outputs/azuresearch/constants.rb
91
+ - logstash-output-azuresearch.gemspec
92
+ - spec/outputs/azuresearch_spec.rb
93
+ homepage: http://github.com/denzuko/logstash-output-azuresearch
94
+ licenses:
95
+ - Apache License (2.0)
96
+ metadata:
97
+ logstash_plugin: 'true'
98
+ logstash_group: output
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.5.2.1
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: logstash output plugin to store events into Azure Search
119
+ test_files:
120
+ - spec/outputs/azuresearch_spec.rb