chili_logger 0.0.10 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -11,7 +11,8 @@ Gem::Specification.new do |spec|
11
11
  spec.homepage = 'https://gitlab.com/chiligumdev/chili_logger'
12
12
  spec.license = 'MIT'
13
13
  spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
14
- spec.add_dependency 'aws-sdk', '~> 2.9', '>= 2.9.0'
14
+ spec.add_dependency 'aws-sdk-sqs', '~> 1.30.0'
15
+ spec.add_dependency 'aws-sdk-secretsmanager', '~> 1.36.0'
15
16
  spec.add_dependency 'bunny'
16
17
  spec.add_dependency 'httparty'
17
18
 
@@ -0,0 +1,49 @@
1
+ require 'errors/error_messages/config_error'
2
+ require 'brokers/rabbit_broker'
3
+
4
+ # class for centralizing Creative's logging logic
5
+ class ChiliLogger
6
+ # class that configures and manages all supported brokers
7
+ class MainBroker
8
+ def initialize(broker_name, broker_config, logging_error_handler)
9
+ return if ChiliLogger.instance.deactivated
10
+
11
+ @default = ChiliLogger::Values::Default.new
12
+ @logging_error_handler = logging_error_handler
13
+ broker_config ||= {}
14
+ validate_config(broker_config)
15
+
16
+ broker_name ||= @default.msg_broker
17
+ broker_class = supported_brokers[broker_name.to_sym]
18
+ unsupported_broker_error(broker_name) unless broker_class
19
+
20
+ @broker = broker_class.new(broker_config)
21
+ end
22
+
23
+ def publish(message)
24
+ return if ChiliLogger.instance.deactivated
25
+
26
+ @broker.publish(message)
27
+ rescue StandardError => e
28
+ @logging_error_handler.handle_error(e, message)
29
+ end
30
+
31
+ private
32
+
33
+ def validate_config(config)
34
+ invalid_config_err = ':msg_broker_config must be a hash'
35
+ raise(ChiliLogger::ConfigError, invalid_config_err) unless [Hash, NilClass].include?(config.class)
36
+ end
37
+
38
+ def unsupported_broker_error(broker_name)
39
+ err_msg = "'#{broker_name}' is not a supported broker_name. Supported broker_names: #{supported_brokers}"
40
+ raise(ConfigError, err_msg)
41
+ end
42
+
43
+ def supported_brokers
44
+ {
45
+ rabbitmq: RabbitBroker
46
+ }
47
+ end
48
+ end
49
+ end
@@ -1,23 +1,21 @@
1
1
  require 'bunny'
2
2
  require 'brokers/sqs_broker'
3
+ require 'helpers/values/secrets/secrets'
3
4
 
4
5
  # class for centralizing Creative's logging logic
5
6
  class ChiliLogger
6
7
  # class that configures and manages the RabbitMQ client
7
8
  class RabbitBroker
8
- def initialize(logging_error_handler)
9
- @logging_error_handler = logging_error_handler
10
- end
11
-
12
- def config(config)
13
- validate_config(config)
9
+ def initialize(custom_config = {})
10
+ custom_config ||= {}
11
+ config = rabbit_config(custom_config)
14
12
 
15
13
  @user = config[:user]
16
14
  @password = config[:password]
17
15
  @ip = config[:ip]
18
16
  @port = config[:port]
19
17
  @exchange_name = config[:exchange_name]
20
- @routing_key_overwriter = config[:routing_key_overwriter]
18
+ @routing_key_overwriter = custom_config[:routing_key_overwriter]
21
19
 
22
20
  connect
23
21
  end
@@ -30,39 +28,22 @@ class ChiliLogger
30
28
 
31
29
  @channel = @connection.create_channel
32
30
  @exchange = @channel.topic(@exchange_name, durable: true)
33
-
34
31
  rescue StandardError => e
35
32
  puts 'Could not connect to RabbitMQ due to the following error:'
36
33
  puts e
37
34
  end
38
35
 
39
- def disconnect
40
- @connection.close
41
- end
42
-
43
- def publish(message, routing_key)
36
+ def publish(message)
44
37
  return if ChiliLogger.instance.deactivated
45
38
 
46
- # if no routing_key was provided when configuring RabbitBroker, than use the one received by the method here
47
- # temporary solution so we can force configure ChiliLogger to use a specific routing_key
48
- key = @routing_key_overwriter || routing_key
39
+ # if no routing_key was provided when configuring RabbitBroker, than use the message's description tag
40
+ key = @routing_key_overwriter || message[:desc] || message['desc']
49
41
  @exchange.publish(message.to_json, routing_key: key)
50
42
  puts "sent message to #{@exchange_name}, with routing_key = '#{key}'"
