TUN-9511: Add metrics for virtual DNS origin

Closes TUN-9511
This commit is contained in:
Devin Carr
2025-07-01 13:26:34 -07:00
parent 242fccefa4
commit 6ec699509d
5 changed files with 65 additions and 13 deletions

View File

@@ -11,6 +11,7 @@ import (
"time"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/rs/zerolog"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
@@ -229,14 +230,15 @@ func prepareTunnelConfig(
}, log)
// Setup DNS Resolver Service
originMetrics := origins.NewMetrics(prometheus.DefaultRegisterer)
dnsResolverAddrs := c.StringSlice(flags.VirtualDNSServiceResolverAddresses)
dnsService := origins.NewDNSResolverService(origins.NewDNSDialer(), log)
dnsService := origins.NewDNSResolverService(origins.NewDNSDialer(), log, originMetrics)
if len(dnsResolverAddrs) > 0 {
addrs, err := parseResolverAddrPorts(dnsResolverAddrs)
if err != nil {
return nil, nil, fmt.Errorf("invalid %s provided: %w", flags.VirtualDNSServiceResolverAddresses, err)
}
dnsService = origins.NewStaticDNSResolverService(addrs, origins.NewDNSDialer(), log)
dnsService = origins.NewStaticDNSResolverService(addrs, origins.NewDNSDialer(), log, originMetrics)
}
originDialerService.AddReservedService(dnsService, []netip.AddrPort{origins.VirtualDNSServiceAddr})

View File

