cem_acpt 0.2.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/spec.yml +30 -0
  3. data/Gemfile +4 -3
  4. data/Gemfile.lock +95 -43
  5. data/README.md +144 -83
  6. data/cem_acpt.gemspec +12 -7
  7. data/exe/cem_acpt +41 -7
  8. data/lib/cem_acpt/config.rb +340 -0
  9. data/lib/cem_acpt/core_extensions.rb +17 -61
  10. data/lib/cem_acpt/goss/api/action_response.rb +175 -0
  11. data/lib/cem_acpt/goss/api.rb +83 -0
  12. data/lib/cem_acpt/goss.rb +8 -0
  13. data/lib/cem_acpt/image_name_builder.rb +0 -9
  14. data/lib/cem_acpt/logging/formatter.rb +97 -0
  15. data/lib/cem_acpt/logging.rb +168 -142
  16. data/lib/cem_acpt/platform/base.rb +26 -37
  17. data/lib/cem_acpt/platform/gcp.rb +48 -62
  18. data/lib/cem_acpt/platform.rb +30 -28
  19. data/lib/cem_acpt/provision/terraform/linux.rb +47 -0
  20. data/lib/cem_acpt/provision/terraform/os_data.rb +72 -0
  21. data/lib/cem_acpt/provision/terraform/windows.rb +22 -0
  22. data/lib/cem_acpt/provision/terraform.rb +193 -0
  23. data/lib/cem_acpt/provision.rb +20 -0
  24. data/lib/cem_acpt/puppet_helpers.rb +0 -1
  25. data/lib/cem_acpt/test_data.rb +23 -13
  26. data/lib/cem_acpt/test_runner/log_formatter/goss_action_response.rb +104 -0
  27. data/lib/cem_acpt/test_runner/log_formatter.rb +10 -0
  28. data/lib/cem_acpt/test_runner.rb +170 -3
  29. data/lib/cem_acpt/utils/puppet.rb +29 -0
  30. data/lib/cem_acpt/utils/ssh.rb +197 -0
  31. data/lib/cem_acpt/utils/terminal.rb +27 -0
  32. data/lib/cem_acpt/utils.rb +4 -138
  33. data/lib/cem_acpt/version.rb +1 -1
  34. data/lib/cem_acpt.rb +73 -23
  35. data/lib/terraform/gcp/linux/goss/puppet_idempotent.yaml +10 -0
  36. data/lib/terraform/gcp/linux/goss/puppet_noop.yaml +12 -0
  37. data/lib/terraform/gcp/linux/main.tf +191 -0
  38. data/lib/terraform/gcp/linux/systemd/goss-acpt.service +8 -0
  39. data/lib/terraform/gcp/linux/systemd/goss-idempotent.service +8 -0
  40. data/lib/terraform/gcp/linux/systemd/goss-noop.service +8 -0
  41. data/lib/terraform/gcp/windows/.keep +0 -0
  42. data/sample_config.yaml +22 -21
  43. metadata +151 -51
  44. data/lib/cem_acpt/bootstrap/bootstrapper.rb +0 -206
  45. data/lib/cem_acpt/bootstrap/operating_system/rhel_family.rb +0 -129
  46. data/lib/cem_acpt/bootstrap/operating_system.rb +0 -17
  47. data/lib/cem_acpt/bootstrap.rb +0 -12
  48. data/lib/cem_acpt/context.rb +0 -153
  49. data/lib/cem_acpt/platform/base/cmd.rb +0 -71
  50. data/lib/cem_acpt/platform/gcp/cmd.rb +0 -353
  51. data/lib/cem_acpt/platform/gcp/compute.rb +0 -332
  52. data/lib/cem_acpt/platform/vmpooler.rb +0 -24
  53. data/lib/cem_acpt/rspec_utils.rb +0 -242
  54. data/lib/cem_acpt/shared_objects.rb +0 -537
  55. data/lib/cem_acpt/spec_helper_acceptance.rb +0 -184
  56. data/lib/cem_acpt/test_runner/run_handler.rb +0 -187
  57. data/lib/cem_acpt/test_runner/runner.rb +0 -210
  58. data/lib/cem_acpt/test_runner/runner_result.rb +0 -103
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'async'
4
+ require 'async/barrier'
5
+ require 'async/http/internet'
6
+ require 'json'
7
+ require_relative 'api/action_response'
8
+
9
+ module CemAcpt
10
+ module Goss
11
+ # Holds methods for interacting with the Goss API running on a test node.
12
+ module Api
13
+ class << self
14
+ # The actions that can be run against the Goss API. The key is the action
15
+ # name and the value is the port/endpoint of the action.
16
+ ACTIONS = {
17
+ acpt: '8080/acpt',
18
+ idempotent: '8081/idempotent',
19
+ noop: '8082/noop',
20
+ }.freeze
21
+
22
+ # Create a URI for the specified action against the specified host.
23
+ # @param host [String] The host to run the action against. This should be
24
+ # a public IP address or a DNS-resolvable name.
25
+ # @param action [Symbol] The action to run.
26
+ # @return [URI] The URI for the action.
27
+ def action_uri(host, action)
28
+ URI("http://#{host}:#{ACTIONS[action.to_sym]}")
29
+ end
30
+
31
+ # Run the specified actions against the specified hosts asynchronously.
32
+ # @param hosts [Array<String>] The hosts to run the actions against. Each
33
+ # host should be a public IP address or a DNS-resolvable name.
34
+ # @param results [Queue] The queue to push the results to.
35
+ # @param only [Array<Symbol>] The actions to run.
36
+ # @param except [Array<Symbol>] The actions to skip.
37
+ # @return [Queue] The queue of results.
38
+ def run_actions_async(hosts, results: Queue.new, only: [], except: [])
39
+ raise ArgumentError, 'hosts must be an Array' unless hosts.is_a?(Array)
40
+ raise ArgumentError, 'results must be a Queue-like object implementing #<<' unless results.respond_to?(:<<)
41
+ raise ArgumentError, 'only must be an Array' unless except.is_a?(Array)
42
+ raise ArgumentError, 'except must be an Array' unless except.is_a?(Array)
43
+ only.map!(&:to_sym)
44
+ except.map!(&:to_sym)
45
+ only_specified = !only.empty?
46
+ except_specified = !except.empty?
47
+ Async do
48
+ internet = Async::HTTP::Internet.new
49
+ barrier = Async::Barrier.new
50
+ barrier.async do
51
+ hosts.each do |host|
52
+ ACTIONS.keys.each do |action, _|
53
+ next if only_specified && !only.include?(action)
54
+ next if except_specified && except.include?(action)
55
+
56
+ results << run_action(internet, host, action)
57
+ end
58
+ end
59
+ end
60
+ barrier.wait
61
+ ensure
62
+ internet&.close
63
+ results.close if results.respond_to?(:close)
64
+ end
65
+ results
66
+ end
67
+
68
+ # Run the specified action against the specified host.
69
+ # @param internet [Async::HTTP::Internet] The Async::HTTP::Internet object to use for the request.
70
+ # @param host [String] The host to run the action against. This should be
71
+ # a public IP address or a DNS-resolvable name.
72
+ # @param action [Symbol] The action to run.
73
+ # @return [ActionResponse] The response from the action.
74
+ def run_action(internet, host, action)
75
+ uri = action_uri(host, action)
76
+ response = internet.get(uri.to_s)
77
+ body = JSON.parse(response.read)
78
+ ActionResponse.new(host, action, response.status, body)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'goss/api'
4
+
5
+ module CemAcpt
6
+ # Holds all the Goss related code
7
+ module Goss; end
8
+ end
@@ -41,13 +41,8 @@ module CemAcpt
41
41
  # @param test_data [Hash] The test data to use to build the image name.
