Hierarchical logs

44 views
Skip to first unread message

jweiss

unread,
Feb 11, 2012, 11:39:50 PM2/11/12
to Clojure
I've been working on a tracing library, that works much like
clojure.contrib.trace (based on it, actually). One sticky problem
I've found is, hierarchical logs are really crappy to try to stream to
a file. You can't just keep writing to the end of the file - new data
needs to be inserted before existing end-tags. So what I'm doing is
storing the data as a list, until I know the data is complete, and
then i turn it back into a tree to write the file.

However I can't think of a simple way to do it, even though it seems
like a simple operation.

I want to turn this list of pairs (first item is the fn call or return
value, the second is a truthy value marking whether it's a call or
return)

'[[(+ 1 (- 5 2) nil]
[(- 5 2) nil]
[3 true]
[4 true]]

I want to turn that into
[(+ 1 (- 5 2))
[(- 5 2)
3]
4]

Is there a simple way to do this?

Alan Malloy

unread,
Feb 12, 2012, 3:42:19 AM2/12/12
to Clojure
I toyed with some simple ways of doing this, but I don't think any of
them will actually work out. I think the advice you got in #clojure to
use zippers is probably correct. Here's a sketch I bashed out that
seems to do roughly what you want: https://gist.github.com/1807340 (I
took the liberty of wrapping the whole thing in another [] under the
assumption you'd want to record multiple top-level calls; if not you
can just call first on the result).

Jon Seltzer

unread,
Feb 12, 2012, 2:09:55 AM2/12/12
to Clojure
I'm not sure I'm getting your data example (seems like there are some
characters missing or out of place) but this might be what you're
looking for:

user=> (def stuff
[['(+ 1 (- 5 2)) nil]
['(- 5 2) nil]
[3 true]
[4 true]])
#'user/stuff
user=> (vec (for [m stuff] (vec (butlast m))))
[[(+ 1 (- 5 2))] [(- 5 2)] [3] [4]]

On Feb 11, 8:39 pm, jweiss <jeffrey.m.we...@gmail.com> wrote:

jweiss

unread,
Feb 14, 2012, 10:14:39 AM2/14/12
to Clojure
Thanks, Alan,

The solution I used looks exactly like yours:

(defn mktree [vz [i out?]]
  (if out?
    (-> vz (zip/append-child i) zip/up )
    (-> vz (zip/append-child [i]) zip/down zip/rightmost)))

(defn as-tree [tracelist]
  (zip/root (reduce mktree (zip/vector-zip []) tracelist)))

Thinking about it some more, I don't think I'm going to come up with a
solution that's any more efficient or easy to code as this one.  The
real "work" is figuring out where the next element needs to be
inserted.  Zipper keeps that information as part of the data structure
so it doesn't have to be re-calculated every iteration.  My previous
solution using loop had kept an accumulator (a list of indices to pass
to assoc-in).

-jeff

jweiss

unread,
Feb 14, 2012, 9:33:04 PM2/14/12
to Clojure
It occurred to me that ultimately what I want is just a pretty-printed
output that I can put on a webpage and apply syntaxhighlighter to.

I should be able to use a custom pprint dispatch to take this
[[(+ 5 (- 4 2 (* 9 3)) (* 5 (+ 6 3))) nil]
[(- 4 2 (* 9 3)) nil]
[(* 9 3) nil]
[27 true]
[-25 true]
[(* 5 (+ 6 3)) nil]
[(+ 6 3) nil]
[9 true]
[45 true]
[25 true]]

and print something like this:

(+ 5 (- 4 2 (* 9 3)) (* 5 (+ 6 3)))
(- 4 2 (* 9 3))
(* 9 3)
27
-25
(* 5 (+ 6 3))
(+ 6 3)
9
45
25

Without even converting it into a tree. But I am having a hard time
finding an example of custom dispatch, or docs on how to write one. I
really just want things printed the same as pprint currently does, but
being able to specify extra indent for the whole block. I had
originally planned to output html where each item was properly nested
as html divs, but I think that is getting overly complex.

-jeff

Kevin Downey

unread,
Feb 15, 2012, 3:02:30 AM2/15/12
to clo...@googlegroups.com
https://gist.github.com/1314616 is a small example of a custom
dispatch, doesn't do custom indenting though

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

jweiss

unread,
Feb 15, 2012, 2:17:20 PM2/15/12
to Clojure
Unfortunately it doesn't call the functions/macros that the pprint
code says are meant for custom dispatch:

pprint-logical-block
pprint-newline
pprint-indent
etc

Wish I could find an example of those being used in a custom dispatch,
I made a lame attempt and for some reason my custom dispatch printed
nothing at all :) I can dig in and figure it out, but it would be
quicker if someone has already been there. Surely someone has done
this :)

-jeff

On Feb 15, 3:02 am, Kevin Downey <redc...@gmail.com> wrote:
> https://gist.github.com/1314616is a small example of a custom
Reply all
Reply to author
Forward
0 new messages