logstash-output-application_insights 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -2
  3. data/lib/logstash/outputs/application_insights.rb +13 -5
  4. data/lib/logstash/outputs/application_insights/blob.rb +27 -381
  5. data/lib/logstash/outputs/application_insights/block.rb +28 -21
  6. data/lib/logstash/outputs/application_insights/channel.rb +143 -48
  7. data/lib/logstash/outputs/application_insights/channels.rb +4 -3
  8. data/lib/logstash/outputs/application_insights/clients.rb +1 -1
  9. data/lib/logstash/outputs/application_insights/config.rb +3 -2
  10. data/lib/logstash/outputs/application_insights/constants.rb +9 -5
  11. data/lib/logstash/outputs/application_insights/context.rb +97 -0
  12. data/lib/logstash/outputs/application_insights/local_file.rb +113 -0
  13. data/lib/logstash/outputs/application_insights/notification.rb +116 -0
  14. data/lib/logstash/outputs/application_insights/notification_recovery.rb +5 -6
  15. data/lib/logstash/outputs/application_insights/shutdown_recovery.rb +3 -2
  16. data/lib/logstash/outputs/application_insights/state_table.rb +108 -0
  17. data/lib/logstash/outputs/application_insights/storage_cleanup.rb +4 -3
  18. data/lib/logstash/outputs/application_insights/storage_recovery.rb +10 -3
  19. data/lib/logstash/outputs/application_insights/test_notification.rb +3 -6
  20. data/lib/logstash/outputs/application_insights/test_storage.rb +1 -1
  21. data/lib/logstash/outputs/application_insights/upload_pipe.rb +285 -0
  22. data/lib/logstash/outputs/application_insights/validate_notification.rb +1 -1
  23. data/lib/logstash/outputs/application_insights/validate_storage.rb +1 -1
  24. data/lib/logstash/outputs/application_insights/version.rb +1 -1
  25. data/logstash-output-application-insights.gemspec +1 -1
  26. metadata +9 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 800b0ad22dc672b293d6f6aba51437e0544e919e
4
- data.tar.gz: 45f3ef6fe212653bb90e92855a3f28ce8b9ee863
3
+ metadata.gz: 3218d55e7606dde93f2414ddaf149afc7793c2ad
4
+ data.tar.gz: 51b48f9e2438b62892070a4a1fc729d59eed4404
5
5
  SHA512:
6
- metadata.gz: 21ed44eca0a8e7fc4ddc0a67e1c08bfef8e98d4531e2b06d73e034009b263058125fa74279c197059535238f7ef9481e0d79cc88070cfc55ba0c6be8fdb3dfd2
7
- data.tar.gz: 381a07cccf8dcd5d96995229bc0cc87327670fd740f961c5fce1f6a867fc03ea080b562e8b0c171e0f9a00398b348b1a94783272c39e35facee08d4e46eec5db
6
+ metadata.gz: 8795709d9c9d9ab0a33b5b2298dfb0d8259cf7c1d10849cbc7074eff14f8d6915b868ca8e9832e17e5aeffb5d1739ac104d2e3fffb6d4f710ca8728117cd5650
7
+ data.tar.gz: 4eaa0df1d5fdf204c667f848c028e4daaa24ed4311bb936c9194f848a5a98362a72cc3b8aa9e70dfadd4fe3dd885ff525dea48d6c34e4d3ea52ff8eed8e6ad37
data/README.md CHANGED
@@ -185,7 +185,7 @@ case_insensitive_columns => true
185
185
  ```
186
186
 
187
187
  ### blob_max_bytesize
188
- Advanced, internal, should not be set. Default 1 GB.
188
+ Advanced, internal, should not be set. Default 4 GB.
189
189
  Azure storage maximum bytesize is 192 GB ( = 50,000 * 4 MB )
190
190
  example:
191
191
  ```ruby
