Skip to content

Commit

Permalink
Merge pull request #6 from meshcloud/master
Browse files Browse the repository at this point in the history
Adding ravendb_database_tasks metric
  • Loading branch information
marcinbudny authored Jan 7, 2024
2 parents 405d202 + 0700516 commit e281174
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 28 deletions.
174 changes: 146 additions & 28 deletions collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ const (
subsystem = ""
)

type metricInfo struct {
Value float64
Labels prometheus.Labels
}

type exporter struct {
up prometheus.Gauge
workingSet prometheus.Gauge
Expand All @@ -29,6 +34,7 @@ type exporter struct {
databaseIndexes *prometheus.GaugeVec
databaseStaleIndexes *prometheus.GaugeVec
databaseSize *prometheus.GaugeVec
databaseTasks *prometheus.GaugeVec

databaseRequestTotal *prometheus.CounterVec
databaseDocumentPutTotal *prometheus.CounterVec
Expand All @@ -55,6 +61,7 @@ func newExporter() *exporter {
databaseIndexes: createDatabaseGaugeVec("database_indexes", "Count of indexes in a database"),
databaseStaleIndexes: createDatabaseGaugeVec("database_stale_indexes", "Count of stale indexes in a database"),
databaseSize: createDatabaseGaugeVec("database_size_bytes", "Database size in bytes"),
databaseTasks: createDatabaseGaugeVec("database_tasks", "Tasks in a database", "type", "connection_status"),

databaseRequestTotal: createDatabaseCounterVec("database_request_total", "Database request count"),
databaseDocumentPutTotal: createDatabaseCounterVec("database_document_put_total", "Database document puts count"),
Expand All @@ -81,6 +88,7 @@ func (e *exporter) Describe(ch chan<- *prometheus.Desc) {
e.databaseIndexes.Describe(ch)
e.databaseStaleIndexes.Describe(ch)
e.databaseSize.Describe(ch)
e.databaseTasks.Describe(ch)

e.databaseRequestTotal.Describe(ch)
e.databaseDocumentPutTotal.Describe(ch)
Expand Down Expand Up @@ -132,6 +140,7 @@ func (e *exporter) Collect(ch chan<- prometheus.Metric) {
collectPerDatabaseGauge(stats, e.databaseIndexes, getDatabaseIndexes, ch)
collectPerDatabaseGauge(stats, e.databaseStaleIndexes, getDatabaseStaleIndexes, ch)
collectPerDatabaseGauge(stats, e.databaseSize, getDatabaseSize, ch)
collectPerDatabaseGauge(stats, e.databaseTasks, getDatabaseTasks, ch)

collectPerDatabaseCounter(stats, e.databaseRequestTotal, getDatabaseRequestTotal, ch)
collectPerDatabaseCounter(stats, e.databaseDocumentPutBytes, getDatabaseDocumentPutBytes, ch)
Expand All @@ -144,16 +153,24 @@ func (e *exporter) Collect(ch chan<- prometheus.Metric) {
}
}

func collectPerDatabaseGauge(stats *stats, vec *prometheus.GaugeVec, collectFunc func(*dbStats) float64, ch chan<- prometheus.Metric) {
func collectPerDatabaseGauge(stats *stats, vec *prometheus.GaugeVec, collectFunc func(*dbStats) []metricInfo, ch chan<- prometheus.Metric) {
for _, dbs := range stats.dbStats {
vec.WithLabelValues(dbs.database).Set(collectFunc(dbs))
metricInfos := collectFunc(dbs)

for _, metricInfo := range metricInfos {
vec.With(metricInfo.Labels).Set(metricInfo.Value)
}
}
vec.Collect(ch)
}

func collectPerDatabaseCounter(stats *stats, vec *prometheus.CounterVec, collectFunc func(*dbStats) float64, ch chan<- prometheus.Metric) {
func collectPerDatabaseCounter(stats *stats, vec *prometheus.CounterVec, collectFunc func(*dbStats) []metricInfo, ch chan<- prometheus.Metric) {
for _, dbs := range stats.dbStats {
vec.WithLabelValues(dbs.database).Set(collectFunc(dbs))
metricInfos := collectFunc(dbs)

for _, metricInfo := range metricInfos {
vec.With(metricInfo.Labels).Set(metricInfo.Value)
}
}
vec.Collect(ch)
}
Expand Down Expand Up @@ -210,60 +227,142 @@ func getMapReduceIndexReducedTotal(stats *stats) float64 {
return value
}

func getDatabaseDocuments(dbStats *dbStats) float64 {
func getDatabaseDocuments(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.databaseStats, "CountOfDocuments")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseIndexes(dbStats *dbStats) float64 {
func getDatabaseIndexes(dbStats *dbStats) []metricInfo {
var mi []metricInfo
value, _ := jp.GetFloat(dbStats.databaseStats, "CountOfIndexes")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseStaleIndexes(dbStats *dbStats) float64 {
func getDatabaseTasks(dbStats *dbStats) []metricInfo {
var mi []metricInfo

// Required for compatibility with versions 5 and 6
onGoingTasksKey := "OngoingTasks"
_, _, _, err := jp.Get(dbStats.tasks, onGoingTasksKey)
if err != nil {
onGoingTasksKey = "OngoingTasksList"
}

type key struct {
taskType, connectionStatus string
}

taskAggregate := make(map[key]float64)

jp.ArrayEach(dbStats.tasks, func(value []byte, dataType jp.ValueType, offset int, err error) {
taskType, _ := jp.GetString(value, "TaskType")
connectionStatus, _ := jp.GetString(value, "TaskConnectionStatus")
taskAggregate[key{taskType, connectionStatus}] += 1
}, onGoingTasksKey)

for k, v := range taskAggregate {
labels := generateDatabaseLabels(dbStats, map[string]string{
"type": k.taskType,
"connection_status": k.connectionStatus,
})

mi = appendMetricInfo(mi, v, labels)
}

return mi
}

func getDatabaseStaleIndexes(dbStats *dbStats) []metricInfo {
var mi []metricInfo

labels := generateDatabaseLabels(dbStats, nil)
count := 0
jp.ArrayEach(dbStats.databaseStats, func(value []byte, dataType jp.ValueType, offset int, err error) {
if isStale, _ := jp.GetBoolean(value, "IsStale"); isStale {
count++
}
}, "Indexes")

return float64(count)
mi = appendMetricInfo(mi, float64(count), labels)
return mi
}

func getDatabaseSize(dbStats *dbStats) float64 {
func getDatabaseSize(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.databaseStats, "SizeOnDisk", "SizeInBytes")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseRequestTotal(dbStats *dbStats) float64 {
func getDatabaseRequestTotal(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.metrics, "Requests", "RequestsPerSec", "Count")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseDocumentPutTotal(dbStats *dbStats) float64 {
func getDatabaseDocumentPutTotal(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.metrics, "Docs", "PutsPerSec", "Count")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseDocumentPutBytes(dbStats *dbStats) float64 {
func getDatabaseDocumentPutBytes(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.metrics, "Docs", "BytesPutsPerSec", "Count")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseMapIndexIndexedTotal(dbStats *dbStats) float64 {
func getDatabaseMapIndexIndexedTotal(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.metrics, "MapIndexes", "IndexedPerSec", "Count")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseMapReduceIndexMappedTotal(dbStats *dbStats) float64 {
func getDatabaseMapReduceIndexMappedTotal(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.metrics, "MapIndexes", "MappedPerSec", "Count")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func getDatabaseMapReduceIndexReducedTotal(dbStats *dbStats) float64 {
func getDatabaseMapReduceIndexReducedTotal(dbStats *dbStats) []metricInfo {
var mi []metricInfo

value, _ := jp.GetFloat(dbStats.metrics, "MapIndexes", "ReducedPerSec", "Count")
return value
labels := generateDatabaseLabels(dbStats, nil)
mi = appendMetricInfo(mi, value, labels)

return mi
}

func createGauge(name string, help string) prometheus.Gauge {
Expand All @@ -275,13 +374,13 @@ func createGauge(name string, help string) prometheus.Gauge {
})
}

func createDatabaseGaugeVec(name string, help string) *prometheus.GaugeVec {
func createDatabaseGaugeVec(name string, help string, labels ...string) *prometheus.GaugeVec {
return prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: name,
Help: help,
}, []string{"database"})
}, append([]string{"database"}, labels...))
}

func createCounter(name string, help string) prometheus.Counter {
Expand All @@ -293,13 +392,13 @@ func createCounter(name string, help string) prometheus.Counter {
})
}

func createDatabaseCounterVec(name string, help string) *prometheus.CounterVec {
func createDatabaseCounterVec(name string, help string, labels ...string) *prometheus.CounterVec {
return prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: name,
Help: help,
}, []string{"database"})
}, append([]string{"database"}, labels...))
}

var timespanRegex = regexp.MustCompile(`((?P<days>\d+)\.)?(?P<hours>\d{2}):(?P<minutes>\d{2}):(?P<seconds>\d{2})(\.(?P<secondfraction>\d{7}))?`)
Expand Down Expand Up @@ -344,3 +443,22 @@ func matchNamedGroups(regex *regexp.Regexp, text string) map[string]string {
}
return results
}

func generateDatabaseLabels(dbStats *dbStats, additionalLabels map[string]string) prometheus.Labels {
labels := prometheus.Labels{
"database": dbStats.database,
}

for key, value := range additionalLabels {
labels[key] = value
}

return labels
}

func appendMetricInfo(tasks []metricInfo, value float64, labels prometheus.Labels) []metricInfo {
return append(tasks, metricInfo{
Value: value,
Labels: labels,
})
}
3 changes: 3 additions & 0 deletions ravendb_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type dbStats struct {
indexes []byte
databaseStats []byte
storage []byte
tasks []byte
}

func initializeClient() {
Expand Down Expand Up @@ -84,6 +85,7 @@ func preparePaths(databases []string) []string {
paths = append(paths, fmt.Sprintf("/databases/%s/metrics", database))
paths = append(paths, fmt.Sprintf("/databases/%s/stats", database))
paths = append(paths, fmt.Sprintf("/databases/%s/debug/storage/report", database))
paths = append(paths, fmt.Sprintf("/databases/%s/tasks", database))
}

return paths
Expand Down Expand Up @@ -184,6 +186,7 @@ func organizeGetResults(results map[string]getResult, databases []string) (*stat
metrics: results[fmt.Sprintf("/databases/%s/metrics", database)].result,
databaseStats: results[fmt.Sprintf("/databases/%s/stats", database)].result,
storage: results[fmt.Sprintf("/databases/%s//debug/storage/report", database)].result,
tasks: results[fmt.Sprintf("/databases/%s/tasks", database)].result,
}

stats.dbStats = append(stats.dbStats, dbs)
Expand Down
10 changes: 10 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ ravendb_database_size_bytes{database="Demo"} 6.35568128e+08
# HELP ravendb_database_stale_indexes Count of stale indexes in a database
# TYPE ravendb_database_stale_indexes gauge
ravendb_database_stale_indexes{database="Demo"} 0
# HELP ravendb_database_tasks Tasks in a database
# TYPE ravendb_database_tasks gauge
ravendb_database_tasks{connection_status="Active",database="Demo",type="Backup"} 2
ravendb_database_tasks{connection_status="NotActive",database="Demo",type="Backup"} 1
ravendb_database_tasks{connection_status="NotActive",database="Demo",type="Subscription"} 2
# HELP ravendb_document_put_bytes_total Server-wide document put bytes
# TYPE ravendb_document_put_bytes_total counter
ravendb_document_put_bytes_total 0
Expand Down Expand Up @@ -117,7 +122,12 @@ ravendb_working_set_bytes 1.651195904e+09

## Changelog

### 0.5.0

* Added database gauge metric: `ravendb_database_tasks`

### 0.4.0

* Updated golang version, some of the dependencies
* Used `scratch` as base for the docker image

Expand Down

0 comments on commit e281174

Please sign in to comment.