diff --git a/src/invidious.cr b/src/invidious.cr index 4bde39ef9..7c98735fb 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -16,6 +16,7 @@ require "detect_language" require "digest/md5" +require "file_utils" require "kemal" require "openssl/hmac" require "option_parser" @@ -35,6 +36,8 @@ channel_threads = CONFIG.channel_threads feed_threads = CONFIG.feed_threads video_threads = CONFIG.video_threads +logger = Invidious::LogHandler.new + Kemal.config.extra_options do |parser| parser.banner = "Usage: invidious [arguments]" parser.on("-t THREADS", "--crawl-threads=THREADS", "Number of threads for crawling YouTube (default: #{crawl_threads})") do |number| @@ -69,6 +72,10 @@ Kemal.config.extra_options do |parser| exit end end + parser.on("-o OUTPUT", "--output=OUTPUT", "Redirect output (default: STDOUT)") do |output| + FileUtils.mkdir_p(File.dirname(output)) + logger = Invidious::LogHandler.new(File.open(output, mode: "a")) + end end Kemal::CLI.new @@ -295,7 +302,7 @@ get "/watch" do |env| next env.redirect "/watch?v=#{ex.message}" rescue ex error_message = ex.message - STDOUT << id << " : " << ex.message << "\n" + logger.write("#{id} : #{ex.message}\n") next templated "error" end @@ -3849,4 +3856,5 @@ add_handler FilteredCompressHandler.new add_handler DenyFrame.new add_context_storage_type(User) +Kemal.config.logger = logger Kemal.run diff --git a/src/invidious/helpers/logger.cr b/src/invidious/helpers/logger.cr new file mode 100644 index 000000000..5bb1eb408 --- /dev/null +++ b/src/invidious/helpers/logger.cr @@ -0,0 +1,35 @@ +require "logger" + +class Invidious::LogHandler < Kemal::BaseLogHandler + def initialize(@io : IO = STDOUT) + end + + def call(context : HTTP::Server::Context) + time = Time.now + call_next(context) + elapsed_text = elapsed_text(Time.now - time) + + @io << time << ' ' << context.response.status_code << ' ' << context.request.method << ' ' << context.request.resource << ' ' << elapsed_text << '\n' + + if @io.is_a? File + @io.flush + end + + context + end + + def write(message : String) + @io << message + + if @io.is_a? File + @io.flush + end + end + + private def elapsed_text(elapsed) + millis = elapsed.total_milliseconds + return "#{millis.round(2)}ms" if millis >= 1 + + "#{(millis * 1000).round(2)}µs" + end +end