@@ -193,7 +193,7 @@ blob_max_bytesize => 4000000000
193
193
  ```
194
194
 
195
195
  ### blob_max_events
196
- Specifies, maximum number of events in one blob. Default 256,000 events
196
+ Specifies, maximum number of events in one blob. Default 1,000,000 events
197
197
  Setting it too low may improve latency, but will reduce ingestion performance
198
198
  Setting it too high may damage latency up to maximum delay, but ingestion will be more efficient, and load on network will be lower
199
199
  example:
@@ -359,12 +359,20 @@ example:
359
359
  disable_cleanup => true
360
360
  ```
361
361
 
362
+ ### disable_compression
363
+ When set to true, blobs won't be compressed (beware: it will require more storage, more memory and more bandwidth) Default false
364
+ example:
365
+ ```ruby
366
+ disable_compression => true
367
+ ```
368
+
362
369
  ### delete_not_notified_blobs
363
370
  When set to true, not notified blobs are deleted, if not set they are copied to the orphan-blobs container. Default false
364
371
  example:
365
372
  ```ruby
366
373
  delete_not_notified_blobs => true
367
374
  ```
375
+
368
376
  ### validate_notification
369
377
  When set to true, access to application insights will be validated at initialization and if validation fail, logstash process will abort. Default false
370
378
  example:
@@ -44,14 +44,21 @@ require "concurrent" # for atomic and thread safe operations
44
44
  require "logger"
45
45
  require "csv"
46
46
 
47
+ require "zlib"
48
+
47
49
  require "application_insights"
48
50
 
49
51
  class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
50
52
  require "logstash/outputs/application_insights/version"
51
- require "logstash/outputs/application_insights/utils"
52
- require "logstash/outputs/application_insights/constants"
53
- require "logstash/outputs/application_insights/config"
54
- require "logstash/outputs/application_insights/blob"
53
+ autoload :Context, "logstash/outputs/application_insights/context"
54
+ autoload :Local_file, "logstash/outputs/application_insights/local_file"
55
+ require "logstash/outputs/application_insights/utils"
56
+ require "logstash/outputs/application_insights/constants"
57
+ require "logstash/outputs/application_insights/config"
58
+ require "logstash/outputs/application_insights/blob"
59
+ require "logstash/outputs/application_insights/notification"
60
+ require "logstash/outputs/application_insights/upload_pipe"
61
+
55
62
  autoload :Block, "logstash/outputs/application_insights/block"
56
63
  autoload :Storage_cleanup, "logstash/outputs/application_insights/storage_cleanup"
57
64
  autoload :Shutdown_recovery, "logstash/outputs/application_insights/shutdown_recovery"
@@ -296,6 +303,8 @@ class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
296
303
  # and if validation fail, logstash process will abort
297
304
  config :validate_storage, :validate => :boolean
298
305
 
306
+ # When set to true, blobs won't be compressed.
307
+ config :disable_compression, :validate => :boolean
299
308
  public
300
309
 
301
310
  def register
@@ -356,7 +365,6 @@ class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
356
365
 
357
366
  @telemetry.track_event { { :name => "register", :properties => masked_configuration } }
358
367
 
359
-
360
368
  return "ok\n"
361
369
  end # def register
362
370
 
@@ -19,18 +19,7 @@
19
19
  # permissions and limitations under the License.
20
20
  # ----------------------------------------------------------------------------------
21
21
  class LogStash::Outputs::Application_insights
22
- class Blob
23
-
24
- attr_reader :instrumentation_key
25
- attr_reader :table_id
26
- attr_reader :storage_account_name
27
- attr_reader :container_name
28
- attr_reader :blob_name
29
- attr_reader :uploaded_events_count
30
- attr_reader :uploaded_bytesize
31
- attr_reader :oldest_event_time
32
-
33
- attr_reader :io_queue
22
+ class Blob < Context
34
23
 
35
24
  attr_reader :last_io_exception
36
25
 
@@ -46,230 +35,38 @@ class LogStash::Outputs::Application_insights
46
35
  @@closing
47
36
  end
48
37
 
49
- def initialize ( channel = nil, id = nil , no_queue = false )
38
+ def initialize ( tuple = nil )
50
39
  @configuration = Config.current
51
40
  @logger = @configuration[:logger]
52
41
  @storage_recovery = Storage_recovery.instance
53
42
  @notification_recovery = Notification_recovery.instance
54
43
  @max_tries = @configuration[:io_max_retries] + 1
55
44
 
56
- @uploaded_block_ids = [ ]
57
- @uploaded_block_numbers = [ ]
58
- @uploaded_bytesize = 0
59
- @uploaded_events_count = 0
60
- @sub_state = :none
61
-
62
- if channel
63
- @id = id
64
- @instrumentation_key = channel.instrumentation_key
65
- @table_id = channel.table_id
66
- @blob_max_delay = channel.blob_max_delay
67
-
68
- @event_format_ext = channel.event_format_ext
69
-
70
- unless no_queue
71
-
72
- @io_queue = Queue.new
73
- @timer = Timer.new
74
-
75
- # create a thread that handles the IO of the blob
76
- Thread.new do
77
- next_block = nil
78
- loop do
79
- block_to_upload = nil # release reference to resource for GC
80
- block_to_upload = next_block || @io_queue.pop
81
- next_block = nil
82
-
83
- if :trigger == @timer.state
84
- next_block = block_to_upload unless :wakeup == block_to_upload
85
- block_to_upload = :timeout
86
- to_commit = :commit
87
-
88
- elsif :close == block_to_upload
89
- to_commit = :commit
90
-
91
- # ignore :trigger as they are only to casue check timeout
92
- elsif :wakeup == block_to_upload # ignore :wakeup
93
- next
94
-
95
- else
96
- while @io_queue.length > 0
97
- next_block = @io_queue.pop
98
- next if :wakeup == next_block # ignore :wakeup
99
- break if :close == next_block
100
- break if blob_full?( next_block )
101
- break unless block_to_upload.concat( next_block )
102
- next_block = nil
103
- end
104
- end
105
-
106
- unless to_commit
107
- @timer.set( block_to_upload.oldest_event_time + @blob_max_delay, nil ) {|object| @io_queue << :wakeup if 0 == @io_queue.length } if blob_empty?
108
- upload( block_to_upload )
109
- block_to_upload = nil # release reference to resource for GC
110
- to_commit = :commit if blob_full?
111
- end
112
-
113
- if to_commit
114
- commit unless @uploaded_block_ids.empty?
115
- to_commit = nil
116
- @uploaded_block_ids = [ ]
117
- @timer.cancel
118
- break if :close == block_to_upload
119
- end
120
- end
121
- end
122
- end
123
-
124
- end
125
-
126
- end
127
-
128
- # close blob. It will finish whatever was already on the queue, and if necessary commit
129
- # called on shutdown
130
- def close
131
- @io_queue << :close
132
- end
133
-
134
- def blob_full? ( next_block = nil )
135
- if next_block
136
- BLOB_MAX_BLOCKS < @uploaded_block_ids.length + 1 || @configuration[:blob_max_events] < @uploaded_events_count + next_block.events_count || @configuration[:blob_max_bytesize] < @uploaded_bytesize + next_block.bytesize
137
- else
138
- BLOB_MAX_BLOCKS <= @uploaded_block_ids.length || @configuration[:blob_max_events] <= @uploaded_events_count || @configuration[:blob_max_bytesize] <= @uploaded_bytesize
139
- end
140
- end
141
-
142
- def blob_empty?
143
- @uploaded_block_ids.empty?
144
- end
145
-
146
- def queue_empty?
147
- @io_queue.length == 0 if @io_queue
148
- end
149
-
150
-
151
- def queue_size
152
- @io_queue.length
153
- end
154
-
155
- def clear_state
156
- @action = nil
157
- @storage_account_name = nil
158
- @container_name = nil
159
- @blob_name = nil
160
- @uploaded_block_ids = [ ]
161
- @uploaded_block_numbers = [ ]
162
- @uploaded_events_count = 0
163
- @uploaded_bytesize = 0
164
- @oldest_event_time = nil
165
- end
166
-
167
- def table_entity_to_tuple( options = {} )
168
- [ options[:start_time.to_s] || Time.now.utc, options[:action.to_s], options[:instrumentation_key.to_s], options[:table_id.to_s],
169
- options[:storage_account_name.to_s], options[:container_name.to_s], options[:blob_name.to_s],
170
- eval( options[:uploaded_block_ids.to_s] ), eval( options[:uploaded_block_numbers.to_s] ),
171
- options[:uploaded_events_count.to_s] || 0, options[:uploaded_bytesize.to_s] || 0, options[:oldest_event_time.to_s] || Time.now.utc,
172
- options[:event_format_ext.to_s], options[:blob_max_delay.to_s] || 0,
173
- options[:log_state.to_s].to_sym, (options[:sub_state.to_s] || :none).to_sym
174
- ]
175
- end
176
-
177
- def state_to_tuple
178
- [ @start_time || Time.now.utc, @action, @instrumentation_key, @table_id,
179
- @storage_account_name, @container_name, @blob_name,
180
- @uploaded_block_ids, @uploaded_block_numbers,
181
- @uploaded_events_count, @uploaded_bytesize, @oldest_event_time,
182
- @event_format_ext, @blob_max_delay,
183
- @log_state, @sub_state
184
- ]
185
- end
186
-
187
- def tuple_to_state ( tuple )
188
- ( @start_time, @action, @instrumentation_key, @table_id,
189
- @storage_account_name, @container_name, @blob_name,
190
- @uploaded_block_ids, @uploaded_block_numbers,
191
- @uploaded_events_count, @uploaded_bytesize, @oldest_event_time,
192
- @event_format_ext, @blob_max_delay,
193
- @log_state, @sub_state) = tuple
194
- end
195
-
196
- def state_to_table_entity
197
- { :start_time => @start_time, :instrumentation_key => @instrumentation_key, :table_id => @table_id,
198
- :storage_account_name => @storage_account_name, :container_name => @container_name, :blob_name => @blob_name,
199
- :uploaded_block_ids => @uploaded_block_ids.to_s, :uploaded_block_numbers => @uploaded_block_numbers.to_s,
200
- :uploaded_events_count => @uploaded_events_count, :uploaded_bytesize => @uploaded_bytesize, :oldest_event_time => @oldest_event_time,
201
- :log_state => @log_state, :sub_state => @sub_state
202
- }
203
- end
204
-
205
-
206
- def notify_retry_later
207
- if :notify_failed_blob_not_accessible == @recovery
208
- @sub_state = @recovery
209
- @storage_recovery.recover_later( state_to_tuple, :notify, @storage_account_name )
210
- elsif :invalid_instrumentation_key == @recovery || :invalid_table_id == @recovery
211
- @sub_state = @recovery
212
- Channels.instance.channel( @instrumentation_key, @table_id ).failed_on_notify_retry_Q << state_to_tuple
213
-
214
- else
215
- if :notify_failed_blob_not_accessible == @sub_state
216
- @storage_recovery.recover_later( state_to_tuple, :notify, @storage_account_name )
217
- elsif :invalid_instrumentation_key == @sub_state || :invalid_table_id == @sub_state
218
- Channels.instance.channel( @instrumentation_key, @table_id ).failed_on_notify_retry_Q << state_to_tuple
219
- else
220
- @notification_recovery.recover_later( state_to_tuple )
221
- end
222
- end
223
- end
224
-
225
- # must return whether notification was successful or failed
226
- def notify ( tuple = nil )
227
- tuple_to_state( tuple ) if tuple
228
- @action = :notify
229
- @force_client = true # to enable get a client even if all storage_accounts marked dead
230
- @recoverable = [ :notify_failed_blob_not_accessible, :io_failure, :service_unavailable ]
231
- success = storage_io_block {
232
- set_blob_sas_url
233
- payload = create_payload
234
- @logger.debug { "notification payload: #{payload}" }
235
- @info = "#{@action.to_s} #{@storage_account_name}/#{@container_name}/#{@blob_name}, events: #{@uploaded_events_count}, size: #{@uploaded_bytesize}, blocks: #{@uploaded_block_numbers}, delay: #{Time.now.utc - @oldest_event_time}, blob_sas_url: #{@blob_sas_url}"
236
-
237
- # assume that exceptions can be raised due to this method:
238
- post_notification( @client.notifyClient, payload ) unless @configuration[:disable_notification]
239
- @log_state = :notified
240
- }
241
- if success
242
- Telemetry.instance.track_event { { :name => "notified", :properties => state_to_table_entity } }
243
- state_table_update
244
- else
245
- notify_retry_later
246
- end
247
- success
45
+ super( tuple )
248
46
  end
249
47
 
250
48
  CREATE_EXIST_ERRORS = { :container => [ :create_container, :container_exist ], :table => [ :create_table, :table_exist ] }
251
- def create_exist_recovery( type, name = nil )
252
- prev_info = @info
49
+ def create_exist_recovery( type, name )
253
50
  if CREATE_EXIST_ERRORS[type][0] == @recovery
254
- name ||= ( :table == type ? @configuration[:state_table_name] : @container_name )
51
+ @prev_info = @info
255
52
  @info = "create #{type} #{@storage_account_name}/#{name}"
256
53
 
257
54
  # assume that exceptions can be raised due to this method:
258
55
  yield name
259
56
  @logger.info { "Successed to #{@info}" }
260
- @info = prev_info
57
+ @info = @prev_info
261
58
  elsif CREATE_EXIST_ERRORS[type][1] == @recovery
262
59
  @logger.info { "Successed (already exist) to #{@info}" }
263
- @info = prev_info
60
+ @info = @prev_info
264
61
  end
265
62
  end
266
63
 
267
64
  def create_table_exist_recovery
268
- create_exist_recovery( :table ) { |name| @client.tableClient.create_table( name ) }
65
+ create_exist_recovery( :table, @configuration[:state_table_name] ) { |name| @client.tableClient.create_table( name ) }
269
66
  end
