featurebase/performancecounters.go
pokeeffe-molecula 7f6ea0e6e5
introduce performance counters and system table fanout, plus refactor metrics (#2363)
* performance counters

* first cut of perf counters and system table fanout and a wire protocol
* significantly refactored prometheus support; removed statsd and exprvar

* removed node_id

* put dax subquery test back

* Change Translator.TranslateFieldIDs method to take a dax.TableKeyer

There are a bunch of other calls to the Translator interface methods
with currently take an `index string`, and those need to be converted to
dax.TableKeyer as well. But I need to review each call, because in at
least one place I noticed one being called with `result.Index` instead
of with the qtbl available. And I don't yet know how those could be
different.

Co-authored-by: Travis Turner <travis@molecula.com>
2023-01-11 20:37:00 -06:00

203 lines
5.6 KiB
Go

package pilosa
import (
"sync/atomic"
"github.com/prometheus/client_golang/prometheus"
)
// PerformanceCounter holds data about a performance counter for external consumers
type PerformanceCounter struct {
NameSpace string
SubSystem string
CounterName string
Help string
Value int64
CounterType int64
}
// constants for the counter types
const (
// raw - for when you just want a count of something
CTR_TYPE_RAW = 0
// per second - for when you accumulate counts of things
// a consumer would sample this at intervals to arrive at a delta
// then divide by the time in seconds between the samples to get a
// per-second value
CTR_TYPE_PER_SECOND = 1
// ratio - for when you accumulate a count of something that you
// want to use as a numerator in a ratio calculation
// e.g. 'cache hits' could be a counter of this type and you could
// divide it by a 'cache lookups' counter to get the hit ratio (see below)
CTR_TYPE_RATIO = 2
// ratio base - for when you accumulate a count of something that you
// want to use as a denominator in a ratio calculation
// e.g. 'cache lookups' could be a counter of this type and you could
// use it as the denominator in a division with a 'cache hits' counter
// as the numerator to get the hit ratio
CTR_TYPE_RATIO_BASE = 3
)
type PerformanceCounters struct {
counterValues [5]perfCtrWrapper
}
type perfCtr struct {
nameSpace string
subSystem string
name string
help string
value int64
counterType int64
}
func (p *perfCtr) Add(increment int64) {
atomic.AddInt64(&p.value, increment)
}
type perfCtrWrapper struct {
ctr *perfCtr
fun prometheus.CounterFunc
}
var PerfCounterSQLRequestSec = perfCtr{
nameSpace: "pilosa",
subSystem: "sql_statistics",
name: "sql_requests_sec",
help: "TODO",
value: 0,
counterType: CTR_TYPE_PER_SECOND,
}
var PerfCounterSQLInsertsSec = perfCtr{
nameSpace: "pilosa",
subSystem: "sql_statistics",
name: "sql_inserts_sec",
help: "TODO",
value: 0,
counterType: CTR_TYPE_PER_SECOND,
}
var PerfCounterSQLBulkInsertsSec = perfCtr{
nameSpace: "pilosa",
subSystem: "sql_statistics",
name: "sql_bulk_inserts_sec",
help: "TODO",
value: 0,
counterType: CTR_TYPE_PER_SECOND,
}
var PerfCounterSQLBulkInsertBatchesSec = perfCtr{
nameSpace: "pilosa",
subSystem: "sql_statistics",
name: "sql_bulk_insert_batches_sec",
help: "TODO",
value: 0,
counterType: CTR_TYPE_PER_SECOND,
}
var PerfCounterSQLDeletesSec = perfCtr{
nameSpace: "pilosa",
subSystem: "sql_statistics",
name: "sql_deletes_sec",
help: "TODO",
value: 0,
counterType: CTR_TYPE_PER_SECOND,
}
var PerfCounters *PerformanceCounters = newPerformanceCounters()
func newPerformanceCounters() *PerformanceCounters {
ctrs := &PerformanceCounters{
counterValues: [5]perfCtrWrapper{
{
&PerfCounterSQLRequestSec,
prometheus.NewCounterFunc(
prometheus.CounterOpts{
Namespace: PerfCounterSQLRequestSec.nameSpace,
Subsystem: PerfCounterSQLRequestSec.subSystem,
Name: PerfCounterSQLRequestSec.name,
Help: PerfCounterSQLRequestSec.help,
},
func() float64 {
return float64(atomic.LoadInt64(&PerfCounterSQLRequestSec.value))
}),
},
{
&PerfCounterSQLInsertsSec,
prometheus.NewCounterFunc(
prometheus.CounterOpts{
Namespace: PerfCounterSQLInsertsSec.nameSpace,
Subsystem: PerfCounterSQLInsertsSec.subSystem,
Name: PerfCounterSQLInsertsSec.name,
Help: PerfCounterSQLInsertsSec.help,
},
func() float64 {
return float64(atomic.LoadInt64(&PerfCounterSQLInsertsSec.value))
}),
},
{
&PerfCounterSQLBulkInsertsSec,
prometheus.NewCounterFunc(
prometheus.CounterOpts{
Namespace: PerfCounterSQLBulkInsertsSec.nameSpace,
Subsystem: PerfCounterSQLBulkInsertsSec.subSystem,
Name: PerfCounterSQLBulkInsertsSec.name,
Help: PerfCounterSQLBulkInsertsSec.help,
},
func() float64 {
return float64(atomic.LoadInt64(&PerfCounterSQLBulkInsertsSec.value))
}),
},
{
&PerfCounterSQLBulkInsertBatchesSec,
prometheus.NewCounterFunc(
prometheus.CounterOpts{
Namespace: PerfCounterSQLBulkInsertBatchesSec.nameSpace,
Subsystem: PerfCounterSQLBulkInsertBatchesSec.subSystem,
Name: PerfCounterSQLBulkInsertBatchesSec.name,
Help: PerfCounterSQLBulkInsertBatchesSec.help,
},
func() float64 {
return float64(atomic.LoadInt64(&PerfCounterSQLBulkInsertBatchesSec.value))
}),
},
{
&PerfCounterSQLDeletesSec,
prometheus.NewCounterFunc(
prometheus.CounterOpts{
Namespace: PerfCounterSQLDeletesSec.nameSpace,
Subsystem: PerfCounterSQLDeletesSec.subSystem,
Name: PerfCounterSQLDeletesSec.name,
Help: PerfCounterSQLDeletesSec.help,
},
func() float64 {
return float64(atomic.LoadInt64(&PerfCounterSQLDeletesSec.value))
}),
},
},
}
for _, w := range ctrs.counterValues {
prometheus.MustRegister(w.fun)
}
return ctrs
}
// list all the counters
// we can just read here without locking because if the counters get changed
// midway thru the loop, absent evidence to the contrary, the world will not end
func (p *PerformanceCounters) ListCounters() ([]PerformanceCounter, error) {
result := make([]PerformanceCounter, len(p.counterValues))
for i, c := range p.counterValues {
result[i] = PerformanceCounter{
NameSpace: c.ctr.nameSpace,
SubSystem: c.ctr.subSystem,
CounterName: c.ctr.name,
Value: c.ctr.value,
CounterType: c.ctr.counterType,
}
}
return result, nil
}