ecoportal-api 0.10.1 → 0.10.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 +4 -4
- data/.rubocop.yml +7 -0
- data/CHANGELOG.md +30 -6
- data/ecoportal-api.gemspec +19 -10
- data/lib/ecoportal/api/common/batch_operation.rb +23 -12
- data/lib/ecoportal/api/common/client/elastic_apm_integration.rb +111 -0
- data/lib/ecoportal/api/common/client/error/checks.rb +39 -0
- data/lib/ecoportal/api/common/client/error.rb +17 -0
- data/lib/ecoportal/api/common/client/time_out.rb +28 -0
- data/lib/ecoportal/api/common/client/with_retry.rb +86 -0
- data/lib/ecoportal/api/common/client.rb +45 -77
- data/lib/ecoportal/api/common/doc_helpers.rb +1 -1
- data/lib/ecoportal/api/common.rb +0 -1
- data/lib/ecoportal/api/v1/job_status.rb +33 -0
- data/lib/ecoportal/api/v1/people.rb +26 -18
- data/lib/ecoportal/api/v1.rb +1 -0
- data/lib/ecoportal/api/version.rb +1 -1
- metadata +55 -30
- data/lib/ecoportal/api/common/elastic_apm_integration.rb +0 -112
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dde26458f8ba991809f2218f6a4594101350f861a811d1bf4c6b508b2194ef67
|
4
|
+
data.tar.gz: f9bd67ceaea38ec6ea82d9a53ae0651c36fb7f74e417b37029acd7d72fd00d97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09dd4b2cde2bd8f6c6689433c7472fedb6110d076603afcd8edc39f5275aed0296470e57900eaceb335dc875f31554d515925c6b1eae060786a055ac706f6a66'
|
7
|
+
data.tar.gz: 3363216e775f38601146617ee80abab13625163c46739f536d77f94c17247fcce139331cad8af02b4cbcc0848a352211a34c476d0d766082e18b5d4b222f43cf
|
data/.rubocop.yml
CHANGED
@@ -30,6 +30,11 @@ Style/ConditionalAssignment:
|
|
30
30
|
Style/BlockDelimiters:
|
31
31
|
BracesRequiredMethods: ['log']
|
32
32
|
AllowedPatterns: ['proc', 'new']
|
33
|
+
Style/HashSyntax:
|
34
|
+
EnforcedShorthandSyntax: either
|
35
|
+
EnforcedStyle: no_mixed_keys
|
36
|
+
Style/ArgumentsForwarding:
|
37
|
+
UseAnonymousForwarding: false
|
33
38
|
Style/ClassAndModuleChildren:
|
34
39
|
Enabled: false
|
35
40
|
Style/FrozenStringLiteralComment:
|
@@ -93,3 +98,5 @@ Naming/MethodParameterName:
|
|
93
98
|
AllowedNames: ['x', 'y', 'i', 'j', 'id', 'io', 'to']
|
94
99
|
Naming/RescuedExceptionsVariableName:
|
95
100
|
Enabled: false
|
101
|
+
Naming/BlockForwarding:
|
102
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -2,19 +2,45 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
+
## [0.10.4] - 2024-10-xx
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
|
11
|
+
### Fixed
|
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
|
+
|
21
|
+
## [0.10.2] - 2024-09-27
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- `Ecoportal::API::Common::TimeOut` to calculate adaptive time outs.
|
26
|
+
|
27
|
+
### Changed
|
28
|
+
|
29
|
+
- `Ecoportal::API::V1::Person#job`
|
30
|
+
- added **adaptative await**
|
31
|
+
- evaluate `true` to `complete?` if `progress` is that of total count.
|
32
|
+
|
5
33
|
## [0.10.1] - 2024-08-01
|
6
34
|
|
7
35
|
### Added
|
8
36
|
|
9
|
-
- `Ecoportal::V1::Person#brand_id`
|
10
|
-
- `Ecoportal::V1::Person#archived`
|
37
|
+
- `Ecoportal::API::V1::Person#brand_id`
|
38
|
+
- `Ecoportal::API::V1::Person#archived`
|
11
39
|
|
12
40
|
### Changed
|
13
41
|
|
14
42
|
- require `ruby 3`
|
15
43
|
|
16
|
-
### Fixed
|
17
|
-
|
18
44
|
## [0.9.8] - 2024-05-15
|
19
45
|
|
20
46
|
### Added
|
@@ -344,5 +370,3 @@ All notable changes to this project will be documented in this file.
|
|
344
370
|
|
345
371
|
- this `CHANGELOG.md` file
|
346
372
|
- person model: `freemium` core property
|
347
|
-
|
348
|
-
|
data/ecoportal-api.gemspec
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
+
# rubocop:disable Gemspec/DevelopmentDependencies
|
1
2
|
lib = File.expand_path('lib', __dir__)
|
2
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
|
4
|
+
|
5
|
+
require 'ecoportal/api/version'
|
4
6
|
|
5
7
|
Gem::Specification.new do |spec|
|
6
8
|
spec.name = "ecoportal-api"
|
7
9
|
spec.version = Ecoportal::API::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
10
|
+
spec.authors = ['Tapio Saarinen']
|
11
|
+
spec.email = [
|
12
|
+
'tapio@ecoportal.co.nz',
|
13
|
+
'oscar@ecoportal.co.nz'
|
14
|
+
]
|
10
15
|
|
11
16
|
spec.summary = %q{A collection of helpers for interacting with the ecoPortal MS's various APIs}
|
12
17
|
spec.homepage = "https://www.ecoportal.com"
|
@@ -19,17 +24,21 @@ Gem::Specification.new do |spec|
|
|
19
24
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
25
|
f.match(%r{^(test|spec|features)/})
|
21
26
|
end
|
22
|
-
spec.bindir =
|
27
|
+
spec.bindir = 'exe'
|
23
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
-
spec.require_paths = [
|
29
|
+
spec.require_paths = ['lib']
|
25
30
|
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
31
|
+
spec.add_development_dependency 'pry' , '~> 0.14'
|
32
|
+
spec.add_development_dependency 'rake', '>= 13.0.3', '< 14'
|
33
|
+
spec.add_development_dependency 'redcarpet', '>= 3.6.0', '< 4'
|
34
|
+
spec.add_development_dependency 'rspec', '>= 3.12.0', '< 4'
|
35
|
+
spec.add_development_dependency 'rubocop', '~> 1'
|
36
|
+
spec.add_development_dependency 'rubocop-rake', '~> 0'
|
37
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
31
38
|
|
32
39
|
spec.add_dependency 'dotenv', '~> 3'
|
33
40
|
spec.add_dependency 'elastic-apm', '>= 4.7', "< 5"
|
34
41
|
spec.add_dependency 'http', '~> 5.1', "< 6"
|
35
42
|
end
|
43
|
+
|
44
|
+
# rubocop:enable Gemspec/DevelopmentDependencies
|
@@ -4,11 +4,16 @@ module Ecoportal
|
|
4
4
|
class BatchOperation
|
5
5
|
include Common::DocHelpers
|
6
6
|
|
7
|
-
def initialize(base_path, wrapper, logger: nil)
|
8
|
-
@base_path
|
9
|
-
@wrapper
|
10
|
-
@operations
|
11
|
-
@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
|
13
|
+
end
|
14
|
+
|
15
|
+
def count
|
16
|
+
@operations.count
|
12
17
|
end
|
13
18
|
|
14
19
|
def as_json
|
@@ -21,11 +26,12 @@ module Ecoportal
|
|
21
26
|
|
22
27
|
def process_response(response)
|
23
28
|
unless response.success?
|
24
|
-
|
25
|
-
|
29
|
+
msg = "Error: total failure in batch operation."
|
30
|
+
log(:debug) { msg }
|
31
|
+
raise msg
|
26
32
|
end
|
27
33
|
|
28
|
-
log(:
|
34
|
+
log(:debug) { "Processing batch responses" } if deep_logging?
|
29
35
|
|
30
36
|
body_data(response.body).each.with_index do |subresponse, idx|
|
31
37
|
status = subresponse["status"]
|
@@ -106,14 +112,19 @@ module Ecoportal
|
|
106
112
|
end
|
107
113
|
|
108
114
|
def log_batch_response(operation, response)
|
109
|
-
|
110
|
-
|
115
|
+
return unless deep_logging?
|
116
|
+
|
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
|
111
121
|
|
112
|
-
|
113
|
-
|
122
|
+
def deep_logging?
|
123
|
+
@deep_logging
|
114
124
|
end
|
115
125
|
|
116
126
|
def log(level, &block)
|
127
|
+
puts "(#{level}) #{yield}"
|
117
128
|
@logger&.send(level, &block)
|
118
129
|
end
|
119
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
|
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
|
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,
|
34
|
-
@version
|
35
|
-
@api_key
|
36
|
-
@logger
|
37
|
-
@host
|
38
|
-
@
|
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
|
-
|
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
|
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
|
-
|
165
|
-
|
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
|
-
|
170
|
+
|
171
|
+
log(:debug) {
|
170
172
|
"Took %.2fs, Status #{result.status}" % (end_time - start_time) # rubocop:disable Style/FormatString
|
171
173
|
}
|
172
174
|
|
173
|
-
|
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
|
-
|
182
|
-
|
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
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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
|
data/lib/ecoportal/api/common.rb
CHANGED
@@ -10,7 +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
13
|
require 'ecoportal/api/common/client'
|
15
14
|
require 'ecoportal/api/common/response'
|
16
15
|
require 'ecoportal/api/common/wrapped_response'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ecoportal
|
2
|
+
module API
|
3
|
+
class V1
|
4
|
+
class JobStatus
|
5
|
+
attr_reader :id, :progress
|
6
|
+
|
7
|
+
def initialize(id, complete, errored, progress)
|
8
|
+
@id = id
|
9
|
+
@complete = complete
|
10
|
+
@errored = errored
|
11
|
+
@progress = progress
|
12
|
+
end
|
13
|
+
|
14
|
+
def complete?(total = nil)
|
15
|
+
return @complete if total.nil?
|
16
|
+
|
17
|
+
progress >= total
|
18
|
+
end
|
19
|
+
|
20
|
+
def errored?
|
21
|
+
@errored
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
msg = complete? ? "Completed" : "In progress"
|
26
|
+
msg = "Errored" if errored?
|
27
|
+
msg << " with #{progress} done."
|
28
|
+
msg
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -6,9 +6,9 @@ module Ecoportal
|
|
6
6
|
class People
|
7
7
|
extend Common::BaseClass
|
8
8
|
include Common::DocHelpers
|
9
|
+
include Common::Client::TimeOut
|
9
10
|
include Enumerable
|
10
11
|
|
11
|
-
JOB_TIMEOUT = 240
|
12
12
|
DELAY_STATUS_CHECK = 5
|
13
13
|
|
14
14
|
class_resolver :person_class, "Ecoportal::API::V1::Person"
|
@@ -169,15 +169,20 @@ module Ecoportal
|
|
169
169
|
|
170
170
|
yield operation
|
171
171
|
|
172
|
-
|
173
|
-
|
172
|
+
total = operation.count
|
173
|
+
timeout = timeout_for(total)
|
174
174
|
|
175
|
-
|
175
|
+
job_id = create_job(operation)
|
176
|
+
status = wait_for_job_completion(job_id, timeout: timeout, total: total)
|
177
|
+
|
178
|
+
# @todo
|
179
|
+
# if total == status.progress
|
180
|
+
if status&.complete?(total)
|
176
181
|
job_result(job_id, operation)
|
177
182
|
else
|
178
|
-
msg = "Job
|
179
|
-
msg << "Probably timeout after #{
|
180
|
-
msg << "Current status: #{status}"
|
183
|
+
msg = "Job '#{job_id}' not complete (size: #{total}).\n"
|
184
|
+
msg << " Probably timeout after #{timeout} seconds.\n"
|
185
|
+
msg << " Current status: #{status}"
|
181
186
|
|
182
187
|
raise API::Errors::TimeOut, msg
|
183
188
|
end
|
@@ -191,8 +196,6 @@ module Ecoportal
|
|
191
196
|
|
192
197
|
private
|
193
198
|
|
194
|
-
JobStatus = Struct.new(:id, :complete?, :errored?, :progress)
|
195
|
-
|
196
199
|
def job_status(job_id)
|
197
200
|
response = client.get("/people/job/#{CGI.escape(job_id)}/status")
|
198
201
|
body = response && body_data(response.body)
|
@@ -201,12 +204,7 @@ module Ecoportal
|
|
201
204
|
msg << "Errors: #{body}"
|
202
205
|
raise msg unless response.success?
|
203
206
|
|
204
|
-
JobStatus.new(
|
205
|
-
body["id"],
|
206
|
-
body["complete"],
|
207
|
-
body["errored"],
|
208
|
-
body["progress"]
|
209
|
-
)
|
207
|
+
JobStatus.new(*body.values_at(*%w[id complete errored progress]))
|
210
208
|
end
|
211
209
|
|
212
210
|
# @return [Ecoportal::API::Common::Response] the results of the batch job
|
@@ -216,15 +214,25 @@ module Ecoportal
|
|
216
214
|
end
|
217
215
|
end
|
218
216
|
|
219
|
-
def wait_for_job_completion(job_id)
|
217
|
+
def wait_for_job_completion(job_id, timeout:, total:)
|
220
218
|
# timeout library is evil. So we make poor-man timeout.
|
221
219
|
# https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
|
222
220
|
before = Time.now
|
223
221
|
|
224
222
|
loop do
|
225
223
|
status = job_status(job_id)
|
226
|
-
break status if status.complete?
|
227
|
-
|
224
|
+
break status if status.complete?(total)
|
225
|
+
|
226
|
+
left = (before + timeout) - Time.now
|
227
|
+
break status unless left.positive?
|
228
|
+
# break status if Time.now >= before + timeout
|
229
|
+
|
230
|
+
msg = " ... Await job "
|
231
|
+
msg << "('#{job_id}'; done: #{status.progress}): "
|
232
|
+
msg << "#{left.ceil} sec. \r"
|
233
|
+
|
234
|
+
print msg
|
235
|
+
$stdout.flush
|
228
236
|
|
229
237
|
sleep(DELAY_STATUS_CHECK)
|
230
238
|
status
|
data/lib/ecoportal/api/v1.rb
CHANGED
metadata
CHANGED
@@ -1,42 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecoportal-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
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-
|
11
|
+
date: 2024-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: pry
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 3.12.0
|
20
|
-
- - "<"
|
17
|
+
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
19
|
+
version: '0.14'
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 3.12.0
|
30
|
-
- - "<"
|
24
|
+
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
26
|
+
version: '0.14'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: rake
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
31
|
- - ">="
|
38
32
|
- !ruby/object:Gem::Version
|
39
|
-
version: 13.
|
33
|
+
version: 13.0.3
|
40
34
|
- - "<"
|
41
35
|
- !ruby/object:Gem::Version
|
42
36
|
version: '14'
|
@@ -46,37 +40,37 @@ dependencies:
|
|
46
40
|
requirements:
|
47
41
|
- - ">="
|
48
42
|
- !ruby/object:Gem::Version
|
49
|
-
version: 13.
|
43
|
+
version: 13.0.3
|
50
44
|
- - "<"
|
51
45
|
- !ruby/object:Gem::Version
|
52
46
|
version: '14'
|
53
47
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
48
|
+
name: redcarpet
|
55
49
|
requirement: !ruby/object:Gem::Requirement
|
56
50
|
requirements:
|
57
51
|
- - ">="
|
58
52
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
53
|
+
version: 3.6.0
|
60
54
|
- - "<"
|
61
55
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
56
|
+
version: '4'
|
63
57
|
type: :development
|
64
58
|
prerelease: false
|
65
59
|
version_requirements: !ruby/object:Gem::Requirement
|
66
60
|
requirements:
|
67
61
|
- - ">="
|
68
62
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
63
|
+
version: 3.6.0
|
70
64
|
- - "<"
|
71
65
|
- !ruby/object:Gem::Version
|
72
|
-
version: '
|
66
|
+
version: '4'
|
73
67
|
- !ruby/object:Gem::Dependency
|
74
|
-
name:
|
68
|
+
name: rspec
|
75
69
|
requirement: !ruby/object:Gem::Requirement
|
76
70
|
requirements:
|
77
71
|
- - ">="
|
78
72
|
- !ruby/object:Gem::Version
|
79
|
-
version: 3.
|
73
|
+
version: 3.12.0
|
80
74
|
- - "<"
|
81
75
|
- !ruby/object:Gem::Version
|
82
76
|
version: '4'
|
@@ -86,24 +80,52 @@ dependencies:
|
|
86
80
|
requirements:
|
87
81
|
- - ">="
|
88
82
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.
|
83
|
+
version: 3.12.0
|
90
84
|
- - "<"
|
91
85
|
- !ruby/object:Gem::Version
|
92
86
|
version: '4'
|
93
87
|
- !ruby/object:Gem::Dependency
|
94
|
-
name:
|
88
|
+
name: rubocop
|
95
89
|
requirement: !ruby/object:Gem::Requirement
|
96
90
|
requirements:
|
97
91
|
- - "~>"
|
98
92
|
- !ruby/object:Gem::Version
|
99
|
-
version: '
|
93
|
+
version: '1'
|
100
94
|
type: :development
|
101
95
|
prerelease: false
|
102
96
|
version_requirements: !ruby/object:Gem::Requirement
|
103
97
|
requirements:
|
104
98
|
- - "~>"
|
105
99
|
- !ruby/object:Gem::Version
|
106
|
-
version: '
|
100
|
+
version: '1'
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: rubocop-rake
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
type: :development
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - "~>"
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: yard
|
117
|
+
requirement: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - "~>"
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0.9'
|
122
|
+
type: :development
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - "~>"
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0.9'
|
107
129
|
- !ruby/object:Gem::Dependency
|
108
130
|
name: dotenv
|
109
131
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,9 +183,7 @@ dependencies:
|
|
161
183
|
description:
|
162
184
|
email:
|
163
185
|
- tapio@ecoportal.co.nz
|
164
|
-
- rien@ecoportal.co.nz
|
165
186
|
- oscar@ecoportal.co.nz
|
166
|
-
- bozydar@ecoportal.co.nz
|
167
187
|
executables: []
|
168
188
|
extensions: []
|
169
189
|
extra_rdoc_files: []
|
@@ -189,8 +209,12 @@ files:
|
|
189
209
|
- lib/ecoportal/api/common/batch_operation.rb
|
190
210
|
- lib/ecoportal/api/common/batch_response.rb
|
191
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
|
192
217
|
- lib/ecoportal/api/common/doc_helpers.rb
|
193
|
-
- lib/ecoportal/api/common/elastic_apm_integration.rb
|
194
218
|
- lib/ecoportal/api/common/hash_diff.rb
|
195
219
|
- lib/ecoportal/api/common/logging.rb
|
196
220
|
- lib/ecoportal/api/common/response.rb
|
@@ -215,6 +239,7 @@ files:
|
|
215
239
|
- lib/ecoportal/api/internal/schema_field_value.rb
|
216
240
|
- lib/ecoportal/api/logger.rb
|
217
241
|
- lib/ecoportal/api/v1.rb
|
242
|
+
- lib/ecoportal/api/v1/job_status.rb
|
218
243
|
- lib/ecoportal/api/v1/people.rb
|
219
244
|
- lib/ecoportal/api/v1/person.rb
|
220
245
|
- lib/ecoportal/api/v1/person_details.rb
|
@@ -243,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
268
|
- !ruby/object:Gem::Version
|
244
269
|
version: '0'
|
245
270
|
requirements: []
|
246
|
-
rubygems_version: 3.5.
|
271
|
+
rubygems_version: 3.5.18
|
247
272
|
signing_key:
|
248
273
|
specification_version: 4
|
249
274
|
summary: A collection of helpers for interacting with the ecoPortal MS's various APIs
|
@@ -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
|