logstash-output-application_insights 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CONTRIBUTORS +9 -0
  4. data/DEVELOPER.md +0 -0
  5. data/Gemfile +26 -0
  6. data/LICENSE +17 -0
  7. data/README.md +495 -0
  8. data/Rakefile +22 -0
  9. data/lib/logstash/outputs/application_insights.rb +393 -0
  10. data/lib/logstash/outputs/application_insights/blob.rb +923 -0
  11. data/lib/logstash/outputs/application_insights/block.rb +118 -0
  12. data/lib/logstash/outputs/application_insights/channel.rb +259 -0
  13. data/lib/logstash/outputs/application_insights/channels.rb +142 -0
  14. data/lib/logstash/outputs/application_insights/client.rb +110 -0
  15. data/lib/logstash/outputs/application_insights/clients.rb +113 -0
  16. data/lib/logstash/outputs/application_insights/config.rb +341 -0
  17. data/lib/logstash/outputs/application_insights/constants.rb +208 -0
  18. data/lib/logstash/outputs/application_insights/exceptions.rb +55 -0
  19. data/lib/logstash/outputs/application_insights/flow_control.rb +80 -0
  20. data/lib/logstash/outputs/application_insights/multi_io_logger.rb +69 -0
  21. data/lib/logstash/outputs/application_insights/shutdown.rb +96 -0
  22. data/lib/logstash/outputs/application_insights/state.rb +89 -0
  23. data/lib/logstash/outputs/application_insights/storage_cleanup.rb +214 -0
  24. data/lib/logstash/outputs/application_insights/sub_channel.rb +75 -0
  25. data/lib/logstash/outputs/application_insights/telemetry.rb +99 -0
  26. data/lib/logstash/outputs/application_insights/timer.rb +90 -0
  27. data/lib/logstash/outputs/application_insights/utils.rb +139 -0
  28. data/lib/logstash/outputs/application_insights/version.rb +24 -0
  29. data/logstash-output-application-insights.gemspec +50 -0
  30. data/spec/outputs/application_insights_spec.rb +42 -0
  31. metadata +151 -0
