triglav-agent 1.0.0.pre1

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.
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