109 lines
2.6 KiB
Crystal
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
|