Module: OSlg

Defined in:
lib/oslg/oslog.rb,
lib/oslg/version.rb

Overview

BSD 3-Clause License

Copyright (c) 2022-2025, Denis Bourgeois All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Constant Summary collapse

DEBUG =

e.g. for debugging e.g. "argument String? expecting Integer"

1
INFO =

e.g. informative e.g. "success! no errors, no warnings"

2
WARN =

e.g. warnings e.g. "partial success, see non-fatal warnings"

3
ERROR =

e.g. erros e.g. "partial success, see non-fatal errors"

4
FATAL =

e.g. failures e.g. "stopping! encountered fatal errors"

5
VERSION =

OSlg version

"0.4.0".freeze
@@logs =

each log is a Hash with keys :level (Integer) and :message (String)

[]
@@tag =

preset strings matching log levels

[
         "", # (empty string)
    "DEBUG", # DEBUG
     "INFO", # INFO
  "WARNING", # WARNING
    "ERROR", # ERROR
    "FATAL"  # FATAL
].freeze
@@msg =

preset strings matching log status

[
                                               "", # (empty string)
                                  "Debugging ...", # DEBUG
                "Success! No errors, no warnings", # INFO
     "Partial success, raised non-fatal warnings", # WARNING
  "Partial success, encountered non-fatal errors", # ERROR
                "Failure, triggered fatal errors"  # FATAL
].freeze
@@level =

initial log level

INFO
@@status =

initial status

0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object

Callback when other modules extend OSlg



458
459
460
# File 'lib/oslg/oslog.rb', line 458

def self.extended(base)
  base.send(:include, self)
end

Instance Method Details

#clean!Integer

Resets log status and entries.



447
448
449
450
451
452
# File 'lib/oslg/oslog.rb', line 447

def clean!
  @@status = 0
  @@logs   = []

  @@level
end

#debug?Bool

Returns whether current status is DEBUG.



92
93
94
# File 'lib/oslg/oslog.rb', line 92

def debug?
  @@status == DEBUG
end

#empty(id = "", mth = "", lvl = DEBUG, res = nil, len = nil) ⇒ Object

Logs template 'empty' message, if provided arguments are valid.

Examples:

An uninitialized variable, logging an ERROR, returning FALSE

empty("zone", "conditioned?", FATAL, false) if space.thermalZone.empty?


360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/oslg/oslog.rb', line 360

def empty(id = "", mth = "", lvl = DEBUG, res = nil, len = nil)
  return res unless id.respond_to?(:to_s)
  return res unless mth.respond_to?(:to_s)
  return res unless lvl.respond_to?(:to_i)

  lvl = lvl.to_i
  id  = trim(id)
  mth = trim(mth)
  return res if id.empty?
  return res if mth.empty?
  return res if lvl < DEBUG
  return res if lvl > FATAL

  log(lvl, "Empty '#{id}' (#{mth})", len)

  res
end

#error?Bool

Returns whether current status is ERROR.



116
117
118
# File 'lib/oslg/oslog.rb', line 116

def error?
  @@status == ERROR
end

#fatal?Bool

Returns whether current status is FATAL.



124
125
126
# File 'lib/oslg/oslog.rb', line 124

def fatal?
  @@status == FATAL
end

#hashkey(id = "", hsh = {}, key = "", mth = "", lvl = DEBUG, res = nil, len = nil) ⇒ Object

Logs template 'missing hash key' message, if provided arguments are valid. The message is not logged if the provided key exists.

Examples:

A missing Hash key

hashkey("floor area", floor, :area, "sum") unless floor.key?(:area)


326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/oslg/oslog.rb', line 326