42
42
  # @return [String] The image name.
43
43
  def build(test_data)
44
- logger.debug 'Building image name...'
45
- logger.debug "Using config: #{@config.to_h}"
46
- logger.debug "Test data: #{test_data}"
47
44
  parts = resolve_parts(test_data)
48
- logger.debug "Resolved parts: #{parts}"
49
45
  image_name = create_image_name(parts)
50
- logger.debug "Created image name: #{image_name}"
51
46
  final_image_name = character_substitutions(image_name)
52
47
  logger.debug "Final image name: #{final_image_name}"
53
48
  final_image_name
@@ -61,10 +56,8 @@ module CemAcpt
61
56
  # @return [Array] The parts array with variables resolved.
62
57
  def resolve_parts(test_data)
63
58
  @config[:parts].each_with_object([]) do |part, ary|
64
- logger.debug "Resolving part: #{part}"
65
59
  if part.start_with?('$')
66
60
  var_path = part[1..-1]
67
- logger.debug "Resolving variable path: #{var_path}"
68
61
  ary << test_data.dot_dig(var_path)
69
62
  else
70
63
  ary << part
@@ -77,10 +70,8 @@ module CemAcpt
77
70
  # @return [String] The image name.
78
71
  def create_image_name(parts)
79
72
  image_name = @config[:join_with] ? parts.join(@config[:join_with]) : parts.join
