\input luatexbase.sty

% \def\cbktype{hpack_filter}
\def\cbktype{pre_linebreak_filter}
\directlua{
  local ncalls, nnodes = 0, 0
  cbk = function (head)
    ncalls = ncalls + 1
    print("···············[" .. ncalls .. "]···············")
    for n in node.traverse(head) do
      nnodes = nnodes + 1
      local nid = n.id
      print(n, (nid == node.id"glyph" and unicode.utf8.char(n.char) or false))
    end
    return head
  end
  dumpstats = function (head)
    print(string.rep("·", 71))
    print(string.format("callback invoked \%d times, \%d nodes inspected", ncalls, nnodes))
    print(string.rep("·", 71))
  end
}

\def\startfoo{\par\directlua{luatexbase.     add_to_callback("\cbktype",cbk, "cbk")}}
\def \stopfoo{\par\directlua{luatexbase.remove_from_callback("\cbktype",     "cbk")}}

\def\dumpstats{\directlua{dumpstats()}}

\startfoo
  foo \vbox{\hbox{bar}} baz
\stopfoo

\dumpstats\bye
