[#9999] blobstor: Add IO tag label to metrics

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2025-02-18 11:23:10 +03:00
parent 6f4566a3ae
commit b510d3b13f
Signed by: dstepanov-yadro
GPG key ID: 237AF1A763293BC0
12 changed files with 65 additions and 42 deletions

View file

@ -12,7 +12,7 @@ type BlobstoreMetrics interface {
SetMode(shardID string, readOnly bool) SetMode(shardID string, readOnly bool)
Close(shardID string) Close(shardID string)
MethodDuration(shardID string, method string, d time.Duration, success bool, withStorageID NullBool) MethodDuration(shardID string, method string, d time.Duration, success bool, withStorageID NullBool, ioTag string)
AddPut(shardID string, size int) AddPut(shardID string, size int)
AddGet(shardID string, size int) AddGet(shardID string, size int)
} }
@ -32,7 +32,7 @@ func newBlobstoreMetrics() *blobstoreMetrics {
Subsystem: blobstoreSubSystem, Subsystem: blobstoreSubSystem,
Name: "request_duration_seconds", Name: "request_duration_seconds",
Help: "Accumulated Blobstore request process duration", Help: "Accumulated Blobstore request process duration",
}, []string{shardIDLabel, successLabel, methodLabel, withStorageIDLabel}), }, []string{shardIDLabel, successLabel, methodLabel, withStorageIDLabel, ioTagLabel}),
put: metrics.NewCounterVec(prometheus.CounterOpts{ put: metrics.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: blobstoreSubSystem, Subsystem: blobstoreSubSystem,
@ -65,12 +65,13 @@ func (m *blobstoreMetrics) Close(shardID string) {
}) })
} }
func (m *blobstoreMetrics) MethodDuration(shardID string, method string, d time.Duration, success bool, withStorageID NullBool) { func (m *blobstoreMetrics) MethodDuration(shardID string, method string, d time.Duration, success bool, withStorageID NullBool, ioTag string) {
m.reqDuration.With(prometheus.Labels{ m.reqDuration.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
successLabel: strconv.FormatBool(success), successLabel: strconv.FormatBool(success),
methodLabel: method, methodLabel: method,
withStorageIDLabel: withStorageID.String(), withStorageIDLabel: withStorageID.String(),
ioTagLabel: ioTag,
}).Observe(d.Seconds()) }).Observe(d.Seconds())
} }

View file

