tlogger 0.7.0 → 0.25.0

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: 9f9b1b28c4dfcbe2b0fd0de47df01d8f14e83ae00efa3b3abbd6db9bd8330d1f
4
- data.tar.gz: a59d64d311798dd9a523b2e13223e580db07e3a1b67825b7e680192f69414051
3
+ metadata.gz: 7cf3256d26a571615fe3121d443904dcbeb8cf54ea1761a1d52704d36f5a9418
4
+ data.tar.gz: e0c620dca8f28c1f2177bd4e460c68b43bd4a31be6906cf304423240481a59b9
5
5
  SHA512:
6
- metadata.gz: 2c238b0a66dd21096b9e0d0d9a36557bfb19f2fda136fd0bc38afd1d9caeafa218c865a20e8c30a4d7bcab5414aafda160d4ade4d81da1e723b92590e6453cc1
7
- data.tar.gz: 638660c6d8e855986608c112d1b2a1e5792f862538983229cbbcae4f867b40f891c0abb3ada22daa8f6555d38e3352c9e66ea2eff91d787a121e6631cd51e726
6
+ metadata.gz: 26a1ecb562014272126bcbe5669ca7e6cee341d93f1c0bca7f52a85f099f60d7e8f5557001ad032ce00379f295ec14a749242020f7b5e9797c4bc25ee28b7f28
7
+ data.tar.gz: b22ed97e724d855d993533cd5062920c85934358e2e1e62fb691d81e4045c28e2335a93f3b8c7c83dd3646dffb985b3e9bc89abd897ef5f6ee5966565c86c4e8
data/.gitignore CHANGED
@@ -6,3 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+
10
+ *.log
11
+ *.gem
12
+ Gemfile.lock
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.6.3
6
+ before_install: gem install bundler -v 2.1.4
@@ -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
@@ -2,3 +2,6 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in tlogger.gemspec
4
4
  gemspec
5
+
6
+ gem "rake", ">= 12.3.3"
7
+ gem "minitest", "~> 5.0"
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
- TODO: Write usage instructions here
46
+ ### Basic - Adding Context
47
+
48
+ Since Tlogger is just wrapped around Ruby Logger, it is initiated like Logger:
24
49
 
25
- ## Development
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
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
113
+ ### Possible Concern
30
114
 
31
- ## Contributing
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
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/tlogger.
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
@@ -1,2 +1,12 @@
1
1
  require "bundler/gem_tasks"
2
- task :default => :spec
2
+ require "rake/testtask"
3
+
4
+ require 'devops_helper'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ task :default => :test
@@ -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
- #require "irb"
14
- #IRB.start(__FILE__)
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -1,327 +1,54 @@
1
-
2
-
3
- require 'logger'
4
- require 'singleton'
5
-
6
1
  require "tlogger/version"
7
2
 
3
+ require_relative "tlogger/tlogger"
4
+ require_relative "tlogger/logger_group"
5
+
6
+ #
7
+ # :nodoc:
8
+ #
8
9
  module Tlogger
9
10
  class Error < StandardError; end
