ecoportal-api 0.10.2 → 0.10.3

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
  SHA256:
3
- metadata.gz: 4cc0547ca88715ad6b0f2d3bc7ed4661bab0f9259117ce28aa5d43aab0761d02
4
- data.tar.gz: 1e109b427a0e71bd91edf1d4e9ce6e7cf9ac2df998662c97746df30b8e07998b
3
+ metadata.gz: dde26458f8ba991809f2218f6a4594101350f861a811d1bf4c6b508b2194ef67
4
+ data.tar.gz: f9bd67ceaea38ec6ea82d9a53ae0651c36fb7f74e417b37029acd7d72fd00d97
5
5
  SHA512:
6
- metadata.gz: 44eba3743e30beff3c04e71b1191900b8477d81af1371f1a5003cb6847384e384d535e51390e4f8db39e8aa81a0cbf7fc200a87ac18036c45e56530b72b09342
7
- data.tar.gz: 1749045310b0748e8935027cd0d1b9d69e7a84c4534b27017bd1581848d579c6359e59dedfe19e3cbe451038e2a4c70fb82150a01ca4c9260eadde64bfac5a92
6
+ metadata.gz: '09dd4b2cde2bd8f6c6689433c7472fedb6110d076603afcd8edc39f5275aed0296470e57900eaceb335dc875f31554d515925c6b1eae060786a055ac706f6a66'
7
+ data.tar.gz: 3363216e775f38601146617ee80abab13625163c46739f536d77f94c17247fcce139331cad8af02b4cbcc0848a352211a34c476d0d766082e18b5d4b222f43cf
data/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.10.3] - 2024-09-xx
5
+ ## [0.10.4] - 2024-10-xx
6
6
 
7
7
  ### Added
8
8
 
@@ -10,6 +10,14 @@ All notable changes to this project will be documented in this file.
10
10
 
11
11
  ### Fixed
12
12
 
13
+ ## [0.10.3] - 2024-10-01
14
+
15
+ ### Changed
16
+
17
+ - refactored Client
18
+ - initialized with `deep_logging` named argumnet
19
+ - previously `response_logging`
20
+
13
21
  ## [0.10.2] - 2024-09-27
14
22
 
15
23
  ### Added
@@ -4,11 +4,12 @@ module Ecoportal
4
4
  class BatchOperation
5
5
  include Common::DocHelpers
6
6
 
7
- def initialize(base_path, wrapper, logger: nil)
8
- @base_path = base_path
9
- @wrapper = wrapper
10
- @operations = []
11
- @logger = logger
7
+ def initialize(base_path, wrapper, logger: nil, deep_logging: false)
8
+ @base_path = base_path
9
+ @wrapper = wrapper
10
+ @operations = []
11
+ @logger = logger
12
+ @deep_logging = deep_logging
12
13
  end
13
14
 
14
15
  def count
@@ -25,11 +26,12 @@ module Ecoportal
25
26
 
26
27
  def process_response(response)
27
28
  unless response.success?
28
- log(:error) { "Total failure in batch operation." }
29
- raise "Total failure in batch operation"
29
+ msg = "Error: total failure in batch operation."
30
+ log(:debug) { msg }
31
+ raise msg
30
32
  end
31
33
 
32
- log(:info) { "Processing batch responses" }
34
+ log(:debug) { "Processing batch responses" } if deep_logging?
33
35
 
34
36
  body_data(response.body).each.with_index do |subresponse, idx|
35
37
  status = subresponse["status"]
@@ -110,14 +112,19 @@ module Ecoportal
110
112
  end
111
113
 
112
114
  def log_batch_response(operation, response)
113
- log(:info) { "BATCH #{operation[:method]} #{operation[:path]}" }
114
- log(:info) { "Status #{response.status}" }
115
+ return unless deep_logging?
115
116
 
116
- level = response.success?? :debug : :warn
117
- log(level) { "Response: #{JSON.pretty_generate(response.body)}" }
117
+ log(:debug) { "BATCH #{operation[:method]} #{operation[:path]}" }
118
+ log(:debug) { "Status #{response.status}" }
119
+ log(:debug) { "Response: #{JSON.pretty_generate(response.body)}" }
120
+ end
121
+
122
+ def deep_logging?
123
+ @deep_logging
118
124
  end
119
125
 
120
126
  def log(level, &block)
127
+ puts "(#{level}) #{yield}"
121
128
  @logger&.send(level, &block)
122
129
  end
123
130
  end
