tlogger 0.8.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +3 -0
- data/README.md +91 -9
- data/Rakefile +9 -1
- data/bin/console +4 -4
- data/lib/tlogger/logger_group.rb +105 -0
- data/lib/tlogger/tlogger.rb +352 -0
- data/lib/tlogger/version.rb +1 -1
- data/lib/tlogger.rb +6 -325
- data/samples/basic.rb +54 -36
- data/samples/group.rb +54 -0
- data/tlogger.gemspec +12 -27
- metadata +18 -71
- data/Gemfile.lock +0 -31
- data/LICENSE.txt +0 -21
- data/release.job +0 -53
- data/samples/basic2.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e5e945c26521b256ba6c54e4bfa3cdabd734872bb98d2ca5e1f5ce5e5005638
|
4
|
+
data.tar.gz: 80622dc6905d7f80c05bd2f2c81a987bcafa089fb21602e132e165e87f03cc2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a260719058fe3c4cc1ab51cc4540d52a92c56cb82a5cc1a8088fb4affbf9e662b4250e73efe6ed40a44a6ad879a4da88e971b2a4ea4be456def6ad37beeeb305
|
7
|
+
data.tar.gz: c72dee13fc95be607c60726749d10ea3de968e46c35c21495cdd245bbfa2fe0b93576ab3d7e96d4f365c409781f3041b37e6e78c879cf2c33271ff9f2425356a
|
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at chrisliaw@antrapol.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [https://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: https://contributor-covenant.org
|
74
|
+
[version]: https://contributor-covenant.org/version/1/4/
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# Tlogger
|
2
2
|
|
3
|
+
Tlogger is the attempt to have some control in logging by the developer.
|
4
|
+
|
5
|
+
I 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 you can just disable all other log messages and only focus on the log messages around the suspected issue? That is the reason of this library.
|
6
|
+
|
7
|
+
Tlogger 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 Tlogger 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. STDOUT and log file)
|
3
26
|
|
4
27
|
|
5
28
|
## Installation
|
@@ -12,7 +35,7 @@ gem 'tlogger'
|
|
12
35
|
|
13
36
|
And then execute:
|
14
37
|
|
15
|
-
$ bundle
|
38
|
+
$ bundle install
|
16
39
|
|
17
40
|
Or install it yourself as:
|
18
41
|
|
@@ -20,18 +43,77 @@ Or install it yourself as:
|
|
20
43
|
|
21
44
|
## Usage
|
22
45
|
|
23
|
-
|
46
|
+
### Basic - Adding Context
|
47
|
+
|
48
|
+
Since Tlogger is just wrapped around Ruby Logger, it is initiated like Logger:
|
24
49
|
|
25
|
-
|
50
|
+
```ruby
|
51
|
+
require 'tlogger'
|
52
|
+
|
53
|
+
# Initiate without parameters shall print out the log to STDOUT
|
54
|
+
log = Tlogger::Tlogger.new
|
55
|
+
|
56
|
+
# Alternatively, this initiate logging with log file
|
57
|
+
# The parameter is directly pass to Ruby Logger.new method
|
58
|
+
log = Tlogger::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
|
+
### Filter Log Messages
|
100
|
+
|
101
|
+
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
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
# turned off all tags except the one given
|
105
|
+
log.off_all_tags_except(:phase1, :phase2)
|
106
|
+
|
107
|
+
# OR turned off selected tags only
|
108
|
+
log.tag_off(:init)
|
109
|
+
```
|
110
|
+
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.
|
26
111
|
|
27
|
-
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
28
112
|
|
29
|
-
|
113
|
+
### Possible Concern
|
30
114
|
|
31
|
-
|
115
|
+
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.
|
32
116
|
|
33
|
-
|
117
|
+
To me I can 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.
|
34
118
|
|
35
|
-
## License
|
36
119
|
|
37
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -7,8 +7,8 @@ require "tlogger"
|
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
8
8
|
|
9
9
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
require "pry"
|
11
|
-
Pry.start
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Tlogger
|
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 add_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
|
+
# Close the logger group, effectively close all registered loggers
|
79
|
+
def close
|
80
|
+
@loggers.each do |k,v|
|
81
|
+
v.close
|
82
|
+
v = nil
|
83
|
+
end
|
84
|
+
@loggers.clear
|
85
|
+
end # # close
|
86
|
+
|
87
|
+
# Delegate unknown method to the underlying logger
|
88
|
+
def method_missing(mtd,*args,&block)
|
89
|
+
|
90
|
+
#hit = false
|
91
|
+
@loggers.each do |k,v|
|
92
|
+
begin
|
93
|
+
v.send(mtd,*args,&block)
|
94
|
+
#hit = true
|
95
|
+
rescue Exception => ex
|
96
|
+
STDERR.puts ex.message
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
#super if not hit
|
101
|
+
|
102
|
+
end # # method_missing
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|