fix(auth): 公开登录门按来源限速并设全站发信上限,冷却表定期清理
This commit is contained in:
26 files changed
+1141
-64
No files matched your search
@@ -64,8 +64,44 @@ var (
|
||||
Name: "auth_otp_lockouts_total",
|
||||
Help: "Email-code doors locked after too many wrong codes, by purpose.",
|
||||
}, []string{"purpose"})
|
||||
|
||||
// MailTotal counts mail the API tried to send, by kind (otp, notice) and
|
||||
// result: sent, failed (the relay refused it) or throttled (the
|
||||
// install-wide mail budget refused it before it reached the relay).
|
||||
MailTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Name: "mail_total",
|
||||
Help: "Mail the API tried to send, by kind and result (sent, failed, throttled).",
|
||||
}, []string{"kind", "result"})
|
||||
|
||||
// RateLimitedTotal counts requests refused by a volumetric limit, by scope
|
||||
// (auth_door: one client address calling the public sign-in doors too fast).
|
||||
RateLimitedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Name: "rate_limited_total",
|
||||
Help: "Requests refused by a volumetric rate limit, by scope.",
|
||||
}, []string{"scope"})
|
||||
)
|
||||
|
||||
// OTPPurposes are the email-code doors OTPLockoutsTotal is labelled by.
|
||||
var OTPPurposes = []string{"onboard_email", "login_email", "op_login", "migrate_confirm"}
|
||||
|
||||
// The sign-in alerts watch these counters with increase(). A labelled child
|
||||
// that does not exist yet has no sample before its first event, so increase()
|
||||
// would miss exactly the first lockout or throttle; every child the alerts use
|
||||
// is created at zero up front.
|
||||
func init() {
|
||||
for _, kind := range []string{"otp", "notice"} {
|
||||
for _, result := range []string{"sent", "failed", "throttled"} {
|
||||
MailTotal.WithLabelValues(kind, result)
|
||||
}
|
||||
}
|
||||
RateLimitedTotal.WithLabelValues("auth_door")
|
||||
for _, p := range OTPPurposes {
|
||||
OTPLockoutsTotal.WithLabelValues(p)
|
||||
}
|
||||
}
|
||||
|
||||
// SyncServerGauge republishes felis_servers_total from a full snapshot of the
|
||||
// fleet's per-server states. states holds one entry per MinecraftServer the
|
||||
// operator knows about (its desiredState).
|
||||
@@ -97,6 +133,8 @@ func Collectors() []prometheus.Collector {
|
||||
ImageBuildFailuresTotal,
|
||||
ReaperWorldsDeletedTotal,
|
||||
OTPLockoutsTotal,
|
||||
MailTotal,
|
||||
RateLimitedTotal,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,3 +116,26 @@ func TestCountersRecordExpectedValues(t *testing.T) {
|
||||
t.Errorf("start_duration_seconds collected %d metrics, want 1 histogram", n)
|
||||
}
|
||||
}
|
||||
|
||||
// The sign-in alerts use increase(), which needs a zero sample before the first
|
||||
// event; every child they watch must be exposed before anything is counted.
|
||||
func TestSignInSeriesStartAtZero(t *testing.T) {
|
||||
want := map[string]int{
|
||||
"felis_mail_total": 6,
|
||||
"felis_rate_limited_total": 1,
|
||||
"felis_auth_otp_lockouts_total": len(OTPPurposes),
|
||||
}
|
||||
for _, c := range []prometheus.Collector{MailTotal, RateLimitedTotal, OTPLockoutsTotal} {
|
||||
reg := prometheus.NewRegistry()
|
||||
reg.MustRegister(c)
|
||||
mfs, err := reg.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("Gather: %v", err)
|
||||
}
|
||||
for _, mf := range mfs {
|
||||
if n := len(mf.GetMetric()); n < want[mf.GetName()] {
|
||||
t.Errorf("%s exposes %d children, want at least %d", mf.GetName(), n, want[mf.GetName()])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user