def hashkey(id = "", hsh = {}, key = "", mth = "", lvl = DEBUG, res = nil, len = nil)
  return res unless id.respond_to?(:to_s)
  return res unless hsh.is_a?(Hash)
  return res if hsh.key?(key)
  return res unless mth.respond_to?(:to_s)
  return res unless lvl.respond_to?(:to_i)

  lvl = lvl.to_i
  id  = trim(id)
  mth = trim(mth)
  return res if id.empty?
  return res if mth.empty?
  return res if lvl < DEBUG
  return res if lvl > FATAL

  log(lvl, "Missing '#{key}' key in '#{id}' Hash (#{mth})", len)

  res
end

#info?Bool

Returns whether current status is INFO.



100
101
102
# File 'lib/oslg/oslog.rb', line 100

def info?
  @@status == INFO
end

#invalid(id = "", mth = "", ord = 0, lvl = DEBUG, res = nil, len = nil) ⇒ Object

Logs template 'invalid object' message, if provided arguments are valid. Relies on OSlg method 'log()': first check out its own operation, exit conditions and module side effects. Candidate log entry is ignored and status remains unchanged if 'ord' cannot be converted to an integer. Argument 'ord' is ignored unless > 0.

Examples:

An invalid argument, logging a FATAL error, returning FALSE

return invalid("area", "sum", 0, FATAL, false) if area > 1000000


248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/oslg/oslog.rb', line 248

def invalid(id = "", mth = "", ord = 0, lvl = DEBUG, res = nil, len = nil)
  return res unless id.respond_to?(:to_s)
  return res unless mth.respond_to?(:to_s)
  return res unless ord.respond_to?(:to_i)
  return res unless lvl.respond_to?(:to_i)

  ord = ord.to_i
  lvl = lvl.to_i
  id  = trim(id)
  mth = trim(mth)
  return res if id.empty?
  return res if mth.empty?
  return res if lvl < DEBUG
  return res if lvl > FATAL

  msg = "Invalid '#{id}' "
  msg += "arg ##{ord} " if ord > 0
  msg += "(#{mth})"
  log(lvl, msg, len)

  res
end

#levelDEBUG, ...

Returns current log level.



76
77
78
# File 'lib/oslg/oslog.rb', line 76

def level
  @@level
end

#log(lvl = DEBUG, message = "", len = nil) ⇒ DEBUG, ...

Logs a new entry. Overall log status is raised if new level is greater than current level (e.g. FATAL > ERROR). Candidate log entry is ignored and status remains unchanged if the new level cannot be converted to an integer, if not an OSlg constant (once converted), or if new level is below the current log level. Relies on OSlg method 'trim()': candidate log message is ignored and status unchanged if message is not a valid string.

Examples:

A user warning

log(WARN, "Surface area < 100cm2")


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/oslg/oslog.rb', line 212

def log(lvl = DEBUG, message = "", len = nil)
  return @@status unless lvl.respond_to?(:to_i)
  return @@status unless message.respond_to?(:to_s)

  lvl = lvl.to_i
  message = trim(message, len)
  return @@status if message.empty?
  return @@status if lvl < DEBUG
  return @@status if lvl > FATAL
  return @@status if lvl < @@level

  @@logs << {level: lvl, message: message}
  return @@status unless lvl > @@status

  @@status = lvl
end

#logsArray<Hash>

Returns log entries.



68
69
70
# File 'lib/oslg/oslog.rb', line 68

def logs
  @@logs
end

#mismatch(id = "", obj = nil, cl = nil, mth = "", lvl = DEBUG, res = nil, len = nil) ⇒ Object

Logs template 'instance/class mismatch' message, if provided arguments are valid. The message is not logged if the provided object to evaluate is an actual instance of the target class.

Examples:

A mismatched argument instance/class

mismatch("area", area, Float, "sum") unless area.is_a?(Numeric)


289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/oslg/oslog.rb', line 289

def mismatch(id = "", obj = nil, cl = nil, mth = "", lvl = DEBUG, res = nil, len = nil)
  return res unless id.respond_to?(:to_s)
  return res unless mth.respond_to?(:to_s)
  return res unless cl.is_a?(Class)
  return res if obj.is_a?(cl)
  return res unless lvl.respond_to?(:to_i)

  lvl = lvl.to_i
  id  = trim(id)
  mth = trim(mth)
  return res if id.empty?
  return res if mth.empty?
  return res if lvl < DEBUG
  return res if lvl > FATAL

  log(lvl, "'#{id}' #{obj.class}? expecting #{cl} (#{mth})", len)

  res
