Watchers are not only good for logging and counting, but they are also useful for debugging. If an agent or reference is not getting updated the way we expect, we can temporarily add a watcher to track what's happening so we can see what's going on.
For this recipe, we'll continue the theme we've been working with for the last few recipes. This time, instead of counting the data, the watch function will print the change of state to the console.
We'll use the dependencies and requirements that we did in the Monitoring processing with watchers recipe. For this recipe, we just need to add a two more functions to them.
watch
function. Here's the new one:(defn debug-watch [watch-key watch-agent old-state new-state] (let [output (str watch-key ": " (pr-str old-state) " => " (pr-str new-state) ewline)] (print output)))
(defn watch-debugging
[input-file]
(let [reader (agent
(seque
(mapcat
lazy-read-csv
input-files)))
caster (agent nil)
sink (agent [])
counter (ref 0)
done (ref false)]
(add-watch caster :counter
(partial watch-caster counter))
(add-watch caster :debug debug-watch)
(send reader read-row caster sink done)
(wait-for-it 250 done)
{:results @sink
:count-watcher @counter}))
user=> (:count-watcher (watch-debugging (take 2 data-files))) :debug: [1990 "|0028670|" "|C00186288|" "|N00001783|" 1000 "06/15/1990" "|C4100|" "|24K|" "|D|" "|H6MI16034|"] => [1990 "|0028677|" "|C00186288|" "|N00007967|" 2000 "06/15/1990" "|C4100|" "|24K|" "|D|" "|H6WA05023|"] :debug: [1990 "|0028677|" "|C00186288|" "|N00007967|" 2000 "06/15/1990" "|C4100|" "|24K|" "|D|" "|H6WA05023|"] => [1990 "|0028687|" "|C00186288|" "|N00002497|" 500 "07/18/1990" "|C4100|" "|24K|" "|D|" "|H6SC03025|"] :debug: [1990 "|0028687|" "|C00186288|" "|N00002497|" 500 "07/18/1990" "|C4100|" "|24K|" "|D|" "|H6SC03025|"] => [1990 "|0028706|" "|C00186288|" "|N00007763|" 1000 "09/28/1990" "|C4100|" "|24K|" "|D|" "|S8OR00017|"]
This is a good option to debug output if you need a lot of flexibility. However, if all you need is to track function calls, arguments, and outputs, clojure.tools.trace
(https://github.com/clojure/tools.trace) is better. It does this and only this, and it's also less intrusive on your program's structure.