logstash-output-application_insights 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eeff77711bd05c02e3efc1c3a0a7ab7dc40fb109
4
- data.tar.gz: d4e3a91792cccfd42befb748d1dfc0dea6181735
3
+ metadata.gz: 800b0ad22dc672b293d6f6aba51437e0544e919e
4
+ data.tar.gz: 45f3ef6fe212653bb90e92855a3f28ce8b9ee863
5
5
  SHA512:
6
- metadata.gz: bff4c4074ed237dc768c9c69d555eee4241651d240dc69786431f7f24d7ab67487a01c7f209cc51b8d210561bb348f4c2f32c3b183ebf9c7d52bb0f2eb2c7039
7
- data.tar.gz: 18a245f8fd5ecdff45c0efdb6fc73b236d9f89996d711ed8cce63fb9bd2a09e66a0731ec2cea5a8d0a23fb5b4cd02d58ae2cf2fe112b3d14aebd0ca9297759ba
6
+ metadata.gz: 21ed44eca0a8e7fc4ddc0a67e1c08bfef8e98d4531e2b06d73e034009b263058125fa74279c197059535238f7ef9481e0d79cc88070cfc55ba0c6be8fdb3dfd2
7
+ data.tar.gz: 381a07cccf8dcd5d96995229bc0cc87327670fd740f961c5fce1f6a867fc03ea080b562e8b0c171e0f9a00398b348b1a94783272c39e35facee08d4e46eec5db
@@ -59,6 +59,8 @@ class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
59
59
  autoload :Notification_recovery, "logstash/outputs/application_insights/notification_recovery"
60
60
  autoload :Validate_storage, "logstash/outputs/application_insights/validate_storage"
61
61
  autoload :Validate_notification, "logstash/outputs/application_insights/validate_notification"
62
+ autoload :Test_storage, "logstash/outputs/application_insights/test_storage"
63
+ autoload :Test_notification, "logstash/outputs/application_insights/test_notification"
62
64
 
63
65
 
64
66
  autoload :Clients, "logstash/outputs/application_insights/clients"
@@ -304,19 +306,24 @@ class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
304
306
  # set configuration
305
307
  Config.validate_and_adjust_configuration( default_configuration )
306
308
  configuration = Config.current
309
+ masked_configuration = Config.masked_current
307
310
 
308
311
  Multi_io_logger.config( configuration )
309
312
 
310
313
  # be careful don't use here @logger, as it will override Logstash @logger, and may create starnge behaviour
311
314
  @private_logger = configuration[:logger]
312
315
 
313
- @private_logger.info { "configuration: #{configuration}" }
316
+ @private_logger.info { "configuration: #{masked_configuration}" }
314
317
 
315
318
  @telemetry = Telemetry.instance
316
319
  configuration[:telemetry_channel] = @telemetry.telemetry_channel
317
320
 
318
321
  Timer.config( configuration )
319
322
 
323
+ @notification_recovery = Notification_recovery.instance
324
+ @storage_recovery = Storage_recovery.instance
325
+ @shutdown_recovery = Shutdown_recovery.instance
326
+
320
327
  if @validate_notification
321
328
  status = Validate_notification.new.validate
322
329
  raise ConfigurationError, "Failed to access application insights at #{configuration[:application_insights_endpoint]}, due to error #{status[:error].inspect}" unless status[:success]
@@ -329,18 +336,16 @@ class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
329
336
  end
330
337
  end
331
338
 
332
- @notification_recovery = Notification_recovery.instance
333
339
  @notification_recovery.start
334
-
335
- @storage_recovery = Storage_recovery.instance
336
340
  @storage_recovery.start
337
-
338
- @shutdown_recovery = Shutdown_recovery.instance
339
341
  @shutdown_recovery.start
340
342
 
341
343
  @shutdown = Shutdown.instance
342
344
  @channels = Channels.instance
343
345
 
346
+ @shutdown.start
347
+ @channels.start
348
+
344
349
  @storage_cleanup = Storage_cleanup.start
345
350
 
346
351
  @private_logger.info { "plugin registered" }
@@ -349,7 +354,7 @@ class LogStash::Outputs::Application_insights < LogStash::Outputs::Base
349
354
  # @channels.receive( event, encoded_event )
350
355
  # end
351
356
 
352
- @telemetry.track_event { { :name => "register", :properties => configuration } }
357
+ @telemetry.track_event { { :name => "register", :properties => masked_configuration } }
353
358
 
354
359
 
355
360
  return "ok\n"
@@ -203,43 +203,6 @@ class LogStash::Outputs::Application_insights
203
203
  end
204
204
 
205
205
 
206
- def test_storage ( storage_account_name )
207
- @storage_account_name = storage_account_name
208
- @action = :test_storage
209
- @max_tries = 1
210
- @force_client = true # to enable get a client even if all storage_accounts marked dead
211
- @recoverable = [ :invalid_storage_key, :container_exist, :create_container ]
212
- storage_io_block {
213
- if @recovery.nil? || :invalid_storage_key == @recovery
214
- @info = "#{@action} #{@storage_account_name}"
215
- @client.blobClient.create_container( @configuration[:test_storage_container] ) unless @configuration[:disable_blob_upload]
216
- end
217
- }
218
- end
219
-
220
- def test_notification( storage_account_name )
221
- @storage_account_name = storage_account_name
222
- @action = :test_notification
223
- @max_tries = 1
224
- @force_client = true # to enable get a client even if all storage_accounts marked dead
225
- @recoverable = [ :invalid_instrumentation_key, :invalid_table_id ]
226
- success = storage_io_block {
227
- if @recovery.nil?
228
- @container_name = "logstash-test-container"
229
- @blob_name = "logstash-test-blob"
230
- @table_id = GUID_NULL
231
- @instrumentation_key = GUID_NULL
232
- @info = "#{@action}"
233
- set_blob_sas_url
234
- payload = create_payload
235
- post_notification( @client.notifyClient, payload )
236
- end
237
- }
238
- sleep( 30 ) unless success
239
- success
240
- end
241
-
242
-
243
206
  def notify_retry_later
244
207
  if :notify_failed_blob_not_accessible == @recovery
245
208
  @sub_state = @recovery
@@ -36,9 +36,10 @@ class LogStash::Outputs::Application_insights
36
36
  @default_instrumentation_key = configuration[:instrumentation_key]
37
37
  @default_table_id = configuration[:table_id]
38
38
  @tables = configuration[:tables]
39
+ end
39
40
 
41
+ def start
40
42
  @flow_control = Flow_control.instance
41
-
42
43
  # launch tread that forward events from channels to azure storage
43
44
  periodic_forward_events
44
45
  end
@@ -133,6 +134,7 @@ class LogStash::Outputs::Application_insights
133
134
  public
134
135
 
135
136
  @@instance = Channels.new
137
+
136
138
  def self.instance
137
139
  @@instance
138
140
  end
@@ -78,9 +78,10 @@ class LogStash::Outputs::Application_insights
78
78
  @current_storage_account_names = current_storage_account_names
79
79
 
80
80
  Thread.new( storage_account_name ) do |account_name|
81
+ test_storage = Test_storage.new( account_name )
81
82
  loop do
82
83
  sleep( @resurrect_delay )