@@ -0,0 +1,111 @@
1
+ require 'elastic-apm'
2
+ module Ecoportal
3
+ module API
4
+ module Common
5
+ class Client
6
+ module ElasticApmIntegration
7
+ include Ecoportal::API::Common::Client::Error::Checks
8
+
9
+ APM_SERVICE_NAME = 'ecoportal-api-gem'.freeze
10
+
11
+ # Log only errors that are only server's responsibility
12
+ def log_unexpected_server_error(response)
13
+ msg = "Expecting Ecoportal::API::Common::Response. Given: #{response.class}"
14
+ raise msg unless response.is_a?(Common::Response)
15
+
16
+ return unless elastic_apm_service
17
+ return unless unexpected_server_error_code?(response.status)
18
+ return unless ElasticAPM.running?
19
+
20
+ ElasticAPM.report(
21
+ Ecoportal::API::Common::Client::Error::UnexpectedServerError.new(
22
+ response.body,
23
+ code: response.status
24
+ )
25
+ )
26
+ end
27
+
28
+ private
29
+
30
+ # finalizer to stop the agent
31
+ close_elastic_apm = proc do |_id|
32
+ next unless ElasticAPM.running?
33
+
34
+ puts "Stopping ElasticAPM service"
35
+ ElasticAPM.stop
36
+ rescue StandardError
37
+ # Silent
38
+ end
39
+
40
+ ObjectSpace.define_finalizer("ElasticAPM", close_elastic_apm)
41
+
42
+ def elastic_apm_service
43
+ return false if @disable_apm
44
+
45
+ ElasticAPM.start(**elastic_apm_options) unless ElasticAPM.running?
46
+ rescue StandardError => err
47
+ @disable_apm = true
48
+ puts "ElasticAPM services not available: #{err}"
49
+ end
50
+
51
+ def elastic_apm_options
52
+ {
53
+ service_name: APM_SERVICE_NAME,
54
+ server_url: elastic_apm_url,
55
+ secret_token: elastic_apm_key,
56
+ environment: environment,
57
+ # http_compression: false,
58
+ transaction_sample_rate: 0.1,
59
+ transaction_max_spans: 100,
60
+ span_frames_min_duration: "5ms"
61
+ }.tap do |options|
62
+ # next unless false
63
+
64
+ options.merge!({
65
+ log_level: Logger::DEBUG,
66
+ log_path: File.join(__dir__, "elastic_apm.log")
67
+ })
68
+ end
69
+ end
70
+
71
+ def elastic_apm_url
72
+ @elastic_apm_url ||= "https://".tap do |url|
73
+ url << elastic_apm_account_id.to_s
74
+ url << ".#{elastic_apm_base_url}"
75
+ url << ":#{elastic_apm_port}"
76
+ end
77
+ end
78
+
79
+ def elastic_apm_key
80
+ @elastic_apm_key ||= ENV['ELASTIC_APM_KEY']
81
+ end
82
+
83
+ def elastic_apm_account_id
84
+ @elastic_apm_account_id ||= ENV['ELASTIC_APM_ACCOUNT_ID']
85
+ end
86
+
87
+ def elastic_apm_base_url
88
+ @elastic_apm_base_url ||= "apm.#{elastic_apm_region}.aws.cloud.es.io"
89
+ end
90
+
91
+ def elastic_apm_region
92
+ @elastic_apm_region ||= ENV['ELASTIC_APM_REGION'] || "ap-southeast-2"
93
+ end
94
+
95
+ def elastic_apm_port
96
+ @elastic_apm_port ||= ENV['ELASTIC_APM_PORT'] || "443"
97
+ end
98
+
99
+ def environment
100
+ @environment ||= "unknown".tap do |value|
101
+ next unless instance_variable_defined?(:@host)
102
+ next unless (env = @host.gsub(".ecoportal.com", ''))
103
+
104
+ value.clear << env
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,39 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ class Client
5
+ module Error
6
+ module Checks
7
+ private
8
+
9
+ def unexpected_server_error_code?(code)
10
+ return true unless code
11
+ return true if (code >= 500) && (code <= 599)
12
+
13
+ code <= 99
14
+ end
15
+
16
+ # Sometimes response body is wrong but status code
17
+ # doesn't reflect. Let it retry
18
+ def some_unexpected_error?(response)
19
+ return true if unexpected_server_error_code?(response.status)
20
+
21
+ unexpected_body?(response)
22
+ end
23
+
24
+ def unexpected_body?(response)
25
+ response.body.nil?.tap do |wrong|
26
+ next unless wrong
27
+
28
+ msg = "Received non json body in response "
29
+ msg << "(#{response.src_body.class}):\n "
30
+ msg << response.src_body
31
+ puts
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ require 'ecoportal/api/common/client/error/checks'
2
+
3
+ module Ecoportal
4
+ module API
5
+ module Common
6
+ class Client
7
+ module Error
8
+ class UnexpectedServerError < StandardError
9
+ def initialize(msg, code:)
10
+ super("Code: #{code} -- Error: #{msg}")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ class Client
5
+ module TimeOut
6
+ MIN_THROUGHPUT = 0.2 # people per second
7
+ MIN_SIZE = 10
8
+
9
+ private
10
+
11
+ def min_throughput
12
+ self.class::MIN_THROUGHPUT
13
+ end
14
+
15
+ def min_size
16
+ self.class::MIN_SIZE
17
+ end
18
+
19
+ def timeout_for(count)
20
+ count = 1 unless count&.positive?
21
+ count = min_size if count < min_size
22
+ (count.ceil / min_throughput).ceil
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,86 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ class Client
5
+ module WithRetry
6
+ DELAY_REQUEST_RETRY = 5
7
+ RETRY_ATTEMPTS = 5
8
+ HANDLED_CONNECTION_ERRORS = [
9
+ HTTP::ConnectionError,
10
+ IOError
11
+ ].freeze
12
+
13
+ include Ecoportal::API::Common::Client::ElasticApmIntegration
14
+
15
+ private
16
+
17
+ # Helper to ensure unexpected server errors do not bring
18
+ # client scripts immediately down
19
+ # @note it manages limited range of errors, the rest
20
+ # are not handled.
21
+ def with_retry(
22
+ attempts = retry_attemps,
23
+ delay = delay_request_retry,
24
+ error_safe: true,
25
+ &block
26
+ )
27
+ response = nil
28
+
29
+ attempts.times do |i|
30
+ remaining = attempts - i - 1
31
+
32
+ response = with_connection_error_handling(
33
+ remaining,
34
+ error_safe: error_safe,
35
+ callback: block
36
+ ) do
37
+ block.call
38
+ end
39
+
40
+ return response unless some_unexpected_error?(response)
41
+
42
+ # handle server errors (5xx) & server bugs (i.e. empty body)
43
+ msg = "re-attempting (remaining: "
44
+ msg << "#{remaining} attempts out of #{attempts})"
45
+ log(:debug) { msg }
46
+
47
+ log_unexpected_server_error(response)
48
+
49
+ msg = "Got server error (#{response.status}): #{response.body}\n"
50
+ msg << "Going to retry (##{i} of #{attempts})"
51
+ log(:debug) { msg }
52
+
53
+ sleep(delay) if i < attempts
54
+ end
55
+
56
+ response
57
+ end
58
+
59
+ def with_connection_error_handling(remaining, callback:, error_safe: true)
60
+ yield
61
+ rescue *handled_connection_errors => err
62
+ raise unless error_safe && remaining.positive?
63
+
64
+ msg = "Got #{err.class}: #{err.message}"
65
+ log(:debug) { msg }
66
+
67
+ with_retry(remaining, error_safe: error_safe, &callback)
68
+ end
69
+
70
+ # Add here other connection errors
71
+ def handled_connection_errors
72
+ self.class::HANDLED_CONNECTION_ERRORS
73
+ end
74
+
75
+ def retry_attemps
76
+ self.class::RETRY_ATTEMPTS
77
+ end
78
+
79
+ def delay_request_retry
80
+ self.class::DELAY_REQUEST_RETRY
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,4 +1,10 @@
1
1
  require 'http'
