feat: gamemaster
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/metric"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||
)
|
||||
|
||||
func TestProcessConfigValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.NoError(t, ProcessConfig{
|
||||
TracesExporter: "none",
|
||||
MetricsExporter: "none",
|
||||
}.Validate())
|
||||
|
||||
require.NoError(t, ProcessConfig{
|
||||
TracesExporter: "otlp",
|
||||
MetricsExporter: "otlp",
|
||||
TracesProtocol: "grpc",
|
||||
MetricsProtocol: "http/protobuf",
|
||||
}.Validate())
|
||||
|
||||
require.Error(t, ProcessConfig{
|
||||
TracesExporter: "stdout",
|
||||
MetricsExporter: "none",
|
||||
}.Validate())
|
||||
|
||||
require.Error(t, ProcessConfig{
|
||||
TracesExporter: "none",
|
||||
MetricsExporter: "kafka",
|
||||
}.Validate())
|
||||
|
||||
require.Error(t, ProcessConfig{
|
||||
TracesExporter: "otlp",
|
||||
MetricsExporter: "none",
|
||||
TracesProtocol: "thrift",
|
||||
}.Validate())
|
||||
}
|
||||
|
||||
func TestNewWithProvidersBuildsRuntime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reader := metric.NewManualReader()
|
||||
meterProvider := metric.NewMeterProvider(metric.WithReader(reader))
|
||||
|
||||
runtime, err := NewWithProviders(meterProvider, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, runtime)
|
||||
require.NotNil(t, runtime.MeterProvider())
|
||||
require.NotNil(t, runtime.TracerProvider())
|
||||
}
|
||||
|
||||
func TestRecordHelpersEmitInstruments(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reader := metric.NewManualReader()
|
||||
meterProvider := metric.NewMeterProvider(metric.WithReader(reader))
|
||||
runtime, err := NewWithProviders(meterProvider, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
runtime.RecordInternalHTTPRequest(ctx, []attribute.KeyValue{
|
||||
attribute.String("route", "/healthz"),
|
||||
attribute.String("method", "GET"),
|
||||
attribute.String("status_code", "200"),
|
||||
}, 10*time.Millisecond)
|
||||
runtime.RecordRegisterRuntimeOutcome(ctx, "success", "")
|
||||
runtime.RecordTurnGenerationOutcome(ctx, "success", "", "scheduler")
|
||||
runtime.RecordCommandExecuteOutcome(ctx, "success", "")
|
||||
runtime.RecordOrderPutOutcome(ctx, "success", "")
|
||||
runtime.RecordReportGetOutcome(ctx, "success", "")
|
||||
runtime.RecordBanishOutcome(ctx, "success", "")
|
||||
runtime.RecordHealthEventConsumed(ctx)
|
||||
runtime.RecordLobbyEventPublished(ctx, "runtime_snapshot_update")
|
||||
runtime.RecordNotificationPublishAttempt(ctx, "game.turn.ready", "ok")
|
||||
runtime.RecordMembershipCacheResult(ctx, "hit")
|
||||
runtime.RecordEngineCall(ctx, "init", 25*time.Millisecond)
|
||||
|
||||
var rm metricdata.ResourceMetrics
|
||||
require.NoError(t, reader.Collect(ctx, &rm))
|
||||
|
||||
names := collectInstrumentNames(rm)
|
||||
expected := []string{
|
||||
"gamemaster.internal_http.requests",
|
||||
"gamemaster.internal_http.duration",
|
||||
"gamemaster.register_runtime.outcomes",
|
||||
"gamemaster.turn_generation.outcomes",
|
||||
"gamemaster.command_execute.outcomes",
|
||||
"gamemaster.order_put.outcomes",
|
||||
"gamemaster.report_get.outcomes",
|
||||
"gamemaster.banish.outcomes",
|
||||
"gamemaster.health_events.consumed",
|
||||
"gamemaster.lobby_events.published",
|
||||
"gamemaster.notification.publish_attempts",
|
||||
"gamemaster.membership_cache.hits",
|
||||
"gamemaster.engine_call.latency",
|
||||
}
|
||||
for _, name := range expected {
|
||||
require.Contains(t, names, name, "expected instrument %s to be recorded", name)
|
||||
}
|
||||
}
|
||||
|
||||
func collectInstrumentNames(rm metricdata.ResourceMetrics) map[string]struct{} {
|
||||
names := make(map[string]struct{})
|
||||
for _, sm := range rm.ScopeMetrics {
|
||||
for _, m := range sm.Metrics {
|
||||
names[m.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
type stubRuntimeProbe struct {
|
||||
counts map[string]int
|
||||
err error
|
||||
}
|
||||
|
||||
func (probe stubRuntimeProbe) CountByStatus(_ context.Context) (map[string]int, error) {
|
||||
return probe.counts, probe.err
|
||||
}
|
||||
|
||||
type stubSchedulerProbe struct {
|
||||
due int
|
||||
err error
|
||||
}
|
||||
|
||||
func (probe stubSchedulerProbe) CountDue(_ context.Context) (int, error) {
|
||||
return probe.due, probe.err
|
||||
}
|
||||
|
||||
type stubVersionsProbe struct {
|
||||
count int
|
||||
err error
|
||||
}
|
||||
|
||||
func (probe stubVersionsProbe) CountVersions(_ context.Context) (int, error) {
|
||||
return probe.count, probe.err
|
||||
}
|
||||
|
||||
func TestRegisterGaugesEmitsObservations(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reader := metric.NewManualReader()
|
||||
meterProvider := metric.NewMeterProvider(metric.WithReader(reader))
|
||||
runtime, err := NewWithProviders(meterProvider, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, runtime.RegisterGauges(GaugeDependencies{
|
||||
RuntimeRecordsByStatus: stubRuntimeProbe{counts: map[string]int{"running": 3}},
|
||||
SchedulerDueGames: stubSchedulerProbe{due: 2},
|
||||
EngineVersionsTotal: stubVersionsProbe{count: 5},
|
||||
}))
|
||||
|
||||
var rm metricdata.ResourceMetrics
|
||||
require.NoError(t, reader.Collect(context.Background(), &rm))
|
||||
|
||||
names := collectInstrumentNames(rm)
|
||||
require.Contains(t, names, "gamemaster.runtime_records_by_status")
|
||||
require.Contains(t, names, "gamemaster.scheduler.due_games")
|
||||
require.Contains(t, names, "gamemaster.engine_versions_total")
|
||||
}
|
||||
|
||||
func TestRegisterGaugesRejectsNilDependencies(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reader := metric.NewManualReader()
|
||||
meterProvider := metric.NewMeterProvider(metric.WithReader(reader))
|
||||
runtime, err := NewWithProviders(meterProvider, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Error(t, runtime.RegisterGauges(GaugeDependencies{
|
||||
SchedulerDueGames: stubSchedulerProbe{},
|
||||
EngineVersionsTotal: stubVersionsProbe{},
|
||||
}))
|
||||
require.Error(t, runtime.RegisterGauges(GaugeDependencies{
|
||||
RuntimeRecordsByStatus: stubRuntimeProbe{},
|
||||
EngineVersionsTotal: stubVersionsProbe{},
|
||||
}))
|
||||
require.Error(t, runtime.RegisterGauges(GaugeDependencies{
|
||||
RuntimeRecordsByStatus: stubRuntimeProbe{},
|
||||
SchedulerDueGames: stubSchedulerProbe{},
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user