80
- logger.debug("Final image name: #{image_name}")
81
73
 
82
74
  if @config[:validation_pattern]
83
- logger.debug "Validating image name: #{image_name}..."
84
75
  return image_name if image_name.match?(@config[:validation_pattern])
85
76
 
86
77
  raise "Image name #{image_name} does not match validation pattern #{@config[:validation_pattern]}"
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CemAcpt
4
+ module Logging
5
+ module Formatter
6
+ class << self
7
+ def valid_format?(log_format)
8
+ all.any? { |f| f.log_format == log_format.downcase.to_sym }
9
+ end
10
+
11
+ def for(log_format)
12
+ formatter = all.find { |f| f.log_format == log_format.downcase.to_sym }
13
+ raise "Unknown log format: #{log_format}" unless formatter
14
+
15
+ formatter.get
16
+ end
17
+
18
+ def all
19
+ @all ||= [FileFormatter.new, JSONFormatter.new, TextFormatter.new, GithubActionFormatter.new]
20
+ end
21
+ end
22
+
23
+ class FileFormatter
24
+ attr_reader :log_format
25
+
26
+ def initialize
27
+ @log_format = :file
28
+ end
29
+
30
+ def get
31
+ proc do |severity, datetime, progname, msg|
32
+ format(severity, datetime, progname, msg)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def format(severity, datetime, progname, msg)
39
+ "[#{datetime}] #{severity}: #{progname}: #{msg}\n"
40
+ end
41
+ end
42
+
43
+ class JSONFormatter < FileFormatter
44
+ def initialize
45
+ super
46
+ @log_format = :json
47
+ end
48
+
49
+ private
50
+
51
+ def format(severity, datetime, progname, msg)
52
+ require 'json'
53
+ {
54
+ timestamp: datetime,
55
+ progname: progname,
56
+ severity: severity,
57
+ message: msg,
58
+ }.to_json + "\n"
59
+ end
60
+ end
61
+
62
+ class TextFormatter < FileFormatter
63
+ def initialize
64
+ super
65
+ @log_format = :text
66
+ end
67
+
68
+ private
69
+
70
+ def format(severity, _datetime, progname, msg)
71
+ "#{severity}: #{progname}: #{msg}\n"
72
+ end
73
+ end
74
+
75
+ class GithubActionFormatter < FileFormatter
76
+ SEV_MAP = {
77
+ 'DEBUG' => '::debug::',
78
+ 'INFO' => '::notice::',
79
+ 'WARN' => '::warning::',
80
+ 'ERROR' => '::error::',
81
+ 'FATAL' => '::error::',
82
+ }.freeze
83
+
84
+ def initialize
85
+ super
86
+ @log_format = :github_action
87
+ end
88
+
89
+ private
90
+
91
+ def format(severity, _datetime, progname, msg)
92
+ "#{SEV_MAP[severity]}[#{progname}] #{msg}\n"
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,27 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'logger'
4
+ require 'cem_acpt/logging/formatter'
4
5
 
5
6
  module CemAcpt
6
7
  # Logging for CemAcpt
7
8
  module Logging
8
9
  LEVEL_MAP = {
9
- 'debug' => Logger::DEBUG,
10
- 'info' => Logger::INFO,
11
- 'warn' => Logger::WARN,
12
- 'error' => Logger::ERROR,
13
- 'fatal' => Logger::FATAL,
14
- 'unknown' => Logger::UNKNOWN,
10
+ 'debug' => ::Logger::DEBUG,
11
+ 'info' => ::Logger::INFO,
12
+ 'warn' => ::Logger::WARN,
13
+ 'error' => ::Logger::ERROR,
14
+ 'fatal' => ::Logger::FATAL,
15
+ 'unknown' => ::Logger::UNKNOWN,
15
16
  }
16
17
 
17
18
  # Delegator class for when you want to log to multiple devices
18
19
  # at the same time, such as STDOUT and a file.
19
- # @param loggers [::Logger] one or more instances of Logger
20
+ # @param loggers [Logger] one or more instances of CemAcpt::Logging::Logger
20
21
  class MultiLogger
