generik-logstash-input-azureblob 1.0.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
+ SHA1:
3
+ metadata.gz: f5020155403abd1393bc355a70f783a0674f8886
4
+ data.tar.gz: f4df1a5e97fcdd9217653639f162ae2329c9df4f
5
+ SHA512:
6
+ metadata.gz: b6ae69be71131a5798eb142a1e262d39df13faa9183a78263716fa8653f0b1b094e0dfac7cfc44390a241ba5c3883031110c4a823e24704cf69a69399a972be8
7
+ data.tar.gz: 88e0cd67a2d08a24b47f98641e88e25885ce753286f6fe519fccdee74547a4d077b45ea136b97de0d6c399a225356ddfc328525351c0a8caa078f529a55e2d59
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ require "logstash/codecs/base"
3
+ require "logstash/codecs/line"
4
+ require "json"
5
+
6
+ class LogStash::Codecs::JSONList < LogStash::Codecs::Base
7
+ config_name "json_list"
8
+
9
+ milestone 0
10
+
11
+ config :charset, :validate => ::Encoding.name_list, :default => "UTF-8"
12
+
13
+ public
14
+ def register
15
+ end # def register
16
+
17
+ public
18
+ def decode(data)
19
+ begin
20
+ JSON.parse(data).each do |obj|
21
+ yield LogStash::Event.new(obj)
22
+ end
23
+ rescue JSON::ParserError => e
24
+ @logger.info("JSON parse failure. Falling back to plain-text", :error => e, :data => data)
25
+ yield LogStash::Event.new("message" => event["message"])
26
+ end
27
+ end # def decode
28
+
29
+ public
30
+ def encode(data)
31
+ arr = Array.new
32
+ arr << data
33
+ @on_event.call(arr.to_json)
34
+ end # def encode
35
+
36
+ end # class LogStash::Codecs::JSONList
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/namespace"
4
+
5
+ require "azure"
6
+ require "securerandom"
7
+
8
+ # Reads events from Azure Blobs
9
+ class LogStash::Inputs::Azureblob < LogStash::Inputs::Base
10
+
11
+ config_name "azureblob"
12
+ milestone 0
13
+
14
+ default :codec, "json_lines"
15
+
16
+ config :storage_account_name, :validate => :string
17
+ config :storage_access_key, :validate => :string
18
+
19
+ config :container, :validate => :string
20
+ config :sleep_time, :validate => :number, :default => 10
21
+
22
+ def initialize(*args)
23
+ super(*args)
24
+ end # def initialize
25
+
26
+ public
27
+ def register
28
+ Azure.configure do |config|
29
+ config.storage_account_name = @storage_account_name
30
+ config.storage_access_key = @storage_access_key
31
+ end
32
+ @azure_blob = Azure::Blob::BlobService.new
33
+ end # def register
34
+
35
+ def list_blob_names
36
+ blob_names = Set.new []
37
+ loop do
38
+ continuation_token = NIL
39
+ entries = @azure_blob.list_blobs(@container, { :timeout => 10, :marker => continuation_token})
40
+ entries.each do |entry|
41
+ blob_names << entry.name
42
+ end
43
+ continuation_token = entries.continuation_token
44
+ break if continuation_token.empty?
45
+ end
46
+ return blob_names
47
+ end # def list_blobs
48
+
49
+ def acquire_lock(blob_name)
50
+ @azure_blob.create_page_blob(@container, blob_name, 512)
51
+ @azure_blob.acquire_lease(@container, blob_name,{:duration=>60, :timeout=>10, :proposed_lease_id=>SecureRandom.uuid})
52
+ return true
53
+ rescue LogStash::ShutdownSignal => e
54
+ raise e
55
+ rescue => e
56
+ @logger.error("Caught exception while locking", :exception => e)
57
+ return false
58
+ end # def acquire_lock
59
+
60
+ def lock_blob(blob_names)
61
+ real_blob_names = blob_names.select { |name| !name.end_with?(".lock") }
62
+ real_blob_names.each do |blob_name|
63
+ if !blob_names.include?(blob_name + ".lock")
64
+ if acquire_lock(blob_name + ".lock")
65
+ return blob_name
66
+ end
67
+ end
68
+ end
69
+ return NIL
70
+ end # def lock_blob
71
+
72
+ def process(output_queue)
73
+ blob_names = list_blob_names
74
+ blob_name = lock_blob(blob_names)
75
+ return if !blob_name
76
+ blob, content = @azure_blob.get_blob(@container, blob_name)
77
+ @codec.decode(content) do |event|
78
+ output_queue << event
79
+ end
80
+ rescue LogStash::ShutdownSignal => e
81
+ raise e
82
+ rescue => e
83
+ @logger.error("Oh My, An error occurred.", :exception => e)
84
+ end # def process
85
+
86
+ public
87
+ def run(output_queue)
88
+ while true
89
+ process(output_queue)
90
+ end # loop
91
+ end # def run
92
+
93
+ public
94
+ def teardown
95
+ end # def teardown
96
+ end # class LogStash::Inputs::Azuretopic
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/namespace"
4
+
5
+ require "azure"
6
+
7
+ # Reads events from Azure topics
8
+ class LogStash::Inputs::Azuretopic < LogStash::Inputs::Base
9
+ class Interrupted < StandardError; end
10
+
11
+ config_name "azuretopic"
12
+ milestone 0
13
+
14
+ default :codec, "json_list"
15
+
16
+ config :namespace, :validate => :string
17
+ config :access_key, :validate => :string
18
+ config :subscription, :validate => :string
19
+ config :topic, :validate => :string
20
+ config :deliverycount, :validate => :number, :default => 10
21
+
22
+ def initialize(*args)
23
+ super(*args)
24
+ end # def initialize
25
+
26
+ public
27
+ def register
28
+ Azure.configure do |config|
29
+ config.sb_namespace = @namespace
30
+ config.sb_access_key = @access_key
31
+ end
32
+ @azure_service_bus = Azure::ServiceBus::ServiceBusService.new
33
+ end # def register
34
+
35
+ def process(output_queue)
36
+ message = @azure_service_bus.receive_subscription_message(@topic ,@subscription, { :peek_lock => true, :timeout => 1 } )
37
+ if message
38
+ codec.decode(message.body) do |event|
39
+ output_queue << event
40
+ end # codec.decode
41
+ @azure_service_bus.delete_subscription_message(message)
42
+ end
43
+ rescue LogStash::ShutdownSignal => e
44
+ raise e
45
+ rescue => e
46
+ @logger.error("Oh My, An error occurred.", :exception => e)
47
+ if message and message.delivery_count > @deliverycount
48
+ @azure_service_bus.delete_subscription_message(message)
49
+ end
50
+ end # def process
51
+
52
+ public
53
+ def run(output_queue)
54
+ while true
55
+ process(output_queue)
56
+ end # loop
57
+ end # def run
58
+
59
+ public
60
+ def teardown
61
+ end # def teardown
62
+ end # class LogStash::Inputs::Azuretopic
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/namespace"
4
+
5
+ require "thread"
6
+
7
+ require "azure"
8
+
9
+ # Reads events from Azure topics
10
+ class LogStash::Inputs::Azuretopicthreadable < LogStash::Inputs::Base
11
+ class Interrupted < StandardError; end
12
+
13
+ config_name "azuretopicthreadable"
14
+ milestone 0
15
+
16
+ default :codec, "json" # default json codec
17
+
18
+ config :namespace, :validate => :string
19
+ config :access_key, :validate => :string
20
+ config :subscription, :validate => :string
21
+ config :topic, :validate => :string
22
+ config :deliverycount, :validate => :number, :default => 10
23
+ config :threads, :validate => :number, :default => 1
24
+ config :thread_sleep_time, :validate => :number, :default => 1.0/50.0
25
+
26
+ def initialize(*args)
27
+ super(*args)
28
+ end # def initialize
29
+
30
+ public
31
+ def register
32
+ # Configure credentials
33
+ Azure.configure do |config|
34
+ config.sb_namespace = @namespace
35
+ config.sb_access_key = @access_key
36
+ end
37
+ end # def register
38
+
39
+ def process(output_queue, pid)
40
+ # Get a new instance of a service
41
+ azure_service_bus = Azure::ServiceBus::ServiceBusService.new
42
+ while true
43
+ begin
44
+ # check if we have a message in the subscription
45
+ message = azure_service_bus.receive_subscription_message(@topic ,@subscription, { :peek_lock => true, :timeout => 1 } )
46
+ if message
47
+ # decoding returns a yield
48
+ codec.decode(message.body) do |event|
49
+ output_queue << event
50
+ end # codec.decode
51
+ # delete the message after reading it
52
+ azure_service_bus.delete_subscription_message(message)
53
+ end
54
+ rescue LogStash::ShutdownSignal => e
55
+ raise e
56
+ rescue => e
57
+ @logger.error("Oh My, An error occurred. Thread id:" + pid.to_s, :exception => e)
58
+ if message and message.delivery_count > @deliverycount
59
+ azure_service_bus.delete_subscription_message(message)
60
+ end
61
+ end
62
+ sleep(@thread_sleep_time)
63
+ end
64
+ end # def process
65
+
66
+ public
67
+ def run(output_queue)
68
+ threads = []
69
+ (0..(@threads-1)).each do |pid|
70
+ threads << Thread.new { process(output_queue, pid) }
71
+ end
72
+ threads.each { |thr| thr.join }
73
+ end # def run
74
+
75
+ public
76
+ def teardown
77
+ end # def teardown
78
+ end # class LogStash::Inputs::Azuretopic
@@ -0,0 +1,132 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/namespace"
4
+
5
+ require "azure"
6
+
7
+ class LogStash::Inputs::AzureWADTable < LogStash::Inputs::Base
8
+ class Interrupted < StandardError; end
9
+
10
+ config_name "azurewadtable"
11
+ milestone 0
12
+
13
+ config :account_name, :validate => :string
14
+ config :access_key, :validate => :string
15
+ config :table_name, :validate => :string
16
+ config :entity_count_to_process, :validate => :string, :default => 100
17
+ config :collection_start_time_utc, :validate => :string, :default => Time.now.utc.iso8601
18
+ config :etw_pretty_print, :validate => :boolean, :default => false
19
+ config :idle_delay_seconds, :validate => :number, :default => 15
20
+
21
+ TICKS_SINCE_EPOCH = Time.utc(0001, 01, 01).to_i * 10000000
22
+
23
+ def initialize(*args)
24
+ super(*args)
25
+ end # initialize
26
+
27
+ public
28
+ def register
29
+ Azure.configure do |config|
30
+ config.storage_account_name = @account_name
31
+ config.storage_access_key = @access_key
32
+ end
33
+ @azure_table_service = Azure::Table::TableService.new
34
+ @last_timestamp = @collection_start_time_utc
35
+ @idle_delay = @idle_delay_seconds
36
+ @continuation_token = nil
37
+ end # register
38
+
39
+ public
40
+ def run(output_queue)
41
+ loop do
42
+ @logger.debug("Starting process method @" + Time.now.to_s);
43
+ process(output_queue)
44
+ @logger.debug("Starting delay of: " + @idle_delay_seconds.to_s + " seconds @" + Time.now.to_s);
45
+ sleep @idle_delay
46
+ end # loop
47
+ end # run
48
+
49
+ public
50
+ def teardown
51
+ end
52
+
53
+ def process(output_queue)
54
+ @logger.debug(@last_timestamp)
55
+ # query data using start_from_time
56
+ query_filter = "(PartitionKey gt '#{partitionkey_from_datetime(@last_timestamp)}')"
57
+ for i in 0..99
58
+ query_filter << " or (PartitionKey gt '#{i.to_s.rjust(19, '0')}___#{partitionkey_from_datetime(@last_timestamp)}' and PartitionKey lt '#{i.to_s.rjust(19, '0')}___9999999999999999999')"
59
+ end # for block
60
+ query_filter = query_filter.gsub('"','')
61
+ @logger.debug("Query filter: " + query_filter)
62
+ query = { :top => @entity_count_to_process, :filter => query_filter, :continuation_token => @continuation_token }
63
+ result = @azure_table_service.query_entities(@table_name, query)
64
+ @continuation_token = result.continuation_token
65
+
66
+ if result and result.length > 0
67
+ result.each do |entity|
68
+ event = LogStash::Event.new(entity.properties)
69
+ event["type"] = @table_name
70
+
71
+ # Help pretty print etw files
72
+ if (@etw_pretty_print && !event["EventMessage"].nil? && !event["Message"].nil?)
73
+ logger.debug("event: " + event.to_s)
74
+ eventMessage = event["EventMessage"].to_s
75
+ message = event["Message"].to_s
76
+ logger.debug("EventMessage: " + eventMessage)
77
+ logger.debug("Message: " + message)
78
+ if (eventMessage.include? "%")
79
+ logger.debug("starting pretty print")
80
+ toReplace = eventMessage.scan(/%\d+/)
81
+ payload = message.scan(/(?<!\\S)([a-zA-Z]+)=(\"[^\"]*\")(?!\\S)/)
82
+ # Split up the format string to seperate all of the numbers
83
+ toReplace.each do |key|
84
+ logger.debug("Replacing key: " + key.to_s)
85
+ index = key.scan(/\d+/).join.to_i
86
+ newValue = payload[index - 1][1]
87
+ logger.debug("New Value: " + newValue)
88
+ eventMessage[key] = newValue
89
+ end
90
+ event["EventMessage"] = eventMessage
91
+ logger.debug("pretty print end. result: " + event["EventMessage"].to_s)
92
+ end
93
+ end
94
+
95
+ output_queue << event
96
+ end # each block
97
+ @idle_delay = 0
98
+ @last_timestamp = result.last.properties["TIMESTAMP"].iso8601 unless @continuation_token
99
+ else
100
+ @logger.debug("No new results found.")
101
+ @idle_delay = @idle_delay_seconds
102
+ end # if block
103
+
104
+ rescue => e
105
+ @logger.error("Oh My, An error occurred.", :exception => e)
106
+ raise
107
+ end # process
108
+
109
+ # Windows Azure Diagnostic's algorithm for determining the partition key based on time is as follows:
110
+ # 1. Take time in UTC without seconds.
111
+ # 2. Convert it into .net ticks
112
+ # 3. add a '0' prefix.
113
+ def partitionkey_from_datetime(time_string)
114
+ collection_time = Time.parse(time_string)
115
+ if collection_time
116
+ @logger.debug("collection time parsed successfully #{collection_time}")
117
+ else
118
+ raise(ArgumentError, "Could not parse the time_string")
119
+ end # if else block
120
+
121
+ collection_time -= collection_time.sec
122
+ ticks = to_ticks(collection_time)
123
+ "0#{ticks}"
124
+ end # partitionkey_from_datetime
125
+
126
+ # Convert time to ticks
127
+ def to_ticks(time_to_convert)
128
+ @logger.debug("Converting time to ticks")
129
+ time_to_convert.to_i * 10000000 - TICKS_SINCE_EPOCH
130
+ end # to_ticks
131
+
132
+ end # LogStash::Inputs::AzureWADTable
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: generik-logstash-input-azureblob
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - gongdo
8
+ - Microsoft
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-02-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: logstash-core
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 1.4.0
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.0
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 1.4.0
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.0
34
+ - !ruby/object:Gem::Dependency
35
+ name: logstash-codec-plain
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: stud
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: azure
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: logstash-devutils
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ description: This gem is a logstash plugin in order to use Microsoft Azure as an input
91
+ source.
92
+ email: gongdo@live.com
93
+ executables: []
94
+ extensions: []
95
+ extra_rdoc_files: []
96
+ files:
97
+ - lib/logstash/codecs/json_list.rb
98
+ - lib/logstash/inputs/azureblob.rb
99
+ - lib/logstash/inputs/azuretopic.rb
100
+ - lib/logstash/inputs/azuretopicthreadable.rb
101
+ - lib/logstash/inputs/azurewadtable.rb
102
+ homepage: ''
103
+ licenses:
104
+ - Apache License (2.0)
105
+ metadata:
106
+ logstash_plugin: 'true'
107
+ logstash_group: input
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: Logstash input source from Azure.
128
+ test_files: []