diff --git a/internal/aggregate/metrics.go b/internal/aggregate/metrics.go index 11b8e83..917fc1c 100644 --- a/internal/aggregate/metrics.go +++ b/internal/aggregate/metrics.go @@ -9,7 +9,7 @@ import ( "notashelf.dev/watchdog/internal/config" ) -var prometheusLabelPattern = regexp.MustCompile(`^[a-zA-Z0-9_/:-]*$`) +var prometheusLabelPattern = regexp.MustCompile(`^[a-zA-Z0-9_/:.-]*$`) // Records analytics events as Prometheus metrics type MetricsAggregator struct { diff --git a/internal/aggregate/metrics_test.go b/internal/aggregate/metrics_test.go index c067198..3f964b5 100644 --- a/internal/aggregate/metrics_test.go +++ b/internal/aggregate/metrics_test.go @@ -22,7 +22,7 @@ func TestMetricsAggregator_RecordPageview(t *testing.T) { }, } - agg := NewMetricsAggregator(registry, cfg) + agg := NewMetricsAggregator(registry, NewCustomEventRegistry(100), cfg) // Record pageview with all dimensions agg.RecordPageview("/home", "US", "desktop", "google.com") @@ -51,7 +51,7 @@ func TestMetricsAggregator_RecordPageview_MinimalDimensions(t *testing.T) { }, } - agg := NewMetricsAggregator(registry, cfg) + agg := NewMetricsAggregator(registry, NewCustomEventRegistry(100), cfg) // Record pageview with only path agg.RecordPageview("/home", "", "", "") @@ -78,7 +78,7 @@ func TestMetricsAggregator_PathOverflow(t *testing.T) { }, } - agg := NewMetricsAggregator(registry, cfg) + agg := NewMetricsAggregator(registry, NewCustomEventRegistry(100), cfg) // Add two paths successfully registry.Add("/path1") @@ -114,7 +114,7 @@ func TestMetricsAggregator_RecordCustomEvent(t *testing.T) { }, } - agg := NewMetricsAggregator(registry, cfg) + agg := NewMetricsAggregator(registry, NewCustomEventRegistry(100), cfg) // Record custom event agg.RecordCustomEvent("signup") @@ -141,7 +141,7 @@ func TestMetricsAggregator_RecordCustomEvent_MultipleEvents(t *testing.T) { }, } - agg := NewMetricsAggregator(registry, cfg) + agg := NewMetricsAggregator(registry, NewCustomEventRegistry(100), cfg) // Record multiple events agg.RecordCustomEvent("signup") @@ -170,7 +170,7 @@ func TestMetricsAggregator_MustRegister(t *testing.T) { } promRegistry := prometheus.NewRegistry() - agg := NewMetricsAggregator(registry, cfg) + agg := NewMetricsAggregator(registry, NewCustomEventRegistry(100), cfg) // Register metrics agg.MustRegister(promRegistry) diff --git a/internal/api/handler.go b/internal/api/handler.go index f02ac95..4265d38 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -74,8 +74,8 @@ func (h *IngestionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - // Apply sampling - if h.cfg.Site.Sampling < 1.0 { + // Apply sampling (0.0 or 1.0 = no sampling, < 1.0 = sample) + if h.cfg.Site.Sampling > 0.0 && h.cfg.Site.Sampling < 1.0 { if h.rng.Float64() > h.cfg.Site.Sampling { // Sampled out, return success but don't track w.WriteHeader(http.StatusNoContent) diff --git a/internal/api/handler_test.go b/internal/api/handler_test.go index 227c23d..af50bfe 100644 --- a/internal/api/handler_test.go +++ b/internal/api/handler_test.go @@ -38,7 +38,7 @@ func TestIngestionHandler_Pageview(t *testing.T) { pathNorm := normalize.NewPathNormalizer(cfg.Site.Path) pathRegistry := aggregate.NewPathRegistry(cfg.Limits.MaxPaths) refRegistry := normalize.NewReferrerRegistry(cfg.Limits.MaxSources) - metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, cfg) + metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, aggregate.NewCustomEventRegistry(100), cfg) handler := NewIngestionHandler(cfg, pathNorm, pathRegistry, refRegistry, metricsAgg) @@ -80,7 +80,7 @@ func TestIngestionHandler_CustomEvent(t *testing.T) { pathNorm := normalize.NewPathNormalizer(cfg.Site.Path) pathRegistry := aggregate.NewPathRegistry(cfg.Limits.MaxPaths) refRegistry := normalize.NewReferrerRegistry(cfg.Limits.MaxSources) - metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, cfg) + metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, aggregate.NewCustomEventRegistry(100), cfg) handler := NewIngestionHandler(cfg, pathNorm, pathRegistry, refRegistry, metricsAgg) @@ -114,7 +114,7 @@ func TestIngestionHandler_WrongDomain(t *testing.T) { pathNorm := normalize.NewPathNormalizer(cfg.Site.Path) pathRegistry := aggregate.NewPathRegistry(cfg.Limits.MaxPaths) refRegistry := normalize.NewReferrerRegistry(cfg.Limits.MaxSources) - metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, cfg) + metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, aggregate.NewCustomEventRegistry(100), cfg) handler := NewIngestionHandler(cfg, pathNorm, pathRegistry, refRegistry, metricsAgg) @@ -144,7 +144,7 @@ func TestIngestionHandler_MethodNotAllowed(t *testing.T) { pathNorm := normalize.NewPathNormalizer(cfg.Site.Path) pathRegistry := aggregate.NewPathRegistry(cfg.Limits.MaxPaths) refRegistry := normalize.NewReferrerRegistry(cfg.Limits.MaxSources) - metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, cfg) + metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, aggregate.NewCustomEventRegistry(100), cfg) handler := NewIngestionHandler(cfg, pathNorm, pathRegistry, refRegistry, metricsAgg) @@ -171,7 +171,7 @@ func TestIngestionHandler_InvalidJSON(t *testing.T) { pathNorm := normalize.NewPathNormalizer(cfg.Site.Path) pathRegistry := aggregate.NewPathRegistry(cfg.Limits.MaxPaths) refRegistry := normalize.NewReferrerRegistry(cfg.Limits.MaxSources) - metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, cfg) + metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, aggregate.NewCustomEventRegistry(100), cfg) handler := NewIngestionHandler(cfg, pathNorm, pathRegistry, refRegistry, metricsAgg) @@ -206,7 +206,7 @@ func TestIngestionHandler_DeviceClassification(t *testing.T) { pathNorm := normalize.NewPathNormalizer(cfg.Site.Path) pathRegistry := aggregate.NewPathRegistry(cfg.Limits.MaxPaths) refRegistry := normalize.NewReferrerRegistry(cfg.Limits.MaxSources) - metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, cfg) + metricsAgg := aggregate.NewMetricsAggregator(pathRegistry, aggregate.NewCustomEventRegistry(100), cfg) handler := NewIngestionHandler(cfg, pathNorm, pathRegistry, refRegistry, metricsAgg) diff --git a/internal/normalize/path_test.go b/internal/normalize/path_test.go index b96c5ce..2ffc8a4 100644 --- a/internal/normalize/path_test.go +++ b/internal/normalize/path_test.go @@ -121,7 +121,7 @@ func TestNormalizePath(t *testing.T) { name: "very long path", cfg: config.PathConfig{}, input: "/" + strings.Repeat("a", 2050), - want: "/" + strings.Repeat("a", 2050), + want: "/", // reject overly long paths }, { name: "dot segments only", diff --git a/testdata/config.valid.yaml b/testdata/config.valid.yaml index b9a5f28..b3b362c 100644 --- a/testdata/config.valid.yaml +++ b/testdata/config.valid.yaml @@ -5,7 +5,7 @@ site: pageviews: true country: true device: true - referrer: classify + referrer: domain custom_events: - signup - purchase