Created
April 16, 2018 17:36
-
-
Save bcardiff/ea21543eff6437c508abb48c060116ef to your computer and use it in GitHub Desktop.
Logger POC with lazy init
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A Logger allow sending logging information to a stream. | |
# Each logger instance is built and binded to a specific | |
# context that is sent on each entry. | |
# | |
# When requesting a logger via `Logger#get` a context needs to be | |
# specified. Context are meant to be dot seperated path as: | |
# `"http.client"`. Class names and modules are translated into that format. | |
# | |
# ``` | |
# class HTTP::Client | |
# @@logger = Logger.get self # Same as Logger.get "http.client" | |
# # ... | |
# end | |
# ``` | |
struct Logger2 | |
enum Severity | |
DEBUG | |
INFO | |
end | |
# Handlers are responsible of sending the log entry to the | |
# actual stream | |
abstract class Handler | |
abstract def log(severity : Severity, message, context : String) | |
end | |
@handler : Handler? | |
private def initialize(@context : String) | |
end | |
def log(severity, message) | |
handler = @handler ||= @@handler_factory.call(@context) | |
handler.log(severity, message, @context) | |
end | |
{% for name in Logger2::Severity.constants %} | |
def {{name.id.downcase}}(message) | |
log(Logger2::Severity::{{name.id}}, message) | |
end | |
{% end %} | |
def self.get(context : Class) : Logger2 | |
get(context.name.gsub(/::/, ".").downcase) | |
end | |
def self.get(context : String) : Logger2 | |
new(context) | |
end | |
@@handler_factory : String -> Handler = ->(context : String) { NullLoggerHandler.new.as(Handler) } | |
# Set handler factory to be used in `Logger.get` | |
def self.set_handler_factory(&block : String -> Handler) | |
@@handler_factory = block | |
end | |
end | |
class NullLoggerHandler < Logger2::Handler | |
def log(severity, message, context) | |
end | |
end | |
# A IO logger with severity level filtering | |
class BasicLoggerHandler < Logger2::Handler | |
property level = Logger2::Severity::INFO | |
def initialize(@io : IO = STDOUT) | |
end | |
def log(severity, message, context) | |
return if severity < level | |
label = severity.to_s | |
@io << label[0] << ", [" << Time.now << " #" << Process.pid << "] " | |
@io << label.rjust(5) << " -- " << context << ": " << message.to_s | |
@io.puts | |
@io.flush | |
end | |
end | |
# Out of stdlib | |
# App code | |
class Foo | |
@@logger = Logger2.get "app.foo" | |
@bar = App::Bar.new | |
def do | |
@@logger.info "doing do" | |
@bar.do_to | |
end | |
end | |
module App | |
class Bar | |
@@logger = Logger2.get self | |
def do_to | |
@@logger.debug "doing do to" | |
end | |
end | |
end | |
# Allow apps to define logger handler based on context | |
# Apps / frameworks are resposible of initializing | |
# configurations | |
Logger2.set_handler_factory do |context| | |
BasicLoggerHandler.new.tap do |handler| | |
handler.level = Logger2::Severity::DEBUG if context =~ /^app\./ | |
end | |
end | |
foo = Foo.new | |
foo.do |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment