From 03ae510c686a7770cdf75fc7e4803da51a7f3bce Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 26 May 2026 17:21:56 +0800 Subject: [PATCH] fix(ops): exclude count-tokens from metrics errors Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- .../internal/service/ops_metrics_collector.go | 3 +- .../service/ops_metrics_collector_test.go | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 backend/internal/service/ops_metrics_collector_test.go diff --git a/backend/internal/service/ops_metrics_collector.go b/backend/internal/service/ops_metrics_collector.go index 6c337071..b654190c 100644 --- a/backend/internal/service/ops_metrics_collector.go +++ b/backend/internal/service/ops_metrics_collector.go @@ -538,7 +538,8 @@ SELECT COALESCE(COUNT(*) FILTER (WHERE error_owner = 'provider' AND NOT is_business_limited AND COALESCE(upstream_status_code, status_code, 0) = 429), 0) AS upstream_429, COALESCE(COUNT(*) FILTER (WHERE error_owner = 'provider' AND NOT is_business_limited AND COALESCE(upstream_status_code, status_code, 0) = 529), 0) AS upstream_529 FROM ops_error_logs -WHERE created_at >= $1 AND created_at < $2` +WHERE created_at >= $1 AND created_at < $2 + AND is_count_tokens = FALSE` if err := c.db.QueryRowContext(ctx, q, start, end).Scan( &errorTotal, diff --git a/backend/internal/service/ops_metrics_collector_test.go b/backend/internal/service/ops_metrics_collector_test.go new file mode 100644 index 00000000..5b069c1b --- /dev/null +++ b/backend/internal/service/ops_metrics_collector_test.go @@ -0,0 +1,60 @@ +package service + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/require" +) + +func TestWriteOpenAIFastPolicyBlockedResponseMarksBusinessLimited(t *testing.T) { + gin.SetMode(gin.TestMode) + rec := httptest.NewRecorder() + c, _ := gin.CreateTestContext(rec) + + writeOpenAIFastPolicyBlockedResponse(c, &OpenAIFastBlockedError{Message: "custom fast policy block"}) + + require.Equal(t, http.StatusForbidden, rec.Code) + require.True(t, HasOpsClientBusinessLimited(c)) + reason, ok := c.Get(OpsClientBusinessLimitedReasonKey) + require.True(t, ok) + require.Equal(t, OpsClientBusinessLimitedReasonLocalPolicyDenied, reason) +} + +func TestOpsMetricsCollectorQueryErrorCountsExcludesCountTokens(t *testing.T) { + db, mock, err := sqlmock.New() + require.NoError(t, err) + + collector := &OpsMetricsCollector{db: db} + start := time.Date(2026, 5, 26, 10, 0, 0, 0, time.UTC) + end := start.Add(time.Hour) + + mock.ExpectQuery(`(?s)FROM ops_error_logs\s+WHERE created_at >= \$1 AND created_at < \$2\s+AND is_count_tokens = FALSE`). + WithArgs(start, end). + WillReturnRows(sqlmock.NewRows([]string{ + "error_total", + "business_limited", + "error_sla", + "upstream_excl", + "upstream_429", + "upstream_529", + }).AddRow(int64(5), int64(2), int64(3), int64(1), int64(1), int64(1))) + + errorTotal, businessLimited, errorSLA, upstreamExcl429529, upstream429, upstream529, err := collector.queryErrorCounts(context.Background(), start, end) + require.NoError(t, err) + require.Equal(t, int64(5), errorTotal) + require.Equal(t, int64(2), businessLimited) + require.Equal(t, int64(3), errorSLA) + require.Equal(t, int64(1), upstreamExcl429529) + require.Equal(t, int64(1), upstream429) + require.Equal(t, int64(1), upstream529) + require.NoError(t, mock.ExpectationsWereMet()) + mock.ExpectClose() + require.NoError(t, db.Close()) + require.NoError(t, mock.ExpectationsWereMet()) +}