Term.jl / logging / sending messages to multiple locations

I’d like to ask if sending logging messages both to terminal and to a file is supported by Term.jl [Logging · Term.jl]. I read in JuliaLogging documentation that Logging together with LoggingExtras is supporting such option (for more info on this topic pls see: [Send messages to multiple locations · JuliaLogging]). Edit: Pinging @FedeClaudi, should there be no info here, I will allow myself to ask at GitHub.

julia> using Term, LoggingExtras

julia> global_logger(
           TeeLogger(
               Term.TermLogger(Term.TERM_THEME[]),
               FileLogger("julia.log"),
           ),
       );

julia> @info "hello info"
@Info (Main):  hello info
  ╰────────────────────────────────────────────────
                      Thu, 28 Jul 2022 00:49:09

julia> @warn "hello warn"
@Warn (Main):  hello warn
  ╰────────────────────────────────────────────────
                      Thu, 28 Jul 2022 00:49:11

shell> cat julia.log
┌ Info: hello info
└ @ Main REPL[20]:1
┌ Warning: hello warn
└ @ Main REPL[21]:1

Edit: I submitted this patch to make it a bit easier to construct a TermLogger.

1 Like

Thanks a lot @fredrikekre. Having the opportunity, I am wondering, is there any recommended way to log the output of functions / commands that return “nothing” with the use of TeeLogger?. Two examples of such functions / commands: Pkg.status() and Base.Sys.cpu_summary(). To log output of such commands / functions I came up (based on Logging documentation) with the following idea [link], however, I am not quite sure how to implement it with TeeLogger. Is it possible at all? What I am trying to achieve is to reduce println commands in my code and exchange them with logging.

Not directly, because those functions don’t use the logging system, they simply print to stdout. You can of course create the string and log that:

julia> using Pkg

julia> str = sprint(io -> Pkg.status(; io = io));

julia> @info str
┌ Info: Status `/tmp/tmp.oJfx8Aw4So/Project.toml`
└   [7876af07] Example v0.5.3
1 Like

Thanks for the PR and for answering the question ( I didn’t know the answer as well!) @fredrikekre

I will link to this discussion in the Term docs for future reference.

1 Like

Thanks @fredrikekre for detailed info! I just came by one more case that is misterious to me: Hwloc.topology_info(). It also returns nothing, however, if trying:

str = sprint(io -> Hwloc.topology_info(; io = io));

I am receiving:

ERROR: MethodError: no method matching topology_info(; io=IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1))
Closest candidates are:
  topology_info() at ~/.julia/packages/Hwloc/HorQV/src/highlevel_api.jl:76 got unsupported keyword argument "io"

Is there any chance you may have an advice on this as well?

@FedeClaudi, great package Term.jl!

1 Like

I will try to investigate it further and when / if I come with a solution to this particular case I will post it here. Many thanks to both of you for the advice and for great packages.

You can of course only pass the IO if the method supports that.

Hwloc.topology_info() doesn’t support it, but I am sure a contribution of topology_info(io::IO=stdout) would be welcome.

1 Like

Aha! I’m relatively new to coding, I’ve written only a few hundred / thousands lines, mostly data analysis and visualizations. I’ve been using modules, structs, functions rather in their basic forms. I’ll read more on the topic of methods and I’ll try to implement your advice in the near future. Thanks again.