triglav-agent 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/.yardopts +6 -0
  6. data/CHANGELOG.md +3 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +5 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +59 -0
  11. data/Rakefile +11 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/docs/Triglav/Agent/ApiClient/AuthenticationError.html +150 -0
  15. data/docs/Triglav/Agent/ApiClient/ConnectionError.html +150 -0
  16. data/docs/Triglav/Agent/ApiClient/Error.html +296 -0
  17. data/docs/Triglav/Agent/ApiClient.html +545 -0
  18. data/docs/Triglav/Agent/Base/CLI.html +498 -0
  19. data/docs/Triglav/Agent/Base/Connection.html +258 -0
  20. data/docs/Triglav/Agent/Base/Monitor.html +370 -0
  21. data/docs/Triglav/Agent/Base/Processor.html +623 -0
  22. data/docs/Triglav/Agent/Base/Setting.html +1081 -0
  23. data/docs/Triglav/Agent/Base/Worker.html +635 -0
  24. data/docs/Triglav/Agent/Base.html +121 -0
  25. data/docs/Triglav/Agent/Configuration.html +967 -0
  26. data/docs/Triglav/Agent/Error.html +130 -0
  27. data/docs/Triglav/Agent/HashUtil.html +351 -0
  28. data/docs/Triglav/Agent/LogFormatter.html +271 -0
  29. data/docs/Triglav/Agent/Logger.html +287 -0
  30. data/docs/Triglav/Agent/StorageFile.html +1130 -0
  31. data/docs/Triglav/Agent/Timer.html +424 -0
  32. data/docs/Triglav/Agent/TooManyError.html +134 -0
  33. data/docs/Triglav/Agent.html +131 -0
  34. data/docs/Triglav.html +119 -0
  35. data/docs/_index.html +335 -0
  36. data/docs/class_list.html +51 -0
  37. data/docs/css/common.css +1 -0
  38. data/docs/css/full_list.css +58 -0
  39. data/docs/css/style.css +481 -0
  40. data/docs/file.LICENSE.html +72 -0
  41. data/docs/file.README.html +137 -0
  42. data/docs/file_list.html +61 -0
  43. data/docs/frames.html +17 -0
  44. data/docs/index.html +137 -0
  45. data/docs/js/app.js +243 -0
  46. data/docs/js/full_list.js +216 -0
  47. data/docs/js/jquery.js +4 -0
  48. data/docs/method_list.html +659 -0
  49. data/docs/top-level-namespace.html +112 -0
  50. data/example/config.yml +40 -0
  51. data/lib/triglav/agent/api_client.rb +199 -0
  52. data/lib/triglav/agent/base/cli.rb +98 -0
  53. data/lib/triglav/agent/base/connection.rb +30 -0
  54. data/lib/triglav/agent/base/monitor.rb +32 -0
  55. data/lib/triglav/agent/base/processor.rb +136 -0
  56. data/lib/triglav/agent/base/setting.rb +112 -0
  57. data/lib/triglav/agent/base/worker.rb +95 -0
  58. data/lib/triglav/agent/configuration.rb +79 -0
  59. data/lib/triglav/agent/error.rb +4 -0
  60. data/lib/triglav/agent/hash_util.rb +36 -0
  61. data/lib/triglav/agent/logger.rb +50 -0
  62. data/lib/triglav/agent/storage_file.rb +144 -0
  63. data/lib/triglav/agent/timer.rb +80 -0
  64. data/lib/triglav/agent/version.rb +5 -0
  65. data/lib/triglav/agent.rb +20 -0
  66. data/lib/triglav-agent.rb +1 -0
  67. data/triglav-agent.gemspec +33 -0
  68. metadata +250 -0
