Files
logger/src/logger.cr
Tristan Ancelet 172e7e7521 Committing changes
2026-03-31 10:25:36 -05:00

109 lines
2.6 KiB
Crystal

require "time"
require "colorize"
module Logger
annotation LoggerWatcher
end
struct LOG_LEVEL
getter value : Int32
getter color : Symbol
delegate in?, to: @value
def initialize(@value : Int32, @color : Symbol)
end
def to_s
LOG_LEVELS.keys[@value].to_s.downcase
end
{% for op, i in %w[ < > == <= >= ] %}
def {{op.id}} (other : LOG_LEVEL)
@value {{op.id}} other.value
end
{% end %}
end
LOG_LEVELS = {
"DEBUG" => LOG_LEVEL.new(value: 0, color: :green),
"INFO" => LOG_LEVEL.new(value: 1, color: :blue),
"WARN" => LOG_LEVEL.new(value: 2, color: :yellow),
"ERROR" => LOG_LEVEL.new(value: 3, color: :red),
"FATAL" => LOG_LEVEL.new(value: 4, color: :red)
}
@@min_level : LOG_LEVEL = LOG_LEVELS["INFO"]
@@max_level : LOG_LEVEL = LOG_LEVELS["FATAL"]
@@debug : Bool = false
LOG_MUTEX = ::Mutex.new
macro generate_log_line
{% verbatim do %}
{% if @type && @def %}
"{{(@type.module? ? "Module" : "Class").id}}({{@type.name.id}})" + " : " + "Method({{@def.name}})" + " : "
{% elsif @type %}
"{{(@type.module? ? "Module" : "Class").id}}({{@type.name.id}})" + " : "
{% elsif @def %}
"Method({{@def.name}})" + " : "
{% else %}
{{message}}
{% end %}
{% end %}
end
{% for level in LOG_LEVELS.keys %}
macro {{level.downcase.id}}(message)
::Logger.log {{level}}, Logger.generate_log_line + \{{message}}
end
{% end %}
protected def self.synchronize(&block : -> )
LOG_MUTEX.synchronize do
yield
end
end
def self.debug? : Bool
LOG_MUTEX.synchronize do
@@debug
end
end
{% for level in %w[ min max ] %}
def self.{{level.id}}=(selection : String) : Nil
Logger.debug "Entering with #{selection}"
raise "ERROR : {{level.id}}= : Invalid level" unless _level = LOG_LEVELS[selection.upcase]
synchronize {
@@{{level.id}}_level = _level
}
end
def self.{{level.id}} : String
@@{{level.id}}_level.to_s.downcase
end
{% end %}
def self.valid?(level : LOG_LEVEL) : Bool
level.in?(@@min_level.value..@@max_level.value)
end
def self.debug= (state : Bool) : Nil
synchronize {
@@debug = state
}
Logger.debug "Debug set to #{state}"
end
def self.log(level : String, message : String)
_level = LOG_LEVELS[level]
if valid?(_level) || debug?
synchronize {
time = Time.local
STDERR.puts [time, level.to_s.colorize(_level.color), message].join(" : ")
raise "ERROR : Fatal error detected (#{message})" if level == "FATAL"
}
end
end
end