Skip to content

Commit 3b5d11b

Browse files
committed
chore: clean up
Signed-off-by: Danny Kopping <[email protected]>
1 parent 6a50dda commit 3b5d11b

7 files changed

+53
-12
lines changed

intercept_anthropic_messages_blocking.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func (i *AnthropicMessagesBlockingInterception) ProcessRequest(w http.ResponseWr
5757

5858
opts := []option.RequestOption{option.WithRequestTimeout(time.Second * 60)} // TODO: configurable timeout
5959

60-
client := newAnthropicClient(i.cfg, i.id.String(), i.Model(), opts...)
60+
client := newAnthropicClient(i.logger, i.cfg, i.id.String(), i.Model(), opts...)
6161
messages := i.req.MessageNewParams
6262
logger := i.logger.With(slog.F("model", i.req.Model))
6363

intercept_anthropic_messages_streaming.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (i *AnthropicMessagesStreamingInterception) ProcessRequest(w http.ResponseW
9494
_ = events.Shutdown(streamCtx) // Catch-all in case it doesn't get shutdown after stream completes.
9595
}()
9696

97-
client := newAnthropicClient(i.cfg, i.id.String(), i.Model())
97+
client := newAnthropicClient(i.logger, i.cfg, i.id.String(), i.Model())
9898
messages := i.req.MessageNewParams
9999

100100
// Accumulate usage across the entire streaming interaction (including tool reinvocations).

intercept_openai_chat_blocking.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func (i *OpenAIBlockingChatInterception) ProcessRequest(w http.ResponseWriter, r
4141
}
4242

4343
ctx := r.Context()
44-
client := newOpenAIClient(i.cfg, i.id.String(), i.Model())
44+
client := newOpenAIClient(i.logger, i.cfg, i.id.String(), i.Model())
4545
logger := i.logger.With(slog.F("model", i.req.Model))
4646

4747
var (

intercept_openai_chat_streaming.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (i *OpenAIStreamingChatInterception) ProcessRequest(w http.ResponseWriter,
6363
defer cancel()
6464
r = r.WithContext(ctx) // Rewire context for SSE cancellation.
6565

66-
client := newOpenAIClient(i.cfg, i.id.String(), i.Model())
66+
client := newOpenAIClient(i.logger, i.cfg, i.id.String(), i.Model())
6767
logger := i.logger.With(slog.F("model", i.req.Model))
6868

6969
streamCtx, streamCancel := context.WithCancelCause(ctx)

provider_anthropic.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"os"
1010

11+
"cdr.dev/slog"
1112
"github.com/anthropics/anthropic-sdk-go"
1213
"github.com/anthropics/anthropic-sdk-go/option"
1314
"github.com/anthropics/anthropic-sdk-go/shared"
@@ -98,12 +99,12 @@ func (p *AnthropicProvider) InjectAuthHeader(headers *http.Header) {
9899
headers.Set(p.AuthHeader(), p.cfg.Key)
99100
}
100101

101-
func newAnthropicClient(cfg *ProviderConfig, id, model string, opts ...option.RequestOption) anthropic.Client {
102+
func newAnthropicClient(logger slog.Logger, cfg *ProviderConfig, id, model string, opts ...option.RequestOption) anthropic.Client {
102103
opts = append(opts, option.WithAPIKey(cfg.Key))
103104
opts = append(opts, option.WithBaseURL(cfg.BaseURL))
104105

105106
if cfg.EnableUpstreamLogging() {
106-
if middleware := createLoggingMiddleware("anthropic", id, model); middleware != nil {
107+
if middleware := createLoggingMiddleware(logger, "anthropic", id, model); middleware != nil {
107108
opts = append(opts, option.WithMiddleware(middleware))
108109
}
109110
}

provider_openai.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"os"
99

10+
"cdr.dev/slog"
1011
"github.com/google/uuid"
1112
"github.com/openai/openai-go/v2"
1213
"github.com/openai/openai-go/v2/option"
@@ -100,13 +101,13 @@ func (p *OpenAIProvider) InjectAuthHeader(headers *http.Header) {
100101
headers.Set(p.AuthHeader(), "Bearer "+p.cfg.Key)
101102
}
102103

103-
func newOpenAIClient(cfg *ProviderConfig, id, model string) openai.Client {
104+
func newOpenAIClient(logger slog.Logger, cfg *ProviderConfig, id, model string) openai.Client {
104105
var opts []option.RequestOption
105106
opts = append(opts, option.WithAPIKey(cfg.Key))
106107
opts = append(opts, option.WithBaseURL(cfg.BaseURL))
107108

108109
if cfg.EnableUpstreamLogging() {
109-
if middleware := createLoggingMiddleware("openai", id, model); middleware != nil {
110+
if middleware := createLoggingMiddleware(logger, "openai", id, model); middleware != nil {
110111
opts = append(opts, option.WithMiddleware(middleware))
111112
}
112113
}

request_logger.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,35 @@
11
package aibridge
22

33
import (
4+
"context"
5+
"fmt"
46
"log"
57
"net/http"
68
"net/http/httputil"
79
"os"
10+
"path/filepath"
11+
"strings"
12+
13+
"cdr.dev/slog"
814
)
915

16+
// sanitizeModelName makes a model name safe for use as a directory name.
17+
// Replaces filesystem-unsafe characters with underscores.
18+
func sanitizeModelName(model string) string {
19+
replacer := strings.NewReplacer(
20+
"/", "_",
21+
"\\", "_",
22+
":", "_",
23+
"*", "_",
24+
"?", "_",
25+
"\"", "_",
26+
"<", "_",
27+
">", "_",
28+
"|", "_",
29+
)
30+
return replacer.Replace(model)
31+
}
32+
1033
// logUpstreamRequest logs an HTTP request with the given ID and model name.
1134
// The prefix format is: [req] [id] [model]
1235
func logUpstreamRequest(logger *log.Logger, id, model string, req *http.Request) {
@@ -42,16 +65,32 @@ func logUpstreamError(logger *log.Logger, id, model string, err error) {
4265
}
4366

4467
// createLoggingMiddleware creates a middleware function that logs requests and responses.
45-
// Returns nil if logging setup fails.
46-
func createLoggingMiddleware(provider, id, model string) func(*http.Request, func(*http.Request) (*http.Response, error)) (*http.Response, error) {
47-
reqLogFile, err := os.OpenFile("/tmp/"+provider+"-req.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
68+
// Logs are written to $TMPDIR/$provider/$model/$id.req.log and $TMPDIR/$provider/$model/$id.res.log
69+
// Returns nil if logging setup fails, logging errors via the provided logger.
70+
func createLoggingMiddleware(logger slog.Logger, provider, id, model string) func(*http.Request, func(*http.Request) (*http.Response, error)) (*http.Response, error) {
71+
ctx := context.Background()
72+
safeModel := sanitizeModelName(model)
73+
logDir := filepath.Join(os.TempDir(), provider, safeModel)
74+
75+
// Create the directory structure if it doesn't exist
76+
if err := os.MkdirAll(logDir, 0755); err != nil {
77+
logger.Warn(ctx, "failed to create log directory", slog.Error(err), slog.F("dir", logDir))
78+
return nil
79+
}
80+
81+
reqLogPath := filepath.Join(logDir, fmt.Sprintf("%s.req.log", id))
82+
resLogPath := filepath.Join(logDir, fmt.Sprintf("%s.res.log", id))
83+
84+
reqLogFile, err := os.OpenFile(reqLogPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
4885
if err != nil {
86+
logger.Warn(ctx, "failed to open request log file", slog.Error(err), slog.F("path", reqLogPath))
4987
return nil
5088
}
5189

52-
resLogFile, err := os.OpenFile("/tmp/"+provider+"-res.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
90+
resLogFile, err := os.OpenFile(resLogPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
5391
if err != nil {
5492
reqLogFile.Close()
93+
logger.Warn(ctx, "failed to open response log file", slog.Error(err), slog.F("path", resLogPath))
5594
return nil
5695
}
5796

0 commit comments

Comments
 (0)