10
- # Your code goes here...
11
-
12
- #
13
- # Singleton object to facilitate tag management
14
- #
15
- class TloggerConf
16
- include Singleton
17
- attr_reader :active_tags, :scoped_tag, :blacklisted_tags, :show_source
18
- #GLOBAL_TAG = :global
19
- GLOBAL_TAG = ""
20
- INT_TAG = :tlogger
21
-
22
- def initialize
23
- @active_tags = []
24
- # tag added to black listed will not be printed out even the tag is added later in the code path
25
- @blacklisted_tags = []
26
- @disable_all_tags = false
27
- @auto_tag = false
28
- # todo
29
- # allow to redirect certain tag to specific output. tag: [<config>]
30
- @output_map = {}
31
- # if output_map is there, then there should be pre created log file with specific output defined in the map. [<config>] => log_instance
32
- @output_log = {}
33
- # show where is the log being printed out. Like auto_tag output
34
- @show_source = false
35
- # end todo
36
- end
37
-
38
- def show_source
39
- @show_source = true
40
- end
41
- alias_method :auto_tag_on, :show_source
42
-
43
- def hide_source
44
- @show_source = false
45
- end
46
- alias_method :auto_tag_off, :hide_source
47
-
48
- def is_show_source?
49
- @show_source
50
- end
51
- alias_method :is_auto_tag_on?, :is_show_source?
52
-
53
- #def auto_tag_on
54
- # @auto_tag = true
55
- #end
56
-
57
- #def auto_tag_off
58
- # @auto_tag = false
59
- #end
60
-
61
- #def is_auto_tag_on?
62
- # @auto_tag
63
- #end
64
-
65
- def activate_tag(tag)
66
- @active_tags << tag
67
- end
68
-
69
- def deactivate_tag(tag)
70
- @active_tags.delete(tag)
71
- end
72
-
73
- def blacklist_tag(tag)
74
- if tag.is_a?(Array)
75
- @blacklisted_tags += tag
76
- else
77
- @blacklisted_tags << tag
78
- end
79
- end
80
-
81
- def all_tags_off
82
- @disable_all_tags = true
83
- end
84
-
85
- def all_tags_on
86
- @disable_all_tags = false
87
- end
88
-
89
- def whitelist_tag(tag)
90
- if tag.is_a?(Array)
91
- tag.each do |t|
92
- @blacklisted_tags.delete(t)
93
- end
94
- else
95
- @blacklisted_tags.delete(tag)
96
- end
97
- end
98
-
99
- def whitelist_all_tags
100
- @disabled_tags.clear
101
- end
102
-
103
- def is_tag_active?(tag)
104
- if @disable_all_tags
105
- false
106
- else
107
- @active_tags.include?(tag) #and not @disabled_tags.include?(tag)
108
- end
109
- end
110
-
111
- def remove_all_active_tags
112
- @active_tags.clear
113
- end
114
-
115
- def set_scoped_tag(tag)
116
- @scoped_tag = tag
117
- end
118
-
119
- def clear_scoped_tag
120
- @scoped_tag = nil
121
- end
122
11
 
123
- def has_scoped_tag?
124
- if @disable_all_tags
125
- false
126
- else
127
- not @scoped_tag.nil? and not @scoped_tag.empty?
128
- end
129
- end
130
-
131
- def is_scoped_tag_active?
132
- #@active_tags.include?(@scoped_tag)
133
- not @blacklisted_tags.include?(@scoped_tag)
134
- end
135
-
136
- def self.method_missing(mtd,*args,&block)
137
- if TloggerConf.instance.respond_to?(mtd)
138
- TloggerConf.instance.send(mtd,*args,&block)
139
- else
140
- super
141
- end
142
- end
143
- end
144
- #
145
- # end TloggerConf singleton
146
- #
147
-
148
- #
149
- # add object like methods to make module a class
150
- #
12
+ # shorten the initializer to Tlogger.new instead of the longer Tlogger::Tlogger.new
151
13
  class << self
152
- attr_accessor :tag
153
- include Tlogger
154
-
155
- PROXY_MTD = [:debug, :info, :error, :warn]
156
- def new(*args)
157
- if args.length == 0
158
- args << STDOUT
159
- end
160
- @tlogger = Logger.new(*args)
161
- @tag = TloggerConf::GLOBAL_TAG
162
- # disable by default
163
- # If there is issue then enable it back in application level
164
- self
165
- end
166
-
167
- def tag=(val)
168
- @tag = val
169
- TloggerConf.activate_tag(@tag)
170
- self
171
- end
172
-
173
- def tdebug(tag,*args)
174
- with_tag(tag) do
175
- self.debug(*args)
176
- end
177
- self
178
- end
179
-
180
- def terror(tag, *args)
181
- with_tag(tag) do
182
- self.error(*args)
183
- end
184
- self
185
- end
186
-
187
- def tinfo(tag, *args)
188
- with_tag(tag) do
189
- self.info(*args)
190
- end
191
- self
14
+ def new(*args,&block)
15
+ ::Tlogger::Tlogger.new(*args,&block)
192
16
  end
193
17
 
194
- def twarn(tag, *args)
195
- with_tag(tag) do
196
- self.warn(*args)
197
- end
198
- self
199
- end
200
-
201
- def intDebug(msg)
202
- #puts TloggerConf.active_tags
203
- if TloggerConf.instance.is_tag_active?(TloggerConf::INT_TAG)
204
- msg2 = "[#{TloggerConf::INT_TAG}] #{msg}"
205
- #puts "intDebug"
206
- @tlogger.debug(msg2)
18
+ # detect if the prompt should be to env or file
19
+ def init
20
+ if is_dev?
21
+ new(STDOUT)
22
+ else
23
+ c = output_channel
24
+ new(*c[:path])
207
25
  end
208
26
  end
209
27
 
