Skip to content

Commit 5dae6ed

Browse files
bhaumanBruce Hauman
andauthored
Migrate from clojure.tools.logging to Timbre (#131)
* Migrate from clojure.tools.logging to Timbre Replace clojure.tools.logging with taoensso.timbre for pure Clojure logging. Changes: - Create src/clojure_mcp/logging.clj with centralized Timbre configuration - Add logging initialization to all main entry points (main.clj, sse_main.clj, figwheel_main.clj, shadow_main.clj) - Update all 26 source files to use [taoensso.timbre :as log] - Add test/clojure_mcp/test_helper.clj to suppress logging during tests - Update :test alias in deps.edn to use -M flag with test helper - Add helpful error message when using -X:test instead of -M:test - Remove clojure.tools.logging and logback dependencies - Add slf4j-nop to main deps to suppress Java library logging - Delete dev/logback.xml (no longer needed) Benefits: - Pure Clojure logging solution (no Java dependencies) - Simplified configuration - Better REPL integration - Clean test output with zero logging noise - Consistent logging across all entry points * chagne logging defaults --------- Co-authored-by: Bruce Hauman <bhauman@gmail.com>
1 parent 818d0c9 commit 5dae6ed

File tree

33 files changed

+161
-121
lines changed

33 files changed

+161
-121
lines changed

deps.edn

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
:deps {org.clojure/clojure {:mvn/version "1.12.1"}
33
org.clojure/data.json {:mvn/version "2.5.1"}
44
nrepl/nrepl {:mvn/version "1.3.1"}
5-
org.clojure/tools.logging {:mvn/version "1.3.0"}
65
org.clojure/tools.cli {:mvn/version "1.1.230"}
76
org.clj-commons/pretty {:mvn/version "3.6.7"}
87

@@ -27,22 +26,22 @@
2726
dev.langchain4j/langchain4j-anthropic {:mvn/version "1.8.0"}
2827
dev.langchain4j/langchain4j-google-ai-gemini {:mvn/version "1.8.0"}
2928

30-
;; in order to use the stdio server you have to handle logging somehow
31-
;; org.slf4j/slf4j-nop {:mvn/version "2.0.16"}
29+
com.taoensso/timbre {:mvn/version "6.8.0"}
30+
31+
;; Suppress logging from Java libraries (MCP SDK, LangChain4j, etc.)
32+
org.slf4j/slf4j-nop {:mvn/version "2.0.16"}
3233

3334
;; native Java diff library
3435
io.github.java-diff-utils/java-diff-utils {:mvn/version "4.15"}}
3536
:aliases
3637

3738
{:mcp
38-
{:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}}
39-
:exec-fn clojure-mcp.main/start-mcp-server
39+
{:exec-fn clojure-mcp.main/start-mcp-server
4040
;; it needs an nrepl port to talk to
4141
:exec-args {:port 7888}}
4242

4343
:mcp-sse
44-
{:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"} ;; optional
45-
jakarta.servlet/jakarta.servlet-api {:mvn/version "6.1.0"}
44+
{:extra-deps {jakarta.servlet/jakarta.servlet-api {:mvn/version "6.1.0"}
4645
org.eclipse.jetty/jetty-server {:mvn/version "11.0.20"}
4746
org.eclipse.jetty/jetty-servlet {:mvn/version "11.0.20"}}
4847
:exec-fn clojure-mcp.sse-main/start-sse-mcp-server
@@ -52,86 +51,72 @@
5251
:mcp-sse-port 8078}}
5352

5453
:mcp-figwheel
55-
{:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}}
56-
:exec-fn clojure-mcp.main-examples.figwheel-main/start-mcp-server
54+
{:exec-fn clojure-mcp.main-examples.figwheel-main/start-mcp-server
5755
:exec-args {:port 7888 :figwheel-build "dev"}}
5856

5957
:mcp-shadow
60-
{:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}}
61-
:exec-fn clojure-mcp.main-examples.shadow-main/start-mcp-server
58+
{:exec-fn clojure-mcp.main-examples.shadow-main/start-mcp-server
6259
:exec-args {:port 7888 :shadow-build "app"}}
6360

6461
;; dual shadow and project nrepl setup
6562
:mcp-shadow-dual
66-
{:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}}
67-
:extra-paths ["dev" "test"]
63+
{:extra-paths ["dev" "test"]
6864
:exec-fn clojure-mcp.main-examples.shadow-main/start-mcp-server
6965
;; it needs an nrepl port to talk to
7066
:exec-args {:port 7888 :shadow-build "app" :shadow-port 7889}}
7167