@@ -0,0 +1,112 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.5
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <iframe id="search_frame" src="class_list.html"></iframe>
63
+
64
+ <div id="content"><h1>Top Level Namespace
65
+
66
+
67
+
68
+ </h1>
69
+ <div class="box_info">
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ </div>
82
+
83
+ <h2>Defined Under Namespace</h2>
84
+ <p class="children">
85
+
86
+
87
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="Triglav.html" title="Triglav (module)">Triglav</a></span>
88
+
89
+
90
+
91
+
92
+ </p>
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+ </div>
103
+
104
+ <div id="footer">
105
+ Generated on Thu Feb 23 23:20:33 2017 by
106
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
107
+ 0.9.5 (ruby-2.3.2).
108
+ </div>
109
+
110
+ </div>
111
+ </body>
112
+ </html>
@@ -0,0 +1,40 @@
1
+ defaults: &defaults
2
+ serverengine:
3
+ log: 'STDOUT'
4
+ log_level: 'debug'
5
+ log_rotate_age: 5
6
+ log_rotate_size: 10485760
7
+ triglav:
8
+ url: <%= ENV['TRIGLAV_URL'] || 'http://localhost:7800' %>
9
+ credential:
10
+ username: <%= ENV['TRIGLAV_USERNAME'] || 'triglav_test' %>
11
+ password: <%= ENV['TRIGLAV_PASSWORD'] || 'triglav_test' %>
12
+ authenticator: local
13
+ timeout: 60
14
+ debugging: false
15
+ retries: 3
16
+ retry_interval: 3 # sec
17
+ vertica:
18
+ monitor_interval: 5
19
+ parallel_size: 1 # default: 1
20
+ parallel_type: 'thread' # thread or process. default: thread
21
+ connection_pool_size: 1 # default: same with parallel.size
22
+ connection_pool_timeout: 60 # sec. default: 60
23
+ date_column: d
24
+ timestamp_column: t
25
+ connection_info:
26
+ "vertica://":
27
+ host: <%= ENV['VERTICA_HOST'] %>
28
+ port: <%= ENV['VERTICA_PORT'] %>
29
+ database: <%= ENV['VERTICA_DATABASE'] %>
30
+ user: <%= ENV['VERTICA_USER'] %>
31
+ password: <%= ENV['VERTICA_PASSWORD'] %>
32
+ resource_pool: <%= ENV['VERTICA_RESOURCE_POOL'] %>
33
+ interruptable: true
34
+ read_timeout: 5
35
+
36
+ development:
37
+ <<: *defaults
38
+
39
+ test:
40
+ <<: *defaults
@@ -0,0 +1,199 @@
1
+ require 'triglav/agent/storage_file'
2
+ require 'triglav_client'
3
+
4
+ module Triglav::Agent
5
+ # This Triglav client connects to triglav API with $setting.triglav.url,
6
+ # and authenticates with $setting.triglav.credential, and
7
+ # stores the token into $setting.token_file.
8
+ #
9
+ # Re-authenticate automatically if token is expired
10
+ #
11
+ # require 'triglav/agent/api_client'
12
+ #
13
+ # api_client = Triglav::Agent::ApiClient.new
14
+ # resources = api_client.list_resources(uri_prefix)
15
+ # resources.each do |resource|
16
+ # events = get_events(resource) # implement this!
17
+ # api_client.send_messages(events)
18
+ # end
19
+ class ApiClient
20
+ class Error < StandardError
21
+ attr_reader :cause
22
+ def initialize(message, cause)
23
+ @cause = cause
24
+ super(message)
25
+ end
26
+ end
27
+ class AuthenticationError < Error; end
28
+ class ConnectionError < Error; end
29
+
30
+ # Initialize TriglavClient
31
+ def initialize(opts = {})
32
+ @opts = opts || {}
33
+ config = TriglavClient::Configuration.new do |config|
34
+ uri = URI.parse(triglav_url)
35
+ config.scheme = uri.scheme
36
+ config.host = "#{uri.host}:#{uri.port}"
37
+ config.timeout = timeout if timeout
38
+ config.debugging = debugging if debugging
39
+ end
40
+ @api_client = TriglavClient::ApiClient.new(config)
41
+ initialize_current_token
42
+ authenticate
43
+ end
44
+
45
+ def close
46
+ # typhoeus makes a new connection and disconnects it on each request
47
+ end
48
+
49
+ # List resources required to be monitored
50
+ #
51
+ # @param [String] uri_prefix
52
+ # @return [Array of TriglavClient::ResourceEachResponse] array of resources
53
+ # @see TriglavClient::ResourceEachResponse
54
+ def list_aggregated_resources(uri_prefix)
55
+ $logger.debug { "ApiClient#list_aggregated_resources(#{uri_prefix.inspect})" }
56
+ resources_api = TriglavClient::ResourcesApi.new(@api_client)
57
+ handle_error { resources_api.list_aggregated_resources(uri_prefix) }
58
+ end
59
+
60
+ # Send messages
61
+ #
62
+ # @param [Array of TriglavClient::MessageRequest] array of event messages
63
+ # @see TriglavClient::MessageRequest
64
+ def send_messages(events)
65
+ $logger.debug { "ApiClient#send_messages(#{events.inspect})" }
66
+ messages_api = TriglavClient::MessagesApi.new(@api_client)
67
+ handle_error { messages_api.send_messages(events) }
68
+ end
69
+
70
+ def authorized?
71
+ @current_token.has_key?(:access_token)
72
+ end
73
+
74
+ private
75
+
76
+ # Authenticate
77
+ #
78
+ # 1. Another process saved a newer token onto the token_file => read it
79
+ # 2. The token saved on the token_file is same with current token => re-authenticate
80
+ # 3. The token saved on the token_file is older than the current token
81
+ # => unknown situation, re-authenticate and save into token_file to refresh anyway
82
+ # 4. No token is saved on the token_file => authenticate
83
+ def authenticate
84
+ $logger.debug { 'ApiClient#authenticate' }
85
+ StorageFile.open(token_file) do |fp|
86
+ token = fp.load
87
+ if should_read_token_from_file?(token)
88
+ $logger.debug { "Read token from file" }
89
+ update_current_token(token)
90
+ return
91
+ end
92
+ $logger.debug { "AuthApi#create_token" }
93
+ auth_api = TriglavClient::AuthApi.new(@api_client)
94
+ credential = TriglavClient::Credential.new(
95
+ username: username, password: password, authenticator: authenticator
96
+ )
97
+ handle_auth_error do
98
+ $logger.debug { 'TriglavClient::AuthApi' }
99
+ result = auth_api.create_token(credential)
100
+ token = {access_token: result.access_token}
101
+ update_current_token(token)
102
+ fp.dump(token)
103
+ end
104
+ end
105
+ end
106
+
107
+ def initialize_current_token
108
+ @current_token = {
109
+ access_token: (@api_client.config.api_key['Authorization'] = String.new),
110
+ }
111
+ end
112
+
113
+ def update_current_token(token)
114
+ @current_token[:access_token].replace(token[:access_token])
115
+ end
116
+
117
+ def should_read_token_from_file?(token)
118
+ return true if @current_token[:access_token].empty? && !(token[:access_token] ||= '').empty?
119
+ return @current_token[:access_token] != token[:access_token]
120
+ end
121
+
122
+ def handle_auth_error(&block)
123
+ retries = 0
124
+ begin
125
+ yield
126
+ rescue TriglavClient::ApiError => e
127
+ if e.code == 0
128
+ if retries < max_retries
129
+ sleep retry_interval
130
+ retries += 1
131
+ retry
132
+ end
133
+ raise ConnectionError.new("Could not connect to #{triglav_url} with #{retries} retries", e)
134
+ elsif e.message == 'Unauthorized'.freeze
135
+ raise AuthenticationError.new("Failed to authenticate on triglav API.".freeze, e)
136
+ else
137
+ raise Error.new(e.message, e)
138
+ end
139
+ end
140
+ end
141
+
142
+ def handle_error(&block)
143
+ retries = 0
144
+ begin
145
+ yield
146
+ rescue TriglavClient::ApiError => e
147
+ if e.code == 0
148
+ if retries < max_retries
149
+ sleep retry_interval
150
+ retries += 1
151
+ retry
152
+ end
153
+ raise ConnectionError.new("Could not connect to #{triglav_url} with #{retries} retries", e)
154
+ elsif e.message == 'Unauthorized'.freeze
155
+ authenticate
156
+ retry
157
+ else
158
+ raise Error.new(e.message, e)
159
+ end
160
+ end
161
+ end
162
+
163
+ def triglav_url
164
+ @opts[:url] || $setting.dig(:triglav, :url)
165
+ end
166
+
167
+ def username
168
+ @opts.dig(:credential, :username) || $setting.dig(:triglav, :credential, :username)
169
+ end
170
+
171
+ def password
172
+ @opts.dig(:credential, :password) || $setting.dig(:triglav, :credential, :password)
173
+ end
174
+
175
+ def authenticator
176
+ @opts.dig(:credential, :authenticator) || $setting.dig(:triglav, :credential, :authenticator)
177
+ end
178
+
179
+ def timeout
180
+ @opts[:timeout] || $setting.dig(:triglav, :timeout)
181
+ end
182
+
183
+ def debugging
184
+ @opts[:debugging] || $setting.dig(:triglav, :debugging)
185
+ end
186
+
187
+ def max_retries
188
+ @opts[:retries] || $setting.dig(:triglav, :retries) || 3
189
+ end
190
+
191
+ def retry_interval
192
+ @opts[:retry_interval] || $setting.dig(:triglav, :retry_interval) || 3 # second
193
+ end
194
+
195
+ def token_file
196
+ @opts[:token_file] || $setting.token_file
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,98 @@
1
+ require "triglav/agent/configuration"
2
+ require "triglav/agent/base/setting"
3
+ require 'optparse'
4
+ require 'serverengine'
5
+
6
+ module Triglav::Agent
7
+ module Base
8
+ # A base class for cli option parser
9
+ #
10
+ # This base class usually should be enough for agent plugins, but
11
+ # you can override this class and configure with Configuration#cli_classe=
12
+ class CLI
13
+ def run
14
+ opts, _ = parse_options(ARGV)
15
+ $setting = Configuration.setting_class.new(opts)
16
+ $logger = $setting.logger
17
+ se = ServerEngine.create(nil, Configuration.worker_module) do
18
+ $setting.serverengine_options
19
+ end
20
+ se.run
21
+ end
22
+
23
+ def default_opts
24
+ {
25
+ config: 'config.yml',
26
+ dotenv: false,
27
+ debug: false,
28
+ }
29
+ end
30
+
31
+ def option_parser(opts = {})
32
+ op = OptionParser.new
33
+
34
+ self.class.module_eval do
35
+ define_method(:usage) do |msg = nil|
36
+ puts op.to_s
37
+ puts "error: #{msg}" if msg
38
+ exit 1
39
+ end
40
+ end
41
+
42
+ op.on('-c', '--config VALUE', "Config file (default: #{opts[:config]})") {|v|
43
+ opts[:config] = v
44
+ }
45
+ op.on('-s', '--status VALUE', "Status stroage file (default: status.yml)") {|v|
46
+ opts[:status] = v
47
+ }
48
+ op.on('-t', '--token VALUE', "Triglav access token storage file (default: token.yml)") {|v|
49
+ opts[:token] = v
50
+ }
51
+ op.on('--dotenv', "Load environment variables from .env file (default: #{opts[:dotenv]})") {|v|
52
+ opts[:dotenv] = v
53
+ }
54
+ op.on('--debug', "Debug mode (default: #{opts[:debug]})") {|v|
55
+ opts[:debug] = v
56
+ }
57
+ op.on('-h', '--help', "help") {|v|
58
+ opts[:help] = v
59
+ }
60
+ # serverengine options
61
+ op.on('--log VALUE', "Log path (default: #{Setting::DEFAULT_LOG})") {|v|
62
+ opts[:log] = v
63
+ }
64
+ op.on('--log-level VALUE', "Log level (default: #{Setting::DEFAULT_LOG_LEVEL})") {|v|
65
+ opts[:log_level] = v
66
+ }
67
+
68
+ op.banner += ''
69
+
70
+ op
71
+ end
72
+
73
+ def parse_options(argv = ARGV)
74
+ opts = default_opts
75
+ op = option_parser(opts)
76
+
77
+ begin
78
+ args = op.parse(argv)
79
+ rescue OptionParser::InvalidOption => e
80
+ usage e.message
81
+ end
82
+
83
+ if opts[:help]
84
+ usage
85
+ end
86
+
87
+ if opts[:config].nil?
88
+ usage "--config VALUE is required"
89
+ end
90
+ if !File.readable?(opts[:config])
91
+ usage "Config file '#{opts[:config]}' does not exist or not readable"
92
+ end
93
+
94
+ [opts, args]
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,30 @@
1
+ module Triglav::Agent
2
+ module Base
3
+ # An abstract base class of Connection.
4
+ #
5
+ # Wrap a connection to a storage.
6
+ # You can implement any methods which you want to use in your Monitor class.
7
+ #
8
+ # You have to implement following methods:
9
+ #
10
+ # * initialize
11
+ # * close
12
+ #
13
+ # An instance is created for each `resource_uri_prefix`, that is,
14
+ # shared among resources with of same `resource_uri_prefix`.
15
+ #
16
+ # Note that multiple connection instances would be created
17
+ # when multiple parallel threads are created in Processor class.
18
+ class Connection
19
+ # @param [Hash] connection_info
20
+ def initialize(connection_info)
21
+ raise NotImplementedError
22
+ end
23
+
24
+ # close the connection
25
+ def close
26
+ raise NotImplementedError
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ module Triglav::Agent
2
+ module Base
3
+ # An abstract class of Monitor.
4
+ #
5
+ # Monitor your storage and send messages to triglav.
6
+ #
7
+ # You have to implement following methods:
8
+ #
9
+ # * initialize
10
+ # * process
11
+ #
12
+ # An instance is created per a `resource`.
13
+ # Connection is shared among same `resource_uri_prefix`.
14
+ #
15
+ # Note that multiple instances would be created,
16
+ # one instance for one parallel thread basically, and
17
+ # `#process` is ran concurrently.
18
+ class Monitor
19
+ # @param [Triglav::Agent::Base::Connection] connection
20
+ # @param [TriglavClient::ResourceResponse] resource
21
+ def initialize(connection, resource)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ # @yield [events] Gives an array of events
26
+ def process(&block)
27
+ raise NotImplementedError
28
+ # yield(events) if block_given?
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,136 @@
1
+ require 'parallel'
2
+ require 'connection_pool'
3
+
4
+ module Triglav::Agent
5
+ module Base
6
+ # Triglav agent processor class.
7
+ #
8
+ # An instance is created for a `resource_uri_prefix`.
9
+ #
10
+ # You usually do not need to customize this class, but if you want to
11
+ # implement your original, configure
12
+ #
13
+ # Triglav::Agent::Configuration.processor_class
14
+ class Processor
15
+ attr_reader :worker, :resource_uri_prefix
16
+
17
+ def initialize(worker, resource_uri_prefix)
18
+ @worker = worker
19
+ @resource_uri_prefix = resource_uri_prefix
20
+ end
21
+
22
+ def self.max_consecuitive_error_count
23
+ 3
24
+ end
25
+
26
+ def process
27
+ before_process
28
+ success_count = 0
29
+ consecutive_error_count = 0
30
+ Parallel.each(resources, parallel_opts) do |resource|
31
+ raise Parallel::Break if stopped?
32
+ events = nil
33
+ begin
34
+ @connection_pool.with do |connection|
35
+ monitor = monitor_class.new(connection, resource)
36
+ monitor.process do |_events|
37
+ events = _events
38
+ $logger.info { "send_messages:#{events.map(&:to_hash).to_json}" }
39
+ @api_client_pool.with {|api_client| api_client.send_messages(events) }
40
+ end
41
+ end
42
+ @mutex.synchronize do
43
+ success_count += 1
44
+ consecutive_error_count = 0
45
+ end
46
+ rescue => e
47
+ log_error(e)
48
+ $logger.info { "failed_events:#{events.map(&:to_hash).to_json}" } if events
49
+ @mutex.synchronize do
50
+ raise TooManyError if (consecutive_error_count += 1) > self.class.max_consecuitive_error_count
51
+ end
52
+ end
53
+ end
54
+ success_count
55
+ ensure
56
+ after_process
57
+ end
58
+
59
+ def total_count
60
+ resources.size
61
+ end
62
+
63
+ private
64
+
65
+ def before_process
66
+ @connection_pool = ConnectionPool.new(connection_pool_opts) {
67
+ connection_class.new(get_connection_info(resource_uri_prefix))
68
+ }
69
+ @api_client_pool = ConnectionPool.new(connection_pool_opts) {
70
+ ApiClient.new # renew connection
71
+ }
72
+ @mutex = Mutex.new
73
+ end
74
+
75
+ def after_process
76
+ @connection_pool.shutdown {|conn| conn.close rescue nil }
77
+ @api_client_pool.shutdown {|conn| conn.close rescue nil }
78
+ end
79
+
80
+ def connection_class
81
+ Configuration.connection_class
82
+ end
83
+
84
+ def monitor_class
85
+ Configuration.monitor_class
86
+ end
87
+
88
+ def name
89
+ Configuration.name
90
+ end
91
+
92
+ def resources
93
+ return @resources if @resources
94
+ @resources = ApiClient.new.list_aggregated_resources(resource_uri_prefix) || []
95
+ $logger.debug { "resource_uri_prefix:#{resource_uri_prefix} resources.size:#{@resources.size}" }
96
+ @resources
97
+ end
98
+
99
+ def parallel_opts
100
+ parallel_type == 'process' ? {in_processes: parallel_size} : {in_threads: parallel_size}
101
+ end
102
+
103
+ def connection_pool_opts
104
+ {size: connection_pool_size, timeout: connection_pool_timeout}
105
+ end
106
+
107
+ def parallel_size
108
+ $setting.dig(name, :parallel_size) || 1
109
+ end
110
+
111
+ def parallel_type
112
+ $setting.dig(name, :parallel_type) || 'thread'
113
+ end
114
+
115
+ def connection_pool_size
116
+ $setting.dig(name, :connection_pool_size) || parallel_size
117
+ end
118
+
119
+ def connection_pool_timeout
120
+ $setting.dig(name, :connection_pool_timeout) || 60
121
+ end
122
+
123
+ def get_connection_info(resource_uri_prefix)
124
+ $setting.dig(name, :connection_info)[resource_uri_prefix]
125
+ end
126
+
127
+ def log_error(e)
128
+ $logger.error { "#{e.class} #{e.message} #{e.backtrace.join("\\n")}" } # one line
129
+ end
130
+
131
+ def stopped?
132
+ worker.stopped? if worker and worker.respond_to?(:stopped?)
133
+ end
134
+ end
135
+ end
136
+ end