logstash-output-application_insights 0.1.3

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.
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