270
67
 
271
68
  def create_container_exist_recovery
272
- create_exist_recovery( :container ) { |name| @client.blobClient.create_container( name ) }
69
+ create_exist_recovery( :container, @container_name ) { |name| @client.blobClient.create_container( name ) }
273
70
  end
274
71
 
275
72
  # return true on success
@@ -282,38 +79,36 @@ class LogStash::Outputs::Application_insights
282
79
  if :entity_exist == @recovery
283
80
  raise NotRecoverableError if :uploading == @log_state
284
81
  else
285
- entity_values = state_to_table_entity
82
+ entity_values = context_to_table_entity
286
83
  entity_values[:PartitionKey] = "#{@configuration[:partition_key_prefix]}-#{@log_state}"
287
84
  entity_values[:RowKey] = @blob_name.gsub("/","_")
288
85
  @client.tableClient.insert_entity( @configuration[:state_table_name], entity_values )
289
86
  end
290
87
  }
291
- @storage_recovery.recover_later( state_to_tuple, :state_table_update, @storage_account_name ) unless success || :uploading == @log_state
88
+ @storage_recovery.recover_later( context_to_tuple, :state_table_update, @storage_account_name ) unless success || :uploading == @log_state
292
89
  success
293
90
  end
294
91
 
295
- def state_table_update ( tuple = nil )
296
- tuple_to_state( tuple ) if tuple
92
+ def state_table_update
297
93
  if :uploading == @log_state
298
94
  state_table_delete
299
95
  elsif :committed == @log_state
300
- if state_table_insert && state_table_delete( nil, :uploading )
96
+ if state_table_insert && state_table_delete( :uploading )
301
97
  State.instance.dec_pending_commits
302
98
  State.instance.inc_pending_notifications
303
99
  # this is not a recovery, it is actually enqueue to notify
304
- @notification_recovery.enqueue( state_to_tuple )
100
+ @notification_recovery.enqueue( context_to_tuple )
305
101
  end
