logstash-output-azure_service_bus 0.2.1 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af1daf5ab0f287bfe29993a09437eb840063c5195d5dc9c247985fae757a09bd
4
- data.tar.gz: afb35cc44123159129fc63fe5fcb374c7cb77ac98137b3b2ae0e513e96b12f09
3
+ metadata.gz: 258ba5d4370f9b1553d0742de66e8bb10cc2e685fb451591b02e773e329be171
4
+ data.tar.gz: ce24ff104251bf82c1ffc8107364509e9b06eb5f18e96187b22dcaec80ff71d6
5
5
  SHA512:
6
- metadata.gz: 3727d297acacbee56d2570ac67aca3e05bcc2f677b6ab5ab50c3acfa84aa721c683be70810fdcc26203124d615cbd99e6bb19fc5f1d68d3eccefd859e288d0e9
7
- data.tar.gz: a72b4442be6118a0b933b2d3e9b6736a282e3024f32f00dd9bb4506b6096c02a824777ebe7535340d53eb9c152121b8e9bf2bf70c00d9d5b05b9ccb67307306e
6
+ metadata.gz: fa154761acffb67e497e6705174782d4acc59c72ab702f1b8e1eab08123eaf3530d3aa2cf75cad4a5c5f520b16ee26b0c1433a4290d50e190467151007e3d9c2
7
+ data.tar.gz: dee42c681c9d8fefcad82be870770d61efd7308ec5a49c91f77c57fddb9e9cf6fdfe89e6b73ad8f306ec6039ffd138b33769cbfad848d9ee1812ad051621aa9f
data/README.md CHANGED
@@ -7,7 +7,7 @@ This plugin is hosted on RubyGems.org: [https://rubygems.org/gems/logstash-outpu
7
7
  ## Install
8
8
  To install, use the plugin tool that is part of your Logstash installation:
9
9
  ```
10
- $LOGSTASH_INSTALL/bin/logstash-plugin install logstash-output-azure_service_bus
10
+ $LOGSTASH_PATH/bin/logstash-plugin install logstash-output-azure_service_bus
11
11
  ```
12
12
 
13
13
  ## Pipeline Configuration
@@ -27,17 +27,21 @@ There is one optional setting (`messageid_field`) which sets the Service Bus `Me
27
27
  input { ... }
28
28
  filter {
29
29
  uuid {
30
- target => "uuid"
30
+ target => "[@metadata][uuid]"
31
31
  }
32
32
  }
33
33
  output {
34
34
  azure_service_bus {
35
35
  service_bus_namespace => "service-bus-name"
36
36
  service_bus_entity => "queue-or-topic-name"
37
- messageid_field => "uuid"
37
+ messageid_field => "[@metadata][uuid]"
38
+ }
39
+ elasticsearch {
40
+ ...
41
+ document_id => "%{[@metadata][uuid]}"
38
42
  }
39
43
  }
40
44
  ```
41
45
 
42
- ## Service Bus Configuration
43
- This plugin will retry sending messages if the Service Bus connection times out or returns a bad response. To avoid idempotence issues, you should enable duplicate detection on the destination queue or topic.
46
+ ## Retry
47
+ This plugin will retry sending messages _indefinitely_ if Service Bus times out or returns a [documented bad response](https://docs.microsoft.com/en-us/rest/api/servicebus/send-message-batch#response-codes) (except 400). To avoid idempotence issues, you should enable duplicate detection on the destination queue or topic.
@@ -13,30 +13,33 @@ class LogStash::Outputs::AzureServiceBus < LogStash::Outputs::Base
13
13
  config :messageid_field, :validate => :string
14
14
 
15
15
  def register
16
- retry_options = {
17
- max: 3,
16
+ service_bus_retry_options = {
17
+ max: Float::MAX, # Essentially retries indefinitely
18
18
  interval: 1,
19
19
  interval_randomness: 0.5,
20
20
  backoff_factor: 2,
21
- retry_statuses: [429, 500],
22
21
  exceptions: [Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::RetriableResponse],
23
- methods: %i[get post],
24
- retry_block: ->(env, _options, retries, exception) { @logger.warn("Error (#{exception}) for #{env.method.upcase} #{env.url} - #{retries + 1} retry(s) left") }
22
+ methods: [], # Empty -> all methods
23
+ retry_statuses: [401, 403, 404, 410, 429, 500], # https://docs.microsoft.com/en-us/rest/api/servicebus/send-message-batch#response-codes
24
+ retry_block: lambda do |env, _options, _retries, exception|
25
+ if env.status.nil?
26
+ @logger.warn("Problem (#{exception}) for #{env.method.upcase} #{env.url}")
27
+ else
28
+ @logger.warn("Problem (HTTP #{env.status}) for #{env.method.upcase} #{env.url}")
29
+ end
30
+ end,
31
+ retry_if: lambda do |env, _exc|
32
+ refresh_access_token if env.status == 401
33
+ true # Always retry
34
+ end
25
35
  }
26
- @token_conn = Faraday.new(
27
- url: 'http://169.254.169.254/metadata/identity/oauth2/token',
28
- params: { 'api-version' => '2018-02-01', 'resource' => 'https://servicebus.azure.net/' },
29
- headers: { 'Metadata' => 'true' },
30
- request: { timeout: 4 }
31
- ) do |f|
32
- f.request :retry, retry_options
33
- end
34
36
  @service_bus_conn = Faraday.new(
35
37
  url: "https://#{@service_bus_namespace}.servicebus.windows.net/#{@service_bus_entity}/",
36
38
  request: { timeout: 10 }
37
- ) do |f|
38
- f.request :retry, retry_options
39
+ ) do |conn|
40
+ conn.request :retry, service_bus_retry_options
39
41
  end
42
+ @access_token = ''
40
43
  refresh_access_token
41
44
  end
42
45
 
@@ -59,32 +62,37 @@ class LogStash::Outputs::AzureServiceBus < LogStash::Outputs::Base
59
62
  end
60
63
 
61
64
  def post_messages(messages)
62
- refresh_access_token if access_token_needs_refresh?
63
65
  response = @service_bus_conn.post('messages') do |req|
64
66
  req.body = JSON.generate(messages)
65
67
  req.headers = { 'Authorization' => "Bearer #{@access_token}", 'Content-Type' => 'application/vnd.microsoft.servicebus.json' }
66
68
  end
67
- raise "Error while sending message to Service Bus: HTTP #{response.status}" if response.status != 201
68
-
69
- @logger.debug("Sent #{messages.length} message(s) to Service Bus")
70
- end
71
-
72
- def access_token_needs_refresh?
73
- Time.now.to_i - 60 > @access_token_expiration # Refresh the access token if it will expire within 60 seconds.
69
+ rescue StandardError => e
70
+ # Hopefully we never make it here and "throw away" messages since we have an agressive retry strategy.
71
+ @logger.error("Error (#{e}) while sending message to Service Bus")
72
+ else
73
+ if response.status == 200
74
+ @logger.debug("Sent #{messages.length} message(s) to Service Bus")
75
+ else
76
+ @logger.error("Error while sending message to Service Bus: HTTP #{response.status}")
77
+ end
74
78
  end
75
79
 
76
80
  def refresh_access_token
77
81
  @logger.info('Refreshing Azure access token')
78
82
  begin
79
- response = @token_conn.get
80
- rescue Faraday::ConnectionFailed => e
81
- @logger.error('Unable to connect to the Azure Instance Metadata Service')
82
- raise e
83
+ response = Faraday.get('http://169.254.169.254/metadata/identity/oauth2/token', params: { 'api-version' => '2018-02-01', 'resource' => 'https://servicebus.azure.net/' }) do |req|
84
+ req.headers = { 'Metadata' => 'true' }
85
+ req.options.timeout = 4
86
+ end
87
+ rescue StandardError => e # We just catch everything and move on since @service_bus_conn will handle retries.
88
+ @logger.error("Error while fetching access token: #{e}")
89
+ else
90
+ if response.status == 200
91
+ data = JSON.parse(response.body)
92
+ @access_token = data['access_token']
93
+ else
94
+ @logger.error("HTTP error when fetching access token: #{response.body}")
95
+ end
83
96
  end
84
- raise "Unable to fetch token: #{response.body}" if response.status != 200
85
-
86
- data = JSON.parse(response.body)
87
- @access_token = data['access_token']
88
- @access_token_expiration = data['expires_on'].to_i
89
97
  end
90
98
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-azure_service_bus'
3
- s.version = '0.2.1'
3
+ s.version = '0.3.0'
4
4
  s.licenses = ['Apache-2.0']
5
5
  s.summary = 'Send Logstash messages to Azure Service Bus.'
6
6
  s.homepage = 'https://github.com/gharryg/logstash-output-azure_service_bus'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-azure_service_bus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harrison Golden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-06 00:00:00.000000000 Z
11
+ date: 2022-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement