fix(metrics): add doc comments, fix labels mutation and nil returns, add idempotent Close, add nil guards, add tests
- Fix promMetrics.Gauge/Counter/Observer mutating caller's labels map by using maps.Copy instead of direct assignment - Fix Gauge/Counter/Observer returning nil for unknown metric names (now return noop implementations) - Fix metricService.Close() race with sync.Once for safe concurrent calls - Fix SetDSCP returning nil instead of errUnsupport on unsupported ops - Add nil guards to WrapConn, WrapPacketConn, WrapUDPConn, WrapListener - Add doc comments to all exported symbols - Add 45 unit tests (metrics, noop, prom, service, wrapper)
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-gost/core/metrics"
|
||||
)
|
||||
|
||||
func TestEnableDisable(t *testing.T) {
|
||||
// Save and restore original state.
|
||||
orig := IsEnabled()
|
||||
defer Enable(orig)
|
||||
|
||||
Enable(false)
|
||||
if IsEnabled() {
|
||||
t.Error("IsEnabled should return false after Enable(false)")
|
||||
}
|
||||
|
||||
Enable(true)
|
||||
if !IsEnabled() {
|
||||
t.Error("IsEnabled should return true after Enable(true)")
|
||||
}
|
||||
|
||||
Enable(false)
|
||||
if IsEnabled() {
|
||||
t.Error("IsEnabled should return false after second Enable(false)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCounterDisabled(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(false)
|
||||
defer Enable(orig)
|
||||
|
||||
c := GetCounter(MetricServiceRequestsCounter, metrics.Labels{"service": "s", "client": "c"})
|
||||
if c == nil {
|
||||
t.Error("GetCounter should not return nil when disabled")
|
||||
}
|
||||
// Should be noop — calling methods must not panic.
|
||||
c.Inc()
|
||||
c.Add(42)
|
||||
c.Add(-1)
|
||||
}
|
||||
|
||||
func TestGetGaugeDisabled(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(false)
|
||||
defer Enable(orig)
|
||||
|
||||
// MetricServicesGauge has only ["host"] label (auto-added), so pass no extra labels.
|
||||
g := GetGauge(MetricServicesGauge, nil)
|
||||
if g == nil {
|
||||
t.Error("GetGauge should not return nil when disabled")
|
||||
}
|
||||
g.Inc()
|
||||
g.Dec()
|
||||
g.Add(1.5)
|
||||
g.Set(100)
|
||||
g.Set(-1)
|
||||
}
|
||||
|
||||
func TestGetObserverDisabled(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(false)
|
||||
defer Enable(orig)
|
||||
|
||||
o := GetObserver(MetricServiceRequestsDurationObserver, metrics.Labels{"service": "s"})
|
||||
if o == nil {
|
||||
t.Error("GetObserver should not return nil when disabled")
|
||||
}
|
||||
o.Observe(0.5)
|
||||
o.Observe(0)
|
||||
o.Observe(-1)
|
||||
}
|
||||
|
||||
func TestGetCounterEnabled(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(true)
|
||||
defer Enable(orig)
|
||||
|
||||
c := GetCounter(MetricServiceRequestsCounter, metrics.Labels{"service": "s", "client": "c"})
|
||||
if c == nil {
|
||||
t.Error("GetCounter should not return nil when enabled")
|
||||
}
|
||||
// Methods should not panic.
|
||||
c.Inc()
|
||||
c.Add(10)
|
||||
}
|
||||
|
||||
func TestGetGaugeEnabled(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(true)
|
||||
defer Enable(orig)
|
||||
|
||||
// MetricServicesGauge has only ["host"] label (auto-added).
|
||||
g := GetGauge(MetricServicesGauge, nil)
|
||||
if g == nil {
|
||||
t.Error("GetGauge should not return nil when enabled")
|
||||
}
|
||||
g.Inc()
|
||||
g.Dec()
|
||||
g.Set(5)
|
||||
}
|
||||
|
||||
func TestGetObserverEnabled(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(true)
|
||||
defer Enable(orig)
|
||||
|
||||
o := GetObserver(MetricServiceRequestsDurationObserver, metrics.Labels{"service": "s"})
|
||||
if o == nil {
|
||||
t.Error("GetObserver should not return nil when enabled")
|
||||
}
|
||||
o.Observe(0.25)
|
||||
}
|
||||
|
||||
func TestGetCounterEnabledUnknownName(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(true)
|
||||
defer Enable(orig)
|
||||
|
||||
c := GetCounter("nonexistent_metric", nil)
|
||||
if c == nil {
|
||||
t.Error("GetCounter should not return nil for unknown metric name")
|
||||
}
|
||||
c.Inc()
|
||||
c.Add(5)
|
||||
}
|
||||
|
||||
func TestGetGaugeEnabledUnknownName(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(true)
|
||||
defer Enable(orig)
|
||||
|
||||
g := GetGauge("nonexistent_metric", nil)
|
||||
if g == nil {
|
||||
t.Error("GetGauge should not return nil for unknown metric name")
|
||||
}
|
||||
g.Inc()
|
||||
g.Set(1)
|
||||
}
|
||||
|
||||
func TestGetObserverEnabledUnknownName(t *testing.T) {
|
||||
orig := IsEnabled()
|
||||
Enable(true)
|
||||
defer Enable(orig)
|
||||
|
||||
o := GetObserver("nonexistent_metric", nil)
|
||||
if o == nil {
|
||||
t.Error("GetObserver should not return nil for unknown metric name")
|
||||
}
|
||||
o.Observe(1.0)
|
||||
}
|
||||
|
||||
func TestMetricConstantsNotEmpty(t *testing.T) {
|
||||
names := []metrics.MetricName{
|
||||
MetricServicesGauge,
|
||||
MetricServiceRequestsCounter,
|
||||
MetricServiceRequestsInFlightGauge,
|
||||
MetricServiceRequestsDurationObserver,
|
||||
MetricServiceTransferInputBytesCounter,
|
||||
MetricServiceTransferOutputBytesCounter,
|
||||
MetricNodeConnectDurationObserver,
|
||||
MetricServiceHandlerErrorsCounter,
|
||||
MetricChainErrorsCounter,
|
||||
MetricRecorderRecordsCounter,
|
||||
}
|
||||
for i, n := range names {
|
||||
if n == "" {
|
||||
t.Errorf("metric constant at index %d is empty", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user