From c03bd3e3a2e3a167ed4ffbcac2b268c545c96065 Mon Sep 17 00:00:00 2001 From: Andrej Mickov Date: Mon, 2 Mar 2026 23:26:57 +0100 Subject: [PATCH] Minimal fixes for metrics --- api/api.go | 3 +-- metrics/metrics.go | 2 +- metrics/metrics_test.go | 8 ++++++++ service/service.go | 15 +++++++++------ storage/blob.go | 4 +++- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/api/api.go b/api/api.go index 250bac2..69ccfa9 100644 --- a/api/api.go +++ b/api/api.go @@ -661,13 +661,12 @@ func (l *limitedListener) Accept() (net.Conn, error) { l.slots <- struct{}{} metrics.Default.DecRequestQueueLength() } - metrics.Default.IncConnectionPoolActive() conn, err := l.Listener.Accept() if err != nil { <-l.slots - metrics.Default.DecConnectionPoolActive() return nil, err } + metrics.Default.IncConnectionPoolActive() return &limitedConn{ Conn: conn, done: func() { diff --git a/metrics/metrics.go b/metrics/metrics.go index 8f11b39..45115df 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -762,7 +762,7 @@ func trimFloat(v float64) string { } func escapeLabelValue(value string) string { - value = strings.ReplaceAll(value, `\\`, `\\\\`) + value = strings.ReplaceAll(value, `\`, `\\`) value = strings.ReplaceAll(value, "\n", `\\n`) value = strings.ReplaceAll(value, `"`, `\\"`) return value diff --git a/metrics/metrics_test.go b/metrics/metrics_test.go index 2fffc4f..2f25c23 100644 --- a/metrics/metrics_test.go +++ b/metrics/metrics_test.go @@ -24,3 +24,11 @@ func TestRenderPrometheusHistogramNoEmptyLabelSet(t *testing.T) { t.Fatalf("unexpected empty label set for gc count metric") } } + +func TestEscapeLabelValueEscapesSingleBackslash(t *testing.T) { + got := escapeLabelValue(`a\b`) + want := `a\\b` + if got != want { + t.Fatalf("escapeLabelValue returned %q, want %q", got, want) + } +} diff --git a/service/service.go b/service/service.go index f06dd66..9d7db43 100644 --- a/service/service.go +++ b/service/service.go @@ -106,10 +106,6 @@ func (s *ObjectService) PutObject(bucket, key, contentType string, input io.Read func (s *ObjectService) GetObject(bucket, key string) (io.ReadCloser, *models.ObjectManifest, error) { start := time.Now() - success := false - defer func() { - metrics.Default.ObserveService("get_object", time.Since(start), success) - }() waitStart := time.Now() s.gcMu.RLock() @@ -120,20 +116,27 @@ func (s *ObjectService) GetObject(bucket, key string) (io.ReadCloser, *models.Ob if err != nil { metrics.Default.ObserveLockHold("gc_mu_read", time.Since(holdStart)) s.gcMu.RUnlock() + metrics.Default.ObserveService("get_object", time.Since(start), false) return nil, nil, err } pr, pw := io.Pipe() go func() { + streamOK := false + defer func() { + metrics.Default.ObserveService("get_object", time.Since(start), streamOK) + }() defer metrics.Default.ObserveLockHold("gc_mu_read", time.Since(holdStart)) defer s.gcMu.RUnlock() if err := s.blob.AssembleStream(manifest.Chunks, pw); err != nil { _ = pw.CloseWithError(err) return } - _ = pw.Close() + if err := pw.Close(); err != nil { + return + } + streamOK = true }() - success = true return pr, manifest, nil } diff --git a/storage/blob.go b/storage/blob.go index 41297df..667958f 100644 --- a/storage/blob.go +++ b/storage/blob.go @@ -88,8 +88,9 @@ func (bs *BlobStore) IngestStream(stream io.Reader) ([]string, int64, string, er func (bs *BlobStore) saveBlob(chunkID string, data []byte) error { start := time.Now() success := false + writtenBytes := int64(0) defer func() { - metrics.Default.ObserveBlob("write_chunk", time.Since(start), int64(len(data)), success) + metrics.Default.ObserveBlob("write_chunk", time.Since(start), writtenBytes, success) }() if !isValidChunkID(chunkID) { @@ -144,6 +145,7 @@ func (bs *BlobStore) saveBlob(chunkID string, data []byte) error { if err := syncDir(dir); err != nil { return err } + writtenBytes = int64(len(data)) success = true return nil }