Skip to content

Commit fba79fc

Browse files
author
Krzysztof Dziedzic
committed
improve itk logging
1 parent f2e7ced commit fba79fc

6 files changed

Lines changed: 99 additions & 6 deletions

File tree

.github/workflows/itk.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ jobs:
3838
run: bash run_itk.sh
3939
working-directory: itk
4040
env:
41-
A2A_SAMPLES_REVISION: itk-v.0.11-alpha
41+
A2A_SAMPLES_REVISION: itk-v.015-alpha
4242

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,4 @@ aiwt-*
6363
itk/instruction.proto
6464
itk/pb
6565
itk/a2a-samples
66+
itk/logs

itk/README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ You must set the `A2A_SAMPLES_REVISION` environment variable to specify which re
3636

3737
Example:
3838
```bash
39-
export A2A_SAMPLES_REVISION=itk-v.0.11-alpha
39+
export A2A_SAMPLES_REVISION=itk-v.015-alpha
4040
```
4141

4242
### 2. Execute Tests
@@ -52,3 +52,19 @@ The script will:
5252
- Checkout the specified revision.
5353
- Build the ITK service Docker image.
5454
- Run the tests and output results.
55+
56+
## Debugging
57+
58+
To enable detailed debug logging and capture logs from the agents:
59+
60+
1. Set the `ITK_LOG_LEVEL` environment variable to `DEBUG`:
61+
```bash
62+
export ITK_LOG_LEVEL=DEBUG
63+
```
64+
65+
2. Run the tests as usual:
66+
```bash
67+
./run_itk.sh
68+
```
69+
70+
When run with `DEBUG` level, the script will create a `logs` directory in this `itk` folder and mount it to the container. You can find detailed logs for each agent in the `logs/` directory.

itk/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
)
1111

1212
require (
13-
github.com/a2aproject/a2a-go v0.3.12 // indirect
13+
github.com/a2aproject/a2a-go v0.3.14-0.20260404065426-6a9878f8f8a8 // indirect
1414
github.com/google/uuid v1.6.0 // indirect
1515
golang.org/x/mod v0.33.0 // indirect
1616
golang.org/x/net v0.48.0 // indirect

itk/main.go

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package main
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/base64"
67
"encoding/json"
78
"flag"
89
"fmt"
10+
"io"
911
"iter"
12+
"log/slog"
1013
"net"
1114
"net/http"
1215
"os"
@@ -276,6 +279,27 @@ func main() {
276279
func run() error {
277280
flag.Parse()
278281

282+
logLevelStr := os.Getenv("ITK_LOG_LEVEL")
283+
if logLevelStr == "" {
284+
logLevelStr = "INFO"
285+
}
286+
var level slog.Level
287+
switch strings.ToUpper(logLevelStr) {
288+
case "DEBUG":
289+
level = slog.LevelDebug
290+
case "INFO":
291+
level = slog.LevelInfo
292+
case "WARN":
293+
level = slog.LevelWarn
294+
case "ERROR":
295+
level = slog.LevelError
296+
default:
297+
level = slog.LevelInfo
298+
}
299+
300+
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level}))
301+
slog.SetDefault(logger)
302+
279303
jsonRPCV0Addr := fmt.Sprintf("http://127.0.0.1:%d", *httpPort)
280304

281305
agentCard := &a2a.AgentCard{
@@ -310,7 +334,10 @@ func run() error {
310334
}
311335

312336
executor := &V10AgentExecutor{}
313-
requestHandler := a2asrv.NewHandler(executor)
337+
requestHandler := a2asrv.NewHandler(
338+
executor,
339+
a2asrv.WithCallInterceptors(a2asrv.NewLoggingInterceptor(&a2asrv.LoggingConfig{LogPayload: true})),
340+
)
314341

315342
// Servers
316343
mux := http.NewServeMux()
@@ -324,7 +351,7 @@ func run() error {
324351

325352
httpServer := &http.Server{
326353
Addr: fmt.Sprintf(":%d", *httpPort),
327-
Handler: mux,
354+
Handler: loggingMiddleware(logger, mux),
328355
ReadHeaderTimeout: 3 * time.Second,
329356
}
330357

@@ -342,7 +369,10 @@ func run() error {
342369
return nil
343370
})
344371

345-
grpcServer := grpc.NewServer()
372+
grpcServer := grpc.NewServer(
373+
grpc.UnaryInterceptor(unaryLoggingInterceptor(logger)),
374+
grpc.StreamInterceptor(streamLoggingInterceptor(logger)),
375+
)
346376
a2agrpc.NewHandler(requestHandler).RegisterWith(grpcServer)
347377
g.Go(func() error {
348378
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *grpcPort))
@@ -369,3 +399,34 @@ func run() error {
369399

370400
return g.Wait()
371401
}
402+
403+
func loggingMiddleware(logger *slog.Logger, next http.Handler) http.Handler {
404+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
405+
var bodyBytes []byte
406+
if r.Body != nil {
407+
var err error
408+
bodyBytes, err = io.ReadAll(r.Body)
409+
if err != nil {
410+
logger.Error("Failed to read request body", err)
411+
} else {
412+
r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
413+
}
414+
}
415+
logger.Info("Incoming request", "method", r.Method, "path", r.URL.Path, "remote", r.RemoteAddr, "body", string(bodyBytes))
416+
next.ServeHTTP(w, r)
417+
})
418+
}
419+
420+
func unaryLoggingInterceptor(logger *slog.Logger) grpc.UnaryServerInterceptor {
421+
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
422+
logger.Info("gRPC Unary Call", "method", info.FullMethod)
423+
return handler(ctx, req)
424+
}
425+
}
426+
427+
func streamLoggingInterceptor(logger *slog.Logger) grpc.StreamServerInterceptor {
428+
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
429+
logger.Info("gRPC Stream Call", "method", info.FullMethod)
430+
return handler(srv, ss)
431+
}
432+
}

itk/run_itk.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/bin/bash
22
set -ex
33

4+
# Set default log level
5+
export ITK_LOG_LEVEL="${ITK_LOG_LEVEL:-INFO}"
6+
47
# Initialize default exit code
58
RESULT=1
69

@@ -66,13 +69,25 @@ ITK_DIR=$(pwd)
6669
# Stop existing container if any
6770
docker rm -f itk-service || true
6871

72+
# Create logs directory if debug
73+
if [ "${ITK_LOG_LEVEL^^}" = "DEBUG" ]; then
74+
mkdir -p "$ITK_DIR/logs"
75+
fi
76+
77+
DOCKER_MOUNT_LOGS=""
78+
if [ "${ITK_LOG_LEVEL^^}" = "DEBUG" ]; then
79+
DOCKER_MOUNT_LOGS="-v $ITK_DIR/logs:/app/logs"
80+
fi
81+
6982
# Run container with protobuf registration conflict set to 'warn'
7083
# This is necessary because the SDK v2 depends on its predecessor v0.x,
7184
# causing global proto registration conflicts.
7285
docker run -d --name itk-service \
7386
-e GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn \
87+
-e ITK_LOG_LEVEL="$ITK_LOG_LEVEL" \
7488
-v "$A2A_GO_ROOT:/app/agents/repo" \
7589
-v "$ITK_DIR:/app/agents/repo/itk" \
90+
$DOCKER_MOUNT_LOGS \
7691
-p 8000:8000 \
7792
itk_service
7893

0 commit comments

Comments
 (0)