72-
;; below are dev set ups that need a logback.xml file
68+
;; below are dev set ups
7369
:prompt-cli
74-
{:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}}
75-
:main-opts ["-m" "clojure-mcp.prompt-cli"]}
70+
{:main-opts ["-m" "clojure-mcp.prompt-cli"]}
7671

7772
:dev-mcp
78-
{:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}}
79-
:extra-paths ["dev" "test"]
73+
{:extra-paths ["dev" "test"]
8074
:exec-fn clojure-mcp.main/start-mcp-server
8175
;; it needs an nrepl port to talk to
8276
:exec-args {:port 7888
8377
;; test auto starting the repl
8478
;; :start-nrepl-cmd ["clojure" "-M:nrepl"]
8579
}}
8680

87-
;; DEV setup needs logback.xml
8881
:dev-mcp-figwheel
89-
{:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}}
90-
:extra-paths ["dev" "test"]
82+
{:extra-paths ["dev" "test"]
9183
:exec-fn clojure-mcp.main-examples.figwheel-main/start-mcp-server
9284
;; it needs an nrepl port to talk to
9385
:exec-args {:port 7888 :figwheel-build "dev"}}
9486

95-
;; DEV setup needs logback.xml
9687
:dev-mcp-shadow
97-
{:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}}
98-
:extra-paths ["dev" "test"]
88+
{:extra-paths ["dev" "test"]
9989
:exec-fn clojure-mcp.main-examples.shadow-main/start-mcp-server
10090
;; it needs an nrepl port to talk to
10191
:exec-args {:port 7888 :shadow-build "app"}}
10292

10393
:dev-mcp-shadow-dual
104-
{:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}}
105-
:extra-paths ["dev" "test"]
94+
{:extra-paths ["dev" "test"]
10695
:exec-fn clojure-mcp.main-examples.shadow-main/start-mcp-server
10796
;; it needs an nrepl port to talk to
10897
:exec-args {:port 7888 :shadow-build "app" :shadow-port 7889}}
10998

11099
:nrepl {:extra-paths ["test" "dev"]
111-
:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}}
112100
:main-opts ["-m" "nrepl.cmdline" "--port" "7888"]}
113101

114102
:dkr-nrepl {:extra-paths ["test" "dev"]
115-
:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}}
116103
:main-opts ["-m" "nrepl.cmdline" "--port" "7888"
117104
;; for Docker
118105
"--bind" "0.0.0.0"]}
119106

120107
;; dev cycle
121108
:test
122109
{:extra-paths ["test" "dev"]
123-
:exec-fn cognitect.test-runner/test
124-
:extra-deps {ch.qos.logback/logback-classic {:mvn/version "1.4.14"}
125-
org.clojure/test.check {:mvn/version "1.1.1"}
110+
:exec-fn clojure-mcp.test-helper/run-tests-with-exec
111+
:extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
126112
nrepl/nrepl {:mvn/version "1.3.1"} ;; Add nrepl server for testing
127113
io.github.cognitect-labs/test-runner
128114
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}
129-
:main-opts ["-m" "cognitect.test-runner"]}
115+
:main-opts ["-e" "(require 'clojure-mcp.test-helper)" "-m" "cognitect.test-runner"]}
130116

131117
:index
132118
{:exec-fn clojure-mcp.code-indexer/map-project
133119
:exec-args {}
134-
:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}}
135120
;; Override with: clojure -X:index :dirs '["src" "lib"]' :include-tests true :out-file '"my-index.txt"'
136121
}
137122

dev/logback.xml

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/clojure_mcp/agent/general_agent.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"A generalized agent library that can be parameterized with system prompts,
33
context, tools, memory, and models."
44
(:require [clojure.string :as string]
5-
[clojure.tools.logging :as log]
5+
[taoensso.timbre :as log]
66
[clojure.java.io :as io]
77
[clojure-mcp.agent.langchain :as chain]
88
[clojure-mcp.tools.project.core :as project-core]

src/clojure_mcp/agent/langchain.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
(:require
33
[clojure.data.json :as json]
44
[clojure-mcp.agent.langchain.schema :as schema]
5-
[clojure.tools.logging :as log]
5+
[taoensso.timbre :as log]
66
[clojure.string :as string]
77
[clojure.pprint])
88
(:import

src/clojure_mcp/agent/langchain/chat_listener.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"Creates ChatModelListener instances from Clojure functions that work with EDN data"
33
(:require
44
[clojure-mcp.agent.langchain.message-conv :as msg-conv]
5-
[clojure.tools.logging :as log])
5+
[taoensso.timbre :as log])
66
(:import
77
[dev.langchain4j.model.chat.listener
88
ChatModelListener

src/clojure_mcp/agent/langchain/model.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
(:require
33
[clojure-mcp.config.schema :as schema]
44
[clojure-mcp.config :as config]
5-
[clojure.tools.logging :as log])
5+
[taoensso.timbre :as log])
66
(:import
77
[dev.langchain4j.model.anthropic
88
AnthropicChatModel

src/clojure_mcp/config.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[clojure-mcp.config.schema :as schema]
55
[clojure-mcp.utils.file :as file-utils]
66
[clojure.edn :as edn]
7-
[clojure.tools.logging :as log]))
7+
[taoensso.timbre :as log]))
88

