Skip to content

Commit 8a23124

Browse files
committed
chore: improvements
Signed-off-by: Danny Kopping <danny@coder.com>
1 parent c348da4 commit 8a23124

2 files changed

Lines changed: 75 additions & 25 deletions

File tree

example/main.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package main
55
import (
66
"context"
77
"database/sql"
8-
"log"
98
"net/http"
109
"os"
1110
"regexp"
@@ -27,15 +26,21 @@ func main() {
2726
// Initialize SQLite database with WAL mode for better concurrency.
2827
db, err := sql.Open("sqlite", "aibridge.db?_journal_mode=WAL&_busy_timeout=5000")
2928
if err != nil {
30-
log.Fatalf("open database: %v", err)
29+
logger.Fatal(ctx, "open database", slog.Error(err))
3130
}
3231
defer db.Close()
3332
db.SetMaxOpenConns(1) // SQLite only supports one writer at a time.
3433

3534
if err := initSchema(db); err != nil {
36-
log.Fatalf("init schema: %v", err)
35+
logger.Fatal(ctx, "init schema", slog.Error(err))
3736
}
3837

38+
recorder, err := NewSQLiteRecorder(db, logger)
39+
if err != nil {
40+
logger.Fatal(ctx, "create recorder", slog.Error(err))
41+
}
42+
defer recorder.Close()
43+
3944
// Configure providers.
4045
providers := []aibridge.Provider{
4146
aibridge.NewAnthropicProvider(aibridge.AnthropicConfig{
@@ -63,25 +68,25 @@ func main() {
6368
nil, // denylist
6469
)
6570
if err != nil {
66-
log.Fatalf("create deepwiki mcp proxy: %v", err)
71+
logger.Fatal(ctx, "create deepwiki mcp proxy", slog.Error(err))
6772
}
6873

6974
mcpProxy = mcp.NewServerProxyManager(map[string]mcp.ServerProxier{"deepwiki": deepwikiProxy})
7075
if err := mcpProxy.Init(ctx); err != nil {
71-
log.Printf("mcp init warning: %v", err)
76+
logger.Warn(ctx, "mcp init warning", slog.Error(err))
7277
}
7378

7479
// Create the bridge with SQLite recorder.
7580
bridge, err := aibridge.NewRequestBridge(
7681
ctx,
7782
providers,
78-
&SQLiteRecorder{db: db, logger: logger},
83+
recorder,
7984
mcpProxy,
8085
metrics,
8186
logger,
8287
)
8388
if err != nil {
84-
log.Fatalf("create bridge: %v", err)
89+
logger.Fatal(ctx, "create bridge", slog.Error(err))
8590
}
8691
defer bridge.Shutdown(ctx)
8792

@@ -90,9 +95,9 @@ func main() {
9095
mux.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))
9196
mux.Handle("/", actorMiddleware(bridge))
9297

93-
log.Println("listening on :8080")
98+
logger.Info(ctx, "listening on :8080")
9499
if err := http.ListenAndServe(":8080", mux); err != nil {
95-
log.Fatal(err)
100+
logger.Fatal(ctx, "http server error", slog.Error(err))
96101
}
97102
}
98103

example/recorder.go

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,67 @@ import (
1414
type SQLiteRecorder struct {
1515
db *sql.DB
1616
logger slog.Logger
17+
18+
stmtInsertInterception *sql.Stmt
19+
stmtUpdateInterception *sql.Stmt
20+
stmtInsertTokenUsage *sql.Stmt
21+
stmtInsertPromptUsage *sql.Stmt
22+
stmtInsertToolUsage *sql.Stmt
23+
}
24+
25+
func NewSQLiteRecorder(db *sql.DB, logger slog.Logger) (*SQLiteRecorder, error) {
26+
r := &SQLiteRecorder{db: db, logger: logger}
27+
28+
var err error
29+
r.stmtInsertInterception, err = db.Prepare(`
30+
INSERT INTO aibridge_interceptions (id, initiator_id, provider, model, started_at, metadata)
31+
VALUES (?, ?, ?, ?, ?, ?)`)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
r.stmtUpdateInterception, err = db.Prepare(`
37+
UPDATE aibridge_interceptions SET ended_at = ? WHERE id = ?`)
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
r.stmtInsertTokenUsage, err = db.Prepare(`
43+
INSERT INTO aibridge_token_usages (id, interception_id, provider_response_id, input_tokens, output_tokens, metadata, created_at)
44+
VALUES (?, ?, ?, ?, ?, ?, ?)`)
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
r.stmtInsertPromptUsage, err = db.Prepare(`
50+
INSERT INTO aibridge_user_prompts (id, interception_id, provider_response_id, prompt, metadata, created_at)
51+
VALUES (?, ?, ?, ?, ?, ?)`)
52+
if err != nil {
53+
return nil, err
54+
}
55+
56+
r.stmtInsertToolUsage, err = db.Prepare(`
57+
INSERT INTO aibridge_tool_usages (id, interception_id, provider_response_id, server_url, tool, input, injected, invocation_error, metadata, created_at)
58+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
return r, nil
64+
}
65+
66+
func (r *SQLiteRecorder) Close() error {
67+
r.stmtInsertInterception.Close()
68+
r.stmtUpdateInterception.Close()
69+
r.stmtInsertTokenUsage.Close()
70+
r.stmtInsertPromptUsage.Close()
71+
r.stmtInsertToolUsage.Close()
72+
return nil
1773
}
1874

1975
func (r *SQLiteRecorder) RecordInterception(ctx context.Context, req *aibridge.InterceptionRecord) error {
2076
metadata, _ := json.Marshal(req.Metadata)
21-
_, err := r.db.ExecContext(ctx, `
22-
INSERT INTO aibridge_interceptions (id, initiator_id, provider, model, started_at, metadata)
23-
VALUES (?, ?, ?, ?, ?, ?)`,
77+
_, err := r.stmtInsertInterception.ExecContext(ctx,
2478
req.ID, req.InitiatorID, req.Provider, req.Model, req.StartedAt, string(metadata),
2579
)
2680
if err != nil {
@@ -30,10 +84,7 @@ func (r *SQLiteRecorder) RecordInterception(ctx context.Context, req *aibridge.I
3084
}
3185

3286
func (r *SQLiteRecorder) RecordInterceptionEnded(ctx context.Context, req *aibridge.InterceptionRecordEnded) error {
33-
_, err := r.db.ExecContext(ctx, `
34-
UPDATE aibridge_interceptions SET ended_at = ? WHERE id = ?`,
35-
req.EndedAt, req.ID,
36-
)
87+
_, err := r.stmtUpdateInterception.ExecContext(ctx, req.EndedAt, req.ID)
3788
if err != nil {
3889
r.logger.Warn(ctx, "failed to record interception end", slog.Error(err))
3990
}
@@ -51,9 +102,7 @@ func (r *SQLiteRecorder) RecordTokenUsage(ctx context.Context, req *aibridge.Tok
51102
}
52103
metadata, _ := json.Marshal(merged)
53104

54-
_, err := r.db.ExecContext(ctx, `
55-
INSERT INTO aibridge_token_usages (id, interception_id, provider_response_id, input_tokens, output_tokens, metadata, created_at)
56-
VALUES (?, ?, ?, ?, ?, ?, ?)`,
105+
_, err := r.stmtInsertTokenUsage.ExecContext(ctx,
57106
uuid.NewString(), req.InterceptionID, req.MsgID, req.Input, req.Output, string(metadata), req.CreatedAt,
58107
)
59108
if err != nil {
@@ -64,9 +113,7 @@ func (r *SQLiteRecorder) RecordTokenUsage(ctx context.Context, req *aibridge.Tok
64113

65114
func (r *SQLiteRecorder) RecordPromptUsage(ctx context.Context, req *aibridge.PromptUsageRecord) error {
66115
metadata, _ := json.Marshal(req.Metadata)
67-
_, err := r.db.ExecContext(ctx, `
68-
INSERT INTO aibridge_user_prompts (id, interception_id, provider_response_id, prompt, metadata, created_at)
69-
VALUES (?, ?, ?, ?, ?, ?)`,
116+
_, err := r.stmtInsertPromptUsage.ExecContext(ctx,
70117
uuid.NewString(), req.InterceptionID, req.MsgID, req.Prompt, string(metadata), req.CreatedAt,
71118
)
72119
if err != nil {
@@ -90,9 +137,7 @@ func (r *SQLiteRecorder) RecordToolUsage(ctx context.Context, req *aibridge.Tool
90137
invocationError = &errStr
91138
}
92139

93-
_, err := r.db.ExecContext(ctx, `
94-
INSERT INTO aibridge_tool_usages (id, interception_id, provider_response_id, server_url, tool, input, injected, invocation_error, metadata, created_at)
95-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
140+
_, err := r.stmtInsertToolUsage.ExecContext(ctx,
96141
uuid.NewString(), req.InterceptionID, req.MsgID, serverURL, req.Tool, string(input), req.Injected, invocationError, string(metadata), req.CreatedAt,
97142
)
98143
if err != nil {

0 commit comments

Comments
 (0)