210
- def method_missing(mtd,*args,&block)
211
- #@tlogger.debug "[tlogger] method_missing: Method #{mtd}"
212
- intDebug("method_missing: #{mtd}")
213
- if @tlogger.respond_to?(mtd)
214
-
215
- if PROXY_MTD.include?(mtd)
216
-
217
- if @tag.nil? or @tag.empty?
218
- # no tag. Output like normal log
219
- @tlogger.send(mtd, *args, &block)
220
-
28
+ private
29
+ def is_dev?
30
+ ENV.keys.include?("TLOGGER_MODE") and ENV["TLOGGER_MODE"].downcase == "dev"
31
+ end
32
+
33
+ def output_channel
34
+ out = ENV["TLOGGER_OUT"]
35
+ if not out.nil?
36
+ case out
37
+ when "file"
38
+ path = ENV["TLOGGER_OUTPATH"]
39
+ if path =~ /,/
40
+ { mode: :file, path: path.split(",") }
221
41
  else
222
-
223
- if TloggerConf.has_scoped_tag?
224
- if TloggerConf.is_scoped_tag_active?
225
- intDebug("Scoped tag detected")
226
- tag = []
227
- tag << TloggerConf.scoped_tag
228
- if TloggerConf.instance.is_show_source?
229
- tag << " - "
230
- tag << find_caller
231
- end
232
- args[0] = "[#{tag.join}] #{args[0]}"
233
- @tlogger.send(mtd,*args,&block)
234
- end
235
- elsif TloggerConf.is_auto_tag_on?
236
- intDebug("auto_tag is on...")
237
- args = tag_class(*args)
238
- @tlogger.send(mtd,*args,&block)
239
- elsif TloggerConf.is_tag_active?(@tag)
240
- intDebug("Tagged output...")
241
- tag = []
242
- tag << @tag
243
- if TloggerConf.instance.is_show_source?
244
- tag << " - "
245
- tag << find_caller
246
- end
247
- args[0] = "[#{tag.join}] #{args[0]}"
248
- @tlogger.send(mtd,*args,&block)
249
- end
250
-
42
+ { mode: :file, path: [path] }
251
43
  end
252
-
253
44
  else
254
- intDebug("Not proxy method for logger. Pass to logger to handle. (#{mtd})")
255
- ## not the debug, info, warn and error method, no need change message
256
- @tlogger.send(mtd, *args, &block)
45
+ { mode: :file, path: [nil] }
257
46
  end
258
-
259
-
260
- elsif TloggerConf.instance.respond_to?(mtd)
261
- # redirect the config method to make it consistent API
262
- intDebug("Redirect to TloggerConf for consistancy (#{mtd})")
263
- TloggerConf.send(mtd, *args, &block)
264
47
  else
265
- intDebug("Call method_missing parent to handle method '#{mtd}'")
266
- super
48
+ { mode: :stdio, path: [nil] }
267
49
  end
268
50
  end
269
- # end method_missing
270
- #
51
+ end # class self
271
52
 
272
- private
273
- def tag_class(*args)
274
- args[0] = "[#{find_caller}] #{args[0]}"
275
- args
276
- end
277
- # end tag_class()
278
- #
279
-
280
- def find_caller
281
- caller.each do |c|
282
- next if c =~ /tlogger.rb/
283
- @cal = c
284
- break
285
- end
286
-
287
- if @cal.nil? or @cal.empty?
288
- @cal = caller[0]
289
- end
290
-
291
- # reduce it down to last two folder?
292
- sp = @cal.split(File::SEPARATOR)
293
- if sp.length > 1
294
- msg = "/#{sp[-2]}/#{sp[-1]}"
295
- else
296
- msg = sp[-1]
297
- end
298
- msg
299
-
300
- #wd = Dir.getwd
301
- #indx = @cal =~ /#{wd}/
302
- #if indx != nil
303
- # @scal = []
304
- # @scal << @cal[0..indx]
305
- # @scal << @cal[indx+wd.length..-1]
306
- # @scal.join
307
- #else
308
- # @cal
309
- #end
310
- end
311
- # end find_caller
312
- #
313
- end
314
- #
315
- # end class definition
316
- #
317
-
318
-
319
- def with_tag(tag,&block)
320
- if block
321
- TloggerConf.instance.set_scoped_tag(tag) #if not TloggerConf.instance.disabled_tags.include?(tag)
322
- block.call
323
- TloggerConf.instance.clear_scoped_tag
324
- end
325
- end
326
-
327
53
  end
54
+