306
102
  elsif :notified == @log_state
307
- if (!@configuration[:save_notified_blobs_records] || state_table_insert) && state_table_delete( nil, :committed )
103
+ if (!@configuration[:save_notified_blobs_records] || state_table_insert) && state_table_delete( :committed )
308
104
  State.instance.dec_pending_notifications
309
105
  end
310
106
  end
311
107
  end
312
108
 
313
109
 
314
- # retturn tru on success
315
- def state_table_delete ( tuple = nil, state = nil )
316
- tuple_to_state( tuple ) if tuple
110
+ # return true on success
111
+ def state_table_delete ( state = nil )
317
112
  state ||= @log_state
318
113
  @action = :state_table_delete
319
114
  @recoverable = [ :invalid_storage_key, :io_failure, :service_unavailable, :table_exist, :create_table, :table_busy, :create_resource ]
@@ -327,7 +122,7 @@ class LogStash::Outputs::Application_insights
327
122
  @client.tableClient.delete_entity( @configuration[:state_table_name], "#{@configuration[:partition_key_prefix]}-#{state}", @blob_name.gsub( "/", "_" ) )
328
123
  end
329
124
  }
330
- @storage_recovery.recover_later( state_to_tuple, :state_table_update, @storage_account_name ) unless success
125
+ @storage_recovery.recover_later( context_to_tuple, :state_table_update, @storage_account_name ) unless success
331
126
  success
332
127
  end
333
128
 
@@ -349,109 +144,8 @@ class LogStash::Outputs::Application_insights
349
144
  entities
350
145
  end
351
146
 
352
- def commit ( tuple = nil )
353
- tuple_to_state( tuple ) if tuple
354
-
355
- unless @uploaded_block_ids.empty?
356
- @action = :commit
357
- @recoverable = [ :invalid_storage_key, :io_failure, :service_unavailable ]
358
- success = storage_io_block {
359
- @info = "#{@action.to_s} #{@storage_account_name}/#{@container_name}/#{@blob_name}, events: #{@uploaded_events_count}, size: #{@uploaded_bytesize}, blocks: #{@uploaded_block_numbers}, delay: #{Time.now.utc - @oldest_event_time}"
360
- # assume that exceptions can be raised due to this method:
361
- @client.blobClient.commit_blob_blocks( @container_name, @blob_name, @uploaded_block_ids ) unless @configuration[:disable_blob_upload]
362
- @log_state = :committed
363
- }
364
- if success
365
- # next stage
366
- state_table_update
367
- else
368
- @storage_recovery.recover_later( state_to_tuple, :commit, @storage_account_name )
369
- end
370
- end
371
- end
372
-
373
147
 
