teLogger 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +71 -0
- data/README.md +122 -0
- data/Rakefile +10 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/teLogger/logger_group.rb +110 -0
- data/lib/teLogger/tlogger.rb +411 -0
- data/lib/teLogger/version.rb +5 -0
- data/lib/teLogger.rb +70 -0
- data/teLogger.gemspec +40 -0
- metadata +69 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7919230720df3483a2140226524bde04ad0da1981a6dc612ddf0c1b9c8adfe95
|
4
|
+
data.tar.gz: db1fa0e3029d48c66bfc56c41cd93a56b8d3c20ab69c2dac09fb870e1114b031
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6bccfe28dd331dc3a5e594c7d36c8ddf2ba3449b9702dab305cf6694fa0be159208e73950f0d963728fb5fd1de847d528e96964ba88ce286c7c64f487608820d
|
7
|
+
data.tar.gz: bac3ec9366528a8a6d1dc12056bb6c0ffc0e6432cc4b9d1b2e800c1671062a9a6293e07b52e7728a6fc280801b7a0d688638e5108b0e964eaf522c5f694c5884
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
teLogger (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
base58 (0.2.3)
|
10
|
+
devops_assist (0.1.4)
|
11
|
+
git_cli
|
12
|
+
git_cli_prompt
|
13
|
+
gvcs
|
14
|
+
tlogger
|
15
|
+
toolrack
|
16
|
+
tty-prompt
|
17
|
+
diff-lcs (1.5.0)
|
18
|
+
git_cli (0.9.0)
|
19
|
+
gvcs
|
20
|
+
ptools (~> 1.4.0)
|
21
|
+
tlogger
|
22
|
+
toolrack
|
23
|
+
git_cli_prompt (0.2.2)
|
24
|
+
tlogger
|
25
|
+
toolrack
|
26
|
+
tty-prompt
|
27
|
+
gvcs (0.1.0)
|
28
|
+
pastel (0.8.0)
|
29
|
+
tty-color (~> 0.5)
|
30
|
+
ptools (1.4.2)
|
31
|
+
rake (13.0.6)
|
32
|
+
rspec (3.11.0)
|
33
|
+
rspec-core (~> 3.11.0)
|
34
|
+
rspec-expectations (~> 3.11.0)
|
35
|
+
rspec-mocks (~> 3.11.0)
|
36
|
+
rspec-core (3.11.0)
|
37
|
+
rspec-support (~> 3.11.0)
|
38
|
+
rspec-expectations (3.11.0)
|
39
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
40
|
+
rspec-support (~> 3.11.0)
|
41
|
+
rspec-mocks (3.11.1)
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
43
|
+
rspec-support (~> 3.11.0)
|
44
|
+
rspec-support (3.11.0)
|
45
|
+
tlogger (0.26.3)
|
46
|
+
toolrack (0.18.5)
|
47
|
+
base58
|
48
|
+
tlogger
|
49
|
+
tty-color (0.6.0)
|
50
|
+
tty-cursor (0.7.1)
|
51
|
+
tty-prompt (0.23.1)
|
52
|
+
pastel (~> 0.8)
|
53
|
+
tty-reader (~> 0.8)
|
54
|
+
tty-reader (0.9.0)
|
55
|
+
tty-cursor (~> 0.7)
|
56
|
+
tty-screen (~> 0.8)
|
57
|
+
wisper (~> 2.0)
|
58
|
+
tty-screen (0.8.1)
|
59
|
+
wisper (2.0.1)
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
x86_64-linux
|
63
|
+
|
64
|
+
DEPENDENCIES
|
65
|
+
devops_assist
|
66
|
+
rake (~> 13.0)
|
67
|
+
rspec (~> 3.0)
|
68
|
+
teLogger!
|
69
|
+
|
70
|
+
BUNDLED WITH
|
71
|
+
2.2.28
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# TeLogger
|
2
|
+
|
3
|
+
TeLogger is the attempt to have some control in logging by the developer.
|
4
|
+
|
5
|
+
We found that usually debug message is turned off in production environment but when issue happened and investigation undergoing, there is little help to the developer when ALL debug messages now falls on the developer. Developer now has to go line by line or by searching certain keyword from a big big log file just to see what's happening inside the program. What if developer can just disable all other log messages and only focus on the log messages around the suspected issue? That is the motivation of this library.
|
6
|
+
|
7
|
+
TeLogger wrap around the default Ruby Logger class to provide the actual logging facilities, however allow developer to add some context with the log messages.
|
8
|
+
The context is a string that is printed along with the log messages
|
9
|
+
|
10
|
+
For example:
|
11
|
+
|
12
|
+
```console
|
13
|
+
D, [2020-04-23T16:19:15.537926 #23173] DEBUG -- [global] : Testing 123
|
14
|
+
I, [2020-04-23T16:19:15.537964 #23173] INFO -- [global] : Testing 123
|
15
|
+
W, [2020-04-23T16:19:15.537980 #23173] WARN -- [global] : Testing 123
|
16
|
+
E, [2020-04-23T16:19:15.537993 #23173] ERROR -- [global] : Testing 123
|
17
|
+
```
|
18
|
+
Note the '[global]' in the print out is the context.
|
19
|
+
|
20
|
+
The Ruby Logger actually already supported this feature therefore TeLogger just use the feature, with some additional utilities around the context.
|
21
|
+
|
22
|
+
The utilities include:
|
23
|
+
* Selectively turn on and off certain log messages based on tag
|
24
|
+
* Turn off/on all log messages with tagging
|
25
|
+
* Provide group logging engine whereby single log message can be written to multiple log engines (e.g. write to STDOUT and log file at the same time)
|
26
|
+
|
27
|
+
|
28
|
+
## Installation
|
29
|
+
|
30
|
+
Add this line to your application's Gemfile:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
gem 'teLogger'
|
34
|
+
```
|
35
|
+
|
36
|
+
And then execute:
|
37
|
+
|
38
|
+
$ bundle install
|
39
|
+
|
40
|
+
Or install it yourself as:
|
41
|
+
|
42
|
+
$ gem install teLogger
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
|
46
|
+
### Basic - Adding Context
|
47
|
+
|
48
|
+
Since TeLogger is just wrapped around Ruby Logger, it is initiated like Logger:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require 'teLogger'
|
52
|
+
|
53
|
+
# Initiate without parameters shall print out the log to STDOUT
|
54
|
+
log = TeLogger::Tlogger.new
|
55
|
+
|
56
|
+
# Alternatively, this initiate logging with log file
|
57
|
+
# The parameter is directly pass to Ruby Logger.new method
|
58
|
+
log = TeLogger::Tlogger.new('app.log',10,1024000)
|
59
|
+
|
60
|
+
# default tag for this logger instance / session
|
61
|
+
log.tag = "init"
|
62
|
+
|
63
|
+
# now logging can be done as usual...
|
64
|
+
log.debug "Step 1 rolling"
|
65
|
+
D, [2020-04-23T16:19:15.537926 #23173] DEBUG -- [init] : Step 1 rolling # sample output
|
66
|
+
....
|
67
|
+
...
|
68
|
+
...
|
69
|
+
log.debug "Step 1.1 rolling"
|
70
|
+
D, [2020-04-23T16:19:15.537940 #23173] DEBUG -- [init] : Step 1.1 rolling # sample output
|
71
|
+
...
|
72
|
+
...
|
73
|
+
log.debug "Step 1.1.1 rolling"
|
74
|
+
D, [2020-04-23T16:19:15.537963 #23173] DEBUG -- [init] : Step 1.1.1 rolling # sample output
|
75
|
+
...
|
76
|
+
...
|
77
|
+
|
78
|
+
# context switch
|
79
|
+
log.tdebug :phase1, "Step 2 starting..."
|
80
|
+
D, [2020-04-23T16:19:18.537881 #23173] DEBUG -- [phase1] : Step 2 starting... # sample output
|
81
|
+
...
|
82
|
+
log.tdebug :phase1, "Step 2 setup completed..."
|
83
|
+
D, [2020-04-23T16:19:18.537881 #23173] DEBUG -- [phase1] : Step 2 setup completed... # sample output
|
84
|
+
...
|
85
|
+
...
|
86
|
+
# or tag a group of log files
|
87
|
+
log.with_tag(:phase2) do
|
88
|
+
log.debug "Step 3 starting..."
|
89
|
+
D, [2020-04-23T16:19:18.548893 #23173] DEBUG -- [phase2] : Step 3 starting... # sample output
|
90
|
+
log.error "Step 3 parameter X is wrong"
|
91
|
+
E, [2020-04-23T16:19:18.548893 #23173] ERROR -- [phase2] : Step 3 parameter X is wrong # sample output
|
92
|
+
end
|
93
|
+
|
94
|
+
# after the block, the default tagging shall be restored
|
95
|
+
log.error "Stepping stopped in the middle"
|
96
|
+
E, [2020-04-23T16:19:18.548893 #23173] ERROR -- [init] : Stepping stopped in the middle # sample output
|
97
|
+
```
|
98
|
+
|
99
|
+
Refers to spec/tLogger\_spec.rb for details usage
|
100
|
+
|
101
|
+
|
102
|
+
### Filter Log Messages
|
103
|
+
|
104
|
+
After the log messages are tagged, let say two years down the road the program is reported having error. You suspected should be around phase 1 or phase 2 operation, you can now load back the program, configure the log
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
# turned off all tags except the one given
|
108
|
+
log.off_all_tags_except(:phase1, :phase2)
|
109
|
+
|
110
|
+
# OR turned off selected tags only
|
111
|
+
log.tag_off(:init)
|
112
|
+
```
|
113
|
+
By configuring the log above, only log messages tagged with :phase1 and :phase2 shall be logged inside the log file. This drastically reduce the log entries that developer needs to find from one giant log file.
|
114
|
+
|
115
|
+
|
116
|
+
### Possible Concern
|
117
|
+
|
118
|
+
By limiting the log messages, it may be more difficult some times to spot the issue since the log messages that point out the error has already been filtered from the log file. It is definitely possible that this is happening since not all log messages shall be available if it is filtered. Therefore it is up to the developer if that is a disadvantages or advantages under their specific use case. Also it is up to developer to tag the log messages which can be anything under the sun. It may be only two tags, one for internal usage one for external. Hence it is really up to the use case that makes the scenario possible or otherwise.
|
119
|
+
|
120
|
+
For current use cases now even in production system, hide some log messages under info log level and reveal it if necessary. Since it is part of the code, the tag to hide or show can be configured via a configuration files. No changing of code needed and the debug messages can be as extensive as possible since you know that there is a way to filter after that.
|
121
|
+
|
122
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "teLogger"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module TeLogger
|
4
|
+
|
5
|
+
# LoggerGroup is yet at wrapper around the Tlogger
|
6
|
+
# This class can be used as Tlogger replacement as it is
|
7
|
+
# delegated to the Tlogger upon method_missing method triggered.
|
8
|
+
#
|
9
|
+
# However this allow configuration of multiple loggers into
|
10
|
+
# single class.
|
11
|
+
#
|
12
|
+
# When operation such as 'debug' is called on this class
|
13
|
+
# all the registered logger shall be called the 'debug' method each therefore
|
14
|
+
# it will be logged to all registered loggers
|
15
|
+
class LoggerGroup
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@loggers = { }
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Create and add the logger into the group and registerd it with the given +key+
|
23
|
+
#
|
24
|
+
# *params shall be passed to underlying Tlogger new method
|
25
|
+
#
|
26
|
+
# Returns created Tlogger object
|
27
|
+
def create_logger(key, *params)
|
28
|
+
@loggers[key] = Tlogger.new(*params)
|
29
|
+
@loggers[key]
|
30
|
+
end # #create_logger
|
31
|
+
|
32
|
+
# Delete this logger from the group.
|
33
|
+
#
|
34
|
+
# delete_logger different from detach_logger as delete_logger shall close and set the logger to nil.
|
35
|
+
#
|
36
|
+
# detach_logger however just remove the logger from the group and it is up to the applicaation to close it.
|
37
|
+
def delete_logger(key)
|
38
|
+
logger = @loggers[key]
|
39
|
+
if not logger.nil?
|
40
|
+
logger.close
|
41
|
+
logger = nil
|
42
|
+
end
|
43
|
+
@loggers.delete(key)
|
44
|
+
end # #delete logger
|
45
|
+
|
46
|
+
##
|
47
|
+
# Detach the logger from the group, but not close the logger
|
48
|
+
#
|
49
|
+
# Detach the logger return the object to the caller and remove it from the internal group
|
50
|
+
#
|
51
|
+
# The effect is after detach operation, any logging done to this group would not include that particular logger and
|
52
|
+
# application is free to use the logger to log messages
|
53
|
+
#
|
54
|
+
def detach_logger(key)
|
55
|
+
@loggers.delete(key)
|
56
|
+
end # # detach_logger
|
57
|
+
|
58
|
+
##
|
59
|
+
# Add an existing logger instance to this group
|
60
|
+
#
|
61
|
+
# Noted that this logger object not necessary to be Tlogger object. It can be any object as long as it has the method that
|
62
|
+
# response to the usage.
|
63
|
+
#
|
64
|
+
# This is due to this class just a thin wrapper around the 'logger' object that any method call unknown to local shall be
|
65
|
+
# redirected to the 'logger' class.
|
66
|
+
#
|
67
|
+
# In another way, it is perfectly ok to call say_hello() on LoggerGroup if the 'logger' given response to method say_hello() or else
|
68
|
+
# NoMethodException shall be thrown. It is that simple.
|
69
|
+
def attach_logger(key, logger)
|
70
|
+
@loggers[key] = logger
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the logger that registered to the +key+
|
74
|
+
def get_log(key)
|
75
|
+
@loggers[key]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the registered logger
|
79
|
+
def registered_logger
|
80
|
+
@loggers.keys.freeze
|
81
|
+
end
|
82
|
+
|
83
|
+
# Close the logger group, effectively close all registered loggers
|
84
|
+
def close
|
85
|
+
@loggers.each do |k,v|
|
86
|
+
v.close
|
87
|
+
v = nil
|
88
|
+
end
|
89
|
+
@loggers.clear
|
90
|
+
end # # close
|
91
|
+
|
92
|
+
# Delegate unknown method to the underlying logger
|
93
|
+
def method_missing(mtd,*args,&block)
|
94
|
+
|
95
|
+
#hit = false
|
96
|
+
@loggers.each do |k,v|
|
97
|
+
begin
|
98
|
+
v.send(mtd,*args,&block)
|
99
|
+
#hit = true
|
100
|
+
rescue Exception => ex
|
101
|
+
STDERR.puts ex.message
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#super if not hit
|
106
|
+
|
107
|
+
end # # method_missing
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,411 @@
|
|
1
|
+
|
2
|
+
require 'logger'
|
3
|
+
require 'digest'
|
4
|
+
|
5
|
+
module TeLogger
|
6
|
+
class Tlogger
|
7
|
+
|
8
|
+
# +tag+ is the tag that is being set for this logger session.
|
9
|
+
#
|
10
|
+
# One session shall only have one specific tag value, which is the default tag for this logger session.
|
11
|
+
#
|
12
|
+
# If multiple tags are required, use the method tdebug, terror, twarn, tinfo or #with_tag block to create a new tag
|
13
|
+
#
|
14
|
+
# Note that the tag can be in symbol or string, however shall convert to symbol when processing
|
15
|
+
attr_accessor :tag
|
16
|
+
# +include_caller+ (true/false) tell the logger to print the caller together with the tag
|
17
|
+
attr_accessor :include_caller
|
18
|
+
# +logger+ it is the actual logger instance of this Tlogger
|
19
|
+
attr_reader :logger
|
20
|
+
|
21
|
+
def initialize(*args , &block)
|
22
|
+
# default to console
|
23
|
+
if args.length == 0
|
24
|
+
args << STDOUT
|
25
|
+
end
|
26
|
+
|
27
|
+
@opts = {}
|
28
|
+
if args[-1].is_a?(Hash)
|
29
|
+
@opts = opts
|
30
|
+
@opts = { } if @opts.nil?
|
31
|
+
args = args[0..-2]
|
32
|
+
end
|
33
|
+
|
34
|
+
# allow caller application to create the logger instance instead of internal created
|
35
|
+
@logger = @opts[:logger_instance] || Logger.new(*args,&block)
|
36
|
+
@disabled = []
|
37
|
+
@dHistory = {}
|
38
|
+
@include_caller = false
|
39
|
+
@tag = nil
|
40
|
+
|
41
|
+
@genable = true
|
42
|
+
@exception = []
|
43
|
+
end # initialize
|
44
|
+
|
45
|
+
#
|
46
|
+
# :method: with_tag
|
47
|
+
#
|
48
|
+
# Tag all log inside the block with the given tag value
|
49
|
+
#
|
50
|
+
# Useful to tag multiple lines of log under single tag
|
51
|
+
#
|
52
|
+
def with_tag(tag,&block)
|
53
|
+
if block and not tag.nil?
|
54
|
+
log = self.clone
|
55
|
+
log.tag = tag
|
56
|
+
block.call(log)
|
57
|
+
end
|
58
|
+
end # with_tag
|
59
|
+
|
60
|
+
#
|
61
|
+
# :method: off_tag
|
62
|
+
#
|
63
|
+
# Turn off a tag. After turning off, the log message that tie to this tag shall not be printed out
|
64
|
+
#
|
65
|
+
# Do note that all tags by default are turned on.
|
66
|
+
#
|
67
|
+
def off_tag(*tags)
|
68
|
+
tags.each do |tag|
|
69
|
+
if not (tag.nil? or tag.empty? or @disabled.include?(tag))
|
70
|
+
@disabled << tag.to_sym
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end # off_tag
|
74
|
+
alias_method :tag_off, :off_tag
|
75
|
+
|
76
|
+
#
|
77
|
+
# :method: on_tag
|
78
|
+
#
|
79
|
+
# Turn on a tag.
|
80
|
+
#
|
81
|
+
# Note that by default all tags are turned on. This only affect whatever tags that has been turned off via
|
82
|
+
# the method #off_tag. It doesn't work as adding a tag. Adding a tag message should use tdebug, terror, tinfo,
|
83
|
+
# twarn or #with_tag
|
84
|
+
def on_tag(*tags)
|
85
|
+
tags.each do |tag|
|
86
|
+
@disabled.delete(tag.to_sym) if not (tag.nil? or tag.empty?)
|
87
|
+
end
|
88
|
+
end # on_tag
|
89
|
+
alias_method :tag_on, :on_tag
|
90
|
+
|
91
|
+
#
|
92
|
+
# :method: off_all_tags
|
93
|
+
#
|
94
|
+
# All log messages with tag out of your face!
|
95
|
+
#
|
96
|
+
def off_all_tags
|
97
|
+
@genable = false
|
98
|
+
clear_exceptions
|
99
|
+
end
|
100
|
+
alias_method :all_tags_off, :off_all_tags
|
101
|
+
alias_method :tags_all_off, :off_all_tags
|
102
|
+
|
103
|
+
#
|
104
|
+
# :method: on_all_tags
|
105
|
+
#
|
106
|
+
# All log messages now come down on you! RUN!
|
107
|
+
#
|
108
|
+
# No wait, you need to read that before you run away...
|
109
|
+
#
|
110
|
+
def on_all_tags
|
111
|
+
@genable = true
|
112
|
+
clear_exceptions
|
113
|
+
end
|
114
|
+
alias_method :all_tags_on, :on_all_tags
|
115
|
+
alias_method :tags_all_on, :on_all_tags
|
116
|
+
|
117
|
+
#
|
118
|
+
# :method: off_all_tags_except
|
119
|
+
#
|
120
|
+
# Turn off all tags EXCEPT the tags given.
|
121
|
+
#
|
122
|
+
# Note the parameters can be a list (multiple tags with ',' separator)
|
123
|
+
#
|
124
|
+
def off_all_tags_except(*tags)
|
125
|
+
off_all_tags
|
126
|
+
clear_exceptions
|
127
|
+
@exception.concat tags.map(&:to_sym)
|
128
|
+
end
|
129
|
+
alias_method :off_all_except, :off_all_tags_except
|
130
|
+
alias_method :all_off_except, :off_all_tags_except
|
131
|
+
|
132
|
+
#
|
133
|
+
# :method: on_all_tags_except
|
134
|
+
#
|
135
|
+
# Turn on all tags EXCEPT the tags given
|
136
|
+
#
|
137
|
+
# Note the parameters can be a list (multiple tags with ',' separator)
|
138
|
+
#
|
139
|
+
def on_all_tags_except(*tags)
|
140
|
+
on_all_tags
|
141
|
+
clear_exceptions
|
142
|
+
@exception.concat tags.map(&:to_sym)
|
143
|
+
end
|
144
|
+
alias_method :on_all_except, :on_all_tags_except
|
145
|
+
alias_method :all_on_except, :on_all_tags_except
|
146
|
+
|
147
|
+
#
|
148
|
+
# :method: clear_exceptions
|
149
|
+
#
|
150
|
+
# Clear the exception list. All exampted tags given either by #off_all_tags_except or #on_all_tags_except
|
151
|
+
# shall be reset
|
152
|
+
#
|
153
|
+
def clear_exceptions
|
154
|
+
@exception.clear
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# :method: remove_from_exception
|
159
|
+
#
|
160
|
+
# Remote a set of tags from the exception list
|
161
|
+
#
|
162
|
+
def remove_from_exception(*tags)
|
163
|
+
@exception.delete_if { |e| tags.include?(e) }
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# :method: method_missing
|
168
|
+
#
|
169
|
+
# This is where the delegation to the Logger object happen or no_method_exception shall be thrown
|
170
|
+
#
|
171
|
+
def method_missing(mtd, *args, &block)
|
172
|
+
|
173
|
+
if [:debug, :error, :info, :warn].include?(mtd)
|
174
|
+
|
175
|
+
# proxy the standard API call for logger
|
176
|
+
# Shall print out if the tag is active and vice versa
|
177
|
+
|
178
|
+
if args.length > 0 and args[0].is_a?(Symbol)
|
179
|
+
tag = args[0]
|
180
|
+
args = args[1..-1]
|
181
|
+
else
|
182
|
+
tag = @tag
|
183
|
+
end
|
184
|
+
|
185
|
+
if is_genabled?(tag) and not tag_disabled?(tag)
|
186
|
+
|
187
|
+
if block
|
188
|
+
if not (tag.nil? or tag.empty?) and args.length == 0
|
189
|
+
args = [ format_message(tag) ]
|
190
|
+
end
|
191
|
+
|
192
|
+
out = block
|
193
|
+
else
|
194
|
+
if not (tag.nil? or tag.empty?)
|
195
|
+
str = args[0]
|
196
|
+
args = [ format_message(tag) ]
|
197
|
+
out = Proc.new { str }
|
198
|
+
else
|
199
|
+
out = block
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
@logger.send(mtd, *args, &out)
|
204
|
+
|
205
|
+
end # if not disabled
|
206
|
+
|
207
|
+
|
208
|
+
elsif [:tdebug, :terror, :tinfo, :twarn].include?(mtd)
|
209
|
+
|
210
|
+
# new API that allow caller to include the tag as first parameter and
|
211
|
+
# all subsequent parameters will pass to underlying Logger object
|
212
|
+
|
213
|
+
key = args[0]
|
214
|
+
|
215
|
+
if is_genabled?(key) and not tag_disabled?(key.to_sym)
|
216
|
+
if block
|
217
|
+
out = Proc.new { block.call }
|
218
|
+
args = [ format_message(key) ]
|
219
|
+
else
|
220
|
+
str = args[1]
|
221
|
+
out = Proc.new { str }
|
222
|
+
args = [ format_message(key) ]
|
223
|
+
end
|
224
|
+
|
225
|
+
mtd = mtd.to_s[1..-1].to_sym
|
226
|
+
@logger.send(mtd, *args, &out)
|
227
|
+
end
|
228
|
+
|
229
|
+
elsif [:odebug, :oerror, :oinfo, :owarn].include?(mtd)
|
230
|
+
|
231
|
+
# new API that allow caller to include the tag as first parameter and
|
232
|
+
# all subsequent parameters will pass to underlying Logger object
|
233
|
+
# however only print the message once for each instance
|
234
|
+
|
235
|
+
key = args[0]
|
236
|
+
|
237
|
+
if is_genabled?(key) and not tag_disabled?(key)
|
238
|
+
|
239
|
+
if block
|
240
|
+
out = Proc.new { block.call }
|
241
|
+
args = [ format_message(key) ]
|
242
|
+
else
|
243
|
+
str = args[1]
|
244
|
+
out = Proc.new { str }
|
245
|
+
args = [ format_message(key) ]
|
246
|
+
end
|
247
|
+
|
248
|
+
msg = out.call
|
249
|
+
if not (msg.nil? or msg.empty?)
|
250
|
+
if not already_shown_or_add(key,msg)
|
251
|
+
mtd = mtd.to_s[1..-1].to_sym
|
252
|
+
@logger.send(mtd, *args, &out)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
elsif [:ifdebug, :iferror, :ifinfo, :ifwarn].include?(mtd)
|
259
|
+
|
260
|
+
# new API that allow caller to include
|
261
|
+
# the condition as first parameter
|
262
|
+
# tag as second parameter
|
263
|
+
# Rest of the parameters will be passed to underlying Logger object
|
264
|
+
|
265
|
+
cond = args[0]
|
266
|
+
key = args[1]
|
267
|
+
|
268
|
+
if cond.is_a?(Proc)
|
269
|
+
cond = cond.call
|
270
|
+
end
|
271
|
+
|
272
|
+
if is_genabled?(key) and not tag_disabled?(key) and cond
|
273
|
+
|
274
|
+
if block
|
275
|
+
out = Proc.new { block.call }
|
276
|
+
args = [ format_message(key) ]
|
277
|
+
else
|
278
|
+
str = args[2]
|
279
|
+
out = Proc.new { str }
|
280
|
+
args = [ format_message(key) ]
|
281
|
+
end
|
282
|
+
|
283
|
+
msg = out.call
|
284
|
+
if not (msg.nil? or msg.empty?)
|
285
|
+
mtd = mtd.to_s[2..-1].to_sym
|
286
|
+
@logger.send(mtd, *args, &out)
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
elsif @logger.respond_to?(mtd)
|
292
|
+
|
293
|
+
# rest of the method which not recognized, just passed to underlying Logger object
|
294
|
+
|
295
|
+
@logger.send(mtd, *args, &block)
|
296
|
+
|
297
|
+
else
|
298
|
+
super
|
299
|
+
end
|
300
|
+
end # method_missing
|
301
|
+
|
302
|
+
#
|
303
|
+
# :method: tag_disabled?
|
304
|
+
#
|
305
|
+
# Check if the tag is disabled
|
306
|
+
#
|
307
|
+
def tag_disabled?(tag)
|
308
|
+
if tag.nil? or tag.empty?
|
309
|
+
false
|
310
|
+
else
|
311
|
+
@disabled.include?(tag.to_sym)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
#
|
316
|
+
# :method: show_source
|
317
|
+
# Helper setting the flag include_caller
|
318
|
+
#
|
319
|
+
def show_source
|
320
|
+
@include_caller = true
|
321
|
+
end
|
322
|
+
|
323
|
+
## detect if the prompt should be to env or file
|
324
|
+
#def self.init(out = STDOUT)
|
325
|
+
# if is_dev?
|
326
|
+
# Tlogger.new(out)
|
327
|
+
# else
|
328
|
+
# path = ENV["TLOGGER_FILE_PATH"]
|
329
|
+
# if path.nil? or path.empty?
|
330
|
+
# Tlogger.new(nil)
|
331
|
+
# else
|
332
|
+
# path = [path] if not path.is_a?(Array)
|
333
|
+
# Tlogger.new(*path)
|
334
|
+
# end
|
335
|
+
# end
|
336
|
+
#end
|
337
|
+
|
338
|
+
#def self.set_dev_mode
|
339
|
+
# ENV["TLOGGER_MODE"] = "dev"
|
340
|
+
#end
|
341
|
+
|
342
|
+
#def self.set_production_mode
|
343
|
+
# ENV.delete("TLOGGER_MODE")
|
344
|
+
#end
|
345
|
+
|
346
|
+
#def self.is_dev?
|
347
|
+
# ENV.keys.include?("TLOGGER_MODE") and ENV["TLOGGER_MODE"].downcase == "dev"
|
348
|
+
#end
|
349
|
+
|
350
|
+
|
351
|
+
private
|
352
|
+
def format_message(key)
|
353
|
+
# returning args array
|
354
|
+
if @include_caller
|
355
|
+
"[#{key}] #{find_caller} "
|
356
|
+
else
|
357
|
+
"[#{key}] "
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def is_genabled?(key)
|
362
|
+
if key.nil?
|
363
|
+
true
|
364
|
+
else
|
365
|
+
(@genable and not @exception.include?(key.to_sym)) or (not @genable and @exception.include?(key.to_sym))
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def already_shown_or_add(key,msg)
|
370
|
+
smsg = Digest::SHA256.hexdigest(msg)
|
371
|
+
if @dHistory[key.to_sym].nil?
|
372
|
+
add_to_history(key,smsg)
|
373
|
+
false
|
374
|
+
else
|
375
|
+
res = @dHistory[key.to_sym].include?(smsg)
|
376
|
+
add_to_history(key,smsg) if not res
|
377
|
+
res
|
378
|
+
end
|
379
|
+
end # already_shown_or_add
|
380
|
+
|
381
|
+
def add_to_history(key,dgt)
|
382
|
+
@dHistory[key.to_sym] = [] if @dHistory[key.to_sym].nil?
|
383
|
+
@dHistory[key.to_sym] << dgt if not @dHistory[key.to_sym].include?(dgt)
|
384
|
+
end # add_to_history
|
385
|
+
|
386
|
+
def find_caller
|
387
|
+
caller.each do |c|
|
388
|
+
next if c =~ /tlogger.rb/
|
389
|
+
@cal = c
|
390
|
+
break
|
391
|
+
end
|
392
|
+
|
393
|
+
if @cal.nil? or @cal.empty?
|
394
|
+
@cal = caller[0]
|
395
|
+
end
|
396
|
+
|
397
|
+
# reduce it down to last two folder?
|
398
|
+
sp = @cal.split(File::SEPARATOR)
|
399
|
+
if sp.length > 1
|
400
|
+
msg = "/#{sp[-2]}/#{sp[-1]}"
|
401
|
+
else
|
402
|
+
msg = sp[-1]
|
403
|
+
end
|
404
|
+
|
405
|
+
msg
|
406
|
+
|
407
|
+
end # find_caller
|
408
|
+
|
409
|
+
|
410
|
+
end
|
411
|
+
end
|
data/lib/teLogger.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "teLogger/version"
|
4
|
+
require_relative 'teLogger/tlogger'
|
5
|
+
require_relative 'teLogger/logger_group'
|
6
|
+
|
7
|
+
module TeLogger
|
8
|
+
class Error < StandardError; end
|
9
|
+
# Your code goes here...
|
10
|
+
|
11
|
+
|
12
|
+
# for classes including the TeLogger
|
13
|
+
module TeLogHelper
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
# methods called at class level by included class
|
17
|
+
def teLogger_tag(val)
|
18
|
+
@telTag = val
|
19
|
+
end
|
20
|
+
|
21
|
+
def teLogger_output(*val)
|
22
|
+
@telOutput = val
|
23
|
+
end
|
24
|
+
|
25
|
+
def logTag
|
26
|
+
@telTag
|
27
|
+
end
|
28
|
+
|
29
|
+
def logOutput
|
30
|
+
if @telOutput.nil?
|
31
|
+
[]
|
32
|
+
elsif not @telOutput.is_a?(Array)
|
33
|
+
[@telOutput]
|
34
|
+
else
|
35
|
+
@telOutput
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end # ClassMethods
|
40
|
+
|
41
|
+
def self.included(klass)
|
42
|
+
klass.extend(ClassMethods)
|
43
|
+
klass.class_eval <<-END
|
44
|
+
extend TeLogger::TeLogHelper
|
45
|
+
END
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def teLogger
|
50
|
+
if @teLogger.nil?
|
51
|
+
if self.class.respond_to?(:logOutput)
|
52
|
+
@teLogger = Tlogger.new(*self.class.logOutput)
|
53
|
+
else
|
54
|
+
@teLogger = Tlogger.new(*logOutput)
|
55
|
+
end
|
56
|
+
|
57
|
+
if self.respond_to?(:logTag)
|
58
|
+
@teLogger.tag = logTag
|
59
|
+
elsif self.class.respond_to?(:logTag)
|
60
|
+
@teLogger.tag = self.class.logTag
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@teLogger
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
data/teLogger.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/teLogger/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "teLogger"
|
7
|
+
spec.version = TeLogger::VERSION
|
8
|
+
spec.authors = ["Ian"]
|
9
|
+
spec.email = ["cameronian0@protonmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Restructuring of Tlogger gem"
|
12
|
+
spec.description = "Restructuring of Tlogger library to ensure interfacing layer covers all expected use cases. "
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.required_ruby_version = ">= 2.4.0"
|
15
|
+
|
16
|
+
#spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
17
|
+
|
18
|
+
#spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
#spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
20
|
+
#spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_development_dependency 'devops_assist'
|
34
|
+
|
35
|
+
# Uncomment to register a new dependency of your gem
|
36
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
37
|
+
|
38
|
+
# For more information and examples about making a new gem, checkout our
|
39
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: teLogger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ian
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-06-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: devops_assist
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: 'Restructuring of Tlogger library to ensure interfacing layer covers
|
28
|
+
all expected use cases. '
|
29
|
+
email:
|
30
|
+
- cameronian0@protonmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".rspec"
|
36
|
+
- Gemfile
|
37
|
+
- Gemfile.lock
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- bin/console
|
41
|
+
- bin/setup
|
42
|
+
- lib/teLogger.rb
|
43
|
+
- lib/teLogger/logger_group.rb
|
44
|
+
- lib/teLogger/tlogger.rb
|
45
|
+
- lib/teLogger/version.rb
|
46
|
+
- teLogger.gemspec
|
47
|
+
homepage: ''
|
48
|
+
licenses: []
|
49
|
+
metadata: {}
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 2.4.0
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubygems_version: 3.2.22
|
66
|
+
signing_key:
|
67
|
+
specification_version: 4
|
68
|
+
summary: Restructuring of Tlogger gem
|
69
|
+
test_files: []
|