2
+
3
+ require 'ecoportal/api/common/client/error'
4
+ require 'ecoportal/api/common/client/elastic_apm_integration'
5
+ require 'ecoportal/api/common/client/time_out'
6
+ require 'ecoportal/api/common/client/with_retry'
7
+
2
8
  module Ecoportal
3
9
  module API
4
10
  module Common
@@ -16,9 +22,7 @@ module Ecoportal
16
22
  # @attr_reader logger [Logger] the logger.
17
23
  # @attr_reader host [String] the remote target server.
18
24
  class Client
19
- include Common::ElasticApmIntegration
20
- DELAY_REQUEST_RETRY = 5
21
- RETRY_ATTEMPTS = 5
25
+ include WithRetry
22
26
 
23
27
  attr_accessor :logger
24
28
  attr_reader :host
@@ -28,40 +32,32 @@ module Ecoportal
28
32
  # @param version [String] it is part of the base url and will determine the api version we query against.
29
33
  # @param host [String] api server domain.
30
34
  # @param logger [Logger] an object with `Logger` interface to generate logs.
31
- # @param response_logging [Boolean] whether or not batch responses should be logged
35
+ # @param deep_logging [Boolean] whether or not batch responses should be logged
32
36
  # @return [Client] an object that holds the configuration of the api connection.