end

#msg(stat) ⇒ String

Returns preset OSlg message that matches log status.



151
152
153
154
155
156
157
158
159
# File 'lib/oslg/oslog.rb', line 151

def msg(stat)
  return "" unless stat.respond_to?(:to_i)

  stat = stat.to_i
  return "" if stat < DEBUG
  return "" if stat > FATAL

  @@msg[stat]
end

#negative(id = "", mth = "", lvl = DEBUG, res = nil, len = nil) ⇒ Object

Logs template 'negative' message, if provided arguments are valid.

Examples:

A negative variable

negative("floor area", "sum") if floor[:area] < 0


425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# File 'lib/oslg/oslog.rb', line 425

def negative(id = "", mth = "", lvl = DEBUG, res = nil, len = nil)
  return res unless id.respond_to?(:to_s)
  return res unless mth.respond_to?(:to_s)
  return res unless lvl.respond_to?(:to_i)

  lvl = lvl.to_i
  id  = trim(id)
  mth = trim(mth)
  return res if id.empty?
  return res if mth.empty?
  return res if lvl < DEBUG
  return res if lvl > FATAL

  log(lvl, "Negative '#{id}' (#{mth})", len)

  res
end

#reset(lvl = DEBUG) ⇒ DEBUG, ...

Resets level, if lvl (input) is within accepted range.



186
187
188
189
190
191
192
193
194
# File 'lib/oslg/oslog.rb', line 186

def reset(lvl = DEBUG)
  return @@level unless lvl.respond_to?(:to_i)

  lvl = lvl.to_i
  return @@level if lvl < DEBUG
  return @@level if lvl > FATAL

  @@level = lvl
end

#status0, ...

Returns current log status.



84
85
86
# File 'lib/oslg/oslog.rb', line 84

def status
  @@status
end

#tag(lvl) ⇒ String

Returns preset OSlg string that matches log level.



134
135
136
137
138
139
140
141
142
143
# File 'lib/oslg/oslog.rb', line 134

def tag(lvl)
  return "" unless lvl.respond_to?(:to_i)

  lvl = lvl.to_i
  return "" if lvl < DEBUG
  return "" if lvl > FATAL

  @@tag[lvl]

end

#trim(txt = "", len = nil) ⇒ String

Converts object to String, trims if requested.



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/oslg/oslog.rb', line 168

def trim(txt = "", len = nil)
  return "" unless txt.respond_to?(:to_s)

  txt = txt.to_s.strip

  if len.is_a?(Numeric)
    txt = txt[0...len.to_i] + " ..." if txt.length > len.to_i
  end

  txt
end

#warn?Bool

Returns whether current status is WARNING.



108
109
110
# File 'lib/oslg/oslog.rb', line 108

def warn?
  @@status == WARN
end

#zero(id = "", mth = "", lvl = DEBUG, res = nil, len = nil) ⇒ Object

Logs template 'zero' value message, if provided arguments are valid.

Examples:

A near-zero variable

zero("floor area", "sum") if floor[:area].abs < TOL


392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/oslg/oslog.rb', line 392

def zero(id = "", mth = "", lvl = DEBUG, res = nil, len = nil)
  return res unless id.respond_to?(:to_s)
  return res unless mth.respond_to?(:to_s)
  return res unless lvl.respond_to?(:to_i)

  ord = ord.to_i
  lvl = lvl.to_i
  id  = trim(id)
  mth = trim(mth)
  return res if id.empty?
  return res if mth.empty?
  return res if lvl < DEBUG
  return res if lvl > FATAL

  log(lvl, "Zero '#{id}' (#{mth})", len)

  res
end