github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/chunk/client/metrics.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/prometheus/client_golang/prometheus"
     7  	"github.com/prometheus/client_golang/prometheus/promauto"
     8  
     9  	"github.com/grafana/loki/pkg/storage/chunk"
    10  )
    11  
    12  // takes a chunk client and exposes metrics for its operations.
    13  type MetricsChunkClient struct {
    14  	Client Client
    15  
    16  	metrics ChunkClientMetrics
    17  }
    18  
    19  func NewMetricsChunkClient(client Client, metrics ChunkClientMetrics) MetricsChunkClient {
    20  	return MetricsChunkClient{
    21  		Client:  client,
    22  		metrics: metrics,
    23  	}
    24  }
    25  
    26  type ChunkClientMetrics struct {
    27  	chunksPutPerUser         *prometheus.CounterVec
    28  	chunksSizePutPerUser     *prometheus.CounterVec
    29  	chunksFetchedPerUser     *prometheus.CounterVec
    30  	chunksSizeFetchedPerUser *prometheus.CounterVec
    31  }
    32  
    33  func NewChunkClientMetrics(reg prometheus.Registerer) ChunkClientMetrics {
    34  	return ChunkClientMetrics{
    35  		chunksPutPerUser: promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
    36  			Namespace: "loki",
    37  			Name:      "chunk_store_stored_chunks_total",
    38  			Help:      "Total stored chunks per user.",
    39  		}, []string{"user"}),
    40  		chunksSizePutPerUser: promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
    41  			Namespace: "loki",
    42  			Name:      "chunk_store_stored_chunk_bytes_total",
    43  			Help:      "Total bytes stored in chunks per user.",
    44  		}, []string{"user"}),
    45  		chunksFetchedPerUser: promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
    46  			Namespace: "loki",
    47  			Name:      "chunk_store_fetched_chunks_total",
    48  			Help:      "Total fetched chunks per user.",
    49  		}, []string{"user"}),
    50  		chunksSizeFetchedPerUser: promauto.With(reg).NewCounterVec(prometheus.CounterOpts{
    51  			Namespace: "loki",
    52  			Name:      "chunk_store_fetched_chunk_bytes_total",
    53  			Help:      "Total bytes fetched in chunks per user.",
    54  		}, []string{"user"}),
    55  	}
    56  }
    57  
    58  func (c MetricsChunkClient) Stop() {
    59  	c.Client.Stop()
    60  }
    61  
    62  func (c MetricsChunkClient) PutChunks(ctx context.Context, chunks []chunk.Chunk) error {
    63  	if err := c.Client.PutChunks(ctx, chunks); err != nil {
    64  		return err
    65  	}
    66  
    67  	// For PutChunks, we explicitly encode the userID in the chunk and don't use context.
    68  	userSizes := map[string]int{}
    69  	userCounts := map[string]int{}
    70  	for _, c := range chunks {
    71  		userSizes[c.UserID] += c.Data.Size()
    72  		userCounts[c.UserID]++
    73  	}
    74  	for user, size := range userSizes {
    75  		c.metrics.chunksSizePutPerUser.WithLabelValues(user).Add(float64(size))
    76  	}
    77  	for user, num := range userCounts {
    78  		c.metrics.chunksPutPerUser.WithLabelValues(user).Add(float64(num))
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  func (c MetricsChunkClient) GetChunks(ctx context.Context, chunks []chunk.Chunk) ([]chunk.Chunk, error) {
    85  	chks, err := c.Client.GetChunks(ctx, chunks)
    86  	if err != nil {
    87  		return chks, err
    88  	}
    89  
    90  	// For GetChunks, userID is the chunk and we don't need to use context.
    91  	// For now, we just load one user chunks at once, but the interface lets us do it for multiple users.
    92  	userSizes := map[string]int{}
    93  	userCounts := map[string]int{}
    94  	for _, c := range chks {
    95  		userSizes[c.UserID] += c.Data.Size()
    96  		userCounts[c.UserID]++
    97  	}
    98  	for user, size := range userSizes {
    99  		c.metrics.chunksSizeFetchedPerUser.WithLabelValues(user).Add(float64(size))
   100  	}
   101  	for user, num := range userCounts {
   102  		c.metrics.chunksFetchedPerUser.WithLabelValues(user).Add(float64(num))
   103  	}
   104  
   105  	return chks, nil
   106  }
   107  
   108  func (c MetricsChunkClient) DeleteChunk(ctx context.Context, userID, chunkID string) error {
   109  	return c.Client.DeleteChunk(ctx, userID, chunkID)
   110  }
   111  
   112  func (c MetricsChunkClient) IsChunkNotFoundErr(err error) bool {
   113  	return c.Client.IsChunkNotFoundErr(err)
   114  }