Created
April 16, 2018 17:05
-
-
Save bcardiff/55ebbf2e20b1670681e9352fbaa51be0 to your computer and use it in GitHub Desktop.
Logger POC
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 | |
private def initialize(@handler : Handler?, @context : String) | |
end | |
def log(severity, message) | |
@handler.try &.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(@@handler_factory.call(context), context) | |
end | |
@@handler_factory : String -> Handler? = ->(context : String) { nil.as(Handler?) } | |
# Set handler factory to be used in `Logger.get` | |
def self.set_handler_factory(&block : String -> Handler?) | |
@@handler_factory = block | |
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 | |
# 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 | |
# 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 | |
foo = Foo.new | |
foo.do |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment