RTALogger 2.0.2 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8fb5a3e4e0c67b6e485cf932ab274fc5a55539fb6432e76e119c0877d786c23
4
- data.tar.gz: 57c69c4601f00d24c395fd42b8a75fe74020a5f9b5222b14e38fe9c673134c97
3
+ metadata.gz: 79dce21ae1cfe72961d564f9e750e49db0adcd564885293e971d482b1df6bf87
4
+ data.tar.gz: 44e1d3ae6c92779f6b69677a103c3614f4b2c03429a917c4f61c801b9ab43574
5
5
  SHA512:
6
- metadata.gz: 22b65c1867090cadd8aaff4f735ef401be30fe890e3164b7a45b5df40979ee0d5439d5c2fae66273c929e4c821abaa928b208b2e7c6ad535908be48b2923bea2
7
- data.tar.gz: 191367dfa21447a54f6ad218ed0f66d0615297b126e6a9aeda446c82900f05fbd457fbe0f200d860885be4f2760dd04a62e008634bc525c2e8554d5784883fc5
6
+ metadata.gz: 78bcdaa73b75e68da879c9f60fe9f3c0b0f9d914269572dc53fbaa3e02d5f1ecf56c35af42b33794675f3b4299f8a247f83aba846e1e9e2bbea18853a277b81d
7
+ data.tar.gz: 46b518ac6a9a2df21fd44cfffe3a4ca23e5c6aaba425d8bf5945efb9f590c5a92e945aac407488410f37a897ffb00f42dd0a0d90758eb15495bbab5811ff9bcc
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- RTALogger (2.0.2)
4
+ RTALogger (2.2.2)
5
5
  fluent-logger (~> 0.9)
6
6
  jbuilder (~> 2.10)
7
7
 
data/README.md CHANGED
@@ -94,7 +94,7 @@ To use log manager APIs, first step is to have a quick review on Log Data Struct
94
94
  "app_name": "TestApp",
95
95
  "severity_level": "trace",
96
96
  "buffer_size": 100,
97
- "flush_wait_seconds": 10,
97
+ "flush_wait_seconds": 5,
98
98
  "repositories":
99
99
  [
100
100
  {
@@ -104,8 +104,24 @@ To use log manager APIs, first step is to have a quick review on Log Data Struct
104
104
  "formatter":
105
105
  {
106
106
  "type": "text",
107
- "delimiter": "|"
108
- }
107
+ "delimiter": "|",
108
+ "colorize": true
109
+ },
110
+ "filters":
111
+ [
112
+ {
113
+ "type": "topic",
114
+ "title": "topic_filter_1",
115
+ "enable": true,
116
+ "default_regex" : "^test$"
117
+ },
118
+ {
119
+ "type": "message",
120
+ "title": "message_filter_1",
121
+ "enable": false,
122
+ "default_regex" : "error"
123
+ }
124
+ ]
109
125
  },
110
126
  {
111
127
  "type": "file",
@@ -121,8 +137,8 @@ To use log manager APIs, first step is to have a quick review on Log Data Struct
121
137
  }
122
138
  },
123
139
  {
124
- "enable": true,
125
- "title": "console_repo_1",
140
+ "enable": false,
141
+ "title": "fluentd_repo_1",
126
142
  "type": "fluentd",
127
143
  "host": "localhost",
128
144
  "port": "8888",
@@ -191,7 +207,7 @@ the result will be:
191
207
  "app_name": "TestApp",
192
208
  "severity_level": "trace",
193
209
  "buffer_size": 100,
194
- "flush_wait_seconds": 10,
210
+ "flush_wait_seconds": 5,
195
211
  "repositories":
196
212
  [
197
213
  {
@@ -201,8 +217,24 @@ the result will be:
201
217
  "formatter":
202
218
  {
203
219
  "type": "text",
204
- "delimiter": "|"
205
- }
220
+ "delimiter": "|",
221
+ "colorize": true
222
+ },
223
+ "filters":
224
+ [
225
+ {
226
+ "type": "topic",
227
+ "title": "topic_filter_1",
228
+ "enable": true,
229
+ "default_regex" : "^test$"
230
+ },
231
+ {
232
+ "type": "message",
233
+ "title": "message_filter_1",
234
+ "enable": false,
235
+ "default_regex" : "error"
236
+ }
237
+ ]
206
238
  },
207
239
  {
208
240
  "type": "file",
@@ -218,8 +250,8 @@ the result will be:
218
250
  }
219
251
  },
220
252
  {
221
- "enable": true,
222
- "title": "console_repo_1",
253
+ "enable": false,
254
+ "title": "fluentd_repo_1",
223
255
  "type": "fluentd",
224
256
  "host": "localhost",
225
257
  "port": "8888",
@@ -261,7 +293,7 @@ the result will be:
261
293
  - buffer_size: Minimune possible value for this attribute is 100 and defines memory buffer size (number of buffered log objects) to
262
294
  decread api consumers wait time. when the buffer is full the flush operation will
263
295
  save buffered logs to log repositoies.
264
- - flush_wait_seconds: Minimum possible value for this attribure is 10 seconds and defines time in soconds which log managers wait to flush buffered log records
296
+ - flush_wait_seconds: Minimum possible value for this attribure is 5 seconds and defines time in soconds which log managers wait to flush buffered log records
265
297
  to log repository.
266
298
  - repositories: Array of log repositories. It is possible to define multiple log repositories to
267
299
  store log data. there are variaty of log repositories and it is possible to
@@ -275,6 +307,8 @@ the result will be:
275
307
  - "foramtter" is the text, json or any custome defined types as LogRecord formatter
276
308
  - "type": ["text"/"json"] type of formatter
277
309
  - "delimiter": [any text delimiter you need.(as an instance pipe line "|")]
310
+ - "colorize": [true/false] default value of this attribute is false.
311
+ if you need to colorize your out put format on standard output set this attribute to true.
278
312
  if formatter not defined then the json formatter will be used
279
313
  2- file: Store log data in a file.
280
314
  - "type": "console"
@@ -302,13 +336,30 @@ the result will be:
302
336
  - "type": ["text"/"json"] type of formatter
303
337
  - "delimiter": [any text delimiter you need.(as an instance pipe line "|")]
304
338
  if formatter not defined then the json formatter will be used
339
+ New Features:
340
+ * In RTALogger version 2.1.0 and above defineing filters is possible for each repository.
341
+ * Repositories filtes could restrict the amount of data stored by specific repository.
342
+ * Also you can add new repositories and filters at run time.
343
+ * filters configuration: It's possible to apply multiple filters on a repository. When repository will
344
+ flush a log_record only if the record pass all filter conditions.
345
+ * There are variaty of filter types, including:
346
+ 'topic' which apply a regular expresion on log_record.topic_title to pass filtering condition.
347
+ 'context' which apply a regular expresion on log_record.context_id to pass filtering condition.
348
+ 'message' which apply a regular expression on log_record.full_message to pass filtering condition.
349
+ * Each filter has following attributes to counfigure:
350
+ "type": ["topic"/"context"/"message" or any customized filter] described in previous lines.
351
+ "title": "filte_title" a unique title to make filter run time configuration
352
+ "enable": [true/false] this will enable or disable filtering opration of current filter.
353
+ "default_regex": "valid regual expression" to compare with corresponding attribute.
354
+ * It's possible to implement customize filter classes and integerate with RTALogger filter factory.
355
+ * In RTALogger version 2.2.0 colorize out put format is availabel.
305
356
  - topics: This is an optional item. When you need to customize a specific topic severity level or
306
357
  enable value, you can define the settings here.
307
358
  - title: The topic title to customize. (mandatoy).
308
359
  - severity_level: Defines which level of log data will be stored in log repositories.
309
360
  - enable: [true/false] to enable or disable logging process of the topic.
310
361
  ```
311
- ###Some useful features
362
+ ##Some useful features
312
363
  ```ruby
313
364
  # change log manager app name at run time
314
365
  log_manager.app_name = 'myTestApp'
@@ -341,17 +392,19 @@ the result will be:
341
392
  # log_manager.enable
342
393
  # log_manager.default_severity_level
343
394
  # log_manager.buffer_size (minimum is 100)
344
- # log_manager.flush_wait_time (minimum 15 second)
395
+ # log_manager.flush_wait_time (minimum 5 second)
345
396
  # repository.enable
346
397
  # topic.enable
347
398
  # topic.severity_level
348
399
  # Other attributes could only change via config file via manager config_use_json_file
400
+ # In RTALogger version 2.1.0 and above, it is possible to add new repositories or repository filters at run time
401
+ # using log_manager.apply_run_time_config method.
349
402
  log_manager.apply_run_time_config(config_json)
350
403
  ```
351
404
  ### Implement and Expand
352
- #### Implement new log repository
405
+ #### Implement new customized log repository
353
406
  It is possible to implement new log repositories. There will be fue rules to implement and
354
- integrate new customized log repository with RTALogger LogManager.
407
+ integrate new customized log repository with RTALogger LogManager factory.
355
408
 
356
409
  1- Define you class inside RTALogger module.
357
410
 
@@ -396,6 +449,91 @@ module RTALogger
396
449
  end
397
450
  ```
398
451
 
452
+ #### Implement new customized log repository filter
453
+ It is possible to implement new log repository filter. There will be fue rules to implement and
454
+ integrate new customized log repository filter with RTALogger LogManager factory.
455
+
456
+ 1- Define you class inside RTALogger module.
457
+
458
+ 2- The class should be inherited from 'RTALogger::LogFilterBase'.
459
+
460
+ 3- Also appropriate naming convention is necessary.
461
+ As an example if you are implementing a Console Repo, your class name should be LogFilterTopic and
462
+ your source code should be placed in a ruby file and name it log_filter_topic.rb
463
+
464
+ 4- After implementing your own log filter, you should register the class at run-time using the following syntax:
465
+ ```ruby
466
+ RTALogger::LogFactory.register_log_filter :topic, 'log_filter_topic.rb'
467
+ ```
468
+ Another example: LogFilterMyCustomizedFilter
469
+
470
+ ```ruby
471
+ RTALogger::LogFactory.register_log_filter :my_customized_filter, 'log_repository_my_customized_filter.rb'
472
+ ```
473
+ Here is 'LogRepositoryTopic' implementation:
474
+ ```ruby
475
+ require_relative 'log_filter_base'
476
+
477
+ module RTALogger
478
+ class LogFilterTopic < LogFilterBase
479
+ def match_conditions(log_record)
480
+ return true if !@enable
481
+ result = super
482
+ return result unless result
483
+
484
+ return default_regex.present? ? (Regexp.new(@default_regex).match(log_record.topic_title)) : result
485
+ end
486
+ end
487
+ end
488
+ ```
489
+ #### Implement new customized log formatter
490
+
491
+ It is possible to implement new log formatter. There will be fue rules to implement and
492
+ integrate new customized log formatter with RTALogger LogManager factory.
493
+
494
+ 1- Define you class inside RTALogger module.
495
+
496
+ 2- The class should be inherited from 'RTALogger::LogFormatter'.
497
+
498
+ 3- Also appropriate naming convention is necessary.
499
+ As an example if you are implementing a Text formatter, your class name should be LogFormatterText and
500
+ your source code should be placed in a ruby file and name it log_formatter_text.rb
501
+
502
+ 4- After implementing your own log formatter, you should register the class at run-time using the following syntax:
503
+ ```ruby
504
+ RTALogger::LogFactory.register_log_formatter :text, 'log_formatter_text.rb'
505
+ ```
506
+ Another example: LogFormatterMyCustomizedFormatter
507
+
508
+ ```ruby
509
+ RTALogger::LogFactory.register_log_formatter :my_customized_formatter, 'log_formatter_my_customized_formatter.rb'
510
+ ```
511
+ Here is 'LogFormatterText' implementation:
512
+ ```ruby
513
+ require_relative 'log_formatter_base'
514
+ require_relative 'severity_level'
515
+
516
+ module RTALogger
517
+ # text formatter which receive log_record and
518
+ # returns it's data as delimited text string
519
+ class LogFormatterText < LogFormatterBase
520
+ include SeverityLevel
521
+
522
+ def format(log_record)
523
+ return '' unless log_record
524
+
525
+ result = log_record.occurred_at.strftime('%F %H:%M:%S:%3N')
526
+ result << @delimiter << log_record.app_name
527
+ result << @delimiter << log_record.topic_title
528
+ result << @delimiter << log_record.context_id.to_s
529
+ result << @delimiter << parse_severity_level_to_s(log_record.severity)
530
+ result << @delimiter << log_record.message.join(' ').gsub(delimiter, '$<$')
531
+
532
+ result
533
+ end
534
+ end
535
+ end
536
+ ```
399
537
  ## Contributing
400
538
 
401
539
  Bug reports and pull requests are welcome on GitHub at https://github.com/BBahrainy/RTALogger.
@@ -1,3 +1,3 @@
1
1
  module RTALogger
2
- VERSION = '2.0.2'.freeze
2
+ VERSION = '2.2.2'.freeze
3
3
  end
@@ -0,0 +1,33 @@
1
+ require_relative 'log_filter_base'
2
+
3
+ module RTALogger
4
+ # Log factory to get new instance of log filter
5
+ module LogFactory
6
+ def self.create_filter(type, config_json = '')
7
+ lib_file = @log_filters[type.to_sym]
8
+ raise "unregistered filter class: #{type.to_s}" if lib_file.nil? || lib_file.empty?
9
+ begin
10
+ load lib_file
11
+ rescue
12
+ raise "unable to load formatter class file: #{lib_file}"
13
+ end
14
+
15
+ filter_class_name = 'RTALogger::' + ('log_filter_' + type.to_s).split('_').map(&:capitalize).join
16
+ filter_class = Object.const_get(filter_class_name)
17
+ return nil unless filter_class
18
+ result = filter_class.new
19
+
20
+ return result if config_json.empty?
21
+ result.load_config(config_json) if result.present?
22
+ return result
23
+ end
24
+
25
+ def self.register_log_filter(type, class_file_name)
26
+ @log_filters[type.to_sym] = class_file_name
27
+ end
28
+
29
+ @log_filters = {:topic => 'log_filter_topic.rb',
30
+ :context => 'log_filter_context.rb',
31
+ :message => 'log_filter_message.rb'}
32
+ end
33
+ end
@@ -21,7 +21,7 @@ module RTALogger
21
21
  return nil unless formatter_class
22
22
  result = formatter_class.new
23
23
 
24
- return result if config_json.empty?
24
+ return result if config_json.nil? || config_json.empty?
25
25
  result.load_config(config_json) if result.present?
26
26
  return result
27
27
  end
@@ -0,0 +1,39 @@
1
+ module RTALogger
2
+ class LogFilterBase
3
+ def initialize
4
+ @title = self.class.to_s.split('::').last.underscore
5
+ @enable = true
6
+ end
7
+
8
+ attr_accessor :title
9
+ attr_accessor :enable
10
+ attr_accessor :default_regex
11
+
12
+ def match_conditions(log_record)
13
+ return true if !@enable
14
+ return log_record.present?
15
+ end
16
+
17
+ def load_config(config_json)
18
+ @title = config_json['title'] if config_json['title'].present?
19
+ @enable = config_json['enable'].nil? ? true : config_json['enable'].present?
20
+ @default_regex = config_json['default_regex'] if config_json['default_regex'].present?
21
+ end
22
+
23
+ def apply_run_time_config(config_json)
24
+ @enable = config_json['enable'].nil? ? true : config_json['enable'].present?
25
+ @default_regex = config_json['default_regex'] if config_json['default_regex'].present?
26
+ end
27
+
28
+ def to_builder
29
+ jb = Jbuilder.new do |json|
30
+ json.type self.class.to_s.split('::').last.underscore.sub('log_filter_', '')
31
+ json.title @title
32
+ json.enable @enable
33
+ json.default_regex @default_regex
34
+ end
35
+
36
+ jb
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'log_filter_base'
2
+
3
+ module RTALogger
4
+ class LogFilterContext < LogFilterBase
5
+ def match_conditions(log_record)
6
+ return true if !@enable
7
+ result = super
8
+ return result unless result
9
+
10
+ return default_regex.present? ? (Regexp.new(@default_regex).match(log_record.context_id.to_s)) : result
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'log_filter_base'
2
+
3
+ module RTALogger
4
+ class LogFilterMessage < LogFilterBase
5
+ def match_conditions(log_record)
6
+ return true if !@enable
7
+ result = super
8
+ return result unless result
9
+
10
+ return default_regex.present? ? (Regexp.new(@default_regex).match(log_record.full_message)) : result
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'log_filter_base'
2
+
3
+ module RTALogger
4
+ class LogFilterTopic < LogFilterBase
5
+ def match_conditions(log_record)
6
+ return true if !@enable
7
+ result = super
8
+ return result unless result
9
+
10
+ return default_regex.present? ? (Regexp.new(@default_regex).match(log_record.topic_title)) : result
11
+ end
12
+ end
13
+ end
@@ -1,16 +1,24 @@
1
1
  require 'jbuilder'
2
2
  require_relative 'string'
3
+ require_relative 'severity_level'
3
4
 
4
5
  module RTALogger
5
6
  class LogFormatterBase
7
+ include SeverityLevel
8
+
6
9
  def initialize
7
10
  @delimiter = '|'
11
+ @colorize = false
8
12
  end
9
13
 
10
14
  attr_accessor :delimiter
15
+ attr_accessor :colorize
11
16
 
12
17
  def load_config(config_json)
18
+ return unless config_json.present?
19
+
13
20
  @delimiter = config_json['delimiter'].nil? ? true : config_json['delimiter']
21
+ @colorize = config_json['colorize'].nil? ? false : config_json['colorize']
14
22
  end
15
23
 
16
24
  def format(log_record)
@@ -20,7 +28,8 @@ module RTALogger
20
28
  def to_builder
21
29
  jb = Jbuilder.new do |json|
22
30
  json.type self.class.to_s.split('::').last.underscore.sub('log_formatter_', '')
23
- json.delimiter delimiter
31
+ json.delimiter @delimiter
32
+ json.colorize @colorize
24
33
  end
25
34
 
26
35
  jb
@@ -29,5 +38,41 @@ module RTALogger
29
38
  def reveal_config
30
39
  to_builder.target!
31
40
  end
41
+
42
+ def apply_run_time_config(config_json)
43
+ return unless config_json.present?
44
+
45
+ @delimiter = config_json['delimiter'] unless config_json['delimiter'].nil?
46
+ @colorize = config_json['colorize'] unless config_json['colorize'].nil?
47
+ end
48
+
49
+ protected
50
+
51
+ def severity_text(severity)
52
+ text = parse_severity_level_to_s(severity)
53
+ text = severity_colorized_text(severity, text) if @colorize
54
+ return text
55
+ end
56
+
57
+ def severity_colorized_text(severity, text)
58
+ case severity
59
+ when 0
60
+ text.trace_color
61
+ when 1
62
+ text.debug_color
63
+ when 2
64
+ text
65
+ when 3
66
+ text.warning_color
67
+ when 4
68
+ text.error_color
69
+ when 5
70
+ text.fatal_color
71
+ when 6
72
+ text.unknown_color
73
+ else
74
+ text
75
+ end
76
+ end
32
77
  end
33
78
  end
@@ -1,12 +1,11 @@
1
1
  require 'jbuilder'
2
2
  require_relative 'log_formatter_base'
3
- require_relative 'severity_level'
3
+ require_relative 'string'
4
4
 
5
5
  module RTALogger
6
6
  # json formatter which receive log_record and
7
7
  # returns it's data as json string
8
8
  class LogFormatterJson < LogFormatterBase
9
- include SeverityLevel
10
9
 
11
10
  def format(log_record)
12
11
  return '' unless log_record
@@ -20,7 +19,21 @@ module RTALogger
20
19
  json.message log_record.message.flatten.join(' ')
21
20
  end
22
21
 
23
- jb.target!
22
+ result = jb.target!
23
+ result = colorize_json(result) if @colorize
24
+
25
+ return result
26
+ end
27
+
28
+ protected
29
+
30
+ def colorize_json(json_text)
31
+ json_text.gsub(/"severity":"TRACE"/i, '"severity":"TRACE"'.trace_color)
32
+ .gsub(/"severity":"DEBUG"/i, '"severity":"DEBUG"'.debug_color)
33
+ .gsub(/"severity":"WARN"/i, '"severity":"WARN"'.warning_color)
34
+ .gsub(/"severity":"ERROR"/i, '"severity":"ERROR"'.error_color)
35
+ .gsub(/"severity":"FATAL"/i, '"severity":"FATAL"'.fatal_color)
36
+ .gsub(/"severity":"UNKNOWN"/i, '"severity":"UNKNOWN"'.unknown_color)
24
37
  end
25
38
  end
26
39
  end
@@ -1,12 +1,9 @@
1
1
  require_relative 'log_formatter_base'
2
- require_relative 'severity_level'
3
2
 
4
3
  module RTALogger
5
4
  # text formatter which receive log_record and
6
5
  # returns it's data as delimited text string
7
6
  class LogFormatterText < LogFormatterBase
8
- include SeverityLevel
9
-
10
7
  def format(log_record)
11
8
  return '' unless log_record
12
9
 
@@ -14,7 +11,7 @@ module RTALogger
14
11
  result << @delimiter << log_record.app_name
15
12
  result << @delimiter << log_record.topic_title
16
13
  result << @delimiter << log_record.context_id.to_s
17
- result << @delimiter << parse_severity_level_to_s(log_record.severity)
14
+ result << @delimiter << severity_text(log_record.severity)
18
15
  result << @delimiter << log_record.message.join(' ').gsub(delimiter, '$<$')
19
16
 
20
17
  result
@@ -27,7 +27,7 @@ module RTALogger
27
27
  @topic_semaphore = Mutex.new
28
28
  @log_semaphore = Mutex.new
29
29
  self.buffer_size = ENV.fetch('RTA_LOGGER_BUFFER_SIZE', 100)
30
- self.flush_wait_time = ENV.fetch('RTA_LOGGER_FLUSH_WAIT_SECONDS', 15)
30
+ self.flush_wait_time = ENV.fetch('RTA_LOGGER_FLUSH_WAIT_SECONDS', 5)
31
31
  @topics = {}
32
32
  @log_records = []
33
33
  @propagator = LogFactory.new_log_propagator
@@ -64,7 +64,7 @@ module RTALogger
64
64
  end
65
65
 
66
66
  def flush_wait_time=(time_in_seconds)
67
- @flush_wait_time = time_in_seconds < 10 ? 10 : time_in_seconds
67
+ @flush_wait_time = time_in_seconds < 5 ? 5 : time_in_seconds
68
68
  end
69
69
 
70
70
  def config_use_json_file(file_name, title = '')
@@ -76,7 +76,7 @@ module RTALogger
76
76
  @propagator.add_log_repository(LogFactory.create_repository(:console))
77
77
  end
78
78
 
79
- def config_use_json_string(config_string, title = '')
79
+ def config_use_json_string(config_string, title = '')
80
80
  config_json = load_config_from_json_string(config_string, title)
81
81
  apply_config(config_json)
82
82
  rescue StandardError => e
@@ -138,7 +138,8 @@ module RTALogger
138
138
  json.flush_size flush_size
139
139
  json.flush_wait_time flush_wait_time
140
140
  json.repositories do
141
- json.array! @propagator.repositories.collect { |repository| repository.to_builder.attributes! }
141
+ # json.array! @propagator.repositories.collect { |repository| repository.to_builder.attributes! }
142
+ json.array! @propagator.to_builder
142
143
  end
143
144
  json.topics do
144
145
  json.array! topics.keys.collect { |topic_key| @topics[topic_key].to_builder.attributes! }
@@ -156,22 +157,23 @@ module RTALogger
156
157
  def apply_run_time_config(config_json)
157
158
  return unless config_json
158
159
  @enable = config_json['enable'] unless config_json['enable'].nil?
159
- @default_severity_level = parse_severity_level_to_i(config_json['severity_level']) unless config_json['severity_level'].nil?
160
+ @default_severity_level = parse_severity_level_to_s(config_json['severity_level']) unless config_json['severity_level'].nil?
160
161
  self.buffer_size = config_json['buffer_size'] unless config_json['buffer_size'].nil?
161
162
  self.flush_wait_time = config_json['flush_wait_time'] unless config_json['flush_wait_time'].nil?
162
163
  @propagator.apply_run_time_config(config_json)
163
-
164
- if config_json['topics']
165
- config_json['topics'].each do |topic_config|
166
- next if topic_config['title'].nil?
167
- topic = topic_by_title(topic_config['title'])
168
- topic.apply_run_time_config(topic_config) if topic
169
- end
170
- end
164
+ apply_run_time_config_topics(config_json)
171
165
  end
172
166
 
173
167
  private
174
168
 
169
+ def apply_run_time_config_topics(config_json)
170
+ config_json['topics']&.each do |topic_config|
171
+ next if topic_config['title'].nil?
172
+ topic = topic_by_title(topic_config['title'])
173
+ topic.apply_run_time_config(topic_config) if topic.present?
174
+ end
175
+ end
176
+
175
177
  def load_config_from_json_file(config_file_name, title = '')
176
178
  config_file = File.open config_file_name
177
179
  config_json = ::JSON.load(config_file)
@@ -207,15 +209,10 @@ module RTALogger
207
209
  @default_severity_level = parse_severity_level_to_i(config_json['severity_level']) if config_json['severity_level']
208
210
  self.buffer_size = config_json['buffer_size'] if config_json['buffer_size']
209
211
  self.flush_wait_time = config_json['flush_wait_seconds'] if config_json['flush_wait_seconds']
210
- @propagator.drop_all_repositories
211
- apply_config_repos(config_json)
212
+ @propagator.load_repositories(config_json)
212
213
  apply_config_topics(config_json)
213
214
  end
214
215
 
215
- def apply_config_repos(config_json)
216
- config_json['repositories']&.each { |item| @propagator.load_log_repository(item) }
217
- end
218
-
219
216
  def apply_config_topics(config_json)
220
217
  config_json['topics']&.each do |topic|
221
218
  next unless topic['title']
@@ -6,7 +6,7 @@ module RTALogger
6
6
  def initialize
7
7
  @semaphore = Mutex.new
8
8
  @records = []
9
- @repositories = []
9
+ @repositories = {}
10
10
  end
11
11
 
12
12
  attr_reader :repositories
@@ -16,20 +16,34 @@ module RTALogger
16
16
  end
17
17
 
18
18
  def add_log_repository(repository)
19
+ return if repository.nil? || repository.title.to_s.empty?
19
20
  return unless repository.is_a? RTALogger::LogRepository
20
- @repositories.push(repository) unless @repositories.include?(repository)
21
+ @semaphore.synchronize { @repositories[repository.title.to_sym] = repository unless @repositories[repository.title.to_sym].present? }
21
22
  end
22
23
 
23
24
  def load_log_repository(config_json)
24
25
  type = config_json['type']
25
26
  return if type.to_s.strip.empty?
26
- enable = config_json['enable'].nil? ? true : config_json['enable']
27
- return unless enable
28
27
 
29
28
  repository = ::RTALogger::LogFactory.create_repository(type, config_json)
30
29
  add_log_repository(repository)
31
30
  end
32
31
 
32
+ def load_repositories(config_json)
33
+ return if config_json.nil?
34
+
35
+ @semaphore.synchronize do
36
+ @repositories.clear
37
+ config_json['repositories']&.each do |repository_config|
38
+ type = repository_config['type']
39
+ next if type.to_s.strip.empty?
40
+
41
+ repository = ::RTALogger::LogFactory.create_repository(type, repository_config)
42
+ @repositories[repository.title.to_sym] = repository unless @repositories[repository.title.to_sym].present?
43
+ end
44
+ end
45
+ end
46
+
33
47
  def drop_all_repositories
34
48
  @semaphore.synchronize { @repositories.clear }
35
49
  end
@@ -48,23 +62,41 @@ module RTALogger
48
62
 
49
63
  def apply_run_time_config(config_json)
50
64
  return unless config_json
65
+ apply_run_time_config_repositories(config_json)
66
+ end
51
67
 
52
- if config_json['repositories']
53
- config_json['repositories'].each do |repository_config|
54
- next if repository_config['title'].nil?
55
- repository = repository_by_title(repository_config['title'])
56
- repository.apply_run_time_config(repository_config) if repository
68
+ def propagate
69
+ @semaphore.synchronize do
70
+ @repositories.keys.each do |repository_key|
71
+ @repositories[repository_key.to_sym].add_log_records(@records)
57
72
  end
73
+ @records.clear
58
74
  end
59
75
  end
60
76
 
61
- def propagate
77
+ def to_builder
78
+ result = nil
62
79
  @semaphore.synchronize do
63
- @repositories.each do |repository|
64
- repository.add_log_records(@records)
80
+ result = @repositories&.keys.collect { |repository_key| @repositories[repository_key].to_builder.attributes! }
81
+ end
82
+
83
+ return result
84
+ end
85
+
86
+ private
87
+
88
+ def apply_run_time_config_repositories(config_json)
89
+ config_json['repositories']&.each do |repository_config|
90
+ next if repository_config['title'].nil?
91
+ repository = repository_by_title(repository_config['title'])
92
+ if repository.present?
93
+ repository.apply_run_time_config(repository_config)
94
+ else
95
+ repository = ::RTALogger::LogFactory.create_repository(repository_config['type'], repository_config)
96
+ add_log_repository(repository)
65
97
  end
66
- @records.clear
67
98
  end
68
99
  end
100
+
69
101
  end
70
102
  end
@@ -16,6 +16,10 @@ module RTALogger
16
16
  attr_reader :message
17
17
  attr_reader :occurred_at
18
18
 
19
+ def full_message
20
+ message.join(' ')
21
+ end
22
+
19
23
  def app_name
20
24
  @log_topic.log_manager.app_name
21
25
  end
@@ -1,4 +1,5 @@
1
1
  require_relative 'string'
2
+ require_relative 'log_factory_filter'
2
3
 
3
4
  module RTALogger
4
5
  # base log repository class
@@ -9,6 +10,7 @@ module RTALogger
9
10
  @title = self.class.to_s.split('::').last.underscore
10
11
  @enable = true
11
12
  @formatter = RTALogger::LogFactory.log_formatter_default
13
+ @filters = {}
12
14
  end
13
15
 
14
16
  # @@sub_classes = {}
@@ -33,8 +35,11 @@ module RTALogger
33
35
  def add_log_records(items)
34
36
  return 0 unless @enable
35
37
  @semaphore.synchronize do
36
- items.each { |item| @log_records.push(item.dup) }
38
+ items.each do |item|
39
+ @log_records.push(item.dup) if filters_accept(item)
40
+ end
37
41
  end
42
+
38
43
  flush_and_clear
39
44
  end
40
45
 
@@ -42,16 +47,21 @@ module RTALogger
42
47
  @enable = config_json['enable'].nil? ? true : config_json['enable']
43
48
  @title = config_json['title'].nil? ? self.class.to_s.split('::').last.underscore : config_json['title']
44
49
  formatter_config = config_json['formatter']
45
- if formatter_config && formatter_config['type']
46
- @formatter = LogFactory.create_formatter(formatter_config['type'], formatter_config)
47
- end
50
+
51
+ @formatter = LogFactory.create_formatter(formatter_config['type'], formatter_config) if formatter_config && formatter_config['type']
52
+
53
+ apply_config_filters(config_json)
48
54
  end
49
55
 
50
56
  def to_builder
51
57
  jb = Jbuilder.new do |json|
52
58
  json.type self.class.to_s.split('::').last.underscore.sub('log_repository_', '')
59
+ json.title @title
53
60
  json.enable enable
54
61
  json.formatter @formatter.to_builder.attributes!
62
+ json.filters do
63
+ json.array! @filters.keys.collect { |filter_key| @filters[filter_key].to_builder.attributes! }
64
+ end
55
65
  end
56
66
 
57
67
  jb
@@ -61,17 +71,64 @@ module RTALogger
61
71
  to_builder.target!
62
72
  end
63
73
 
74
+ def filter_by_title(title)
75
+ result = nil
76
+ @semaphore.synchronize do
77
+ @filters.keys.each do |filter_key|
78
+ result = @filters[filter_key.to_sym] if filter_key.to_s.casecmp(title).zero?
79
+ break if result
80
+ end
81
+ end
82
+
83
+ return result
84
+ end
85
+
64
86
  def apply_run_time_config(config_json)
65
87
  return unless config_json
66
88
  @enable = config_json['enable'] unless config_json['enable'].nil?
89
+ @formatter.apply_run_time_config(config_json['formatter'])
90
+ apply_run_time_config_filters(config_json)
67
91
  end
68
92
 
69
93
  protected
70
94
 
95
+ def apply_config_filters(config_json)
96
+ config_json['filters']&.each do |filter_config|
97
+ next if filter_config['type'].nil? || filter_config['title'].nil?
98
+ filter = LogFactory.create_filter(filter_config['type'], filter_config)
99
+ @filters[filter_config['title'].to_sym] = filter if filter.present?
100
+ end
101
+ end
102
+
103
+ def apply_run_time_config_filters(config_json)
104
+ return unless config_json
105
+
106
+ config_json['filters']&.each do |filter_config|
107
+ next if filter_config['title'].nil?
108
+ filter = filter_by_title(filter_config['title'])
109
+ if filter.present?
110
+ filter.apply_run_time_config(filter_config)
111
+ else
112
+ filter = LogFactory.create_filter(filter_config['type'], filter_config)
113
+ @semaphore.synchronize { @filters[filter_config['title'].to_sym] = filter if filter.present? }
114
+ end
115
+ end
116
+ end
117
+
71
118
  def flush_and_clear
72
119
  @semaphore.synchronize { @log_records.clear }
73
120
  end
74
121
 
122
+ def filters_accept(log_record)
123
+ result = true
124
+ @filters&.keys.each do |filter_key|
125
+ result = @filters[filter_key.to_sym]&.match_conditions(log_record)
126
+ break unless result
127
+ end
128
+
129
+ return result
130
+ end
131
+
75
132
  attr_reader :log_records
76
133
  attr_reader :semaphore
77
134
  end
@@ -17,7 +17,7 @@ module RTALogger
17
17
  protected
18
18
 
19
19
  def flush_and_clear
20
- semaphore.synchronize do
20
+ @semaphore.synchronize do
21
21
  @log_records.each { |log_record| puts @formatter.format(log_record) }
22
22
  end
23
23
  super
@@ -31,8 +31,15 @@ module RTALogger
31
31
 
32
32
  json
33
33
  end
34
+
34
35
  # register :file
35
36
 
37
+ def apply_run_time_config(config_json)
38
+ super config_json
39
+
40
+ @formatter.colorize = false
41
+ end
42
+
36
43
  protected
37
44
 
38
45
  def create_ruby_logger(file_path, period, shift_size)
@@ -45,7 +52,7 @@ module RTALogger
45
52
  end
46
53
 
47
54
  def flush_and_clear
48
- semaphore.synchronize do
55
+ @semaphore.synchronize do
49
56
  @log_records.each { |log_record| @file_logger.debug(@formatter.format(log_record)) }
50
57
  end
51
58
  super
@@ -7,43 +7,87 @@ module RTALogger
7
7
  super()
8
8
  @host = host
9
9
  @port = port
10
- @fluent_logger = create_fluentd_logger(host, port, tls_options)
10
+ @tls_options = tls_options
11
+ @fluent_logger = nil
11
12
  end
12
13
 
13
14
  def load_config(config_json)
14
15
  super
15
16
 
16
- host = config_json['host'].to_s
17
- port = config_json['port'].to_s
18
- tls_options = config_json['tls_options']
17
+ @host = config_json['host'].to_s
18
+ @port = config_json['port'].to_i
19
+ @tls_options = config_json['tls_options']
19
20
 
20
- @fluent_logger = create_fluentd_logger(host, port, tls_options)
21
+ @semaphore.synchronize { @fluent_logger = nil }
22
+ end
23
+
24
+ def host=(host)
25
+ if @host != host
26
+ @host = host ? host : 'localhost'
27
+ @semaphore.synchronize { @fluent_logger = nil }
28
+ end
29
+ end
30
+
31
+ def host
32
+ @host
33
+ end
34
+
35
+ def port=(port)
36
+ if @port != port
37
+ @port = port ? port : 24224
38
+ @semaphore.synchronize { @fluent_logger = nil }
39
+ end
40
+ end
41
+
42
+ def port
43
+ @port
21
44
  end
22
45
 
23
46
  def to_builder
24
47
  json = super
25
- json.enable enable
48
+ json.enable @enable
26
49
  json.host @host
27
50
  json.port @port
51
+ json.tls_options @tls_options
28
52
 
29
53
  json
30
54
  end
55
+
31
56
  # register :fluentd
32
57
 
58
+ def apply_run_time_config(config_json)
59
+ super config_json
60
+
61
+ @host = config_json['host'] unless config_json['host'].nil?
62
+ @port = config_json['port'] unless config_json['port'].nil?
63
+ @tls_options = config_json['tls_options'] unless config_json['tls_options'].nil?
64
+ @semaphore.synchronize { @fluent_logger = nil }
65
+
66
+ @formatter.colorize = false
67
+ end
68
+
33
69
  protected
34
70
 
35
71
  def create_fluentd_logger(host, port, tls_options)
72
+ return nil unless @enable
73
+
36
74
  unless tls_options
37
75
  fluent_logger = ::Fluent::Logger::FluentLogger.new(nil, :host => host, :port => port, :use_nonblock => true, :wait_writeable => false)
38
76
  else
39
- fluent_logger = ::Fluent::Logger::FluentLogger.new(nil, :host => host, :port => port, :tls_options => tls_options, :use_nonblock => true, :wait_writeable => false)
77
+ fluent_logger = ::Fluent::Logger::FluentLogger.new(nil, :host => host,
78
+ :port => port,
79
+ :tls_options => tls_options,
80
+ :use_nonblock => true,
81
+ :wait_writeable => false)
40
82
  end
41
83
 
42
84
  fluent_logger
43
85
  end
44
86
 
45
87
  def flush_and_clear
46
- semaphore.synchronize do
88
+ @semaphore.synchronize do
89
+ @fluent_logger = create_fluentd_logger(@host, @port, @tls_options) unless @fluent_logger.present?
90
+
47
91
  @log_records.each do |log_record|
48
92
  fluent_tag = log_record.app_name + '.' + log_record.topic_title
49
93
  log_json_string = @formatter.format(log_record)
@@ -52,6 +96,7 @@ module RTALogger
52
96
  @fluent_logger.post(fluent_tag, log_json)
53
97
  end
54
98
  end
99
+
55
100
  super
56
101
  end
57
102
  end
@@ -10,7 +10,7 @@
10
10
  "app_name": "TestApp",
11
11
  "severity_level": "trace",
12
12
  "buffer_size": 100,
13
- "flush_wait_seconds": 10,
13
+ "flush_wait_seconds": 5,
14
14
  "repositories":
15
15
  [
16
16
  {
@@ -20,8 +20,24 @@
20
20
  "formatter":
21
21
  {
22
22
  "type": "text",
23
- "delimiter": "|"
24
- }
23
+ "delimiter": "|",
24
+ "colorize": true
25
+ },
26
+ "filters":
27
+ [
28
+ {
29
+ "type": "topic",
30
+ "title": "topic_filter_1",
31
+ "enable": false,
32
+ "default_regex" : "^test$"
33
+ },
34
+ {
35
+ "type": "message",
36
+ "title": "message_filter_1",
37
+ "enable": false,
38
+ "default_regex" : "error"
39
+ }
40
+ ]
25
41
  },
26
42
  {
27
43
  "type": "file",
@@ -37,8 +53,8 @@
37
53
  }
38
54
  },
