11 "github.com/prometheus/client_golang/prometheus"
12 "github.com/prometheus/client_golang/prometheus/promauto"
14 "github.com/mjl-/mox/dane"
15 "github.com/mjl-/mox/dkim"
16 "github.com/mjl-/mox/dmarc"
17 "github.com/mjl-/mox/dns"
18 "github.com/mjl-/mox/dnsbl"
19 "github.com/mjl-/mox/iprev"
20 "github.com/mjl-/mox/metrics"
21 "github.com/mjl-/mox/mlog"
22 "github.com/mjl-/mox/mtasts"
23 "github.com/mjl-/mox/smtpclient"
24 "github.com/mjl-/mox/spf"
25 "github.com/mjl-/mox/subjectpass"
26 "github.com/mjl-/mox/tlsrpt"
27 "github.com/mjl-/mox/updates"
30var metricHTTPClient = promauto.NewHistogramVec(
31 prometheus.HistogramOpts{
32 Name: "mox_httpclient_request_duration_seconds",
33 Help: "HTTP requests lookups.",
34 Buckets: []float64{0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30},
44// httpClientObserve tracks the result of an HTTP transaction in a metric, and
46func httpClientObserve(ctx context.Context, elog *slog.Logger, pkg, method string, statusCode int, err error, start time.Time) {
47 log := mlog.New("metrics", elog)
51 switch statusCode / 100 {
57 result = "servererror"
61 case errors.Is(err, os.ErrDeadlineExceeded) || errors.Is(err, context.DeadlineExceeded):
63 case errors.Is(err, context.Canceled):
68 metricHTTPClient.WithLabelValues(pkg, method, result, fmt.Sprintf("%d", statusCode)).Observe(float64(time.Since(start)) / float64(time.Second))
69 log.Debugx("httpclient result", err,
70 slog.String("pkg", pkg),
71 slog.String("method", method),
72 slog.Int("code", statusCode),
73 slog.Duration("duration", time.Since(start)))
77 dane.MetricVerify = promauto.NewCounter(
78 prometheus.CounterOpts{
79 Name: "mox_dane_verify_total",
80 Help: "Total number of DANE verification attempts, including mox_dane_verify_errors_total.",
83 dane.MetricVerifyErrors = promauto.NewCounter(
84 prometheus.CounterOpts{
85 Name: "mox_dane_verify_errors_total",
86 Help: "Total number of DANE verification failures, causing connections to fail.",
90 dkim.MetricSign = counterVec{promauto.NewCounterVec(
91 prometheus.CounterOpts{
92 Name: "mox_dkim_sign_total",
93 Help: "DKIM messages signings, label key is the type of key, rsa or ed25519.",
99 dkim.MetricVerify = histogramVec{
100 promauto.NewHistogramVec(
101 prometheus.HistogramOpts{
102 Name: "mox_dkim_verify_duration_seconds",
103 Help: "DKIM verify, including lookup, duration and result.",
104 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20},
113 dmarc.MetricVerify = histogramVec{promauto.NewHistogramVec(
114 prometheus.HistogramOpts{
115 Name: "mox_dmarc_verify_duration_seconds",
116 Help: "DMARC verify, including lookup, duration and result.",
117 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20},
122 "use", // yes/no, if policy is used after random selection
125 dns.MetricLookup = histogramVec{
126 promauto.NewHistogramVec(
127 prometheus.HistogramOpts{
128 Name: "mox_dns_lookup_duration_seconds",
129 Help: "DNS lookups.",
130 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30},
134 "type", // Lower-case Resolver method name without leading Lookup.
135 "result", // ok, nxdomain, temporary, timeout, canceled, error
140 dnsbl.MetricLookup = histogramVec{promauto.NewHistogramVec(
141 prometheus.HistogramOpts{
142 Name: "mox_dnsbl_lookup_duration_seconds",
143 Help: "DNSBL lookup",
144 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20},
152 iprev.MetricIPRev = histogramVec{promauto.NewHistogramVec(
153 prometheus.HistogramOpts{
154 Name: "mox_iprev_lookup_total",
155 Help: "Number of iprev lookups.",
156 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30},
161 mtasts.MetricGet = histogramVec{promauto.NewHistogramVec(
162 prometheus.HistogramOpts{
163 Name: "mox_mtasts_get_duration_seconds",
164 Help: "MTA-STS get of policy, including lookup, duration and result.",
165 Buckets: []float64{0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20},
168 "result", // ok, lookuperror, fetcherror
171 mtasts.HTTPClientObserve = httpClientObserve
173 smtpclient.MetricCommands = histogramVec{promauto.NewHistogramVec(
174 prometheus.HistogramOpts{
175 Name: "mox_smtpclient_command_duration_seconds",
176 Help: "SMTP client command duration and result codes in seconds.",
177 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30, 60, 120},
185 smtpclient.MetricTLSRequiredNoIgnored = counterVec{promauto.NewCounterVec(
186 prometheus.CounterOpts{
187 Name: "mox_smtpclient_tlsrequiredno_ignored_total",
188 Help: "Connection attempts with TLS policy findings ignored due to message with TLS-Required: No header. Does not cover case where TLS certificate cannot be PKIX-verified.",
191 "ignored", // daneverification (no matching tlsa record)
194 smtpclient.MetricPanicInc = func() {
195 metrics.PanicInc(metrics.Smtpclient)
198 spf.MetricVerify = histogramVec{promauto.NewHistogramVec(
199 prometheus.HistogramOpts{
200 Name: "mox_spf_verify_duration_seconds",
201 Help: "SPF verify, including lookup, duration and result.",
202 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20},
209 subjectpass.MetricGenerate = promauto.NewCounter(
210 prometheus.CounterOpts{
211 Name: "mox_subjectpass_generate_total",
212 Help: "Number of generated subjectpass challenges.",
215 subjectpass.MetricVerify = counterVec{promauto.NewCounterVec(
216 prometheus.CounterOpts{
217 Name: "mox_subjectpass_verify_total",
218 Help: "Number of subjectpass verifications.",
221 "result", // ok, fail
225 tlsrpt.MetricLookup = histogramVec{promauto.NewHistogramVec(
226 prometheus.HistogramOpts{
227 Name: "mox_tlsrpt_lookup_duration_seconds",
228 Help: "TLSRPT lookups with result.",
229 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30},
234 updates.MetricLookup = histogramVec{promauto.NewHistogramVec(
235 prometheus.HistogramOpts{
236 Name: "mox_updates_lookup_duration_seconds",
237 Help: "Updates lookup with result.",
238 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30},
242 updates.MetricFetchChangelog = histogramVec{promauto.NewHistogramVec(
243 prometheus.HistogramOpts{
244 Name: "mox_updates_fetchchangelog_duration_seconds",
245 Help: "Fetch changelog with result.",
246 Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.100, 0.5, 1, 5, 10, 20, 30},
252type counterVec struct {
253 *prometheus.CounterVec
256func (m counterVec) IncLabels(labels ...string) {
257 m.CounterVec.WithLabelValues(labels...).Inc()
260type histogramVec struct {
261 *prometheus.HistogramVec
264func (m histogramVec) ObserveLabels(v float64, labels ...string) {
265 m.HistogramVec.WithLabelValues(labels...).Observe(v)