374
- def upload_retry_later
375
- unless @uploaded_block_ids.empty?
376
- info1 = "#{:commit} #{@storage_account_name}/#{@container_name}/#{@blob_name}, events: #{@uploaded_events_count}, size: #{@uploaded_bytesize}, blocks: #{@uploaded_block_numbers}, delay: #{Time.now.utc - @oldest_event_time}"
377
- @logger.error { "Pospone to #{info1} (; retry later, error: #{@last_io_exception.inspect}" }
378
- @storage_recovery.recover_later( state_to_tuple, :commit, @storage_account_name )
379
- @uploaded_block_ids = [ ]
380
- end
381
- unless :io_all_dead == @recovery
382
- raise UploadRetryError
383
- else
384
- Channels.instance.channel( @instrumentation_key, @table_id ).failed_on_upload_retry_Q << @block_to_upload
385
- @block_to_upload = nil
386
- end
387
- end
388
-
389
- def upload ( block )
390
- @storage_account_name = nil if @uploaded_block_ids.empty?
391
- @block_to_upload = block
392
- block = nil # remove reference for GC
393
- exclude_storage_account_names = [ ]
394
- begin
395
- if @uploaded_block_ids.empty?
396
- @log_state = :uploading
397
- @uploaded_block_numbers = [ ]
398
- @uploaded_bytesize = 0
399
- @uploaded_events_count = 0
400
- @oldest_event_time = nil
401
-
402
- # remove record of previous upload that failed
403
- if @storage_account_name
404
- exclude_storage_account_names << @storage_account_name
405
- @storage_recovery.recover_later( state_to_tuple, :state_table_update, @storage_account_name )
406
- end
407
- set_conatainer_and_blob_names
408
- @storage_account_name = Clients.instance.get_random_active_storage( exclude_storage_account_names )
409
- unless @storage_account_name
410
- upload_recover.call( :io_all_dead, nil )
411
- return false
412
- end
413
- raise UploadRetryError unless state_table_insert
414
- end
415
-
416
- @action = :upload
417
- @block_info = "blocks: #{@block_to_upload.block_numbers}, events: #{@block_to_upload.events_count}, size: #{@block_to_upload.bytes.length}"
418
- @info = "#{@action} #{@storage_account_name}/#{@container_name}/#{@blob_name}, #{@block_info}, commitId: [\"#{100001 + @uploaded_block_ids.length}\"]"
419
- @recoverable = [ :invalid_storage_key, :invalid_storage_account, :io_failure, :service_unavailable, :container_exist, :create_container ]
420
-
421
- success = storage_io_block {
422
- create_container_exist_recovery
423
- block_id = "#{100001 + @uploaded_block_ids.length}"
424
-
425
- # assume that exceptions can be raised due to this method:
426
- @client.blobClient.put_blob_block( @container_name, @blob_name, block_id, @block_to_upload.bytes ) unless @configuration[:disable_blob_upload]
427
-
428
- # upload success
429
- first_block_in_blob = @uploaded_block_ids.empty?
430
- @uploaded_block_ids << [ block_id ]
431
- @uploaded_block_numbers.concat( @block_to_upload.block_numbers )
432
- @uploaded_bytesize += @block_to_upload.bytes.length
433
- @uploaded_events_count += @block_to_upload.events_count
434
- @oldest_event_time ||= @block_to_upload.oldest_event_time
435
-
436
- # release memory
437
- bytesize = @block_to_upload.bytesize
438
- @block_to_upload.dispose
439
- @block_to_upload = nil
440
- State.instance.inc_pending_commits if first_block_in_blob
441
- State.instance.dec_upload_bytesize( bytesize )
442
- }
443
-
444
- upload_retry_later unless success
445
- rescue UploadRetryError
446
- @recovery = nil
447
- retry
448
- end
449
- end
450
-
451
- def update_commited_or_uncommited_list( table_entity )
452
- tuple = table_entity_to_tuple( table_entity )
453
-
454
- tuple_to_state( tuple )
148
+ def update_commited_or_uncommited_list
455
149
  @action = :list_blob_blocks
456
150
  @recoverable = [ :invalid_storage_key, :io_failure, :service_unavailable, :container_exist, :create_container, :create_blob ]
457
151
  list_blob_blocks = nil
@@ -472,21 +166,20 @@ class LogStash::Outputs::Application_insights
472
166
  @uploaded_block_ids << [ block.name ]
473
167
  @uploaded_bytesize += block.size
474
168
  end
475
- type = ( blocks.empty? || 0 == @uploaded_bytesize ? :upload_empty : blocks[0].type )
169
+ if 0 < @file_size && @uploaded_bytesize != @file_size
170
+ type = :upload_empty
171
+ else
172
+ type = ( blocks.empty? || 0 == @uploaded_bytesize ? :upload_empty : blocks[0].type )
173
+ end
476
174
 
477
175
  @log_state = :committed if :committed == type
478
- { type => state_to_tuple }
176
+ { type => context_to_tuple }
479
177
  else
480
178
  nil
481
179
  end
482
180
  end
483
181
 
484
182
 
485
- def << ( block )
486
- @io_queue << block
487
- end
488
-
489
-
490
183
  private
491
184
 
492
185
 
