alog 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/.gitignore +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +20 -0
- data/LICENSE.txt +21 -0
- data/README.md +141 -0
- data/Rakefile +2 -0
- data/alog.gemspec +41 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/alog/version.rb +3 -0
- data/lib/alog.rb +166 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5c99568a04040e5467af6aa0230606d1b3e7e6d12a19da083ce27574a12a67a1
|
4
|
+
data.tar.gz: a0f6cfa695a5b1b1874eb2a55cfa88804f1ceccbe34b6e2c07254a01309508ad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c08f58b90258819bc35b63a40da82aa126645d976edb5b2a625c532dcaf9e44bfecc14b8e4d33915f53c7c6ed25ea8ca842e3f77112589d0987f76238a761cbb
|
7
|
+
data.tar.gz: 921a75bed5bfb7b861e3bc27fa2bfeb87394055f44c18c8133da03c34b7c0da9d9158cfe8d1bead17f55dc2d1cbe05f86b427ce37dc79b5753c158edbed636c9
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Chris Liaw
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# Alog
|
2
|
+
|
3
|
+
Alog (Advanced/Antrapol Logging) is an attempt to tackle the logging issue that is too verbose.
|
4
|
+
|
5
|
+
Logging is better to be verbose but when working on large project, the development is evolution type of progress instead of revolution. Hence the logging output tends to be increasing over the time of development. Those logging generated during the early stage of the development may not be siginificant in later development work.
|
6
|
+
|
7
|
+
In other framework there is conditional logging like #IFDEF in C to ignore logging if a key is not defined.
|
8
|
+
|
9
|
+
This conditional logging however is not related to the log level (DEBUG, ERROR etc) as defined by the log engine.
|
10
|
+
|
11
|
+
Alog is meant to be allow developer to group the logging under a meaningful tag and if the tag is not defined, the log is skipped therefore removing the log entirely out from the view of the developer and left only the current focusing development work's log.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'alog'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install alog
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
First is to include the alog library
|
32
|
+
```ruby
|
33
|
+
require 'alog'
|
34
|
+
```
|
35
|
+
|
36
|
+
Include the namespace into your class and configure the tag that you want the library to show/display.
|
37
|
+
Any tag that is not configured will be skipped
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
class MyApp
|
41
|
+
include Alog
|
42
|
+
|
43
|
+
# STEP 1: Configuration
|
44
|
+
#
|
45
|
+
# Configure logger and bind the logger to a key
|
46
|
+
# Whatever on the right side shall be passed to the standard library Logger object
|
47
|
+
# The array construct is necesary because *args is used in
|
48
|
+
# passing the parameters to actual standard library Logger object via new()
|
49
|
+
LogFacts[:stdout] = [STDOUT]
|
50
|
+
# Also multiple loggers can be configured by creating multiple keys
|
51
|
+
LogFacts[:app_file] = ['app.log',10, 1024000]
|
52
|
+
...
|
53
|
+
|
54
|
+
# STEP 2: Define which keys to activate
|
55
|
+
# Any block/log output tagged by the key included in this array shall be printed
|
56
|
+
LogTag << :feature_1
|
57
|
+
LogTag << :feature_2
|
58
|
+
...
|
59
|
+
# Any tag that is not configured inside the LogTag will not be printed out
|
60
|
+
# If the list is empty, no log under the library shall be printed.
|
61
|
+
# Or there is more then dozens tags and want to show all, use this method
|
62
|
+
show_all_tags
|
63
|
+
|
64
|
+
|
65
|
+
# STEP 3: Create the logging
|
66
|
+
def my_method(p1, p2)
|
67
|
+
# Method 1: block logging
|
68
|
+
l(:feature_1, type: :debug, logEng: [:stdout]) do
|
69
|
+
# All clog() call inside this block will be tagged with key :feature_1
|
70
|
+
# enabling the key :feature_1 shall show all log messages inside this block or disabling otherwise
|
71
|
+
...
|
72
|
+
...
|
73
|
+
# If only message is given, the following is the default:
|
74
|
+
# 1. The system shall use the first logger, in this case it will be using logger with key :stdout
|
75
|
+
# 2. The logger will use debug level to log the message
|
76
|
+
# (System will use log level debug if the log level is not given in the l() above via key 'type'.
|
77
|
+
clog "This is logging message"
|
78
|
+
...
|
79
|
+
...
|
80
|
+
# If the message and tag is given
|
81
|
+
# 1. The tag shall override the global configuration of logging level debug (to whatever level given by developer)
|
82
|
+
# Note that 'error' logging level will ignore the tag-skipping feature since error conditions (and its messages) will likely
|
83
|
+
# affect the subsequent code/logic of a system. Therefore 'error' will always be printed.
|
84
|
+
clog "Error in defining X", :error
|
85
|
+
clog "Reach here means ok", :info
|
86
|
+
|
87
|
+
# Asking the Alogger to write to other logger at the same time,
|
88
|
+
# overriding the parameter given in the l().
|
89
|
+
clog "This will written to both :stdout and :app_file", logEng: [:stdout,:app_file]
|
90
|
+
...
|
91
|
+
...
|
92
|
+
end
|
93
|
+
|
94
|
+
(business logic continues...)
|
95
|
+
...
|
96
|
+
...
|
97
|
+
# Method 2: Call clog() directly
|
98
|
+
# Param 1 : Log messages
|
99
|
+
# Param 2 : Log level [:debug|:info|:error] (empty = :debug)
|
100
|
+
# Param 3 : Tag of the log message (empty = :global)
|
101
|
+
# Param 4 : Log engine to be used (refers to LogFacts hash entries above) (empty = first LogFacts key)
|
102
|
+
clog("Business continue up to level 2", :debug, :feature_2, [:stdout])
|
103
|
+
...
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def my_method2(p2)
|
108
|
+
# Method 3 : Create the AOlogger object
|
109
|
+
# AOlogger is meant to be proxy for standard Logger, with the tagging and multiple log engines included
|
110
|
+
# The initialize parameter is an array containing key to the LogFacts above...
|
111
|
+
# In the following case, the AOlogger shall only configured to :stdout configuration (refers above)
|
112
|
+
@log = AOlogger.new([:stdout])
|
113
|
+
...
|
114
|
+
...
|
115
|
+
# This behave like standard logging engine
|
116
|
+
@log.debug "Code reached here..."
|
117
|
+
...
|
118
|
+
@log.error "Oppss... We did it again!"
|
119
|
+
...
|
120
|
+
...
|
121
|
+
# This allow application to participate in the conditional logging
|
122
|
+
# If the tag :feature_x is not activated, the message will not be printed.
|
123
|
+
@log.log("this only shown if tag :feature_x is activated", :debug, :feature_x, [:app_file])
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
|
131
|
+
## TODO
|
132
|
+
|
133
|
+
Library not yet tested extensively under multi-threaded applications. Some variables may not be thread safe.
|
134
|
+
|
135
|
+
## Contributing
|
136
|
+
|
137
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/chrisliaw/alog.
|
138
|
+
|
139
|
+
## License
|
140
|
+
|
141
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/alog.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "alog/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "alog"
|
8
|
+
spec.version = Alog::VERSION
|
9
|
+
spec.authors = ["Chris Liaw"]
|
10
|
+
spec.email = ["chrisliaw@antrapol.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Conditional logging to provide contextual logging and ability to reconfigure log message visibility during runtime}
|
13
|
+
spec.description = %q{Allow contextual log output to ease developer in log management}
|
14
|
+
spec.homepage = "https://github.com/chrisliaw/alog"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
#if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
|
22
|
+
# spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
24
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
25
|
+
#else
|
26
|
+
# raise "RubyGems 2.0 or newer is required to protect against " \
|
27
|
+
# "public gem pushes."
|
28
|
+
#end
|
29
|
+
|
30
|
+
# Specify which files should be added to the gem when it is released.
|
31
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
32
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
33
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
34
|
+
end
|
35
|
+
spec.bindir = "exe"
|
36
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
|
+
spec.require_paths = ["lib"]
|
38
|
+
|
39
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
40
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
41
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "alog"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/alog/version.rb
ADDED
data/lib/alog.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
require "alog/version"
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Alog
|
6
|
+
class AlogException < StandardError; end
|
7
|
+
|
8
|
+
# allow application to provide which tag should print out
|
9
|
+
LogTag = [:global]
|
10
|
+
|
11
|
+
# allow application to configure multiple logging
|
12
|
+
# log factories configurations
|
13
|
+
LogFacts = {}
|
14
|
+
|
15
|
+
# multi logger created from
|
16
|
+
# LogFacts entry given by application
|
17
|
+
GLog = {}
|
18
|
+
|
19
|
+
#
|
20
|
+
# class Alogger
|
21
|
+
# Inherited from standard library Logger
|
22
|
+
#
|
23
|
+
class Alogger < Logger
|
24
|
+
def initialize(args)
|
25
|
+
@log = Logger.new(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def log(msg, type = :debug, &block)
|
29
|
+
@log.send(type, msg)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
# end class Alogger
|
33
|
+
#
|
34
|
+
|
35
|
+
#
|
36
|
+
# class AloggerObject
|
37
|
+
# Mimiking the original Logger object
|
38
|
+
# to be used by application but with
|
39
|
+
# the conditioning logging logic available
|
40
|
+
# to the application instead
|
41
|
+
#
|
42
|
+
class AOlogger
|
43
|
+
attr_reader :logEng
|
44
|
+
def initialize(logEng = [])
|
45
|
+
@myMethods = [:debug, :error, :warn, :warning]
|
46
|
+
@logEng = logEng || []
|
47
|
+
end
|
48
|
+
|
49
|
+
def log(msg, ltype = :debug, key = :global, logEng = [])
|
50
|
+
CondLog.call(msg, { key: key, type: ltype, logEng: logEng || @logEng })
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(mtd, *args, &block)
|
54
|
+
if @myMethods.include?(mtd)
|
55
|
+
params = {}
|
56
|
+
pa = args[1]
|
57
|
+
params[:key] = :global
|
58
|
+
params[:logEng] = @logEng
|
59
|
+
# TODO cases here may not be extensive to
|
60
|
+
# the original Logger supported.
|
61
|
+
case mtd
|
62
|
+
when :debug
|
63
|
+
params[:type] = :debug
|
64
|
+
CondLog.call(args[0], params, &block)
|
65
|
+
when :error
|
66
|
+
params[:type] = :error
|
67
|
+
CondLog.call(args[0], params, &block)
|
68
|
+
when :warn, :warning
|
69
|
+
params[:type] = :warn
|
70
|
+
CondLog.call(args[0], params, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
else
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
#
|
79
|
+
# end class AloggerObject
|
80
|
+
#
|
81
|
+
|
82
|
+
def show_all_tags
|
83
|
+
LogTag << :all
|
84
|
+
end
|
85
|
+
|
86
|
+
def selected_tags_only
|
87
|
+
LogTag.delete(:all)
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Provide a block construct that can set values consistantly for multiple clog() call
|
92
|
+
# TODO How to make this thread safe?
|
93
|
+
#
|
94
|
+
def l(key = :global, params = { type: :debug, logEng: [] } ,&block)
|
95
|
+
# this construct try to make the variable private to the block
|
96
|
+
# Still not sure will error condition exist for multi threaded application
|
97
|
+
b = Proc.new do |key, params, &block|
|
98
|
+
@lKey = key
|
99
|
+
@lType = params[:type]
|
100
|
+
@llEng = params[:logEng]
|
101
|
+
if block
|
102
|
+
block.call
|
103
|
+
end
|
104
|
+
end
|
105
|
+
b.call(key, params, &block)
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Module level clog() method
|
110
|
+
# Meant to be called by application INSIDE the l()'s block
|
111
|
+
#
|
112
|
+
def clog(msg, ltype = :debug, key = :global, logEng = [])
|
113
|
+
log(msg, { type: @lType != ltype ? ltype : @lType,
|
114
|
+
key: (key == @lKey ? key : @lKey),
|
115
|
+
logEng: @llEng })
|
116
|
+
end
|
117
|
+
#
|
118
|
+
# end of module level clob()
|
119
|
+
#
|
120
|
+
|
121
|
+
#
|
122
|
+
# Actual logic of detecting a tag should be activated and on which logger should it written to
|
123
|
+
#
|
124
|
+
CondLog = Proc.new do |msg, params = {}, &block|
|
125
|
+
key = params[:key] || :global
|
126
|
+
type = params[:type] || :debug
|
127
|
+
if defined?(:LogTag) and LogTag.is_a?(Array) and (LogTag.include?(key) or LogTag.include?(:all)) or type == :error
|
128
|
+
logEng = params[:logEng]
|
129
|
+
if logEng == nil or (logEng != nil and logEng.empty?)
|
130
|
+
logEng = (LogFacts.length > 0 ? [LogFacts.keys[0]] : [:default])
|
131
|
+
end
|
132
|
+
|
133
|
+
logEng = [logEng] if not logEng.is_a?(Array)
|
134
|
+
|
135
|
+
# allow written to multiple logger
|
136
|
+
logEng.each do |e|
|
137
|
+
|
138
|
+
if GLog[e] == nil
|
139
|
+
|
140
|
+
lp = LogFacts[e]
|
141
|
+
if lp == nil
|
142
|
+
# default if empty
|
143
|
+
lp = [STDOUT]
|
144
|
+
end
|
145
|
+
|
146
|
+
# ensure the same configuration only created a logger object once
|
147
|
+
GLog[e] = Alogger.new(lp)
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
GLog[e].log("#{caller.length > 3 ? "[#{File.basename(caller[4])}]" : ""} [#{key}] #{msg}", type, &block)
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
# end CondLog() proc
|
158
|
+
#
|
159
|
+
|
160
|
+
# provide module level method to write to the logger object
|
161
|
+
def log(msg, params = { }, &block)
|
162
|
+
CondLog.call(msg, params, &block)
|
163
|
+
end
|
164
|
+
# end module level log()
|
165
|
+
|
166
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Liaw
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Allow contextual log output to ease developer in log management
|
42
|
+
email:
|
43
|
+
- chrisliaw@antrapol.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- Gemfile.lock
|
51
|
+
- LICENSE.txt
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- alog.gemspec
|
55
|
+
- bin/console
|
56
|
+
- bin/setup
|
57
|
+
- lib/alog.rb
|
58
|
+
- lib/alog/version.rb
|
59
|
+
homepage: https://github.com/chrisliaw/alog
|
60
|
+
licenses:
|
61
|
+
- MIT
|
62
|
+
metadata: {}
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 2.7.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Conditional logging to provide contextual logging and ability to reconfigure
|
83
|
+
log message visibility during runtime
|
84
|
+
test_files: []
|