1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Juliaでログをxtermに出す

Posted at

目的

マルチプロセスのコードをデバッグするためには、ログをそれぞれ別の場所に出すようにしないと大変。個別のファイルに書くようにして、別の窓でtail -fとかすればいいわけなのだけど、毎回やるのはかなり煩雑。なので自動的にウィンドウをオープンしてその中にログを書くようにしたい。

方法

やることは非常に単純で、ログをテンポラリファイルに書き出すようにしておいて、xtermの中でそのファイルにtail -fをすればいい。MacユーザなのでTerminalを使えればもっと良かったのだけど、制御する方法がわからなかったので、xtermを使う。macでxtermを使うにはXquatzが必要だが、brewで簡単に入る。

実装

AbstractLoggerのサブタイプを作る。この際にConsoleLoggerを継承する。継承にはこの記事に書いたようにMacroTools@forwardを用いた。

ここで一つ問題が。ConsoleLoggerは書き出したあとにstreamをフラッシュしない。通常はstderrに書き出していて、stderrが自動的にフラッシュするので問題ないようなのだが、自動フラッシュになっていないストリームだと、リアルタイムに書き出されないので困る。ということでhandle_messageメソッドだけはオーバライドしている。と言っても、ConsoleLoggerhandle_messageを呼出したあとで、streamを不ファッシュしているだけ。

module XtermLogging
export XtermLogger

import MacroTools
import Logging
import Dates

function timed_metafmt(level, _module, group, id, file, line)
    color, prefix, suffix = 
      Logging.default_metafmt(level, _module, group, id, file, line)
    timestamp = Dates.now()
    prefix2 = "$timestamp : $prefix"
    return color, prefix2, suffix
end

struct XtermLogger <: Base.CoreLogging.AbstractLogger
    sl::Logging.ConsoleLogger
    filename
    proc::Base.Process
end

function XtermLogger(title, level=Logging.Info;
                    display=":0",
                    meta_formatter=timed_metafmt, show_limited=true,
                    right_justify=0)
    tmpfile, stream = Base.Filesystem.mktemp()
    xterm = "/usr/local/bin/xterm"
    proc = open(`$xterm -display $display -title $title -e tail -f $tmpfile`)
    XtermLogger(Logging.ConsoleLogger(stream, level;
                    meta_formatter=meta_formatter, 
                    show_limited=show_limited,
                    right_justify=right_justify),
                tmpfile, proc)
end

@MacroTools.forward XtermLogger.sl Base.CoreLogging.shouldlog, 
                                Base.CoreLogging.min_enabled_level, 
                                Base.CoreLogging.catch_exceptions

function Base.CoreLogging.handle_message(logger::XtermLogger, level, message, _module, group, id,
    filepath, line; maxlog=nothing, kwargs...)
    Base.CoreLogging.handle_message(logger.sl, level, message, _module, group, id, filepath, line; maxlog, kwargs...)
    flush(logger.sl.stream)
end

end

デフォルトで時刻を表示するtimed_metafmtを用いるようにしている。このあたりの詳細はこの記事に書いてある。

使い方

XtermLoggingLoggingusingでインポートする。

push!(LOAD_PATH, pwd())
using XtermLogging
using Logging

XtermLoggerを作る。引数はウィンドウのタイトル。

xlogger = XtermLogger("test0")

つくったLoggerは普通のLoggerとして使える。

with_logger(xlogger) do 
    @error("test $i")    
end

image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?