51
-
52
- rescue StandardError => e
53
- @logging_error_handler.handle_error(e, message)
54
43
  end
55
44
 
56
45
  private
57
46
 
58
- def invalid_config_format_error
59
- 'The configuration object must be a Hash'
60
- end
61
-
62
- def config_attr_error(attr)
63
- "The configuration object must include a ':#{attr}' attribute"
64
- end
65
-
66
47
  def connection_config
67
48
  {
68
49
  user: @user,
@@ -72,11 +53,16 @@ class ChiliLogger
72
53
  }
73
54
  end
74
55
 
75
- def validate_config(config)
76
- raise(ChiliLogger::ConfigError, invalid_config_format_error) unless config.is_a?(Hash)
56
+ def rabbit_config(custom_config)
57
+ default_secrets = Values::Secrets.new.get_secrets_collection('ChiliLoggerRabbitCredentials')
58
+ default_keys = %i[user password ip port exchange_name]
59
+ config = {}
60
+
61
+ default_keys.each do |key|
62
+ config[key] = custom_config[key] || default_secrets[key.to_s]
63
+ end
77
64
 
78
- main_config_keys = %i[user password ip port exchange_name]
79
- main_config_keys.each { |key| raise(ChiliLogger::ConfigError, config_attr_error(key)) unless config[key] }
65
+ config
80
66
  end
81
67
  end
82
68
  end
@@ -1,4 +1,4 @@
1
- require 'aws-sdk'
1
+ require 'aws-sdk-sqs'
2
2
 
3
3
  # class for centralizing Creative's logging logic
4
4
  class ChiliLogger
@@ -6,21 +6,50 @@ class ChiliLogger
6
6
  module AWS
7
7
  # class that handles errors when message broker can't be reached, etc...
8
8
  class SqsBroker
9
- def initialize(config)
10
- @sqs_config = validate_config(config)
11
- @queue_name = config[:queue_name]
9
+ def initialize(custom_config = {})
10
+ custom_config ||= {}
11
+
12
+ @default_secrets = Values::Secrets.new.get_secrets_collection('ChiliLoggerSQSCredentials')
12
13
  @default = ChiliLogger::Values::Default.new
14
+ @queue_name = custom_config[:queue_name] || @default_secrets['queue_name']
13
15
 
16
+ @sqs_config = sqs_config(custom_config)
14
17
  @sqs = Aws::SQS::Client.new(@sqs_config)
18
+
19
+ ENV['AWS_REGION'] = @sqs_config[:region] # Aws::SQS::QueuePoller requires region as an env variable
20
+ @poller = Aws::SQS::QueuePoller.new(queue_url(@queue_name), skip_delete: true)
15
21
  end
16
22
 
17
23
  def publish(message = @default.sqs_message)
24
+ return if ChiliLogger.instance.deactivated
25
+
18
26
  message_body = { body: message }
19
27
  queue_message = queue_message(message_body)
20
28
 
21
29
  @sqs.send_message(queue_message)
22
30
  end
23
31
 
32
+ def fetch_messages
33
+ return if ChiliLogger.instance.deactivated
34
+
35
+ messages = []
36
+ remaining_msgs = num_of_msgs_in_queue
37
+ return messages unless remaining_msgs.positive?
38
+
39
+ @poller.poll do |sqs_msg|
40
+ messages << { fallback_broker_msg: sqs_msg, log: JSON.parse(sqs_msg.body)['body']['log'] }
41
+
42
+ remaining_msgs -= 1
43
+ throw :stop_polling if remaining_msgs <= 0 # prevents infinite loop
44
+ end
45
+
46
+ messages
47
+ end
48
+
49
+ def delete_message(msg)
50
+ @poller.delete_messages([msg])
51
+ end
52
+
24
53
  private
25
54
 
26
55
  def queue_message(message_body)
@@ -36,25 +65,20 @@ class ChiliLogger
36
65
  @sqs.get_queue_url(queue_name: queue_name).queue_url
37
66
  end
38
67
 
39
- def invalid_config_format_error
40
- 'The :error_hanldler_config object must be a Hash'
68
+ def num_of_msgs_in_queue
69
+ sqs_queue_attrs = @sqs.get_queue_attributes(queue_url: queue_url(@queue_name), attribute_names: ['All'])
70
+ sqs_queue_attrs.attributes['ApproximateNumberOfMessages'].to_i
41
71
  end
42
72
 
43
- def config_attr_error(attr)
44
- "The configuration object must include a ':#{attr}' attribute"
45
- end
73
+ def sqs_config(custom_config)
74
+ default_keys = %i[region access_key_id secret_access_key]
75
+ config = {}
46
76
 
