<div dir="ltr">Thanks. I understood that Racket starts default receivers, but I didn't understand that when you create a new logger with `define-logger` that it also passes messages to those receivers. But I now see that's the significance of  `define-logger` creating a logger that's a "child of (current-logger)".</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 12, 2014 at 3:27 PM, Matthew Flatt <span dir="ltr"><<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">By default, Racket starts receivers at 'error to direct logged errors<br>
to stderr and syslog. Running your program with<br>
<br>
  racket -W none -L none ....<br>
<br>
avoids the call to `expensive`.<br>
<div class="HOEnZb"><div class="h5"><br>
At Fri, 12 Dec 2014 14:27:24 -0800, Matthew Butterick wrote:<br>
> I see that you're right about `log-debug`, but here's the example that led<br>
> me to make an incorrect generalization. It seems that the (expensive)<br>
> function in `log-test-error` always runs, even if the level is 'none or<br>
> 'fatal. I don't understand why.<br>
><br>
> #lang racket<br>
><br>
> (define-logger test)<br>
><br>
> (define current-level (make-parameter #f))<br>
><br>
> (define (activate-test-logger)<br>
>   (define receiver (make-log-receiver test-logger (current-level)))<br>
>   (void (thread<br>
>          (λ ()<br>
>            (let loop ()<br>
>              (match (sync receiver)<br>
>                [(vector event-level event-message event-value name)<br>
>                 (eprintf (format "[~a] ~a\n" event-level event-message))<br>
>                 (loop)]))))))<br>
><br>
> (define (expensive from)<br>
>   (displayln (format "expensive op requested from log-test-~a at level ~v"<br>
> from (current-level)))<br>
>   (apply + (range 5000000)))<br>
><br>
> (parameterize ([current-level 'none])<br>
>   (activate-test-logger)<br>
>   (log-test-fatal (format "fatal at level ~v" (current-level)))<br>
>   (log-test-error "error at level ~v = ~a" (current-level) (expensive<br>
> "error"))<br>
>   (log-test-debug "debug at level ~v = ~a" (current-level) (expensive<br>
> "debug")))<br>
><br>
> On Fri, Dec 12, 2014 at 1:49 PM, Vincent St-Amour <<a href="mailto:stamourv@ccs.neu.edu">stamourv@ccs.neu.edu</a>><br>
> wrote:<br>
> ><br>
> > I may be missing something, but `log-debug` and friends already do that.<br>
> ><br>
> >     stamourv@westmount:2014-12-12 16:45:plt$ racket<br>
> >     Welcome to Racket v6.1.1.6.<br>
> >     -> (log-debug (begin (displayln "hello!") "log"))<br>
> >     -><br>
> >     stamourv@westmount:2014-12-12 16:45:plt$ racket -W debug<br>
> >     Welcome to Racket v6.1.1.6.<br>
> >     GC: 0:min @ 1,356K(+307K)[+160K]; free 932K(-5,028K) 4ms @ 12<br>
> >     GC: 0:min @ 1,813K(+3,946K)[+232K]; free 755K(-2,051K) 4ms @ 20<br>
> >     GC: 0:min @ 4,040K(+4,087K)[+232K]; free 1,448K(-1,448K) 4ms @ 28<br>
> >     GC: 0:min @ 5,015K(+3,112K)[+240K]; free 1,425K(-6,817K) 4ms @ 40<br>
> >     GC: 0:min @ 7,459K(+6,060K)[+272K]; free 2,162K(-3,458K) 0ms @ 56<br>
> >     GC: 0:min @ 9,356K(+6,211K)[+280K]; free 1,628K(-2,924K) 4ms @ 72<br>
> >     GC: 0:min @ 13,230K(+4,353K)[+296K]; free 2,558K(-16,142K) 12ms @ 96<br>
> >     GC: 0:min @ 17,224K(+13,943K)[+392K]; free 3,900K(-6,492K) 12ms @ 136<br>
> >     GC: 0:min @ 21,878K(+12,457K)[+400K]; free 4,741K(-6,037K) 12ms @ 172<br>
> >     GC: 0:min @ 27,016K(+9,255K)[+988K]; free 6,168K(-8,760K) 16ms @ 232<br>
> >     GC: 0:min @ 32,548K(+6,315K)[+1,276K]; free 7,665K(-26,641K) 36ms @ 312<br>
> >     -> (log-debug (begin (displayln "hello!") "log"))<br>
> >     hello!<br>
> >     log<br>
> >     -><br>
> ><br>
> > `log-message`, however, does not.<br>
> ><br>
> > The problem may be that, when you switch to the lower logging level,<br>
> > your old listener for the higher level is still around to receive the<br>
> > messages.<br>
> ><br>
> > Vincent<br>
> ><br>
> ><br>
> ><br>
> > At Fri, 12 Dec 2014 13:32:41 -0800,<br>
> > Matthew Butterick wrote:<br>
> > ><br>
> > > Is there a reason not to redefine `log-debug` et al as macros that<br>
> > evaluate their arguments lazily?<br>
> > ><br>
> > > Sort of like this;<br>
> > ><br>
> > > (if ((current-logging-level) . is-equal-or-above? . 'debug)<br>
> > >   (log-debug arg ...)<br>
> > >   (void))<br>
> > ><br>
> > > Because I find that my use of these functions often looks like this:<br>
> > ><br>
> > > (log-debug "Value = ~a" (expensive-operation-for-logging-purposes))<br>
> > ><br>
> > > The problem is that when I change to a lower logging level, the<br>
> > (expensive-operation) is still evaluated.<br>
> > ><br>
> > > I asked a similar question about hash-ref! not long ago. The answer was<br>
> > that you can get lazy evaluation by wrapping the default argument in a<br>
> > lambda, like so:<br>
> > ><br>
> > > (hash-ref! hashtable key (λ () (expression-that-produces-value)))<br>
> > ><br>
> > > But it seems there's no equivalent idiom for `log-debug` et al.<br>
> > > ____________________<br>
> > >   Racket Users list:<br>
> > >   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
> ><br>
> ____________________<br>
>   Racket Users list:<br>
>   <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
</div></div></blockquote></div></div>