@@ -51,31 +51,35 @@ type DNSResolverService struct {
dialer ingress.OriginDialer
resolver peekResolver
logger *zerolog.Logger
metrics Metrics
}
func NewDNSResolverService(dialer ingress.OriginDialer, logger *zerolog.Logger) *DNSResolverService {
func NewDNSResolverService(dialer ingress.OriginDialer, logger *zerolog.Logger, metrics Metrics) *DNSResolverService {
return &DNSResolverService{
addresses: []netip.AddrPort{defaultResolverAddr},
dialer: dialer,
resolver: &resolver{dialFunc: net.Dial},
logger: logger,
metrics: metrics,
}
}
func NewStaticDNSResolverService(resolverAddrs []netip.AddrPort, dialer ingress.OriginDialer, logger *zerolog.Logger) *DNSResolverService {
s := NewDNSResolverService(dialer, logger)
func NewStaticDNSResolverService(resolverAddrs []netip.AddrPort, dialer ingress.OriginDialer, logger *zerolog.Logger, metrics Metrics) *DNSResolverService {
s := NewDNSResolverService(dialer, logger, metrics)
s.addresses = resolverAddrs
s.static = true
return s
}
func (s *DNSResolverService) DialTCP(ctx context.Context, _ netip.AddrPort) (net.Conn, error) {
s.metrics.IncrementDNSTCPRequests()
dest := s.getAddress()
// The dialer ignores the provided address because the request will instead go to the local DNS resolver.
return s.dialer.DialTCP(ctx, dest)
}
func (s *DNSResolverService) DialUDP(_ netip.AddrPort) (net.Conn, error) {
s.metrics.IncrementDNSUDPRequests()
dest := s.getAddress()
// The dialer ignores the provided address because the request will instead go to the local DNS resolver.
return s.dialer.DialUDP(dest)

View File

@@ -14,7 +14,7 @@ import (
func TestDNSResolver_DefaultResolver(t *testing.T) {
log := zerolog.Nop()
service := NewDNSResolverService(NewDNSDialer(), &log)
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
mockResolver := &mockPeekResolver{
address: "127.0.0.2:53",
}
@@ -25,7 +25,7 @@ func TestDNSResolver_DefaultResolver(t *testing.T) {
func TestStaticDNSResolver_DefaultResolver(t *testing.T) {
log := zerolog.Nop()
addresses := []netip.AddrPort{netip.MustParseAddrPort("1.1.1.1:53"), netip.MustParseAddrPort("1.0.0.1:53")}
service := NewStaticDNSResolverService(addresses, NewDNSDialer(), &log)
service := NewStaticDNSResolverService(addresses, NewDNSDialer(), &log, &noopMetrics{})
mockResolver := &mockPeekResolver{
address: "127.0.0.2:53",
}
@@ -35,7 +35,7 @@ func TestStaticDNSResolver_DefaultResolver(t *testing.T) {
func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
log := zerolog.Nop()
service := NewDNSResolverService(NewDNSDialer(), &log)
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
mockResolver := &mockPeekResolver{}
service.resolver = mockResolver
@@ -64,7 +64,7 @@ func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
func TestStaticDNSResolver_RefreshLoopExits(t *testing.T) {
log := zerolog.Nop()
addresses := []netip.AddrPort{netip.MustParseAddrPort("1.1.1.1:53"), netip.MustParseAddrPort("1.0.0.1:53")}
service := NewStaticDNSResolverService(addresses, NewDNSDialer(), &log)
service := NewStaticDNSResolverService(addresses, NewDNSDialer(), &log, &noopMetrics{})
mockResolver := &mockPeekResolver{
address: "127.0.0.2:53",
@@ -85,7 +85,7 @@ func TestStaticDNSResolver_RefreshLoopExits(t *testing.T) {
func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
log := zerolog.Nop()
service := NewDNSResolverService(NewDNSDialer(), &log)
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
mockResolver := &mockPeekResolver{}
service.resolver = mockResolver
@@ -109,7 +109,7 @@ func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
func TestDNSResolver_UpdateResolverErrorIgnored(t *testing.T) {
log := zerolog.Nop()
service := NewDNSResolverService(NewDNSDialer(), &log)
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
resolverErr := errors.New("test resolver error")
mockResolver := &mockPeekResolver{err: resolverErr}
service.resolver = mockResolver
@@ -126,7 +126,7 @@ func TestDNSResolver_UpdateResolverErrorIgnored(t *testing.T) {
func TestDNSResolver_DialUDPUsesResolvedAddress(t *testing.T) {
log := zerolog.Nop()
mockDialer := &mockDialer{expected: defaultResolverAddr}
service := NewDNSResolverService(mockDialer, &log)
service := NewDNSResolverService(mockDialer, &log, &noopMetrics{})
mockResolver := &mockPeekResolver{}
service.resolver = mockResolver
@@ -140,7 +140,7 @@ func TestDNSResolver_DialUDPUsesResolvedAddress(t *testing.T) {
func TestDNSResolver_DialTCPUsesResolvedAddress(t *testing.T) {
log := zerolog.Nop()
mockDialer := &mockDialer{expected: defaultResolverAddr}
service := NewDNSResolverService(mockDialer, &log)
service := NewDNSResolverService(mockDialer, &log, &noopMetrics{})
mockResolver := &mockPeekResolver{}
service.resolver = mockResolver

View File

@@ -0,0 +1,40 @@
package origins
import (
"github.com/prometheus/client_golang/prometheus"
)
const (
namespace = "cloudflared"
subsystem = "virtual_origins"
)
type Metrics interface {
IncrementDNSUDPRequests()
IncrementDNSTCPRequests()
}
type metrics struct {
dnsResolverRequests *prometheus.CounterVec
}
func (m *metrics) IncrementDNSUDPRequests() {
m.dnsResolverRequests.WithLabelValues("udp").Inc()
}
func (m *metrics) IncrementDNSTCPRequests() {
m.dnsResolverRequests.WithLabelValues("tcp").Inc()
}
func NewMetrics(registerer prometheus.Registerer) Metrics {
m := &metrics{
dnsResolverRequests: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: subsystem,
Name: "dns_requests_total",
Help: "Total count of DNS requests that have been proxied to the virtual DNS resolver origin",
}, []string{"protocol"}),
}
registerer.MustRegister(m.dnsResolverRequests)
return m
}

View File

@@ -0,0 +1,6 @@
package origins
type noopMetrics struct{}
func (noopMetrics) IncrementDNSUDPRequests() {}
func (noopMetrics) IncrementDNSTCPRequests() {}