47
- def validate_config(config)
48
- raise(ChiliLogger::ConfigError, invalid_config_format_error) unless config.is_a?(Hash)
77
+ default_keys.each do |key|
78
+ config[key] = custom_config[key] || @default_secrets[key.to_s]
79
+ end
49
80
 
50
- main_config_keys = %i[region access_key_id secret_access_key queue_name]
51
- main_config_keys.each { |key| raise(ChiliLogger::ConfigError, config_attr_error(key)) unless config[key] }
52
-
53
- {
54
- region: config[:region],
55
- access_key_id: config[:access_key_id],
56
- secret_access_key: config[:secret_access_key]
57
- }
81
+ config
58
82
  end
59
83
  end
60
84
  end
@@ -1,15 +1,14 @@
1
+ require 'singleton'
2
+ require 'brokers/main_broker'
1
3
  require 'chili_logger/version'
2
4
  require 'current_log_accessor'
3
- require 'errors/error_messages/config_error'
4
5
  require 'errors/logging_error_handler/logging_error_handler'
5
- require 'brokers/rabbit_broker'
6
- require 'message_writer/message_writer'
7
- require 'brokers/sqs_broker'
8
6
  require 'helpers/values/default'
9
7
  require 'helpers/values/type_uniformizer/desc'
10
8
  require 'helpers/values/type_uniformizer/user'
11
9
  require 'helpers/values/type_uniformizer/main_content'
12
- require 'singleton'
10
+ require 'message_writer/message_writer'
11
+ require 'unpublished_logs_manager/unpublished_logs_manager'
13
12
 
14
13
  # class for centralizing Creative's logging logic
15
14
  class ChiliLogger
@@ -32,6 +31,7 @@ class ChiliLogger
32
31
  config_logging_error_handler(config)
33
32
  config_msg_writer(config)
34
33
  config_msg_broker(config)
34
+ config_unpublished_logs_manager
35
35
 
36
36
  @current_log_accessor = CurrentLogAccessor.new(@msg_broker, @msg_writer)
37
37
  end
@@ -59,16 +59,16 @@ class ChiliLogger
59
59
  end
60
60
 
61
61
  message = @msg_writer.write(options)
62
- routing_key = @msg_writer.write_description_tag(options[:desc])
62
+ @msg_broker.publish(message)
63
+ end
63
64
 
64
- @msg_broker.publish(message, routing_key)
65
+ def republish_unpublished_logs
66
+ @unpublished_logs_manager.republish
65
67
  end
66
68
 
67
69
  private
68
70
 
69
71
  def config_logging_error_handler(general_config)
70
- return @logging_error_handler = nil if @deactivated
71
-
72
72
  fallback_name = general_config[:fallback_broker]
73
73
  fallback_config = general_config[:fallback_broker_config]
74
74
  @logging_error_handler = LoggingErrorHandler.new(fallback_name, fallback_config)
@@ -76,8 +76,8 @@ class ChiliLogger
76
76
 
77
77
  def config_msg_writer(general_config)
78
78
  msg_writer_config = {
79
- env: general_config[:log_env],
80
- layer: general_config[:log_layer],
79
+ env: general_config[:log_env]&.downcase,
80
+ layer: general_config[:log_layer]&.downcase,
81
81
  server_url: general_config[:server_url],
82
82
  cloud_provider: general_config[:cloud_provider]
83
83
  }
@@ -86,26 +86,13 @@ class ChiliLogger
86
86
  end
87
87
 
88
88
  def config_msg_broker(general_config)
89
- msg_broker_name = general_config[:msg_broker_name] || @default.msg_broker
90
- msg_broker_config = general_config[:msg_broker_config] || @default.msg_broker_config
91
- @msg_broker = supported_msg_brokers[msg_broker_name.to_sym]
92
- raise(ConfigError, broker_name_error(msg_broker_name)) unless @msg_broker
93
-
94
- # TODO: implement MessageBroker class, an interface between ChiliLogger and possible brokers.
95
- # TODO: add "supported_msg_broker", "broker_name_error" and "return @msg_broker if @deactivated" to MessageBroker
96
- # prevents broker from even starting connection if ChiliLogger is deactivated
97
- return @msg_broker if @deactivated
89
+ msg_broker_name = general_config[:msg_broker_name]
90
+ msg_broker_config = general_config[:msg_broker_config]
98
91
 
99
- @msg_broker.config(msg_broker_config)
92
+ @msg_broker = MainBroker.new(msg_broker_name, msg_broker_config, @logging_error_handler)
100
93
  end
101
94
 
