[squeak-dev] Villainous superpowers (Re: How to do logging)

Keith Hodges keith_hodges at yahoo.co.uk
Fri Nov 28 00:27:28 UTC 2008


 
>>
>> In terms of code smells, this is chemical warfare!! :-D.
I must admit I am having second thoughts!
> No doubt about this. Kids, don't try this at home.
>
> It still tremendous fun that you can do it. Keith, I have no idea what
> you need this for but I think the following is pretty complete - it
> skips until the next pop bytecode which marks the end of the current
> statement. It should get confused only if there was a block in that
> line that had a pop in itself:
>
> send
>     Transcript show: 'send '.
>     self returnToPop.
>     self neverReached
>
> returnToPop
>     | ctxt |
>     ctxt := thisContext sender sender.
>     [ctxt nextByte = 135]
>         whileFalse: [ctxt jump: 1].
>     ctxt resume
>
> Try filing in attachment and eval "Evil new test"
>
> - Bert -
Thats really cool, thanks! It gives me a warm fuzzy feeling just to know
we can do it.

In the Logging framework, the message eating Null WAS used to disable
logging features.

so for example the call...

self log info mysql dumper: theDataReturned asSuitableFormat.

A) to disable the #info level log messages -> MyLogRouterPolicy-#info ^null
B) to disable the #mysql category log messages ->
MyLogRouterPolicy-#mysql ^null
C) to disable all Logging, and even remove the Logging framework
completely. Object-#log ^null

Realizing that some user code may take a lot of time, #asSuitableFormat
in this example, I began looking for alternative solutions. (hence the
question)

Instead of using null as a hammer, I implemented an explicit #isIgnore
flag which covers most use cases. (It still cannot cover the case where
no Logging framework is loaded at all)

My solution is as follows:

self log info mysql use: [

    self log dumper: theDataReturned asSuitableFormat

].

I have a personal convention #use: is my version of #in: which is a bit
more flexible, I use it like this e.g.

To ensure streams close:

 FileStream-#use: ^ [ aBlock value: self ] ensure: [ self close ].

To provide psuedo null behaviour (equivalent of ifNotNilDo:)

UndefinedObject-#use: aBlock ^ self

So...

LogRouter-#use: aBlock

isIgnore ifFalse: [ aBlock value ]

This allows a user to disable mysql Logging by implementing

MyLogRouterPolicy-#mysql ^ self ignore

With this solution I am almost happy. It is cleaner, and allows whole
chunks of logging code to be skipped if the user simply sets part of
their LoggingPolicy to self ignore.

So, we can now spit chunks of verbose logging code without being afraid
of slowing things down for someone else, since we know that any user is
in complete control via their chosen LogRouterPolicy

However, after this I dont think I can resist releasing "SuperNull"
sometime soon.

thanks for an interesting insight,

Keith










More information about the Squeak-dev mailing list