99
(defn- relative-to [dir path]
1010
(try

src/clojure_mcp/core.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
(:require [clojure.data.json :as json]
33
[clojure.java.io :as io]
44
[clojure.spec.alpha :as s]
5-
[clojure.tools.logging :as log]
5+
[taoensso.timbre :as log]
66
[clojure-mcp.nrepl :as nrepl]
77
[clojure-mcp.config :as config]
88
[clojure-mcp.dialects :as dialects]

src/clojure_mcp/dialects.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
and initialization sequences specific to each dialect."
66
(:require [clojure.edn :as edn]
77
[clojure.java.io :as io]
8-
[clojure.tools.logging :as log]
8+
[taoensso.timbre :as log]
99
[clojure-mcp.nrepl :as nrepl]
1010
[clojure-mcp.utils.file :as file-utils]))
1111

src/clojure_mcp/logging.clj

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
(ns clojure-mcp.logging
2+
"Centralized logging configuration using Timbre.
3+
4+
This namespace provides functions to configure Timbre-based logging
5+
for the Clojure MCP server with support for both development and
6+
production modes."
7+
(:require [taoensso.timbre :as timbre]))
8+
9+
(def default-log-file ".clojure-mcp/clojure-mcp.log")
10+
11+
(defn configure-logging!
12+
"Configure Timbre logging with the given options.
13+
14+
Options:
15+
- :log-file Path to log file (default: 'logs/clojure-mcp.log')
16+
- :enable-logging? Whether to enable logging (default: true)
17+
- :log-level Minimum log level (default: :debug)
18+
Valid values: :trace :debug :info :warn :error :fatal :report
19+
20+
Examples:
21+
22+
Development mode with full logging:
23+
(configure-logging! {:log-file \"logs/clojure-mcp.log\"
24+
:enable-logging? true
25+
:log-level :debug})
26+
27+
Production mode with logging suppressed:
28+
(configure-logging! {:enable-logging? false})"
29+
[{:keys [log-file enable-logging? log-level]
30+
:or {log-file default-log-file
31+
enable-logging? false
32+
log-level :debug}}]
33+
(timbre/set-config!
34+
{:appenders (if enable-logging?
35+
{:spit (assoc
36+
(timbre/spit-appender {:fname log-file})
37+
:enabled? enable-logging?
38+
:min-level (or log-level :report)
39+
:ns-filter (if enable-logging?
40+
{:allow #{"clojure-mcp.*"}}
41+
{:deny #{"*"}}))}
42+
{})}))
43+
44+
(defn configure-dev-logging!
45+
"Configure logging for development mode with debug level.
46+
Convenience function that enables full debug logging to logs/clojure-mcp.log"
47+
[]
48+
(configure-logging! {:log-file "logs/clojure-mcp.log"
49+
:enable-logging? true
50+
:log-level :debug}))
51+
52+
(defn configure-prod-logging!
53+
"Configure logging for production mode with all logging suppressed.
54+
Convenience function that disables all logging."
55+
[]
56+
(configure-logging! {:enable-logging? false}))
57+
58+
(defn configure-test-logging!
59+
"Configure logging for test mode with all logging suppressed.
60+
Convenience function that disables all logging during tests."
61+
[]
62+
(configure-logging! {:enable-logging? false}))
63+
64+
(defn suppress-logging-for-tests!
65+
"Automatically suppress logging if running in test mode.
66+
Checks for CLOJURE_MCP_TEST environment variable or
67+
clojure.mcp.test system property."
68+
[]
69+
(when (or (System/getenv "CLOJURE_MCP_TEST")
70+
(System/getProperty "clojure.mcp.test"))
71+
(configure-test-logging!)))

0 commit comments

Comments
 (0)