snowflake/proxy/lib/metrics.go
WofWca f3e040bbd8
improvement: less scary failed conn logs & metrics
...and adjust the `totalFailedConnections` metric name
and description.

This commit should make the periodic stats log messages
and the relevant metric look less scary to users:
P2P connection failures are relatively frequent and are usually
not indicative of the proxy operator having done something wrong.
So let's tone the wording down.

See the discussion: https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/merge_requests/516#note_3173677.
2025-03-15 11:15:22 -04:00

92 lines
2.8 KiB
Go

package snowflake_proxy
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
const (
// metricNamespace represent prometheus namespace
metricNamespace = "tor_snowflake_proxy"
)
type Metrics struct {
totalInBoundTraffic prometheus.Counter
totalOutBoundTraffic prometheus.Counter
totalConnections *prometheus.CounterVec
totalFailedConnections prometheus.Counter
}
func NewMetrics() *Metrics {
return &Metrics{
totalConnections: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: metricNamespace,
Name: "connections_total",
Help: "The total number of successful connections handled by the snowflake proxy",
},
[]string{"country"},
),
totalFailedConnections: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: metricNamespace,
Name: "connection_timeouts_total",
Help: "The total number of client connection attempts that failed after successful rendezvous. Note that failures can occur for reasons outside of the proxy's control, such as the client's NAT and censorship situation.",
}),
totalInBoundTraffic: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: metricNamespace,
Name: "traffic_inbound_bytes_total",
Help: "The total in bound traffic by the snowflake proxy (KB)",
}),
totalOutBoundTraffic: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: metricNamespace,
Name: "traffic_outbound_bytes_total",
Help: "The total out bound traffic by the snowflake proxy (KB)",
}),
}
}
// Start register the metrics server and serve them on the given address
func (m *Metrics) Start(addr string) error {
go func() {
http.Handle("/internal/metrics", promhttp.Handler())
if err := http.ListenAndServe(addr, nil); err != nil {
panic(err)
}
}()
return prometheus.Register(m)
}
func (m *Metrics) Collect(ch chan<- prometheus.Metric) {
m.totalConnections.Collect(ch)
m.totalFailedConnections.Collect(ch)
m.totalInBoundTraffic.Collect(ch)
m.totalOutBoundTraffic.Collect(ch)
}
func (m *Metrics) Describe(descs chan<- *prometheus.Desc) {
prometheus.DescribeByCollect(m, descs)
}
// TrackInBoundTraffic counts the received traffic by the snowflake proxy
func (m *Metrics) TrackInBoundTraffic(value int64) {
m.totalInBoundTraffic.Add(float64(value))
}
// TrackOutBoundTraffic counts the transmitted traffic by the snowflake proxy
func (m *Metrics) TrackOutBoundTraffic(value int64) {
m.totalOutBoundTraffic.Add(float64(value))
}
// TrackNewConnection counts the new connections
func (m *Metrics) TrackNewConnection(country string) {
m.totalConnections.
With(prometheus.Labels{"country": country}).
Inc()
}
// TrackFailedConnection counts failed connection attempts
func (m *Metrics) TrackFailedConnection() {
m.totalFailedConnections.Inc()
}