Skip to content

Commit b8e018f

Browse files
committed
support logging
Signed-off-by: eric-epsilla <[email protected]>
1 parent 3e4066c commit b8e018f

File tree

8 files changed

+922
-44
lines changed

8 files changed

+922
-44
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ thiserror = "1.0"
2222
which = "6.0"
2323
home = "0.5"
2424
async-trait = "0.1"
25+
tracing = "0.1"
26+
tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "chrono"] }
2527

2628
[dev-dependencies]
2729
tokio-test = "0.4"
30+
tracing-test = "0.2"
2831

2932
[lib]
3033
name = "claude_code_sdk"

README.md

Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ use tokio_stream::StreamExt;
2525

2626
#[tokio::main]
2727
async fn main() -> Result<(), Box<dyn std::error::Error>> {
28+
// Optional: Initialize logging to see detailed SDK operations
29+
claude_code_sdk::init_tracing();
30+
2831
let mut stream = query("What is 2 + 2?", None).await?;
2932

3033
while let Some(message) = stream.next().await {
@@ -97,6 +100,140 @@ let options = ClaudeCodeOptions {
97100
};
98101
```
99102

103+
## Logging
104+
105+
The Claude Code SDK provides comprehensive structured logging using the [`tracing`](https://tracing.rs/) ecosystem. This helps with debugging, monitoring, and understanding SDK operations.
106+
107+
### Quick Setup
108+
109+
```rust
110+
use claude_code_sdk;
111+
112+
#[tokio::main]
113+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
114+
// Initialize default logging
115+
claude_code_sdk::init_tracing();
116+
117+
// Your code here...
118+
Ok(())
119+
}
120+
```
121+
122+
### Environment Variables
123+
124+
Control logging levels with the `RUST_LOG` environment variable:
125+
126+
```bash
127+
# Show info and above (default)
128+
RUST_LOG=claude_code_sdk=info cargo run
129+
130+
# Show debug messages (recommended for development)
131+
RUST_LOG=claude_code_sdk=debug cargo run
132+
133+
# Show all messages including trace
134+
RUST_LOG=claude_code_sdk=trace cargo run
135+
136+
# Show only errors
137+
RUST_LOG=claude_code_sdk=error cargo run
138+
139+
# Multiple modules
140+
RUST_LOG=claude_code_sdk=debug,tokio=info cargo run
141+
```
142+
143+
### Custom Logging Setup
144+
145+
For more control over logging, set up `tracing-subscriber` directly:
146+
147+
```rust
148+
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
149+
150+
// JSON structured logging
151+
tracing_subscriber::registry()
152+
.with(tracing_subscriber::EnvFilter::new("claude_code_sdk=debug"))
153+
.with(tracing_subscriber::fmt::layer().json())
154+
.init();
155+
156+
// Custom formatting
157+
tracing_subscriber::registry()
158+
.with(tracing_subscriber::EnvFilter::new("claude_code_sdk=debug"))
159+
.with(
160+
tracing_subscriber::fmt::layer()
161+
.with_target(true)
162+
.with_thread_ids(true)
163+
.with_file(true)
164+
.with_line_number(true)
165+
.pretty()
166+
)
167+
.init();
168+
169+
// File logging
170+
let file = std::fs::OpenOptions::new()
171+
.create(true)
172+
.write(true)
173+
.truncate(true)
174+
.open("claude_sdk.log")?;
175+
176+
tracing_subscriber::registry()
177+
.with(tracing_subscriber::EnvFilter::new("claude_code_sdk=trace"))
178+
.with(tracing_subscriber::fmt::layer().with_writer(file))
179+
.init();
180+
```
181+
182+
### What Gets Logged
183+
184+
The SDK logs various operations at different levels:
185+
186+
- **ERROR**: CLI not found, connection failures, JSON decode errors
187+
- **WARN**: Process termination issues, unexpected states
188+
- **INFO**: Query start/completion, connection events, major operations
189+
- **DEBUG**: Message processing, command building, subprocess management
190+
- **TRACE**: Individual message parsing, detailed state changes
191+
192+
### Log Fields
193+
194+
Structured logs include useful fields:
195+
196+
```json
197+
{
198+
"timestamp": "2024-01-01T12:00:00.000Z",
199+
"level": "INFO",
200+
"target": "claude_code_sdk::client",
201+
"message": "Processing query through transport",
202+
"fields": {
203+
"prompt_length": 25,
204+
"has_options": true,
205+
"system_prompt": "You are helpful",
206+
"allowed_tools": 2,
207+
"permission_mode": "AcceptEdits"
208+
}
209+
}
210+
```
211+
212+
### Performance Monitoring
213+
214+
Enable performance monitoring with tracing spans:
215+
216+
```rust
217+
use tracing::{info, Instrument};
218+
219+
async fn my_function() -> Result<(), Box<dyn std::error::Error>> {
220+
let span = tracing::info_span!("my_operation", operation_type = "query");
221+
222+
async move {
223+
let start = std::time::Instant::now();
224+
225+
// Your Claude SDK operations here
226+
let mut stream = query("Hello", None).await?;
227+
// ... process stream
228+
229+
info!(duration_ms = start.elapsed().as_millis(), "Operation completed");
230+
Ok(())
231+
}
232+
.instrument(span)
233+
.await
234+
}
235+
```
236+
100237
## API Reference
101238

102239
### `query(prompt: &str, options: Option<ClaudeCodeOptions>)`
@@ -149,7 +286,24 @@ See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-co
149286

150287
## Examples
151288

152-
See [examples/quick_start.rs](examples/quick_start.rs) for a complete working example.
289+
- **[examples/quick_start.rs](examples/quick_start.rs)** - Complete working example with logging
290+
- **[examples/logging_demo.rs](examples/logging_demo.rs)** - Advanced logging configurations
291+
292+
### Running Examples
293+
294+
```bash
295+
# Basic example with default logging
296+
cargo run --example quick_start
297+
298+
# Advanced logging demo with JSON output
299+
cargo run --example logging_demo -- --json
300+
301+
# File logging
302+
cargo run --example logging_demo -- --file logs/claude.log
303+
304+
# Performance monitoring
305+
RUST_LOG=claude_code_sdk=debug cargo run --example logging_demo -- --perf
306+
```
153307

154308
## License
155309

0 commit comments

Comments
 (0)