39
55
  {
40
- "enable": true,
41
- "title": "console_repo_1",
56
+ "enable": false,
57
+ "title": "fluentd_repo_1",
42
58
  "type": "fluentd",
43
59
  "host": "localhost",
44
60
  "port": "8888",
@@ -1,5 +1,14 @@
1
1
  require_relative 'log_factory_manager'
2
2
  require_relative 'log_factory_repository'
3
+ # require_relative 'string'
4
+
5
+ # puts 'trace'.gray
6
+ # puts 'debug'.green
7
+ # puts 'info'
8
+ # puts 'warning'.brown
9
+ # puts 'error'.red
10
+ # puts 'fatal'.bg_red
11
+ # puts 'unknown'.bg_cyan
3
12
 
4
13
  controller_name = 'test_controller'
5
14
  userID = 5
@@ -39,7 +48,7 @@ topic.unknown(userID, 'Controller Name=', controller_name, 'unknown')
39
48
  test_topic.error(userID, 'test_topic', 'error')
40
49
  test_topic.fatal(userID, 'test_topic', 'fatal')
41
50
 
42
- puts log_manager.reveal_config
51
+ # puts log_manager.reveal_config
43
52
 
44
53
  # update specific topic log level if necessary
45
54
  # log_manager.update_topic_level(controller_name, RTALogger::SeverityLevel::INFO)
@@ -1,9 +1,40 @@
1
1
  class String
2
2
  def underscore
3
3
  self.gsub(/::/, '/').
4
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
6
6
  tr("-", "_").
7
7
  downcase
8
8
  end
9
+
10
+ def black; "\e[30m#{self}\e[0m" end
11
+ def red; "\e[31m#{self}\e[0m" end
12
+ def green; "\e[32m#{self}\e[0m" end
13
+ def brown; "\e[33m#{self}\e[0m" end
14
+ def blue; "\e[34m#{self}\e[0m" end
15
+ def magenta; "\e[35m#{self}\e[0m" end
16
+ def cyan; "\e[36m#{self}\e[0m" end
17
+ def gray; "\e[37m#{self}\e[0m" end
18
+
19
+ def bg_black; "\e[40m#{self}\e[0m" end
20
+ def bg_red; "\e[41m#{self}\e[0m" end
21
+ def bg_green; "\e[42m#{self}\e[0m" end
22
+ def bg_brown; "\e[43m#{self}\e[0m" end
23
+ def bg_blue; "\e[44m#{self}\e[0m" end
24
+ def bg_magenta; "\e[45m#{self}\e[0m" end
25
+ def bg_cyan; "\e[46m#{self}\e[0m" end
26
+ def bg_gray; "\e[47m#{self}\e[0m" end
27
+
28
+ def bold; "\e[1m#{self}\e[22m" end
29
+ def italic; "\e[3m#{self}\e[23m" end
30
+ def underline; "\e[4m#{self}\e[24m" end
31
+ def blink; "\e[5m#{self}\e[25m" end
32
+ def reverse_color; "\e[7m#{self}\e[27m" end
33
+
34
+ def trace_color; self.gray end
35
+ def debug_color; self.green end
36
+ def warning_color; self.brown end
37
+ def error_color; self.red end
38
+ def fatal_color; self.bg_red end
39
+ def unknown_color; self.bg_cyan end
9
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: RTALogger
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Babak Bahreini, RTA Backend Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-27 00:00:00.000000000 Z
11
+ date: 2020-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluent-logger
@@ -68,12 +68,17 @@ files:
68
68
  - bin/setup
69
69
  - lib/RTALogger.rb
70
70
  - lib/RTALogger/version.rb
71
+ - lib/log_factory_filter.rb
71
72
  - lib/log_factory_log_formatter.rb
72
73
  - lib/log_factory_manager.rb
73
74
  - lib/log_factory_propagator.rb
74
75
  - lib/log_factory_record.rb
75
76
  - lib/log_factory_repository.rb
76
77
  - lib/log_factory_topic.rb
78
+ - lib/log_filter_base.rb
79
+ - lib/log_filter_context.rb
80
+ - lib/log_filter_message.rb
81
+ - lib/log_filter_topic.rb
77
82
  - lib/log_formatter_base.rb
78
83
  - lib/log_formatter_json.rb
79
84
  - lib/log_formatter_text.rb