add basic metrics (#966)

* add metrics

* change how counting works

* also replace dots

* check that metrics exist

* rename NullMetrics to nullMetrics

* update go.sum

* register collectors only once

* add tests

* add tests for metrics and fix bugs

* keep old metrics around for test

* properly reset during shutdown

* use the same method as frankenphp

* Revert "keep old metrics around for test"

This reverts commit 1f0df6f6bdaebf32aec346f068d6f42a0b5f4007.

* change to require.NoError

* compile regex only once

* remove name sanitizer

* use require

* parameterize host port because security software sucks

* remove need for renaming workers

* increase number of threads and add tests

* fix where frankenphp configuration was bleeding into later tests

* adds basic docs for metrics

* Add caddy metrics link

Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>

* Fix typos

Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>

* address feedback

* change comment to be much more "dangerous"

---------

Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>
This commit is contained in:
Rob Landers
2024-09-26 09:53:37 +02:00
committed by GitHub
parent 861fd8b2fa
commit 5d43fc2c8d
11 changed files with 723 additions and 52 deletions

82
metrics_test.go Normal file
View File

@@ -0,0 +1,82 @@
package frankenphp
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestGetWorkerNameForMetrics(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"worker-1", "worker_1"},
{"worker@name", "worker_name"},
{"worker name", "worker_name"},
{"worker/name", "worker_name"},
{"worker.name", "worker_name"},
{"////worker////name...//worker", "worker_name_worker"},
}
for _, test := range tests {
result := getWorkerNameForMetrics(test.input)
assert.Equal(t, test.expected, result)
}
}
func createPrometheusMetrics() *PrometheusMetrics {
return &PrometheusMetrics{
registry: prometheus.NewRegistry(),
totalThreads: prometheus.NewCounter(prometheus.CounterOpts{Name: "total_threads"}),
busyThreads: prometheus.NewGauge(prometheus.GaugeOpts{Name: "busy_threads"}),
totalWorkers: make(map[string]prometheus.Gauge),
busyWorkers: make(map[string]prometheus.Gauge),
workerRequestTime: make(map[string]prometheus.Counter),
workerRequestCount: make(map[string]prometheus.Counter),
mu: sync.Mutex{},
}
}
func TestPrometheusMetrics_TotalWorkers(t *testing.T) {
m := createPrometheusMetrics()
tests := []struct {
name string
worker string
num int
}{
{"SetWorkers", "test_worker", 5},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m.TotalWorkers(tt.worker, tt.num)
actualName, _ := m.getIdentity(tt.worker)
_, ok := m.totalWorkers[actualName]
require.True(t, ok)
})
}
}
func TestPrometheusMetrics_StopWorkerRequest(t *testing.T) {
m := createPrometheusMetrics()
m.StopWorkerRequest("test_worker", 2*time.Second)
name := "test_worker"
_, ok := m.workerRequestTime[name]
require.False(t, ok)
}
func TestPrometheusMetrics_StartWorkerRequest(t *testing.T) {
m := createPrometheusMetrics()
m.StartWorkerRequest("test_worker")
name := "test_worker"
_, ok := m.workerRequestCount[name]
require.False(t, ok)
}