33
- def initialize(api_key:, version: "v1", host: "live.ecoportal.com", logger: nil, response_logging: false)
34
- @version = version
35
- @api_key = api_key
36
- @logger = logger
37
- @host = host
38
- @response_logging_enabled = response_logging
37
+ def initialize(api_key:, version: "v1", host: "live.ecoportal.com", logger: nil, deep_logging: false)
38
+ @version = version
39
+ @api_key = api_key
40
+ @logger = logger
41
+ @host = host
42
+ @deep_logging = deep_logging
39
43
 
40
44
  if host.match(/^localhost|^127\.0\.0\.1/)
41
45
  @base_uri = "http://#{host}/api/"
42
46
  else
43
47
  @base_uri = "https://#{host}/api/"
44
48
  end
45
- log(:info) { "#{version} client initialized pointing at #{host}" }
49
+
50
+ if deep_logging?
51
+ log(:debug) {
52
+ "#{version} client initialized pointing at #{host}"
53
+ }
54
+ end
46
55
 
47
56
  return unless @api_key.nil? || @api_key.match(/\A\W*\z/)
48
57
 
49
58
  log(:error) { "Api-key missing!" }
50
59
  end
51
60
 
52
- # Logger interface.
53
- # @example:
54
- # log(:info) {"General information on what's going on"}
55
- # log(:warn) {"This is a warning that something is likely to have gone amiss"}
56
- # log(:error) {"Something went wrong"}
57
- # log(:fatal) {"An unrecoverable error has happend"}
58
- # @param level [Symbol] the level that the message should be logged.
59
- # @yield [] generates the message.
60
- # @yieldreturn [String] the generated message.
61
- def log(level, &block)
62
- logger&.send(level, &block)
63
- end
64
-
65
61
  # Sends an http `GET` request against the api version using `path` to complete the base url,
66
62
  # and adding the key_value pairs of `params` in the http _header_.
67
63
  # @param path [String] the tail that completes the url of the request.
@@ -152,7 +148,7 @@ module Ecoportal
152
148
  # @param path [String] the tail that completes the url of the request.
153
149
  # @return [String] the final url.
154
150
  def url_for(path)
155
- @base_uri+@version+path
151
+ "#{@base_uri}#{@version}#{path}"
156
152
  end
157
153
 
158
154
  private
@@ -161,71 +157,43 @@ module Ecoportal
161
157
  raise "Expected block" unless block_given?
162
158
 
163
159
  start_time = Time.now.to_f
164
- log(:info) { "#{method} #{url_for(path)}" }
165
- log(:debug) { "Data: #{JSON.pretty_generate(data)}" }
160
+
161
+ if deep_logging?
162
+ log(:debug) { "#{method} #{url_for(path)}" }
163
+ log(:debug) { "Data: #{JSON.pretty_generate(data)}" }
164
+ end
166
165
 
167
166
  with_retry(&block).tap do |result|
167
+ next unless deep_logging?
168
+
168
169
  end_time = Time.now.to_f