@@ -0,0 +1,208 @@
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
+
22
+ class LogStash::Outputs::Application_insights
23
+
24
+ def default_configuration
25
+ {
26
+ :notification_version => @notification_version || DEFAULT_NOTIFICATION_VERSION,
27
+ :event_separator => @event_separator || DEFAULT_EVENT_SEPARATOR,
28
+
29
+ :notification_endpoint => @notification_endpoint || DEFAULT_NOTIFICATION_ENDPOINT,
30
+ :azure_storage_blob_prefix => @azure_storage_blob_prefix || DEFAULT_AZURE_STORAGE_BLOB_PREFIX || Utils.to_storage_name( Socket.gethostname.strip ) || "",
31
+ :azure_storage_container_prefix => @azure_storage_container_prefix || DEFAULT_AZURE_STORAGE_CONTAINER_PREFIX || Utils.to_storage_name( Socket.gethostname.strip ) || "",
32
+ :azure_storage_table_prefix => @azure_storage_table_prefix || DEFAULT_AZURE_STORAGE_TABLE_PREFIX || Utils.to_storage_name( Socket.gethostname.strip ) || "",
33
+ :storage_account_name_key => @storage_account_name_key || [ ],
34
+ :disable_notification => @disable_notification || DEFAULT_DISABLE_NOTIFICATION,
35
+ :disable_blob_upload => @disable_blob_upload || DEFAULT_DISABLE_BLOB_UPLOAD,
36
+ :stop_on_unknown_io_errors => @stop_on_unknown_io_errors || DEFAULT_STOP_ON_UNKNOWN_IO_ERRORS,
37
+ :delete_not_notified_blobs => @delete_not_notified_blobs || DEFAULT_DELETE_NOT_NOTIFIED_BLOBS,
38
+ :save_notified_blobs_records => @save_notified_blobs_records || DEFAULT_SAVE_NOTIFIED_BLOBS_RECORDS,
39
+ :disable_telemetry => @disable_telemetry || DEFAULT_DISABLE_TELEMETRY,
40
+ :disable_cleanup => @disable_cleanup || DEFAULT_DISABLE_CLEANUP,
41
+ :blob_max_bytesize => @blob_max_bytesize || DEFAULT_BLOB_MAX_BYTESIZE,
42
+ :blob_max_events => @blob_max_events || DEFAULT_BLOB_MAX_EVENTS,
43
+ :blob_retention_time => @blob_retention_time || DEFAULT_BLOB_RETENTION_TIME,
44
+ :blob_access_expiry_time => @blob_access_expiry_time || DEFAULT_BLOB_ACCESS_EXPIRY_TIME,
45
+
46
+ :resurrect_delay => @resurrect_delay || DEFAULT_STORAGE_RESURRECT_DELAY,
47
+ :io_retry_delay => @io_retry_delay || DEFAULT_IO_RETRY_DELAY,
48
+ :io_max_retries => @io_max_retries || DEFAULT_IO_MAX_RETRIES,
49
+
50
+ :logger_level => @logger_level || DEFAULT_LOG_LEVEL,
51
+ :logger_files => @logger_files || DEFAULT_LOGGER_FILES,
52
+ :logger_progname => @logger_progname || DEFAULT_LOGGER_PROGNAME,
53
+ :logger_shift_size => @logger_shift_size || DEFAULT_LOGGER_SHIFT_SIZE,
54
+ :logger_shift_age => @logger_shift_age || DEFAULT_LOGGER_SHIFT_AGE,
55
+
56
+ :flow_control_suspend_bytes => @flow_control_suspend_bytes || DEFAULT_FLOW_CONTROL_SUSPEND_BYTES,
57
+ :flow_control_resume_bytes => @flow_control_resume_bytes || DEFAULT_FLOW_CONTROL_RESUME_BYTES,
58
+ :flow_control_delay => @flow_control_delay || DEFAULT_FLOW_CONTROL_DELAY,
59
+
60
+ :ca_file => @ca_file || "",
61
+
62
+ :tables => @tables || { },
63
+ :table_id => @table_id || DEFAULT_TABLE_ID,
64
+ :intrumentation_key => @intrumentation_key || DEFAULT_INSTRUMENTATION_KEY,
65
+ :table_columns => @table_columns,
66
+ :case_insensitive_columns => @case_insensitive_columns || DEFAULT_CASE_INSENSITIVE,
67
+ :serialized_event_field => @serialized_event_field,
68
+ :blob_max_delay => @blob_max_delay || DEFAULT_BLOB_MAX_DELAY,
69
+ :blob_serialization => @blob_serialization || DEFAULT_BLOB_SERIALIZATION,
70
+ :csv_separator => @csv_separator || DEFAULT_CSV_SEPARATOR,
71
+ :csv_default_value => @csv_default_value || DEFAULT_CSV_DEFAULT_VALUE,
72
+
73
+ }
74
+ end
75
+
76
+ BOOLEAN_PROPERTIES = [ :disable_notification, :disable_blob_upload,
77
+ :stop_on_unknown_io_errors, :disable_telemetry,
78
+ :disable_cleanup, :delete_not_notified_blobs,
79
+ :save_notified_blobs_records, :case_insensitive_columns,
80
+ :table_columns, :serialized_event_field ]
81
+
82
+ GUID_NULL = "00000000-0000-0000-0000-000000000000"
83
+ INSTRUMENTATION_KEY_TEMPLATE = "KKKKKKKK-KKKK-KKKK-KKKK-KKKKKKKKKKKK"
84
+ TABLE_ID_TEMPLATE = "SSSSSSSS-SSSS-SSSS-SSSS-SSSSSSSSSSSS"
85
+
86
+ # notification payload constants
87
+ REQUEST_NAME = "Microsoft.ApplicationInsights.OpenSchema"
88
+ BASE_DATA_REQUIRED_VERSION = "2"
89
+ DATA_BASE_TYPE = "OpenSchemaData"
90
+
91
+ # logger constants
92
+ LOGGER_LEVEL_MAP = {:DEBUG => Logger::DEBUG, :INFO => Logger::INFO, :WARN => Logger::WARN, :ERROR => Logger::ERROR, :FATAL => Logger::FATAL, :UNKNOWN => Logger::UNKNOWN}
93
+
94
+ BLOB_BLOCK_MAX_BYTESIZE = 4 * 1024 * 1024 # in bytes - 4 Mega bytes - blob limitation
95
+
96
+ BLOB_MAX_BLOCKS = 50000 # in blocks - 50,0000 blocks - blob limitation
97
+
98
+ MIN_BLOB_MAX_BYTESIZE = BLOB_BLOCK_MAX_BYTESIZE # BLOB_BLOCK_MAX_BYTESIZE
99
+ MAX_BLOB_MAX_BYTESIZE = BLOB_MAX_BLOCKS * BLOB_BLOCK_MAX_BYTESIZE # 192 Giga bytes
100
+
101
+ MIN_BLOB_MAX_EVENTS = 1 # 256 Kilo events
102
+ MAX_BLOB_MAX_EVENTS = 0 # No Limit
103
+
104
+ MIN_BLOB_MAX_DELAY = 1 # in seconds - one second
105
+ MAX_BLOB_MAX_DELAY = 24 * 3600 # in seconds - one day
106
+
107
+ MIN_BLOB_RETENTION_TIME = 60 # in seconds - one minute
108
+ MAX_BLOB_RETENTION_TIME = 60 * 60 * 24 * 365 # in seconds - one year
109
+
110
+ MIN_BLOB_ACCESS_EXPIRY_TIME = 60 # in seconds - one minute
111
+ MAX_BLOB_ACCESS_EXPIRY_TIME = 60 * 60 * 24 * 365 # in seconds - one year
112
+
113
+ MIN_STORAGE_RESURRECT_DELAY = 1 # in seconds - one second
114
+ MAX_STORAGE_RESURRECT_DELAY = 3600 # in seconds - one hour
115
+
116
+ MIN_LOGGER_SHIFT_SIZE = 1024 # in bytes - 1 Kilo bytes
117
+ MAX_LOGGER_SHIFT_SIZE = 1 * 1024 * 1024 * 1024 # in bytes - 1 Giga bytes
118
+
119
+ MIN_LOGGER_SHIFT_AGE = 0 # in retension version - no
120
+ MAX_LOGGER_SHIFT_AGE = 100000 # in retension version - almost limitless
121
+
122
+ MIN_IO_RETRY_DELAY = 0 # in seconds
123
+ MAX_IO_RETRY_DELAY = 300 # in seconds - 5 minutes
124
+
125
+ MIN_IO_MAX_RETRIES = 0
126
+ MAX_IO_MAX_RETRIES = 3
127
+
128
+
129
+ MIN_FLOW_CONTROL_SUSPEND_BYTES = 0 # in bytes,
130
+ MAX_FLOW_CONTROL_SUSPEND_BYTES = 0 # in bytes, 0 means no upper limit
131
+
132
+ MIN_FLOW_CONTROL_RESUME_BYTES = 0 # in bytes
133
+ MAX_FLOW_CONTROL_RESUME_BYTES = 0 # in bytes, 0 means no upper limit
134
+
135
+ MIN_FLOW_CONTROL_DELAY = 0.1 # in seconds, 1 seconds, can be less than 1 seconds, like 0.5, 0.1
136
+ MAX_FLOW_CONTROL_DELAY = 0 # in seconds, 1 seconds, can be less than 1 seconds, like 0.5, 0.1
137
+
138
+ METADATA_FIELD_INSTRUMENTATION_KEY = "[@metadata]intrumentation_key"
139
+ METADATA_FIELD_TABLE_ID = "[@metadata]table_id"
140
+ FIELD_INSTRUMENTATION_KEY = "intrumentation_key"
141
+ FIELD_TABLE_ID = "table_id"
142
+
143
+ STATE_TABLE_NAME = "BlobsState"
144
+
145
+ AZURE_STORAGE_CONTAINER_LOGSTASH_PREFIX = "logstash" # lower case only, dash allowed
146
+ AZURE_STORAGE_BLOB_LOGSTASH_PREFIX = "logstash"
147
+ AZURE_STORAGE_TABLE_LOGSTASH_PREFIX = "Logstash" # case sensitive, no dash
148
+
149
+ AZURE_STORAGE_ORPHAN_BLOBS_CONTAINER_NAME = "orphan-blobs"
150
+ AZURE_STORAGE_NOTIFIED_BLOBS_TABLE_NAME = "orphan-blobs"
151
+
152
+ COLUMN_PROPERTY_NAME = "name"
153
+ COLUMN_PROPERTY_TYPE = "type"
154
+ COLUMN_PROPERTY_DEFAULT = "default"
155
+ VALID_FIELDS_MAP_TYPES = [ "string", "hash", "array", "number", "json", "boolean", "float", "integer", "dynamic", "datetime", "object" ]
156
+
157
+ VALID_LOGGER_SHIFT_AGES = [ "daily", "weekly", "monthly" ]
158
+
159
+ EXT_EVENT_FORMAT_JSON = "json"
160
+ EXT_EVENT_FORMAT_CSV = "csv"
161
+ VALID_EXT_EVENT_FORMAT = [EXT_EVENT_FORMAT_JSON, EXT_EVENT_FORMAT_CSV ]
162
+
163
+ DEFAULT_INSTRUMENTATION_KEY = GUID_NULL
164
+ DEFAULT_TABLE_ID = GUID_NULL
165
+ DEFAULT_EVENT_SEPARATOR = "\r\n"
166
+ DEFAULT_CSV_SEPARATOR = ","
167
+ DEFAULT_CSV_DEFAULT_VALUE = ""
168
+ DEFAULT_AZURE_STORAGE_BLOB_PREFIX = nil
169
+ DEFAULT_AZURE_STORAGE_CONTAINER_PREFIX = nil
170
+ DEFAULT_AZURE_STORAGE_TABLE_PREFIX = nil
171
+ DEFAULT_JSON_EXT = EXT_EVENT_FORMAT_JSON
172
+ DEFAULT_CSV_EXT = EXT_EVENT_FORMAT_CSV
173
+
174
+
175
+ DEFAULT_BLOB_SERIALIZATION = EXT_EVENT_FORMAT_JSON
176
+
177
+ DEFAULT_BLOB_MAX_BYTESIZE = 1 * 1024 * 1024 * 1024
178
+ DEFAULT_BLOB_MAX_EVENTS = 256 * 1024 # 256 Kilo events
179
+
180
+ DEFAULT_BLOB_MAX_DELAY = 60 # in seconds
181
+ DEFAULT_BLOB_RETENTION_TIME = 60 * 60 * 24 * 7 # in seconds - one week
182
+ DEFAULT_BLOB_ACCESS_EXPIRY_TIME = 60 * 60 * 24 * 1 # in seconds - one day
183
+ DEFAULT_STORAGE_RESURRECT_DELAY = 10
184
+ DEFAULT_NOTIFICATION_ENDPOINT = "https://dc.services.visualstudio.com/v2/track"
185
+ DEFAULT_NOTIFICATION_VERSION = 1
186
+ DEFAULT_DISABLE_NOTIFICATION = false
187
+ DEFAULT_DISABLE_BLOB_UPLOAD = false
188
+ DEFAULT_STOP_ON_UNKNOWN_IO_ERRORS = false
189
+ DEFAULT_DISABLE_TELEMETRY = false
190
+ DEFAULT_DISABLE_CLEANUP = false
191
+ DEFAULT_DELETE_NOT_NOTIFIED_BLOBS = false
192
+ DEFAULT_SAVE_NOTIFIED_BLOBS_RECORDS = false
193
+
194
+ DEFAULT_CASE_INSENSITIVE = false
195
+
196
+ DEFAULT_LOGGER_FILES = [ "logstash-output-application-insights.log" ]
197
+ DEFAULT_LOG_LEVEL = "INFO"
198
+ DEFAULT_LOGGER_PROGNAME = "AI"
199
+ DEFAULT_LOGGER_SHIFT_AGE = "daily" # daily back retension
200
+ DEFAULT_LOGGER_SHIFT_SIZE = 1024 * 1024 # in bytes - one Mega bytes
201
+
202
+ DEFAULT_IO_RETRY_DELAY = 10 # in seconds
203
+ DEFAULT_IO_MAX_RETRIES = 2
204
+
205
+ DEFAULT_FLOW_CONTROL_SUSPEND_BYTES = 50 *1024 * 1024 # high water mark, -in bytes, based on my laptop experience, without Java to break to NO MEMORY error
206
+ DEFAULT_FLOW_CONTROL_RESUME_BYTES = 40 *1024 * 1024 # low water mark,
207
+ DEFAULT_FLOW_CONTROL_DELAY = 1 # in seconds, 1 seconds, can be less than 1 seconds, like 0.5, 0.1
208
+ end
@@ -0,0 +1,55 @@
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
+
22
+ class LogStash::Outputs::Application_insights
23
+
24
+ # exception that are handled internally and do NOT cause process to end
25
+ class BlockOverflowError < StandardError
26
+ end
27
+
28
+ class BlockTooSmallError < StandardError
29
+ end
30
+
31
+ class NoChannelError < StandardError
32
+ end
33
+
34
+ class ChannelExistError < StandardError
35
+ end
36
+
37
+ class StorageAccountsOffError < StandardError
38
+ end
39
+
40
+ class UploadRetryError < StandardError
41
+ end
42
+
43
+ class NotRecoverableError < StandardError
44
+ end
45
+
46
+ # exception that cause process to end
47
+ # LogStash::ConfigurationError, "ssl_truststore_location must be set when SSL is enabled"
48
+ # class ConfigurationError < StandardError
49
+ class ConfigurationError < LogStash::ConfigurationError
50
+ end
51
+
52
+ class UnexpectedBranchError < StandardError
53
+ end
54
+
55
+ end
@@ -0,0 +1,80 @@
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
+
22
+ class LogStash::Outputs::Application_insights
23
+ class Flow_control
24
+
25
+ public
26
+
27
+ def initialize
28
+ configuration = Config.current
29
+
30
+ @logger_progname = configuration[:logger_progname]
31
+ @logger = configuration[:logger]
32
+
33
+ @flow_control_suspend_bytes = configuration[:flow_control_suspend_bytes]
34
+ @flow_control_resume_bytes = configuration[:flow_control_resume_bytes]
35
+ @flow_control_delay = configuration[:flow_control_delay]
36
+
37
+ @flow_control_semaphore = Mutex.new
38
+
39
+ @state = State.instance
40
+ end
41
+
42
+
43
+ def pass_or_wait
44
+ bytes_in_memory = @state.bytes_in_memory
45
+ return if bytes_in_memory <= @flow_control_resume_bytes
46
+
47
+ @flow_control_semaphore.synchronize {
48
+ bytes_in_memory = @state.bytes_in_memory
49
+ if bytes_in_memory > @flow_control_suspend_bytes
50
+ display_msg( "suspend receiving event, memory above #{@flow_control_suspend_bytes} bytes, wait till memory below #{@flow_control_resume_bytes} bytes" )
51
+ loop do
52
+ GC.start
53
+ sleep( @flow_control_delay )
54
+ bytes_in_memory = @state.bytes_in_memory
55
+ break if bytes_in_memory <= @flow_control_resume_bytes
56
+ display_msg( "continue to suspend receiving event, memory level #{bytes_in_memory} bytes, wait till memory below #{@flow_control_resume_bytes} bytes " )
57
+ end
58
+ display_msg( "resume receiving event, memory level #{bytes_in_memory}, below #{@flow_control_resume_bytes} bytes" )
59
+ end
60
+ }
61
+ end
62
+
63
+ private
64
+
65
+ def display_msg ( msg )
66
+ puts "+++ #{@logger_progname} #{msg}"
67
+ # @logger.info { "#{msg}" }
68
+ end
69
+
70
+ public
71
+
72
+ @@instance = Flow_control.new
73
+
74
+ def self.instance
75
+ @@instance
76
+ end
77
+
78
+ private_class_method :new
79
+ end
80
+ end
@@ -0,0 +1,69 @@
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
+
22
+ class LogStash::Outputs::Application_insights
23
+ class Multi_io_logger
24
+
25
+ def self.config ( configuration )
26
+ files = configuration[:logger_files].dup
27
+ level = configuration[:logger_level]
28
+ progname = configuration[:logger_progname]
29
+ shift_size = configuration[:logger_shift_size]
30
+ shift_age = configuration[:logger_shift_age]
31
+
32
+ files.rotate! if files.length > 1 && [ :stdout, :stderr ].include?( files[0][0] )
33
+ (name, file) = files.shift || [ :stdout, STDOUT ]
34
+ if [ :stdout, :stderr ].include?( name )
35
+ logger = Logger.new( file )
36
+ else
37
+ begin
38
+ file_renamed = File.rename( name, "#{name}.20160714" )
39
+ file_renamed = File.rename( "#{name}.20160714", name )
40
+ logger = Logger.new( name, shift_age, shift_size )
41
+ rescue
42
+ puts "--- logger do not support log shifting on this OS"
43
+ logger = Logger.new( name )
44
+ end
45
+
46
+ end
47
+ unless files.empty?
48
+ @@targets = files
49
+ logger.formatter = proc do |severity, datetime, progname, msg|
50
+ formatted_msg = "#{severity[0]}, [#{datetime.utc.iso8601(6)} ##{Process.pid}] #{severity} -- #{progname}: #{msg}#{$/}"
51
+ begin
52
+ @@targets.each do |name, t|
53
+ t.write( formatted_msg )
54
+ t.flush
55
+ end
56
+ rescue # ignore errors
57
+ end
58
+ formatted_msg
59
+ end
60
+ end
61
+ logger.progname = progname
62
+ logger.level = ( level unless configuration[:logger_files].empty? ) || Logger::UNKNOWN
63
+ configuration[:logger] = logger
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+
@@ -0,0 +1,96 @@
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
+
22
+ class LogStash::Outputs::Application_insights
23
+ class Shutdown
24
+
25
+ public
26
+
27
+ def initialize
28
+ configuration = Config.current
29
+
30
+ @logger_progname = configuration[:logger_progname]
31
+ @logger = configuration[:logger]
32
+
33
+ @state = State.instance
34
+ @channels = Channels.instance
35
+ end
36
+
37
+ def submit
38
+ display_msg( "start graceful shutdown, flush all events" )
39
+
40
+ # wait for all uploads to finish
41
+ start_bytes_in_memory = @state.bytes_in_memory
42
+ bytes_in_memory = start_bytes_in_memory
43
+ while bytes_in_memory > 0 do
44
+ sleep( 1 )
45
+ bytes_in_memory = @state.bytes_in_memory
46
+ percent = 100 * (1 - ( bytes_in_memory.to_f / start_bytes_in_memory ) )
47
+ display_msg( "#{percent.to_i}% events were uploaded to Azure storage" ) if percent < 100.0
48
+ end
49
+ display_msg( "all events were uploaded to Azure storage" )
50
+
51
+ Blob.close
52
+ @channels.close
53
+
54
+ # wait for all uploads to commit
55
+ start_pending_commits = @state.pending_commits
56
+ pending_commits = start_pending_commits
57
+ while pending_commits > 0 do
58
+ sleep( 1 )
59
+ pending_commits = @state.pending_commits
60
+ percent = 100 * (1 - ( pending_commits.to_f / start_pending_commits ) )
61
+ display_msg( "#{percent.to_i}% events were commited to Azure storage" ) if percent < 100.0
62
+ end
63
+ display_msg( "all events were commited to Azure storage" )
64
+
65
+ # wait for all blobs to be notified
66
+ start_pending_notifications = @state.pending_notifications
67
+ pending_notifications = start_pending_notifications
68
+ while pending_notifications > 0 do
69
+ sleep( 1 )
70
+ pending_notifications = @state.pending_notifications
71
+ percent = 100 * (1 - ( pending_notifications.to_f / start_pending_notifications ) )
72
+ display_msg( "#{percent.to_i}% events were notified to Application Insights Analytics" ) if percent < 100.0
73
+ end
74
+
75
+ # done
76
+ display_msg( "all events were notified to Application Insights Analytics" )
77
+ end
78
+
79
+ private
80
+
81
+ def display_msg ( msg )
82
+ puts "+++ #{@logger_progname} #{msg}"
83
+ # @logger.info { "#{msg}" }
84
+ end
85
+
86
+ public
87
+
88
+ @@instance = Shutdown.new
89
+
90
+ def self.instance
91
+ @@instance
92
+ end
93
+
94
+ private_class_method :new
95
+ end
96
+ end