@@ -509,7 +202,6 @@ class LogStash::Outputs::Application_insights
509
202
  @recovery, reason = recover_retry?( e )
510
203
  retry if @recovery || reason.nil?
511
204
 
512
- puts " +++ recovery: #{@recovery}, reason: #{reason}"
513
205
 
514
206
  @recovery = reason
515
207
  @logger.error { "Failed to #{@info} ; retry later, error: #{e.inspect}" }
@@ -520,6 +212,7 @@ class LogStash::Outputs::Application_insights
520
212
  end
521
213
  end
522
214
 
215
+
523
216
  def error_to_sym ( e )
524
217
  if e.is_a?( Azure::Core::Http::HTTPError )
525
218
  if 404 == e.status_code
@@ -623,7 +316,7 @@ class LogStash::Outputs::Application_insights
623
316
  raise e if @configuration[:stop_on_unknown_io_errors]
624
317
  end
625
318
 
626
- return [recovery, recovery] unless recovery && @recoverable.include?( recovery )
319
+ return [nil, recovery] unless recovery && @recoverable.include?( recovery )
627
320
 
628
321
  case recovery
629
322
  when :container_exist, :table_exist, :entity_exist, :create_container, :create_table
@@ -678,52 +371,5 @@ class LogStash::Outputs::Application_insights
678
371
 
679
372
 
680
373
 
681
- def set_conatainer_and_blob_names
682
- time_utc = Time.now.utc
683
- id = @id.to_s.rjust(4, "0")
684
- strtime = time_utc.strftime( "%F" )
685
- @container_name = "#{AZURE_STORAGE_CONTAINER_LOGSTASH_PREFIX}#{@configuration[:azure_storage_container_prefix]}-#{strtime}"
686
-
687
- strtime = time_utc.strftime( "%F-%H-%M-%S-%L" )
688
- # @blob_name = "#{@configuration[:azure_storage_blob_prefix]}_ikey-#{@instrumentation_key}_table-#{@table_id}_id-#{id}_#{strtime}.#{@event_format_ext}"
689
- @blob_name = "#{AZURE_STORAGE_BLOB_LOGSTASH_PREFIX}#{@configuration[:azure_storage_blob_prefix]}/ikey-#{@instrumentation_key}/table-#{@table_id}/#{strtime}_#{id}.#{@event_format_ext}"
690
- end
691
-
692
-
693
- def create_payload
694
- notification_hash = {
695
- :data => {
696
- :baseType => DATA_BASE_TYPE,
697
- :baseData => {
698
- :ver => BASE_DATA_REQUIRED_VERSION,
699
- :blobSasUri => @blob_sas_url.to_s,
700
- :sourceName => @table_id,
701
- :sourceVersion => @configuration[:notification_version].to_s
702
- }
703
- },
704
- :ver => @configuration[:notification_version],
705
- :name => REQUEST_NAME,
706
- :time => Time.now.utc.iso8601,
707
- :iKey => @instrumentation_key
708
- }
709
- notification_hash.to_json
710
- end
711
-
712
-
713
- def post_notification ( http_client, body )
714
- request = Azure::Core::Http::HttpRequest.new( :post, @configuration[:application_insights_endpoint], { :body => body, :client => http_client } )
715
- request.headers['Content-Type'] = 'application/json; charset=utf-8'
716
- request.headers['Accept'] = 'application/json'
717
- @logger.debug { "send notification : \n endpoint: #{@configuration[:application_insights_endpoint]}\n body : #{body}" }
718
- response = request.call
719
- end
720
-
721
-
722
- def set_blob_sas_url
723
- blob_url ="https://#{@storage_account_name}.blob.core.windows.net/#{@container_name}/#{@blob_name}"
724
- options_and_constrains = {:permissions => "r", :resource => "b", :expiry => ( Time.now.utc + @configuration[:blob_access_expiry_time] ).iso8601 }
725
- @blob_sas_url = @client.storage_auth_sas.signed_uri( URI( blob_url ), options_and_constrains )
726
- end
727
-
728
374
  end
729
375
  end