22
+ # @param configs [Array<Hash>] an array of hashes containing the
23
+ # configuration for each logger. Each hash must contain the keys
24
+ # :logdev, :shift_age, and :shift_size. The values for these keys
25
+ # are passed to the Logger.new method. Any other keys and values
26
+ # are passed to the Logger.new method as keyword arguments.
27
+ # @return [MultiLogger] a new instance of MultiLogger
28
+ def self.from_logger_configs(configs)
29
+ return if configs.nil? || configs.empty?
30
+
31
+ loggers = configs.map do |config|
32
+ CemAcpt::Logging::Logger.new(config[:logdev],
33
+ config[:shift_age],
34
+ config[:shift_size],
35
+ **config.except(:logdev, :shift_age, :shift_size))
36
+ end
37
+ new(*loggers)
38
+ end
39
+
21
40
  def initialize(*loggers)
22
41
  @loggers = loggers
23
42
  end
24
43
 
44
+ def logger_configs
45
+ @loggers.map(&:config_hash)
46
+ end
47
+
25
48
  def method_missing(m, *args, &block)
26
49
  if @loggers.all? { |l| l.respond_to?(m) }
27
50
  @loggers.map { |l| l.send(m, *args, &block) }
@@ -35,6 +58,137 @@ module CemAcpt
35
58
  end
36
59
  end
37
60
 
61
+ # Delagator class for the standard Ruby Logger class.
62
+ # This class is used to ensure the Github Actions formatter
63
+ # correctly formats the log output when using the standard
64
+ # Ruby Logger class methods such as #info, #debug, etc.
65
+ class Logger < ::Logger
66
+ attr_reader :config_hash
67
+ attr_accessor :trap_context
68
+
69
+ def initialize(logdev, shift_age = 0, shift_size = 1_048_576, **kwargs)
70
+ @config_hash = { logdev: logdev, shift_age: shift_age, shift_size: shift_size, **kwargs }
71
+ @ci_mode = (kwargs[:formatter].downcase.to_sym == :github_action || !ENV['GITHUB_ACTIONS'].nil? || !ENV['CI'].nil?)
72
+ kwargs[:formatter] = CemAcpt::Logging::Formatter.for(kwargs[:formatter]) if kwargs[:formatter]
73
+ super(logdev, shift_age, shift_size, **kwargs)
74
+ @raw_logdev = logdev # Used for logging from trap context
75
+ @trap_context = false # If true, will not use the standard Logger methods and will write directly to the logdev
76
+ @verbose = false
77
+ end
78
+
79
+ def set_verbose(value)
80
+ raise ArgumentError, 'value must be a boolean' unless [true, false].include?(value)
81
+
82
+ @verbose = value
83
+ end
84
+
85
+ def verbose(progname = nil, &block)
86
+ return unless @verbose
87
+
88
+ debug(progname, &block)
89
+ end
90
+
91
+ def debug(progname = nil, &block)
92
+ return if log_trap_context('debug', progname, &block)
93
+ return if log_ci_mode('debug', progname, &block)
94
+
95
+ super
96
+ end
97
+
98
+ def info(progname = nil, &block)
99
+ return if log_trap_context('info', progname, &block)
100
+ return if log_ci_mode('info', progname, &block)
101
+
102
+ super
103
+ end
104
+
105
+ def warn(progname = nil, &block)
106
+ return if log_trap_context('warn', progname, &block)
107
+ return if log_ci_mode('warn', progname, &block)
108
+
109
+ super
110
+ end
111
+
112
+ def error(progname = nil, &block)
113
+ return if log_trap_context('error', progname, &block)
114
+ return if log_ci_mode('error', progname, &block)
115
+
116
+ super
117
+ end
118
+
119
+ def fatal(progname = nil, &block)
120
+ return if log_trap_context('fatal', progname, &block)
121
+ return if log_ci_mode('fatal', progname, &block)
122
+
123
+ super
124
+ end
125
+
126
+ # Wraps the given block in a Github Actions group if in CI mode
127
+ # @param name [String] the name of the group
128
+ def with_ci_group(name)
129
+ return yield unless @ci_mode
130
+
131
+ self.<< "::group::#{name}\n"
132
+ yield
133
+ ensure
134
+ self.<< "::endgroup::\n" if @ci_mode
135
+ end
136
+
137
+ private
138
+
139
+ # Can't use the standard Logger methods when in trap context
140
+ # because they don't work. So we have to write directly to the
141
+ # raw logdev. Unlike the standard Logger methods, there is no
142
+ # Mutex lock, so messages are not guaranteed to be in order.
143
+ # This is necessary in the trap context because using a Mutex
144
+ # lock in a trap context will cause a deadlock.
145
+ def log_trap_context(severity, progname = nil, &block)
146
+ return false unless @trap_context && level <= LEVEL_MAP[severity]
147
+
148
+ if @raw_logdev.respond_to?(:puts)
149
+ @raw_logdev.puts(ci_format(severity, false, progname, &block))
150
+ elsif @raw_logdev.respond_to?(:write)
151
+ @raw_logdev.write(ci_format(severity, true, progname, &block))
152
+ else
153
+ # Default to logging to STDERR
154
+ $stderr.puts(ci_format(severity, false, progname, &block))
155
+ end
156
+ true
157
+ end
158
+
159
+ # CI mode uses << instead of the standard Logger methods
160
+ # because Github Actions wants messages to be echoed. This
161
+ # is a way to ensure that, in the event of using a multi-logger
162
+ # with a standard Logger, the CI mode messages are still
163
+ # formatted correctly.
164
+ def log_ci_mode(severity, progname = nil, &block)
165
+ return false unless @ci_mode && level <= LEVEL_MAP[severity]
166
+
167
+ self.<<(ci_format(severity, true, progname, &block))
168
+ true
169
+ end
170
+
171
+ # Formats the log message for CI mode, translating the severity
172
+ # level to the correct format for Github Actions and adding
173
+ # the colon separators.
174
+ def ci_format(severity, newline = true, progname = nil, &block)
175
+ sev = if severity == 'fatal'
176
+ 'error'
177
+ elsif severity == 'warn'
178
+ 'warning'
179
+ elsif severity == 'info'
180
+ 'notice'
181
+ else
182
+ severity
183
+ end
184
+ block_message = block_given? ? block.call : nil
185
+ base = [progname, block_message].compact.join(': ')
186
+ return if base.empty?
187
+
188
+ newline ? "::#{sev}::#{base}\n" : "::#{sev}::#{base}"
189
+ end
190
+ end
191
+
38
192
  class << self
