[Julia, Logging] Logging

Julia에서 log를 기록하기 위해 Memento package를 설치하고 사용하는 것이 편리하고 좋다

Memento가 지원하는 log level 및 format은 여기를 참조 하세요

Memento를 사용한 간단한 SimpleLogging package를 만듦

SimpleLogging package download

SimpleLogging을 사용한 log 처리 예는 아래를 참고.

원하는 로깅 포맷은 아래 그림과 같이 시간,로그레벨,로그발생파일 및 라인, 로그메시지

로그처리 모듈 예) logging.jl

moudle SimpleLogging

import Memento
import Dates

# init_logger를 호출히지 않는 경우 기본 logger
_logger = Memento.getlogger("my_logger")

"""
  init_logger(;logger::String="",
                      level="debug",
                      filename::String="log.log",
                      filename_prefix::String="",
                      fmt::String="")

로그를 남기기 전에 초기화 function

Usage)
init_logger()
@log_debug("debug~~~~")

[output]
[2021-09-29 02:18:38|debug	]:(log_test.jl,  45) debug~~~~


# Arguments
- `logger::String`: logger명칭, 없으면 default로 설정
- `level::String`: logging레벨 
   (ie: `info`, `warn`, `debug`, `trace`, `notice`, `error`, `critical`, `alert`, `emergency`)
- `filename::String`: log를 저장할 파일명
- `filename_prefix::String`: filename앞에 붙는 predfx, {filename_prefix}_{filename}
   빈값인 경우 yyyymmdd형식의 오늘일자 스트링이 생성되어 파일명에 붙는다
   (ie: 20210928_log.log)
- `fmt::String`: log 출력 형식, 아래 URL 참조
   https://github.com/invenia/Memento.jl/blob/master/docs/src/man/intro.md

"""
function init_logger(;logger::String="",
                    level::String="debug",
                    filename::String="log.log",
                    filename_prefix::String="",
                    fmt::String="")
    
    global _logger    
    
    fmt_elms = ["{date}","{level}\t"]    
    if logger != ""
      push!(fmt_elms,"{name}")
    end
    if fmt == ""
      fmt =  string("[",join(fmt_elms,"|"),"]:{msg}")
    end 
    # log lebvel이 주어진 level에 없는 경우 debug로 설정
    if !(level in ("info", "warn", "debug", "trace", "notice", "error", "critical", "alert", "emergency"))
      level = "debug"
    end
    # 기존에 설정된 logger 초기화
    Memento.reset!()
    if logger == ""
        _logger  = Memento.config!(level;fmt=fmt)
    else
        _logger  = Memento.config!("my_logger",level;fmt=fmt)
    end
    # log file이 지정된 경우 파일에 log를 기록 할 수 있도록 성정
    if length(filename) != ""
      if filename_prefix == ""
        filename_prefix = Dates.format(Dates.now(),"yyyymmdd")
        filename = joinpath(dirname(filename),string(filename_prefix ,"_",basename(filename)))
      end        
      handler = Memento.DefaultHandler(
          filename,
          Memento.DefaultFormatter(fmt) )
      push!(_logger, handler)
    end
    nothing
end

function set_level(level::String)
  Memento.setlevel!(_logger,level)
  nothing
end

"로그 발생 소스 파일과 라인번호를 남기 위해 아래와 같이 처리"
function _log(_file,_line,msg,f::Function)
    s = string("(",basename(_file),",",lpad(_line,4," "),") ",msg)
    f(_logger,s)
end

"info log"
macro log_info(msg)  
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.info)
  end 
end

"warning log"
macro log_warn(msg)  
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.warn)
  end
end

"debug log"
macro log_debug(msg)
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.debug)
  end  
end

"tracer log"
macro log_trace(msg)  
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.trace)
  end 
end

"notice log"
macro log_notice(msg)  
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.notice)
  end 
end

"error log를 출력하고 exception 발생, try-catch로 처리 하지 않는 경우 프로그램 종료"
macro log_error(msg)
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.error)
  end 
end

"error log, try-catch로 처리 하지 않는 경우 프로그램 종료"
macro log_critical(msg)  
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.critical)
  end
end

"전체 어플리케이션이 심각한 에러로 복구할 수 없는 경우로 시스템관리자를 불러야 하는 경우, try-catch 필요"
macro log_alert(msg)
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.alert)
  end 
