checker-blacklist/checker/provider.go
Pierre-Olivier Mercier c437339bda Separate observation from evaluation in blacklist sources
Each source's Query() method previously set r.Listed and r.Severity,
embedding verdict logic inside the prober. Evaluation now lives in a
dedicated Evaluate(SourceResult) (bool, string) method per source,
keeping Query() as pure observation.

A package-level EvaluateResult() helper looks up the source by ID and
delegates to its Evaluate method; rules.go, report.go, types.go, and
provider.go all call this instead of reading pre-set r.Listed/r.Severity
values. An unknownSource sentinel handles results whose source is no
longer registered.
2026-05-15 18:04:17 +08:00

52 lines
1.5 KiB
Go

package checker
import (
"encoding/json"
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
)
func Provider() sdk.ObservationProvider { return &blacklistProvider{} }
type blacklistProvider struct{}
func (p *blacklistProvider) Key() sdk.ObservationKey { return ObservationKeyBlacklist }
func (p *blacklistProvider) Definition() *sdk.CheckerDefinition { return Definition() }
// ExtractMetrics turns the (now uniform) per-source results into a
// small set of generic gauges. Source-specific metrics (VT engine
// counts, URLhaus URL count, …) live in SourceResult.Details and are
// rendered in the HTML report; metrics here stay coarse so the
// scheduler / Prometheus side does not have to know which sources are
// installed.
func (p *blacklistProvider) ExtractMetrics(ctx sdk.ReportContext, collectedAt time.Time) ([]sdk.CheckMetric, error) {
var data BlacklistData
if err := json.Unmarshal(ctx.Data(), &data); err != nil {
return nil, err
}
metrics := []sdk.CheckMetric{
{
Name: "blacklist_total_hits", Value: float64(data.TotalHits()),
Unit: "results", Timestamp: collectedAt,
},
}
for _, r := range data.Results {
if !r.Enabled {
continue
}
v := 0.0
if listed, _ := EvaluateResult(r); listed {
v = 1
}
metrics = append(metrics, sdk.CheckMetric{
Name: "blacklist_source_listed",
Value: v,
Unit: "bool",
Labels: map[string]string{"source": r.SourceID, "subject": r.Subject},
Timestamp: collectedAt,
})
}
return metrics, nil
}