# Logger local variable context

**URL:** https://discourse.julialang.org/t/logger-local-variable-context/87828
**Category:** Tooling
**Tags:** logging
**Created:** [September 26, 2022, 5:34pm UTC](https://discourse.julialang.org/t/logger-local-variable-context/87828 "2022-09-26T17:34:49Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![efficiencynuts](https://avatars.discourse-cdn.com/v4/letter/e/278dde/32.png) [@efficiencynuts](https://discourse.julialang.org/u/efficiencynuts)
#### Post date: [September 26, 2022, 5:34pm UTC](https://discourse.julialang.org/t/logger-local-variable-context/87828/1 "2022-09-26T17:34:49Z")

</div>

I want to have a custom logger that will log certain local variables if available. I can’t seem to make the logger see the local variables.  
Normally I could do:

```julia
@info gs_tester

```

to get an output like

```julia
Info: gs_tester="MYGSTESTERvalue"

```

I however, want to just log like this:

```julia
function some_worker(gs_tester)
   @info "blahblah"
end
with_logger(logger_that_logs_gs_tester) do
    some_worker(my_gs_tester)
end

```

And I would expect the logging output to be:

```julia
Info: [MYGSTESTERvalue] blahblah

```

Or, if gs\_tester is undeclared:

```julia
Info: [?] blahblah

```

To this end I have written a logger:

```julia
logger_that_logs_gs_tester(logger) = TransformerLogger(logger) do log
  try  
      merge(log, (; message = "[$gs_tester] $(log.message)"))
  catch e
      merge(log, (; message = "[?] $(log.message)"))
  end
end

```

However, the gs\_tester local variable context is not available. I only get gs\_tester if I declare it before the “with\_logger” statement which makes this a lot less useful.

How could I go about having a custom logger that will automatically prefix my log message with elements of context if available?

I am making extensive use of LoggingExtras.jl but I’ll settle for a working example in any manner.

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [October 28, 2022, 5:56pm UTC](https://discourse.julialang.org/t/logger-local-variable-context/87828/2 "2022-10-28T17:56:23Z")

</div>

I don’t think this is possible at all in Julia.  
Like you can use `@locals` to get local variables.  
But I don’t think you can get the local variables of any other scope.  
And the dictionary you get from using `@locals` is not updated when new ones are defined.

This is kinda by design.  
It is one of the things that makes julia faster than python.

You could define your own logging macro which does this though.

Something like (untested)

```julia
macro smart_info(outer_msg)
    quote
        msg = $(esc(outer_msg))
        if isdefined(gs_tester)
            @info "[gs_tester=$gs_tester] $msg"
        else
            @info "$msg"
        end
    end
end

```

Which you would use as

```julia
@smart_info "hi"

```

---

<div class="post-metadata">

### Author: ![efficiencynuts](https://avatars.discourse-cdn.com/v4/letter/e/278dde/32.png) [@efficiencynuts](https://discourse.julialang.org/u/efficiencynuts)
#### Post date: [October 28, 2022, 6:25pm UTC](https://discourse.julialang.org/t/logger-local-variable-context/87828/3 "2022-10-28T18:25:19Z")

</div>

Seems like the gs\_tester var is still not available using smart\_info macro. Am I missing something obvious? I simplified the example and ran it:

```julia
julia> macro smart_info(outer_msg)
           quote
               @info "$gs_tester"
           end
       end
@smart_info (macro with 1 method)

julia> function testsmartinfo()
          gs_tester=1
          @smart_info "did this work?"
       end
testsmartinfo (generic function with 1 method)

julia> testsmartinfo()
┌ Error: Exception while generating log record in module Main at REPL[22]:3
│ exception =
│ UndefVarError: gs_tester not defined
│ Stacktrace:
│ [1] macro expansion
│ @ ./logging.jl:340 [inlined]
│ [2] macro expansion
│ @ ./REPL[22]:3 [inlined]
│ [3] testsmartinfo()
│ @ Main ./REPL[23]:3
│ [4] top-level scope
│ @ REPL[24]:1
│ [5] eval
│ @ ./boot.jl:360 [inlined]
│ [6] eval_user_input(ast::Any, backend::REPL.REPLBackend)
│ @ REPL /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:139
│ [7] repl_backend_loop(backend::REPL.REPLBackend)
│ @ REPL /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:200
│ [8] start_repl_backend(backend::REPL.REPLBackend, consumer::Any)
│ @ REPL /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:185
│ [9] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool)
│ @ REPL /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:317
│ [10] run_repl(repl::REPL.AbstractREPL, consumer::Any)
│ @ REPL /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:305
│ [11] (::Base.var"#874#876"{Bool, Bool, Bool})(REPL::Module)
│ @ Base ./client.jl:387
│ [12] #invokelatest#2
│ @ ./essentials.jl:708 [inlined]
│ [13] invokelatest
│ @ ./essentials.jl:706 [inlined]
│ [14] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
│ @ Base ./client.jl:372
│ [15] exec_options(opts::Base.JLOptions)
│ @ Base ./client.jl:302
│ [16] _start()
│ @ Base ./client.jl:485
└ @ Main REPL[22]:3

```

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [October 28, 2022, 7:27pm UTC](https://discourse.julialang.org/t/logger-local-variable-context/87828/4 "2022-10-28T19:27:18Z")

</div>

Got it to work, but unfortunately I cannot really explain why it works …

```julia
julia> macro smart_info(outer_msg)
           quote
               @info "$($(esc(:gs_tester)))"
           end
       end
@smart_info (macro with 1 method)

julia> function testsmartinfo()
           gs_tester=1
           @smart_info "did this work?"
       end
testsmartinfo (generic function with 1 method)

julia> testsmartinfo()
[ Info: 1

```

In any case, the `esc(:gs_tester)` is needed to paste the symbol `gs_tester` into the code without the usual hygiene rules. What I don’t quite follow yet is the interaction with the interpolation in the call of the `@info` macro, i.e., simply printing the variable within a function is easier and would work like:

```julia
macro smart_print(outer_msg)
    quote
        print($(esc(:gs_tester))
    end
end

```

Hope you can make some sense out of this …

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [October 30, 2022, 5:40pm UTC](https://discourse.julialang.org/t/logger-local-variable-context/87828/5 "2022-10-30T17:40:12Z")

</div>

Ah yes, it needs to be interpolated twice.  
Once into the quote, and once into the string.  
I always find that fiddly