end

"시스템을 사용할 수 없는 경우,try-catch 필요"
macro log_emergency(msg)
  quote
    _log($(string(__source__.file)),$(string(__source__.line)),$(esc(msg)),Memento.emergency)
  end
end

end

로그처리 모듈 사용
예) log_test.jl

# "MyLogging" module이 있는 path를 LOAD_PATH 환경변수에 추가
my_module_path = "/dev/logging"
if  !(my_module_path ∈ LOAD_PATH)
  push!(LOAD_PATH, my_module_path)
end

using SimpleLogging

init_logger()

println("========debug mode=========")
@log_info("info~~~~")
@log_warn("warn~~~~")
@log_debug("debug~~~~")
@log_trace("trace~~~~")
@log_notice("notice~~~~")

println("========info mode=========")
set_level("info")
@log_info("info~~~~")
@log_warn("warn~~~~")
@log_debug("debug~~~~")
@log_trace("trace~~~~")
@log_notice("notice~~~~")

println("========warn mode=========")
set_level("warn")
@log_info("info~~~~")
@log_warn("warn~~~~")
@log_debug("debug~~~~")
@log_trace("trace~~~~")
@log_notice("notice~~~~")

println("========notice mode=========")
set_level("notice")
@log_info("info~~~~")
@log_warn("warn~~~~")
@log_debug("debug~~~~")
@log_trace("trace~~~~")
@log_notice("notice~~~~")

println("========trace mode=========")
set_level("trace")
@log_info("info~~~~")
@log_warn("warn~~~~")
@log_debug("debug~~~~")
@log_trace("trace~~~~")
@log_notice("notice~~~~")
# try 없이는 실행 후 종료
# @log_emergency("emergency~~~~")
# @log_alert("alert~~~~")
println("========error mode=========")
try
  @log_error("error~~~~")
catch e
  @log_warn(string(e))
end

println("========critical mode=========")
try
  @log_critical("critical~~~~")
catch e
  @log_warn(string(e))
end

println("========alert mode=========")
try
  @log_alert("alert~~~~")
catch e
  @log_warn(string(e))
end

println("========emergency mode=========")
try
  @log_emergency("emergency~~~~")
catch e
  @log_warn(string(e))
end

 
println("========END!=========")

출력

========debug mode=========
[2021-09-29 13:14:05|info	]:(log_test.jl,  11) info~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  12) warn~~~~
[2021-09-29 13:14:06|debug	]:(log_test.jl,  13) debug~~~~
[2021-09-29 13:14:06|notice	]:(log_test.jl,  15) notice~~~~
========info mode=========
[2021-09-29 13:14:06|info	]:(log_test.jl,  19) info~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  20) warn~~~~
[2021-09-29 13:14:06|notice	]:(log_test.jl,  23) notice~~~~
========warn mode=========
[2021-09-29 13:14:06|warn	]:(log_test.jl,  28) warn~~~~
========notice mode=========
[2021-09-29 13:14:06|warn	]:(log_test.jl,  36) warn~~~~
[2021-09-29 13:14:06|notice	]:(log_test.jl,  39) notice~~~~
========trace mode=========
[2021-09-29 13:14:06|info	]:(log_test.jl,  43) info~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  44) warn~~~~
[2021-09-29 13:14:06|debug	]:(log_test.jl,  45) debug~~~~
[2021-09-29 13:14:06|trace	]:(log_test.jl,  46) trace~~~~
[2021-09-29 13:14:06|notice	]:(log_test.jl,  47) notice~~~~
========error mode=========
[2021-09-29 13:14:06|error	]:(log_test.jl,  53) error~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  55) ErrorException("(log_test.jl,  53) error~~~~")
========critical mode=========
[2021-09-29 13:14:06|critical	]:(log_test.jl,  60) critical~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  62) ErrorException("(log_test.jl,  60) critical~~~~")
========alert mode=========
[2021-09-29 13:14:06|alert	]:(log_test.jl,  67) alert~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  69) ErrorException("(log_test.jl,  67) alert~~~~")
========emergency mode=========
[2021-09-29 13:14:06|emergency	]:(log_test.jl,  74) emergency~~~~
[2021-09-29 13:14:06|warn	]:(log_test.jl,  76) ErrorException("(log_test.jl,  74) emergency~~~~")
========END!=========

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다