require "kemal"
get "/" do |env|
"Hello World!"
end
Kemal.run
Using HTTP::LogHandler with Kemal
Kemal: Lightning fast, super simple web framework written in Crystal. https://kemalcr.com/
Kemal provides a basic logger with minimal details about the request and response. It will not integrate with the standard log module that Crystal provides.
HTTP module in the Crystal standard library provides a Log handler, that includes additional details like remote IP, HTTP version etc. But we can’t use HTTP::LogHandler
directly since Kemal expects the class should be derived from BaseLogHandler
.
Kemal.config.logger = HTTP::LogHandler.new
38 | Kemal.config.logger = HTTP::LogHandler.new ^-- Error: expected argument #1 to 'Kemal::Config#logger=' to be Kemal::BaseLogHandler, not HTTP::LogHandler Overloads are: - Kemal::Config#logger=(logger : Kemal::BaseLogHandler)
Kemal provides a way to create the custom handlers(Ref). Why re-implement the handler if the HTTP::LogHandler
already provides the required features. Following hack will help you to use the HTTP::LogHandler
with Kemal.
class AppLogHandler < Kemal::BaseLogHandler
def initialize
@handler = HTTP::LogHandler.new
end
def call(context : HTTP::Server::Context)
@handler.next = @next
@handler.call(context)
end
def write(message : String)
Log.info { message.strip }
end
end
Now add AppLogHandler
as below.
Kemal.config.logger = AppLogHandler.new
2023-01-30 05:07:31 UTC 200 GET /api/monitors 21.88ms
HTTP::LogHandler
2023-01-30T05:06:09.543312Z INFO - http.server: 127.0.0.1 - GET /api/monitors HTTP/1.1 - 200 (4.38ms)
Bonus: Since HTTP::LogHandler
uses the Log
module, it takes care of logging to a file if the application is configured to use the file backend. For example,
require "log"
require "kemal"
Log.setup(
level: Log::Severity::Info,
backend: Log::IOBackend.new(File.new("app.log", "a+"))
)
get "/" do |env|
"Hello World!"
end
class AppLogHandler < Kemal::BaseLogHandler
def initialize
@handler = HTTP::LogHandler.new
end
def call(context : HTTP::Server::Context)
@handler.next = @next
@handler.call(context)
end
def write(message : String)
Log.info { message.strip }
end
end
Kemal.config.logger = AppLogHandler.new
Kemal.run
About Aravinda Vishwanathapura
Co-Founder & CTO at Kadalu Technologies, Creator of Sanka, Creator of Chitra, GlusterFS core team member, Maintainer of Kadalu Storage