Permalink
Browse files

Fix comments to be clojure type

  • Loading branch information...
2 parents 5e75ccc + 7a9e0e0 commit d60d4373adc9a1e6d77afacb4c8c9d0797a4c0d4 @dgrnbrg committed Apr 11, 2013
Showing with 98 additions and 23 deletions.
  1. +98 −23 README.md
View
121 README.md
@@ -22,9 +22,11 @@ keystrokes, optimizing for developer happiness. :)
First, let's look at `#spy/p`, which just pretty-prints the form of interest:
- spyscope.repl=> (take 20 (repeat #spy/p (+ 1 2 3)))
- 6
- (6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```clojure
+spyscope.repl=> (take 20 (repeat #spy/p (+ 1 2 3)))
+6
+(6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```
`#spy/p` is an extremely simple tool that merely saves a few keystores when
one needs to dump out a value in the middle of a calculation.
@@ -33,9 +35,11 @@ one needs to dump out a value in the middle of a calculation.
Next, let's look at `#spy/d`. This is where the real power lies:
- spyscope.repl=> (take 20 (repeat #spy/d (+ 1 2 3)))
- spyscope.repl$eval3869.invoke(NO_SOURCE_FILE:1) (+ 1 2 3) => 6
- (6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```clojure
+spyscope.repl=> (take 20 (repeat #spy/d (+ 1 2 3)))
+spyscope.repl$eval3869.invoke(NO_SOURCE_FILE:1) (+ 1 2 3) => 6
+(6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```
In the simplest usage, the form is printed along with the stack trace
it occurred on, which makes it easier to grep through logs that have
@@ -55,12 +59,14 @@ doing anything:
aside: (`:fs` comes from first and last letters of "frames")
- spyscope.repl=> (take 20 (repeat #spy/d ^{:fs 3} (+ 1 2 3)))
- ----------------------------------------
- clojure.lang.Compiler.eval(Compiler.java:6477)
- clojure.lang.Compiler.eval(Compiler.java:6511)
- spyscope.repl$eval675.invoke(REPL:13) (+ 1 2 3) => 6
- (6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```clojure
+spyscope.repl=> (take 20 (repeat #spy/d ^{:fs 3} (+ 1 2 3)))
+----------------------------------------
+clojure.lang.Compiler.eval(Compiler.java:6477)
+clojure.lang.Compiler.eval(Compiler.java:6511)
+spyscope.repl$eval675.invoke(REPL:13) (+ 1 2 3) => 6
+(6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```
As you can see, when multiple stack frames are printed, a row of dashes
is printed before the trace to keep the start of the stack frame group
@@ -71,12 +77,14 @@ certain values is important; however, if you print out 10 or 20 lines of
stack trace, you'll end up with an unreadable mess. The metadata key `:nses`
allows you to apply a regex to the stacktrace frames to filter out noise:
- spyscope.repl=> (take 20 (repeat #spy/d ^{:fs 3 :nses #"core|spyscope"} (+ 1 2 3)))
- ----------------------------------------
- clojure.core$apply.invoke(core.clj:601)
- clojure.core$eval.invoke(core.clj:2797)
- spyscope.repl$eval678.invoke(REPL:14) (+ 1 2 3) => 6
- (6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```clojure
+spyscope.repl=> (take 20 (repeat #spy/d ^{:fs 3 :nses #"core|spyscope"} (+ 1 2 3)))
+----------------------------------------
+clojure.core$apply.invoke(core.clj:601)
+clojure.core$eval.invoke(core.clj:2797)
+spyscope.repl$eval678.invoke(REPL:14) (+ 1 2 3) => 6
+(6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
+```
If you leave your application unattended for a period of time, you may
wish to have timestamps included in all the output lines. Spyscope can use
@@ -97,11 +105,13 @@ that generated the value, which can be used to de-clutter the output
if you have particularly large forms. This is controlled by setting
the metadata key `:form` to `false`:
- spyscope.repl=> {:a #spy/d ^{:form true} (+ 1 2 3)
- :b #spy/d ^{:form true} (- 16 10)}
- spyscope.repl$eval685.invoke(REPL:16) => 6
- spyscope.repl$eval685.invoke(REPL:16) => 6
- {:a 6, :b 6}
+```clojure
+spyscope.repl=> {:a #spy/d ^{:form true} (+ 1 2 3)
+ :b #spy/d ^{:form true} (- 16 10)}
+spyscope.repl$eval685.invoke(REPL:16) => 6
+spyscope.repl$eval685.invoke(REPL:16) => 6
+{:a 6, :b 6}
+```
Under the hood, `#spy/d` actually does all of its printing on another thread
--the tracing store thread! This provides 2 benefits: if you are printing
@@ -141,6 +151,71 @@ trials or experiments.
data is saved, that can become quite a lot of data, so this can be used
to clean up very long running sessions.
+## Example annotated `#spy/t` session
+
+```clojure
+;;Let's run some code on futures, but see the chronological result
+user=> (future (Thread/sleep 1000) #spy/t (+ 1 2))
+ (future #spy/t ^{:form 1} (+ 3 4))
+#<Future@1013d7df: :pending>
+;;We'll need to use the repl functions
+user=> (use 'spyscope.repl)
+nil
+;;trace-query shows all the traces by default, separated by dashed lines
+user=> (trace-query)
+user$eval35677$fn__35689.invoke(NO_SOURCE_FILE:1) (+ 3 4) => 7
+----------------------------------------
+user$eval35677$fn__35678.invoke(NO_SOURCE_FILE:1) => 3
+nil
+;;We'll define and invoke a function with a #spy/t
+user=> (defn my-best-fn [] #spy/t (* 5 6))
+ (my-best-fn)
+30 ;Here's the return value--note that the trace isn't printed
+;;Let's see all traces so far
+user=> (trace-query)
+user$eval35677$fn__35689.invoke(NO_SOURCE_FILE:1) (+ 3 4) => 7
+----------------------------------------
+user$eval35677$fn__35678.invoke(NO_SOURCE_FILE:1) => 3
+----------------------------------------
+user$eval35822$my_best_fn__35823.invoke(NO_SOURCE_FILE:1) => 30 ;Here's our new trace
+nil
+;;We can use a filter regex to only see matching stack frames
+;;Usually, you can filter by the name of the innermost function
+;;You can increase the :fs metadata parameter to have more context to filter by
+user=> (trace-query #"best")
+user$eval35822$my_best_fn__35823.invoke(NO_SOURCE_FILE:1) => 30
+nil
+;;Move onto a new generation
+user=> (trace-next)
+nil
+;;No traces in this generation
+user=> (trace-query)
+nil
+;;Increase the number of generations in the query to review older traces
+user=> (trace-query 2)
+user$eval35677$fn__35689.invoke(NO_SOURCE_FILE:1) (+ 3 4) => 7
+----------------------------------------
+user$eval35677$fn__35678.invoke(NO_SOURCE_FILE:1) => 3
+----------------------------------------
+user$eval35822$my_best_fn__35823.invoke(NO_SOURCE_FILE:1) => 30
+nil
+;;Add a new trace to the current generation
+user=> (my-best-fn)
+30
+;;We can see that there's only one trace in this generation--the one we just made
+user=> (trace-query)
+user$eval35822$my_best_fn__35823.invoke(NO_SOURCE_FILE:1) => 30
+nil
+;;We can combine the generation and regex filter to search and filter many generations
+;;Here we see the invocations of my-best-fn from the current and previous generation
+user=> (trace-query #"best" 2)
+user$eval35822$my_best_fn__35823.invoke(NO_SOURCE_FILE:1) => 30
+----------------------------------------
+user$eval35822$my_best_fn__35823.invoke(NO_SOURCE_FILE:1) => 30
+nil
+user=>
+```
+
## Contributors
David Greenberg (@dgrnbrg) and Herwig Hochleitner (@bendlas)

0 comments on commit d60d437

Please sign in to comment.