102
- def broker_name_error(msg_broker_name)
103
- "#{msg_broker_name} is not supported. Supported msg_broker_names: #{supported_msg_brokers}"
104
- end
105
-
106
- def supported_msg_brokers
107
- {
108
- rabbitmq: RabbitBroker.new(@logging_error_handler)
109
- }
95
+ def config_unpublished_logs_manager
96
+ @unpublished_logs_manager = UnpublishedLogsManager.new(@msg_broker, @logging_error_handler)
110
97
  end
111
98
  end
@@ -1,3 +1,3 @@
1
1
  class ChiliLogger
2
- VERSION = "0.0.10"
2
+ VERSION = '0.1.4'.freeze
3
3
  end
@@ -1,9 +1,7 @@
1
1
  require 'message_writer/message_writer'
2
- require 'helpers/values/default'
3
2
  require 'helpers/values/type_uniformizer/desc'
4
3
  require 'helpers/values/type_uniformizer/main_content'
5
4
  require 'helpers/values/type_uniformizer/user'
6
- require 'byebug'
7
5
 
8
6
  # class for centralizing Creative's logging logic
9
7
  class ChiliLogger
@@ -20,11 +18,9 @@ class ChiliLogger
20
18
 
21
19
  def publish(**options)
22
20
  update_current_log(options)
23
-
24
21
  message = @msg_writer.write(desc: desc, user: user, main_content: main_content)
25
- routing_key = @msg_writer.write_description_tag(desc)
22
+ @msg_broker.publish(message)
26
23
 
27
- @msg_broker.publish(message, routing_key)
28
24
  clear_log_info
29
25
  end
30
26
 
@@ -5,31 +5,48 @@ require 'errors/error_messages/config_error'
5
5
  class ChiliLogger
6
6
  # class that handles errors when message broker can't be reached, etc...
7
7
  class LoggingErrorHandler
8
- def initialize(fallback_name, config)
9
- raise(ChiliLogger::ConfigError, ':fallback_broker_config must be present and be a hash') unless config.is_a?(Hash)
8
+ def initialize(fallback_name = nil, config = {})
9
+ return if ChiliLogger.instance.deactivated
10
10
 
11
- fallback_name = fallback_name.to_sym if fallback_name
12
- fallback_broker_class = supported_fallback_brokers[fallback_name]
11
+ @default = ChiliLogger::Values::Default.new
12
+ config ||= {}
13
+ validate_config(config)
14
+
15
+ fallback_name ||= @default.fallback_broker
16
+ fallback_broker_class = supported_fallback_brokers[fallback_name.to_sym]
13
17
  unsupported_fallback_broker_error unless fallback_broker_class
14
18
 
15
19
  @fallback_broker = fallback_broker_class.new(config)
16
20
  end
17
21
 
18
22
  def handle_error(error, log = nil)
23
+ return if ChiliLogger.instance.deactivated
24
+
19
25
  message = message(error, log)
20
26
  @fallback_broker.publish(message)
21
27
  rescue StandardError => e
22
- puts '
23
- There was a problem with both the Message Broker and the Fallback Broker simultaneously.
28
+ puts 'There was a problem with both the Message Broker and the Fallback Broker simultaneously.
24
29
  To keep the application running and prevent downtime,
25
30
  ChiliLogger will ignore this errors and discard the log it was currently trying to publish.
26
- Please note that logs are being permanently lost.
27
- '
31
+ Please note that logs are being permanently lost.'
28
32
  puts e
29
33
  end
30
34
 
35
+ def fetch_unpublished_logs
36
+ @fallback_broker.fetch_messages
37
+ end
38
+
39
+ def delete_unpublished_log(msg)
40
+ @fallback_broker.delete_message(msg)
41
+ end
42
+
31
43
  private
32
44
 
45
+ def validate_config(config)
46
+ invalid_config_err = ':fallback_broker_config must be a hash'
47
+ raise(ChiliLogger::ConfigError, invalid_config_err) unless [Hash, NilClass].include?(config.class)
48
+ end
49
+
33
50
  def message(error, log)
34
51
  {
35
52
  error_type: error.class.name,
@@ -1,6 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'fileutils'
3
- require 'helpers/values/default'
3
+ require 'byebug'
4
4
 
5
5
  # class for centralizing Creative's logging logic
6
6
  class ChiliLogger
@@ -22,8 +22,10 @@ class ChiliLogger
22
22
 
23
23
  def self.read_file
24
24
  file_exists = File.file?(file_path)
25
+ file = file_exists ? YAML.load_file(file_path) : {}
25
26
 
26
- file_exists ? YAML.load_file(file_path) : {}
27
+ # workaround for a bug in YAML lib, in which #load_file returns nil if file is empty, instead of an empty hash
28
+ file.nil? ? {} : file
27
29
  end
28
30
 
29
31
  def self.write_file(file)