21461: Fixes log line-breaking behavior for really long strings.
[arvados.git] / services / keepstore / stats_ticker.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package keepstore
6
7 import (
8         "sync"
9         "sync/atomic"
10
11         "github.com/prometheus/client_golang/prometheus"
12 )
13
14 type statsTicker struct {
15         Errors   uint64
16         InBytes  uint64
17         OutBytes uint64
18
19         ErrorCodes map[string]uint64 `json:",omitempty"`
20         lock       sync.Mutex
21
22         opsCounters *prometheus.CounterVec
23         errCounters *prometheus.CounterVec
24         ioBytes     *prometheus.CounterVec
25 }
26
27 // Tick increments each of the given counters by 1 using
28 // atomic.AddUint64.
29 func (s *statsTicker) Tick(counters ...*uint64) {
30         for _, counter := range counters {
31                 atomic.AddUint64(counter, 1)
32         }
33 }
34
35 // TickErr increments the overall error counter, as well as the
36 // ErrorCodes entry for the given errType. If err is nil, TickErr is a
37 // no-op.
38 func (s *statsTicker) TickErr(err error, errType string) {
39         if err == nil {
40                 return
41         }
42         s.Tick(&s.Errors)
43
44         s.lock.Lock()
45         if s.ErrorCodes == nil {
46                 s.ErrorCodes = make(map[string]uint64)
47         }
48         s.ErrorCodes[errType]++
49         s.lock.Unlock()
50         if s.errCounters != nil {
51                 s.errCounters.With(prometheus.Labels{"error_type": errType}).Inc()
52         }
53 }
54
55 // TickInBytes increments the incoming byte counter by n.
56 func (s *statsTicker) TickInBytes(n uint64) {
57         if s.ioBytes != nil {
58                 s.ioBytes.With(prometheus.Labels{"direction": "in"}).Add(float64(n))
59         }
60         atomic.AddUint64(&s.InBytes, n)
61 }
62
63 // TickOutBytes increments the outgoing byte counter by n.
64 func (s *statsTicker) TickOutBytes(n uint64) {
65         if s.ioBytes != nil {
66                 s.ioBytes.With(prometheus.Labels{"direction": "out"}).Add(float64(n))
67         }
68         atomic.AddUint64(&s.OutBytes, n)
69 }
70
71 // TickOps increments the counter of the listed operations by 1.
72 func (s *statsTicker) TickOps(operations ...string) {
73         if s.opsCounters == nil {
74                 return
75         }
76         for _, opType := range operations {
77                 s.opsCounters.With(prometheus.Labels{"operation": opType}).Inc()
78         }
79 }