39
193
  def new_logger(*logdevs, **configs)
40
194
  new_configs = current_log_config.merge(configs.reject { |_, v| v.nil? })
@@ -57,14 +211,9 @@ module CemAcpt
57
211
 
58
212
  # Exposes a logger instance. Will either use the currently set logger or
59
213
  # create a new one.
60
- # @return [Logger]
214
+ # @return [MultiLogger]
61
215
  def logger
62
- @logger ||= Logger.new(
63
- current_log_config[:logdev],
64
- current_log_config[:shift_age],
65
- current_log_config[:shift_size],
66
- **current_log_config.reject { |k, _| %i[logdev shift_age shift_size].include?(k) }
67
- )
216
+ @logger ||= new_logger($stdout)
68
217
  end
69
218
 
70
219
  # Shortcut method for logger.level
@@ -92,41 +241,7 @@ module CemAcpt
92
241
  # @param f [Symbol] the log format style to set
93
242
  # @return [Proc] the proc to be passed to Logger#formatter=
94
243
  def new_log_formatter(f)
95
- case f.downcase.to_sym
96
- when :json
97
- require 'json'
98
- @current_log_format = :json
99
- proc do |severity, datetime, progname, msg|
100
- {
101
- timestamp: datetime,
102
- progname: progname,
103
- severity: severity,
104
- message: msg,
105
- }.to_json + "\n"
106
- end
107
- when :text
108
- @current_log_format = :text
109
- proc do |severity, _datetime, _progname, msg|
110
- "#{severity} - #{msg}\n"
111
- end
112
- when :github_action
113
- @current_log_format = :github_action
114
- sev_map = {
115
- 'DEBUG' => '::debug::',
116
- 'INFO' => '::notice::',
117
- 'WARN' => '::warning::',
118
- 'ERROR' => '::error::',
119
- 'FATAL' => '::error::',
120
- }
121
- proc do |severity, _datetime, _progname, msg|
122
- "#{sev_map[severity]}{#{msg}}\n"
123
- end
124
- else
125
- @current_log_format = :file
126
- proc do |severity, datetime, _progname, msg|
127
- "[#{datetime}] #{severity}: #{msg}\n"
128
- end
129
- end
244
+ CemAcpt::Logging::Formatter.for(f)
130
245
  end
131
246
 
