Changeset 0.33.0 (#207)

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit is contained in:
2026-03-19 21:37:32 +00:00
committed by xcaliber
parent b1266b0d7c
commit ed3e9363f2
42 changed files with 2527 additions and 129 deletions

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"log"
"log/slog"
"net/http"
"strings"
"time"
@@ -21,6 +22,7 @@ import (
"chat-switchboard/filters"
"chat-switchboard/health"
"chat-switchboard/knowledge"
"chat-switchboard/metrics"
"chat-switchboard/models"
"chat-switchboard/notifications"
"chat-switchboard/providers"
@@ -224,6 +226,16 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
userID := getUserID(c)
// v0.33.0: Correlation ID — same as request_id, propagated through
// completion chain for cross-referencing logs.
correlationID, _ := c.Get("request_id")
slog.Info("completion.start",
"request_id", correlationID,
"channel_id", channelID,
"user_id", userID,
"model", req.Model,
)
// v0.24.3: Session participants are pre-validated by AuthOrSession middleware
if isSessionAuth(c) {
if !sessionCanAccessChannel(c, channelID) {
@@ -1912,6 +1924,20 @@ func (h *CompletionHandler) logUsage(
if err := h.stores.Usage.Log(c.Request.Context(), entry); err != nil {
log.Printf("⚠ Failed to log usage: %v", err)
}
// v0.33.0: Prometheus token counters
metrics.CompletionTokensTotal.WithLabelValues("prompt", modelID).Add(float64(inputTokens))
metrics.CompletionTokensTotal.WithLabelValues("completion", modelID).Add(float64(outputTokens))
// v0.33.0: Structured usage log for observability correlation
correlationID, _ := c.Get("request_id")
slog.Info("completion.usage",
"request_id", correlationID,
"model_id", modelID,
"provider_config_id", configID,
"input_tokens", inputTokens,
"output_tokens", outputTokens,
)
}
// calcCost computes the cost for a given token count and price-per-million.
@@ -1923,23 +1949,36 @@ func calcCost(tokens int, pricePerM *float64) *float64 {
return &cost
}
// recordHealth records provider call outcome for health tracking (v0.22.0).
// recordHealth records provider call outcome for health tracking (v0.22.0)
// and Prometheus completion metrics (v0.33.0).
func (h *CompletionHandler) recordHealth(configID string, start time.Time, err error) {
duration := time.Since(start)
latencyMs := int(duration.Milliseconds())
// v0.33.0: Prometheus completion duration (always, even on error)
if configID != "" {
metrics.CompletionDuration.WithLabelValues(configID, "").Observe(duration.Seconds())
}
if h.health == nil || configID == "" {
return
}
latencyMs := int(time.Since(start).Milliseconds())
if err != nil {
errMsg := err.Error()
status := "error"
if strings.Contains(errMsg, "context deadline exceeded") || strings.Contains(errMsg, "timeout") {
h.health.RecordTimeout(configID, latencyMs, errMsg)
status = "timeout"
} else if strings.Contains(errMsg, "HTTP 429") || strings.Contains(errMsg, "rate limit") || strings.Contains(errMsg, "Too Many Requests") {
h.health.RecordRateLimit(configID, latencyMs, errMsg)
status = "rate_limited"
} else {
h.health.RecordError(configID, latencyMs, errMsg)
}
metrics.CompletionsTotal.WithLabelValues(configID, "", status).Inc()
} else {
h.health.RecordSuccess(configID, latencyMs)
metrics.CompletionsTotal.WithLabelValues(configID, "", "success").Inc()
}
}