2010-07-27 2 views
17

방금 ​​내 가정용 프로젝트 중 하나에서 log4j를 사용하기 시작했으며 큰 모듈의 모든 기능에 마우스를 잘라내어 붙여 넣기 (trace (str "entering: " function-name))을 잘라 냈습니다. 이성의 목소리가 잡아 당기면서 "더 나은 방법이 될 수 밖에 없다"고 말했습니다 ... 나는 모든 기능 블록을 감싸고 그 흔적을 그들에게 추가하는 것을 생각할 수 있습니다. 현명한 Stack-Overflowing-Clojurians의 충고?clojure : 네임 스페이스의 모든 함수에 디버그 추적을 추가 하시겠습니까?

답변

17

매크로에 대한 필요가 없습니다 : 비슷한

(defn trace-ns 
    "ns should be a namespace object or a symbol." 
    [ns] 
    (doseq [s (keys (ns-interns ns)) 
      :let [v (ns-resolve ns s)] 
      :when (and (ifn? @v) (-> v meta :macro not))] 
    (intern ns 
      (with-meta s {:traced true :untraced @v}) 
      (let [f @v] (fn [& args] 
          (clojure.contrib.trace/trace (str "entering: " s)) 
          (apply f args)))))) 

(defn untrace-ns [ns] 
    (doseq [s (keys (ns-interns ns)) 
      :let [v (ns-resolve ns s)] 
      :when (:traced (meta v))] 
    (alter-meta! (intern ns s (:untraced (meta v))) 
       #(dissoc % :traced :untraced)))) 

... 또는 뭔가. 가장 가능성있는 추가 요구 사항은 ifn?이 아닌 항목에 trace을 호출하지 않으려면 filter을 사용하는 것입니다. 업데이트 : 해당 솔루션 (매크로도 처리 중)에서 편집 됨. 업데이트 2 : 몇 가지 주요 버그가 수정되었습니다. 업데이트 4 : untrace 기능이 추가되었습니다.

업데이트 3 : 다음은 내 REPL에서 예입니다 :

user> (ns foo) 
nil 
foo> (defn foo [x] x) 
#'foo/foo 
foo> (defmacro bar [x] x) 
#'foo/bar 
foo> (ns user) 
nil 
user> (trace-ns 'foo) 
nil 
user> (foo/foo :foo) 
TRACE: "entering: foo" 
:foo 
user> (foo/bar :foo) 
:foo 
user> (untrace-ns 'foo) 
nil 
user> (foo/foo :foo) 
:foo 
+0

당신은 단순히 최고입니다! 아마도 ns-resolve 부분을 설명 할 수 있습니까? –

+0

:-)'ns-resolve'는 네임 스페이스 또는 네임 스페이스 - 네이밍 기호와 기호를 취하여 (두 번째) 기호로 주어진 이름으로 주어진 네임 스페이스에서 Var를 찾도록 시도합니다. 여기에서 중요한 점은 (1) Var의 루트 바인딩을 변경할 수 있다는 것입니다 (여러 가지 방법이 있지만 '인턴'은 여분의 메타 데이터를 처리하는 방법 때문에 특히 편리합니다.) trace-ns (2) Var의 메타 데이터를 변경할 수 있습니다 (그래서 'untraced-ns'가 가능합니다). –

+0

위의 최신 버전을 보려면 http://gist.github.com/492764를 참조하십시오 (보다 유용한 docstring이 등장합니다!). –

관련 문제