132
247
  # Returns the current log config if set, or the default if not.
@@ -134,15 +249,14 @@ module CemAcpt
134
249
  def current_log_config
135
250
  return @log_config if @log_config
136
251
 
137
- formatter = new_log_formatter(current_log_format)
138
252
  @log_config = {
139
253
  logdev: $stdout,
140
254
  shift_age: 'o',
141
255
  shift_size: 1_048_576,
142
- level: Logger::INFO,
256
+ level: ::Logger::INFO,
143
257
  progname: 'CemAcpt',
144
258
  datetime_format: '%Y%m%dT%H%M%S%z',
145
- formatter: formatter,
259
+ formatter: current_log_format,
146
260
  }
147
261
  @log_config
148
262
  end
@@ -177,12 +291,12 @@ module CemAcpt
177
291
  @log_config[:logdev] = $stdout
178
292
  logger.warn("Unknown log target: #{logdev.inspect}, using STDOUT")
179
293
  end
180
- @logger = Logger.new(
294
+ @logger = MultiLogger.new(Logger.new(
181
295
  @log_config[:logdev],
182
296
  @log_config[:shift_age],
183
297
  @log_config[:shift_size],
184
298
  **@log_config.reject { |k, _| %i[logdev shift_age shift_size].include?(k) },
185
- )
299
+ ))
186
300
  end
187
301
  end
188
302
 
@@ -260,92 +374,4 @@ module CemAcpt
260
374
  CemAcpt::Logging.new_log_config(logdev: logdev, shift_age: shift_age, shift_size: shift_size, level: level, formatter: formatter, datetime_format: datetime_format)
261
375
  end
262
376
  end
263
-
264
- module LoggingAsync
265
- require 'concurrent-ruby'
266
-
267
- class << self
268
- def log_write_thread
269
- @log_write_thread ||= Concurrent::SingleThreadExecutor.new
270
- end
271
-
272
- def async_debug(message, prefix = nil)
273
- msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
274
- CemAcpt::Logging.logger.debug(msg)
275
- end
276
-
277
- def async_info(message, prefix = nil)
278
- msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
279
- CemAcpt::Logging.logger.info(msg)
280
- end
281
-
282
- def async_warn(message, prefix = nil)
283
- msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
284
- CemAcpt::Logging.logger.warn(msg)
285
- end
286
-
287
- def async_error(message, prefix = nil)
288
- msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
289
- CemAcpt::Logging.logger.error(msg)
290
- end
291
-
292
- def async_fatal(message, prefix = nil)
293
- msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
294
- CemAcpt::Logging.logger.fatal(msg)
295
- end
296
- end
297
-
298
- # Provides class method wrappers for logging methods
299
- def self.included(base)
300
- class << base
301
- def log_write_thread
302
- CemAcpt::LoggingAsync.log_write_thread
303
- end
304
-
305
- def async_debug(message, prefix = nil)
306
- CemAcpt::LoggingAsync.async_debug(message, prefix)
307
- end
308
-
309
- def async_info(message, prefix = nil)
310
- CemAcpt::LoggingAsync.async_info(message, prefix)
311
- end
312
-
313
- def async_warn(message, prefix = nil)
314
- CemAcpt::LoggingAsync.async_warn(message, prefix)
315
- end
316
-
317
- def async_error(message, prefix = nil)
318
- CemAcpt::LoggingAsync.async_error(message, prefix)
319
- end
320
-
321
- def async_fatal(message, prefix = nil)
322
- CemAcpt::LoggingAsync.async_fatal(message, prefix)
323
- end
324
- end
325
- end
326
-
327
- def log_write_thread
328
- CemAcpt::LoggingAsync.log_write_thread
329
- end
330
-
331
- def async_debug(message, prefix = nil)
332
- CemAcpt::LoggingAsync.async_debug(message, prefix)
333
- end
334
-
335
- def async_info(message, prefix = nil)
336
- CemAcpt::LoggingAsync.async_info(message, prefix)
337
- end
338
-
339
- def async_warn(message, prefix = nil)
340
- CemAcpt::LoggingAsync.async_warn(message, prefix)
341
- end
342
-
343
- def async_error(message, prefix = nil)
344
- CemAcpt::LoggingAsync.async_error(message, prefix)
345
- end
346
-
347
- def async_fatal(message, prefix = nil)
348
- CemAcpt::LoggingAsync.async_fatal(message, prefix)
349
- end
350
- end
351
377
  end