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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTORS +9 -0
- data/DEVELOPER.md +0 -0
- data/Gemfile +26 -0
- data/LICENSE +17 -0
- data/README.md +495 -0
- data/Rakefile +22 -0
- data/lib/logstash/outputs/application_insights.rb +393 -0
- data/lib/logstash/outputs/application_insights/blob.rb +923 -0
- data/lib/logstash/outputs/application_insights/block.rb +118 -0
- data/lib/logstash/outputs/application_insights/channel.rb +259 -0
- data/lib/logstash/outputs/application_insights/channels.rb +142 -0
- data/lib/logstash/outputs/application_insights/client.rb +110 -0
- data/lib/logstash/outputs/application_insights/clients.rb +113 -0
- data/lib/logstash/outputs/application_insights/config.rb +341 -0
- data/lib/logstash/outputs/application_insights/constants.rb +208 -0
- data/lib/logstash/outputs/application_insights/exceptions.rb +55 -0
- data/lib/logstash/outputs/application_insights/flow_control.rb +80 -0
- data/lib/logstash/outputs/application_insights/multi_io_logger.rb +69 -0
- data/lib/logstash/outputs/application_insights/shutdown.rb +96 -0
- data/lib/logstash/outputs/application_insights/state.rb +89 -0
- data/lib/logstash/outputs/application_insights/storage_cleanup.rb +214 -0
- data/lib/logstash/outputs/application_insights/sub_channel.rb +75 -0
- data/lib/logstash/outputs/application_insights/telemetry.rb +99 -0
- data/lib/logstash/outputs/application_insights/timer.rb +90 -0
- data/lib/logstash/outputs/application_insights/utils.rb +139 -0
- data/lib/logstash/outputs/application_insights/version.rb +24 -0
- data/logstash-output-application-insights.gemspec +50 -0
- data/spec/outputs/application_insights_spec.rb +42 -0
- 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
|