169
- log(result.success?? :info : :warn) {
170
+
171
+ log(:debug) {
170
172
  "Took %.2fs, Status #{result.status}" % (end_time - start_time) # rubocop:disable Style/FormatString
171
173
  }
172
174
 
173
- next unless @response_logging_enabled
174
-
175
- log(result.success?? :debug : :warn) {
175
+ log(:debug) {
176
176
  "Response: #{JSON.pretty_generate(result.body)}"
177
177
  }
178
178
  end
179
179
  end
180
180
 
181
- # Helper to ensure unexpected server errors do not bring client scripts immediately down
182
- def with_retry(attempts = RETRY_ATTEMPTS, delay = DELAY_REQUEST_RETRY, error_safe: true, &block)
183
- response = nil
184
- attempts.times do |i|
185
- remaining = attempts - i - 1
186
-
187
- begin
188
- response = block.call
189
- rescue HTTP::ConnectionError => e
190
- raise unless error_safe && remaining.positive?
191
- log(:error) { "Got connection error: #{e.message}" }
192
- response = with_retry(remaining, error_safe: error_safe, &block)
193
- rescue IOError => e
194
- raise unless error_safe && remaining.positive?
195
- log(:error) { "Got IO error: #{e.message}" }
196
- response = with_retry(remaining, error_safe: error_safe, &block)
197
- end
198
-
199
- return response unless some_unexpected_error?(response)
200
-
201
- puts "re-attempting (remaining: #{remaining} attempts out of #{attempts})"
202
-
203
- log_unexpected_server_error(response)
204
-
205
- msg = "Got server error (#{response.status}): #{response.body}\n"
206
- msg += "Going to retry (#{i} out of #{attempts})"
207
- log(:error) { msg }
208
-
209
- sleep(delay) if i < attempts
210
- end
211
- response
212
- end
213
-
214
- # Sometimes response body is wrong but status code
215
- # doesn't reflect. Let it retry
216
- def some_unexpected_error?(response)
217
- unexpected_server_error?(response.status) ||
218
- unexpected_body?(response)
181
+ def deep_logging?
182
+ @deep_logging
219
183
  end
220
184
 
221
- def unexpected_body?(response)
222
- response.body.nil?.tap do |wrong|
223
- next unless wrong
224
-
225
- msg = "Received non json body in response "
226
- msg << "(#{response.src_body.class}):\n #{response.src_body}"
227
- puts
228
- end
185
+ # Logger interface.
186
+ # @example:
187
+ # log(:info) {"General information on what's going on"}
188
+ # log(:warn) {"This is a warning that something is likely to have gone amiss"}
189
+ # log(:error) {"Something went wrong"}
190
+ # log(:fatal) {"An unrecoverable error has happend"}
191
+ # @param level [Symbol] the level that the message should be logged.
192
+ # @yield [] generates the message.
193
+ # @yieldreturn [String] the generated message.
194
+ def log(level, &block)
195
+ puts "(#{level}) #{yield}"
196
+ logger&.send(level, &block)
229
197
  end
230
198
  end
231
199
  end
@@ -10,8 +10,6 @@ require 'ecoportal/api/common/hash_diff'
10
10
  require 'ecoportal/api/common/base_model'
11
11
  require 'ecoportal/api/common/doc_helpers'
12
12
  require 'ecoportal/api/common/logging'
13
- require 'ecoportal/api/common/elastic_apm_integration'
14
- require 'ecoportal/api/common/time_out'
15
13
  require 'ecoportal/api/common/client'
16
14
  require 'ecoportal/api/common/response'
17
15
  require 'ecoportal/api/common/wrapped_response'
@@ -6,7 +6,7 @@ module Ecoportal
6
6
  class People
7
7
  extend Common::BaseClass
8
8
  include Common::DocHelpers
9
- include Common::TimeOut
9
+ include Common::Client::TimeOut
10
10
  include Enumerable
11
11
 
12
12
  DELAY_STATUS_CHECK = 5
@@ -1,5 +1,5 @@
1
1
  module Ecoportal
2
2
  module API
3
- VERSION = '0.10.2'.freeze
3
+ VERSION = '0.10.3'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecoportal-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.10.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tapio Saarinen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-27 00:00:00.000000000 Z
11
+ date: 2024-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -209,12 +209,15 @@ files:
209
209
  - lib/ecoportal/api/common/batch_operation.rb
210
210
  - lib/ecoportal/api/common/batch_response.rb
211
211
  - lib/ecoportal/api/common/client.rb
212
+ - lib/ecoportal/api/common/client/elastic_apm_integration.rb
213
+ - lib/ecoportal/api/common/client/error.rb
214
+ - lib/ecoportal/api/common/client/error/checks.rb
215
+ - lib/ecoportal/api/common/client/time_out.rb
216
+ - lib/ecoportal/api/common/client/with_retry.rb
212
217
  - lib/ecoportal/api/common/doc_helpers.rb
213
- - lib/ecoportal/api/common/elastic_apm_integration.rb
214
218
  - lib/ecoportal/api/common/hash_diff.rb
215
219
  - lib/ecoportal/api/common/logging.rb
216
220
  - lib/ecoportal/api/common/response.rb
217
- - lib/ecoportal/api/common/time_out.rb
218
221
  - lib/ecoportal/api/common/wrapped_response.rb
219
222
  - lib/ecoportal/api/errors.rb
220
223
  - lib/ecoportal/api/errors/base.rb
@@ -1,112 +0,0 @@
1
- require 'elastic-apm'
2
- module Ecoportal
3
- module API
4
- module Common
5
- module ElasticApmIntegration
6
-
7
- class UnexpectedServerError < StandardError
8
- def initialize(code, msg)
9
- super("Code: #{code} -- Error: #{msg}")
10
- end
11
- end
12
-
13
- APM_SERVICE_NAME = 'ecoportal-api-gem'
14
-
15
- # Log only errors that are only server's responsibility
16
- def log_unexpected_server_error(response)
17
- raise "Expecting Ecoportal::API::Common::Response. Given: #{response.class}" unless response.is_a?(Common::Response)
18
- return nil unless elastic_apm_service
19
- return nil unless unexpected_server_error?(response.status)
20
- if ElasticAPM.running?
21
- ElasticAPM.report(UnexpectedServerError.new(response.status, response.body))
22
- end
23
- end
24
-
25
- private
26
-
27
- def unexpected_server_error?(code)
28
- !code || ((code >= 500) && (code <= 599)) || (code <= 99)
29
- end
30
-
31
- # finalizer to stop the agent
32
- close_elastic_apm = Proc.new do |id|
33
- begin
34
- if ElasticAPM.running?
35
- puts "Stopping ElasticAPM service"
36
- ElasticAPM.stop
37
- end
38
- rescue StandardError => e
39
- # Silent
40
- end
41
- end
42
- ObjectSpace.define_finalizer("ElasticAPM", close_elastic_apm)
43
-
44
- def elastic_apm_service
45
- return false if @disable_apm
46
- begin
47
- ElasticAPM.start(**elastic_apm_options) unless ElasticAPM.running?
48
- rescue StandardError => e
49
- @disable_apm = true
50
- puts "ElasticAPM services not available: #{e}"
51
- end
52
- end
53
-
54
- def elastic_apm_options
55
- {
56
- service_name: APM_SERVICE_NAME,
57
- server_url: elastic_apm_url,
58
- secret_token: elastic_apm_key,
59
- environment: environment,
60
- #http_compression: false,
61
- transaction_sample_rate: 0.1,
62
- transaction_max_spans: 100,
63
- span_frames_min_duration: "5ms"
64
- }.tap do |options|
65
- options.merge!({
66
- log_level: Logger::DEBUG,
67
- log_path: File.join(__dir__, "elastic_apm.log")
68
- }) if false
69
- end
70
- end
71
-
72
- def elastic_apm_url
73
- @elastic_apm_url ||= "https://".tap do |url|
74
- url << "#{elastic_apm_account_id}"
75
- url << ".#{elastic_apm_base_url}"
76
- url << ":#{elastic_apm_port}"
77
- end
78
- end
79
-
80
- def elastic_apm_key
81
- @elastic_apm_key ||= ENV['ELASTIC_APM_KEY']
82
- end
83
-
84
- def elastic_apm_account_id
85
- @elastic_apm_account_id ||= ENV['ELASTIC_APM_ACCOUNT_ID']
86
- end
87
-
88
- def elastic_apm_base_url
89
- @elastic_apm_base_url ||= "apm.#{elastic_apm_region}.aws.cloud.es.io"
90
- end
91
-
92
- def elastic_apm_region
93
- @elastic_apm_region ||= ENV['ELASTIC_APM_REGION'] || "ap-southeast-2"
94
- end
95
-
96
-
97
- def elastic_apm_port
98
- @elastic_apm_port ||= ENV['ELASTIC_APM_PORT'] || "443"
99
- end
100
-
101
- def environment
102
- @environment ||= "unknown".tap do |value|
103
- if instance_variable_defined?(:@host) && env = @host.gsub(".ecoportal.com", '')
104
- value.clear << env
105
- end
106
- end
107
- end
108
-
109
- end
110
- end
111
- end
112
- end
@@ -1,26 +0,0 @@
1
- module Ecoportal
2
- module API
3
- module Common
4
- module TimeOut
5
- MIN_THROUGHPUT = 0.2 # people per second
6
- MIN_SIZE = 10
7
-
8
- private
9
-
10
- def min_throughput
11
- self.class::MIN_THROUGHPUT
12
- end
13
-
14
- def min_size
15
- self.class::MIN_SIZE
16
- end
17
-
18
- def timeout_for(count)
19
- count = 1 unless count&.positive?
20
- count = min_size if count < min_size
21
- (count.ceil / min_throughput).ceil
22
- end
23
- end
24
- end
25
- end
26
- end