MCPcopy
hub / github.com/mudler/LocalAI / TraceMiddleware

Function TraceMiddleware

core/http/middleware/trace.go:160–258  ·  view source on GitHub ↗

TraceMiddleware intercepts and logs JSON API requests and responses

(app *application.Application)

Source from the content-addressed store, hash-verified

158
159// TraceMiddleware intercepts and logs JSON API requests and responses
160func TraceMiddleware(app *application.Application) echo.MiddlewareFunc {
161 return func(next echo.HandlerFunc) echo.HandlerFunc {
162 return func(c echo.Context) error {
163 if !app.ApplicationConfig().EnableTracing {
164 return next(c)
165 }
166
167 initializeTracing(app.ApplicationConfig().TracingMaxItems)
168
169 ct, _, _ := mime.ParseMediaType(c.Request().Header.Get("Content-Type"))
170 if ct != "application/json" {
171 return next(c)
172 }
173
174 body, err := io.ReadAll(c.Request().Body)
175 if err != nil {
176 xlog.Error("Failed to read request body")
177 return err
178 }
179
180 // Restore the body for downstream handlers
181 c.Request().Body = io.NopCloser(bytes.NewBuffer(body))
182
183 startTime := time.Now()
184
185 // Cap captured payload size. Without this, /embeddings and
186 // streaming /chat/completions blow the in-memory buffer into the
187 // tens of MB, which then locks the admin Traces UI fetching the
188 // JSON dump faster than the 5s auto-refresh.
189 maxBodyBytes := app.ApplicationConfig().TracingMaxBodyBytes
190
191 // Wrap response writer to capture body
192 resBody := new(bytes.Buffer)
193 mw := &bodyWriter{
194 ResponseWriter: c.Response().Writer,
195 body: resBody,
196 maxBytes: maxBodyBytes,
197 }
198 c.Response().Writer = mw
199
200 handlerErr := next(c)
201
202 // Restore original writer unconditionally
203 c.Response().Writer = mw.ResponseWriter
204
205 // Determine response status (use 500 if handler errored and no status was set)
206 status := c.Response().Status
207 if status == 0 && handlerErr != nil {
208 status = http.StatusInternalServerError
209 }
210
211 // Create exchange log (always, even on error). Sensitive headers
212 // (Authorization, API keys, cookies) are redacted before storage —
213 // the trace endpoint is admin-only but the buffer is also reachable
214 // via any heap-dump-style introspection, and tokens shouldn't
215 // outlive the request that carried them.
216 requestHeaders := redactSensitiveHeaders(c.Request().Header)
217 requestBody, requestTruncated := truncateForTrace(body, maxBodyBytes)

Callers 5

RegisterOllamaRoutesFunction · 0.92
RegisterAnthropicRoutesFunction · 0.92
RegisterLocalAIRoutesFunction · 0.92
RegisterOpenAIRoutesFunction · 0.92

Calls 12

GetUserFunction · 0.92
initializeTracingFunction · 0.85
redactSensitiveHeadersFunction · 0.85
truncateForTraceFunction · 0.85
ApplicationConfigMethod · 0.80
HeaderMethod · 0.80
GetMethod · 0.65
RequestMethod · 0.65
nextFunction · 0.50
copyFunction · 0.50
ErrorMethod · 0.45
LenMethod · 0.45

Tested by

no test coverage detected