@ -43,6 +43,7 @@ const (
hitLabel = "hit" hitLabel = "hit"
cacheLabel = "cache" cacheLabel = "cache"
sourceIPLabel = "source_ip" sourceIPLabel = "source_ip"
ioTagLabel = "io_tag"
readWriteMode = "READ_WRITE" readWriteMode = "READ_WRITE"
readOnlyMode = "READ_ONLY" readOnlyMode = "READ_ONLY"

View file

@ -1,6 +1,11 @@
package qos package qos
import "fmt" import (
"context"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-qos/tagging"
)
type IOTag string type IOTag string
@ -37,3 +42,12 @@ func FromRawString(s string) (IOTag, error) {
func (t IOTag) String() string { func (t IOTag) String() string {
return string(t) return string(t)
} }
var undefinedIOTag = "undefined"
func IOTagStringFromContext(ctx context.Context) string {
if v, ok := tagging.IOTagFromContext(ctx); ok {
return v
}
return undefinedIOTag
}

View file

@ -5,6 +5,7 @@ import (
"encoding/hex" "encoding/hex"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
@ -20,7 +21,7 @@ func (b *BlobStor) Delete(ctx context.Context, prm common.DeletePrm) (common.Del
success = false success = false
) )
defer func() { defer func() {
b.metrics.Delete(time.Since(startedAt), success, prm.StorageID != nil) b.metrics.Delete(time.Since(startedAt), success, prm.StorageID != nil, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Delete", ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Delete",

View file

@ -6,6 +6,7 @@ import (
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
@ -23,7 +24,7 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi
startedAt = time.Now() startedAt = time.Now()
) )
defer func() { defer func() {
b.metrics.Exists(time.Since(startedAt), exists, prm.StorageID != nil) b.metrics.Exists(time.Since(startedAt), exists, prm.StorageID != nil, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Exists", ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Exists",

View file

@ -5,6 +5,7 @@ import (
"encoding/hex" "encoding/hex"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
@ -20,7 +21,7 @@ import (
func (b *BlobStor) Get(ctx context.Context, prm common.GetPrm) (res common.GetRes, err error) { func (b *BlobStor) Get(ctx context.Context, prm common.GetPrm) (res common.GetRes, err error) {
startedAt := time.Now() startedAt := time.Now()
defer func() { defer func() {
b.metrics.Get(time.Since(startedAt), len(res.RawData), err == nil, prm.StorageID != nil) b.metrics.Get(time.Since(startedAt), len(res.RawData), err == nil, prm.StorageID != nil, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Get", ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Get",

View file

@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
@ -21,7 +22,7 @@ import (
func (b *BlobStor) GetRange(ctx context.Context, prm common.GetRangePrm) (res common.GetRangeRes, err error) { func (b *BlobStor) GetRange(ctx context.Context, prm common.GetRangePrm) (res common.GetRangeRes, err error) {
startedAt := time.Now() startedAt := time.Now()
defer func() { defer func() {
b.metrics.GetRange(time.Since(startedAt), len(res.Data), err == nil, prm.StorageID != nil) b.metrics.GetRange(time.Since(startedAt), len(res.Data), err == nil, prm.StorageID != nil, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.GetRange", ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.GetRange",

View file

@ -5,6 +5,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@ -30,7 +31,7 @@ func (b *BlobStor) ObjectsCount(ctx context.Context) (uint64, error) {
var err error var err error
startedAt := time.Now() startedAt := time.Now()
defer func() { defer func() {
b.metrics.ObjectsCount(time.Since(startedAt), err == nil) b.metrics.ObjectsCount(time.Since(startedAt), err == nil, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.ObjectsCount") ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.ObjectsCount")

View file

@ -6,6 +6,7 @@ import (
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
@ -27,7 +28,7 @@ func (b *BlobStor) Iterate(ctx context.Context, prm common.IteratePrm) (common.I
success = false success = false
) )
defer func() { defer func() {
b.metrics.Iterate(time.Since(startedAt), success) b.metrics.Iterate(time.Since(startedAt), success, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Iterate", ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Iterate",
trace.WithAttributes( trace.WithAttributes(

View file

@ -7,13 +7,13 @@ type Metrics interface {
SetMode(readOnly bool) SetMode(readOnly bool)
Close() Close()
Delete(d time.Duration, success, withStorageID bool) Delete(d time.Duration, success, withStorageID bool, ioTag string)
Exists(d time.Duration, success, withStorageID bool) Exists(d time.Duration, success, withStorageID bool, ioTag string)
GetRange(d time.Duration, size int, success, withStorageID bool) GetRange(d time.Duration, size int, success, withStorageID bool, ioTag string)
Get(d time.Duration, size int, success, withStorageID bool) Get(d time.Duration, size int, success, withStorageID bool, ioTag string)
Iterate(d time.Duration, success bool) Iterate(d time.Duration, success bool, ioTag string)
Put(d time.Duration, size int, success bool) Put(d time.Duration, size int, success bool, ioTag string)
ObjectsCount(d time.Duration, success bool) ObjectsCount(d time.Duration, success bool, ioTag string)
} }
type noopMetrics struct{} type noopMetrics struct{}
@ -21,10 +21,10 @@ type noopMetrics struct{}
func (m *noopMetrics) SetParentID(string) {} func (m *noopMetrics) SetParentID(string) {}
func (m *noopMetrics) SetMode(bool) {} func (m *noopMetrics) SetMode(bool) {}
func (m *noopMetrics) Close() {} func (m *noopMetrics) Close() {}
func (m *noopMetrics) Delete(time.Duration, bool, bool) {} func (m *noopMetrics) Delete(time.Duration, bool, bool, string) {}
func (m *noopMetrics) Exists(time.Duration, bool, bool) {} func (m *noopMetrics) Exists(time.Duration, bool, bool, string) {}
func (m *noopMetrics) GetRange(time.Duration, int, bool, bool) {} func (m *noopMetrics) GetRange(time.Duration, int, bool, bool, string) {}
func (m *noopMetrics) Get(time.Duration, int, bool, bool) {} func (m *noopMetrics) Get(time.Duration, int, bool, bool, string) {}
func (m *noopMetrics) Iterate(time.Duration, bool) {} func (m *noopMetrics) Iterate(time.Duration, bool, string) {}
func (m *noopMetrics) Put(time.Duration, int, bool) {} func (m *noopMetrics) Put(time.Duration, int, bool, string) {}
func (m *noopMetrics) ObjectsCount(time.Duration, bool) {} func (m *noopMetrics) ObjectsCount(time.Duration, bool, string) {}

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
@ -32,7 +33,7 @@ func (b *BlobStor) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, e
size = 0 size = 0
) )
defer func() { defer func() {
b.metrics.Put(time.Since(startedAt), size, success) b.metrics.Put(time.Since(startedAt), size, success, qos.IOTagStringFromContext(ctx))
}() }()
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Put", ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Put",

View file

@ -31,39 +31,39 @@ func (m *blobstoreMetrics) Close() {
m.m.Close(m.shardID) m.m.Close(m.shardID)
} }
func (m *blobstoreMetrics) Delete(d time.Duration, success, withStorageID bool) { func (m *blobstoreMetrics) Delete(d time.Duration, success, withStorageID bool, ioTag string) {
m.m.MethodDuration(m.shardID, "Delete", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}) m.m.MethodDuration(m.shardID, "Delete", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}, ioTag)
} }
func (m *blobstoreMetrics) Exists(d time.Duration, success, withStorageID bool) { func (m *blobstoreMetrics) Exists(d time.Duration, success, withStorageID bool, ioTag string) {
m.m.MethodDuration(m.shardID, "Exists", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}) m.m.MethodDuration(m.shardID, "Exists", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}, ioTag)
} }
func (m *blobstoreMetrics) GetRange(d time.Duration, size int, success, withStorageID bool) { func (m *blobstoreMetrics) GetRange(d time.Duration, size int, success, withStorageID bool, ioTag string) {
m.m.MethodDuration(m.shardID, "GetRange", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}) m.m.MethodDuration(m.shardID, "GetRange", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}, ioTag)
if success { if success {
m.m.AddGet(m.shardID, size) m.m.AddGet(m.shardID, size)
} }
} }
func (m *blobstoreMetrics) Get(d time.Duration, size int, success, withStorageID bool) { func (m *blobstoreMetrics) Get(d time.Duration, size int, success, withStorageID bool, ioTag string) {
m.m.MethodDuration(m.shardID, "Get", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}) m.m.MethodDuration(m.shardID, "Get", d, success, metrics_impl.NullBool{Bool: withStorageID, Valid: true}, ioTag)
if success { if success {
m.m.AddGet(m.shardID, size) m.m.AddGet(m.shardID, size)
} }
} }
func (m *blobstoreMetrics) Iterate(d time.Duration, success bool) { func (m *blobstoreMetrics) Iterate(d time.Duration, success bool, ioTag string) {
m.m.MethodDuration(m.shardID, "Iterate", d, success, metrics_impl.NullBool{}) m.m.MethodDuration(m.shardID, "Iterate", d, success, metrics_impl.NullBool{}, ioTag)
} }
func (m *blobstoreMetrics) Put(d time.Duration, size int, success bool) { func (m *blobstoreMetrics) Put(d time.Duration, size int, success bool, ioTag string) {
m.m.MethodDuration(m.shardID, "Put", d, success, metrics_impl.NullBool{}) m.m.MethodDuration(m.shardID, "Put", d, success, metrics_impl.NullBool{}, ioTag)
if success { if success {
m.m.AddPut(m.shardID, size) m.m.AddPut(m.shardID, size)
} }
} }
func (m *blobstoreMetrics) ObjectsCount(d time.Duration, success bool) { func (m *blobstoreMetrics) ObjectsCount(d time.Duration, success bool, ioTag string) {
m.m.MethodDuration(m.shardID, "ObjectsCount", d, success, metrics_impl.NullBool{}) m.m.MethodDuration(m.shardID, "ObjectsCount", d, success, metrics_impl.NullBool{}, ioTag)
} }