83
- if Blob.new.test_storage( account_name )
84
+ if test_storage.submit
84
85
  @state_semaphore.synchronize {
85
86
  storage_account = @storage_accounts[account_name]
86
87
  storage_account[:off_reason] = [ ]
@@ -25,11 +25,16 @@ class LogStash::Outputs::Application_insights
25
25
  public
26
26
 
27
27
  @@configuration = {}
28
+ @@masked_configuration = {}
28
29
 
29
30
  def self.current
30
31
  @@configuration
31
32
  end
32
33
 
34
+ def self.masked_current
35
+ @@masked_configuration
36
+ end
37
+
33
38
  def self.validate_and_adjust_configuration ( configuration )
34
39
  configuration.each_pair { |config_name, config_value|
35
40
  raise ConfigurationError, "#{config_name.to_s} must be defined" unless config_value || BOOLEAN_PROPERTIES.include?( config_name )
@@ -46,7 +51,7 @@ class LogStash::Outputs::Application_insights
46
51
 
47
52
  i = 0
48
53
  logger_files.map! do |file_name|
49
- file_name = validate_and_adjust( "#{config_name.to_s}[#{i}]", file_name, String )
54
+ file_name = validate_and_adjust( "#{config_name}[#{i}]", file_name, String )
50
55
  i += 1
51
56
  if "stdout" == file_name.downcase
52
57
  file_name = :stdout
@@ -55,7 +60,11 @@ class LogStash::Outputs::Application_insights
55
60
  file_name = :stderr
56
61
  file = STDERR
57
62
  else
58
- file = ::File.open( file_name, "a+" )
63
+ begin
64
+ file = ::File.open( file_name, "a+" )
65
+ rescue => e
66
+ raise ConfigurationError, "#{config_name}[#{i}] cannot open file #{file_name}, due to error #{e.inspect}"
67
+ end
59
68
  end
60
69
  [ file_name, file ]
61
70
  end
@@ -158,26 +167,26 @@ class LogStash::Outputs::Application_insights
158
167
  when :storage_account_name_key
159
168
  config_value = validate_and_adjust( config_name, config_value, Array )
160
169
  if config_value.empty?
161
- raise ConfigurationError, "#{config_name.to_s} is empty, at least one storage account name should be defined" unless ENV['AZURE_STORAGE_ACCOUNT']
162
- raise ConfigurationError, "#{config_name.to_s} is empty, at least one storage account access key should be defined" unless ENV['AZURE_STORAGE_ACCESS_KEY']
170
+ raise ConfigurationError, "#{config_name} is empty, at least one storage account name should be defined" unless ENV['AZURE_STORAGE_ACCOUNT']
171
+ raise ConfigurationError, "#{config_name} is empty, at least one storage account access key should be defined" unless ENV['AZURE_STORAGE_ACCESS_KEY']
163
172
  config_value = [ ENV['AZURE_STORAGE_ACCOUNT'], ENV['AZURE_STORAGE_ACCESS_KEY'] ]
164
173
  end
165
174
 
166
175
  storage_account_name_key = validate_and_adjust( config_name, config_value, Array, :disallow_empty )
167
176
  unless storage_account_name_key[0].is_a?( Array )
168
- raise ConfigurationError, "#{config_name.to_s} property is empty, should contain at least one pair: account_name, key" unless 2 == storage_account_name_key.length
177
+ raise ConfigurationError, "#{config_name} property is empty, should contain at least one pair: account_name, key" unless 2 == storage_account_name_key.length
169
178
  storage_account_name_key = [ [ storage_account_name_key[0], storage_account_name_key[1] ]]
170
179
  end
171
180
 
172
181
  index = 0
173
182
  storage_account_name_key.map! { |pair|
174
- pair = validate_and_adjust( "#{config_name.to_s}[#{index}]", pair, Array, :disallow_empty )
175
- raise ConfigurationError, "#{config_name.to_s}[#{index}] must have two items" unless 2 == pair.length
183
+ pair = validate_and_adjust( "#{config_name}[#{index}]", pair, Array, :disallow_empty )
184
+ raise ConfigurationError, "#{config_name}[#{index}] must have two items" unless 2 == pair.length
176
185
 
177
186
  ( name, keys ) = pair
178
- name = validate_and_adjust( "#{config_name.to_s}[#{index}]:name", name, String, :disallow_empty )
179
- raise ConfigurationError, "#{config_name.to_s}[#{index}]:name must between 3 to 24 characters" unless (name.length >= 3) && (name.length <= 24)
180
- raise ConfigurationError, "##{config_name.to_s}[#{index}]:name bad format, must have only alphanumeric characters" unless Utils.alphanumeric?( name )
187
+ name = validate_and_adjust( "#{config_name}[#{index}]:name", name, String, :disallow_empty )
188
+ raise ConfigurationError, "#{config_name}[#{index}]:name must between 3 to 24 characters" unless (name.length >= 3) && (name.length <= 24)
189
+ raise ConfigurationError, "##{config_name}[#{index}]:name bad format, must have only alphanumeric characters" unless Utils.alphanumeric?( name )
181
190
 
182
191
  keys = [ keys ] if keys.is_a?( String )
183
192
  keys = validate_and_adjust( "#{config_name}[#{index}]:keys", keys, Array, :disallow_empty )
@@ -207,9 +216,23 @@ class LogStash::Outputs::Application_insights
207
216
  configuration[:state_table_name] = "#{AZURE_STORAGE_TABLE_LOGSTASH_PREFIX}#{configuration[:azure_storage_table_prefix]}#{STATE_TABLE_NAME}"
208
217
  configuration[:test_storage_container] = "#{AZURE_STORAGE_CONTAINER_LOGSTASH_PREFIX}#{configuration[:azure_storage_container_prefix]}-#{STORAGE_TEST_CONTAINER_NAME}"
209
218
  configuration[:partition_key_prefix] = configuration[:azure_storage_blob_prefix].gsub( "/", "" )
219
+
220
+ @@masked_configuration = mask_configuration( configuration )
221
+
210
222
  @@configuration = configuration
211
223
  end
212
224
 
225
+ def self.mask_configuration ( configuration )
226
+ masked_configuration = configuration.dup
227
+ storage_account_name_key = masked_configuration[:storage_account_name_key]
228
+ masked_storage_account_name_key = storage_account_name_key.map { |pair|
229
+ ( name, keys ) = pair
230
+ masked_keys = keys.map { |key| "*****************" }
231
+ [ name, masked_keys ]
232
+ }
233
+ masked_configuration[:storage_account_name_key] = masked_storage_account_name_key
234
+ masked_configuration
235
+ end
213
236
 
214
237
  def self.symbolize_table_properties ( properties )
215
238
  new_properties = {}
@@ -25,8 +25,7 @@ class LogStash::Outputs::Application_insights
25
25
 
26
26
  def initialize
27
27
  configuration = Config.current
28
- @logger = configuration[:logger]
29
- @storage_account_name_key = configuration[:storage_account_name_key]
28
+ @resurrect_delay = configuration[:resurrect_delay]
30
29
  @queue = Queue.new
31
30
 
32
31
  @closing = nil
@@ -34,6 +33,7 @@ class LogStash::Outputs::Application_insights
34
33
  end
35
34
 
36
35
  def start
36
+ @test_notification = Test_notification.new
37
37
  @thread = recovery_thread
38
38
  end
39
39
 
@@ -88,7 +88,11 @@ class LogStash::Outputs::Application_insights
88
88
  end
89
89
 
90
90
  def state_on? ( blob )
91
- @notification_state_on ||= blob.test_notification( @storage_account_name_key[0][0] )
91
+ return @notification_state_on if @notification_state_on
92
+ @notification_state_on = @test_notification.submit
93
+ return @notification_state_on if @notification_state_on
94
+ sleep( @resurrect_delay )
95
+ @notification_state_on
92
96
  end
93
97
 
94
98
  public
@@ -30,6 +30,9 @@ class LogStash::Outputs::Application_insights
30
30
  @logger_progname = configuration[:logger_progname]
31
31
  @logger = configuration[:logger]
32
32
 
33
+ end
34
+
35
+ def start
33
36
  @state = State.instance
34
37
  @channels = Channels.instance
35
38
  end
@@ -29,14 +29,13 @@ class LogStash::Outputs::Application_insights
29
29
  @storage_account_name_key = configuration[:storage_account_name_key]
30
30
  @partition_key_prefix =configuration[:azure_storage_blob_prefix].gsub( "/", "" )
31
31
 
32
- @storage_recovery = Storage_recovery.instance
33
- @notification_recovery = Notification_recovery.instance
34
-
35
32
  @closing = nil
36
33
  @threads = []
37
34
  end
38
35
 
39
36
  def start
37
+ @storage_recovery = Storage_recovery.instance
38
+ @notification_recovery = Notification_recovery.instance
40
39
  @storage_account_name_key.each do |storage_account_name, storage_account_keys|
41
40
  @threads << recovery_thread( storage_account_name, :uploading)
42
41
  @threads << recovery_thread( storage_account_name, :committed)
@@ -43,11 +43,9 @@ class LogStash::Outputs::Application_insights
43
43
  # super first parameter must be nil. blob first parameter is channel, otherwise it will pass storage_account_name as channel
44
44
  super( nil )
45
45
  @storage_account_name = storage_account_name
46
- configuration = Config.current
47
- @logger = configuration[:logger]
48
- @azure_storage_container_prefix = configuration[:azure_storage_container_prefix]
49
- @retention_time = configuration[:blob_retention_time] + 24 * 60 * 60
50
- @not_notified_container = "#{configuration[:azure_storage_container_prefix]}-#{AZURE_STORAGE_ORPHAN_BLOBS_CONTAINER_NAME}"
46
+ @azure_storage_container_prefix = @configuration[:azure_storage_container_prefix]
47
+ @retention_time = @configuration[:blob_retention_time] + 24 * 60 * 60
48
+ @not_notified_container = "#{@configuration[:azure_storage_container_prefix]}-#{AZURE_STORAGE_ORPHAN_BLOBS_CONTAINER_NAME}"
51
49
  # launch tread that cleans the storage
52
50
  periodic_storage_cleanup
53
51
  end
@@ -99,7 +99,9 @@ class LogStash::Outputs::Application_insights
99
99
  end
100
100
 
101
101
  def flush
102
- @telemetry_channel.flush
102
+ if @enable_telemetry_to_microsoft
103
+ @telemetry_channel.flush
104
+ end
103
105
  end
104
106
 
105
107
  public
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ # ----------------------------------------------------------------------------------
4
+ # Logstash Output Application Insights
5
+ #
6
+ # Copyright (c) Microsoft Corporation
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Licensed under the Apache License, Version 2.0 (the License);
11
+ # you may not use this file except in compliance with the License.
12
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ #
18
+ # See the Apache Version 2.0 License for specific language governing
19
+ # permissions and limitations under the License.
20
+ # ----------------------------------------------------------------------------------
21
+ class LogStash::Outputs::Application_insights
22
+ class Test_notification < Blob
23
+
24
+
25
+ def initialize
26
+ # super first parameter must be nil. blob first parameter is channel, otherwise it will pass storage_account_name as channel
27
+ super( nil )
28
+ @storage_account_name = @configuration[:storage_account_name_key][0][0]
29
+ @action = :test_notification
30
+ @info = "#{@action}"
31
+ @recoverable = [ :invalid_instrumentation_key, :invalid_table_id ]
32
+ @force_client = true # to enable get a client even if all storage_accounts marked dead
33
+ @container_name = "logstash-test-container"
34
+ @blob_name = "logstash-test-blob"
35
+ @table_id = GUID_NULL
36
+ @instrumentation_key = GUID_NULL
37
+ end
38
+
39
+ def submit
40
+ @max_tries = 1
41
+ storage_io_block {
42
+ if @recovery.nil?
43
+ set_blob_sas_url
44
+ payload = create_payload
45
+ post_notification( @client.notifyClient, payload )
46
+ end
47
+ }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ # ----------------------------------------------------------------------------------
4
+ # Logstash Output Application Insights
5
+ #
6
+ # Copyright (c) Microsoft Corporation
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Licensed under the Apache License, Version 2.0 (the License);
11
+ # you may not use this file except in compliance with the License.
12
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ #
18
+ # See the Apache Version 2.0 License for specific language governing
19
+ # permissions and limitations under the License.
20
+ # ----------------------------------------------------------------------------------
21
+ class LogStash::Outputs::Application_insights
22
+ class Test_storage < Blob
23
+
24
+
25
+ def initialize ( storage_account_name )
26
+ # super first parameter must be nil. blob first parameter is channel, otherwise it will pass storage_account_name as channel
27
+ super( nil )
28
+ @storage_account_name = storage_account_name
29
+ @action = :test_storage
30
+ @info = "#{@action} #{@storage_account_name}"
31
+ @recoverable = [ :invalid_storage_key, :container_exist, :create_container ]
32
+ @force_client = true # to enable get a client even if all storage_accounts marked dead
33
+ end
34
+
35
+ def submit
36
+ @max_tries = 1
37
+ storage_io_block {
38
+ if @recovery.nil? || :invalid_storage_key == @recovery
39
+ @client.blobClient.create_container( @configuration[:test_storage_container] ) unless @configuration[:disable_blob_upload]
40
+ end
41
+ }
42
+ end
43
+ end
44
+ end
@@ -20,18 +20,16 @@
20
20
  # ----------------------------------------------------------------------------------
21
21
 
22
22
  class LogStash::Outputs::Application_insights
23
- class Validate_notification < Blob
23
+ class Validate_notification
24
24
 
25
25
  public
26
26
 
27
27
  def initialize
28
- # super first parameter must be nil. blob first parameter is channel, otherwise it will pass storage_account_name as channel
29
- super( nil )
30
- @storage_account_name_key = @configuration[:storage_account_name_key]
28
+ @test_notification = Test_notification.new
31
29
  end
32
30
 
33
31
  def validate
34
- {:success => test_notification( @storage_account_name_key[0][0] ), :error => @last_io_exception }
32
+ {:success => @test_notification.submit, :error => @test_notification.last_io_exception }
35
33
  end
36
34
  end
37
35
  end
@@ -20,20 +20,20 @@
20
20
  # ----------------------------------------------------------------------------------
21
21
 
22
22
  class LogStash::Outputs::Application_insights
23
- class Validate_storage < Blob
23
+ class Validate_storage
24
24
 
25
25
  public
26
26
 
27
27
  def initialize
28
- # super first parameter must be nil. blob first parameter is channel, otherwise it will pass storage_account_name as channel
29
- super( nil )
30
- @storage_account_name_key = @configuration[:storage_account_name_key]
28
+ configuration = Config.current
29
+ @storage_account_name_key = configuration[:storage_account_name_key]
31
30
  end
32
31
 
33
32
  def validate
34
33
  result = {}
35
34
  @storage_account_name_key.each do |storage_account_name, storage_account_keys|
36
- result[storage_account_name] = {:success => test_storage( storage_account_name ), :error => @last_io_exception }
35
+ test_storage = Test_storage.new( storage_account_name )
36
+ result[storage_account_name] = {:success => test_storage.submit, :error => test_storage.last_io_exception }
37
37
  end
38
38
  result
39
39
  end
@@ -20,5 +20,5 @@
20
20
  # ----------------------------------------------------------------------------------
21
21
 
22
22
  # class LogStash::Outputs::Application_insights
23
- APPLICATION_INSIGHTS_VERSION ||= "0.1.5"
23
+ APPLICATION_INSIGHTS_VERSION ||= "0.1.6"
24
24
  # end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-application_insights
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Microsoft Corporation
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-14 00:00:00.000000000 Z
11
+ date: 2016-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +119,8 @@ files:
119
119
  - lib/logstash/outputs/application_insights/storage_recovery.rb
120
120
  - lib/logstash/outputs/application_insights/sub_channel.rb
121
121
  - lib/logstash/outputs/application_insights/telemetry.rb
122
+ - lib/logstash/outputs/application_insights/test_notification.rb
123
+ - lib/logstash/outputs/application_insights/test_storage.rb
122
124
  - lib/logstash/outputs/application_insights/timer.rb
123
125
  - lib/logstash/outputs/application_insights/utils.rb
124
126
  - lib/logstash/outputs/application_insights/validate_notification.rb