mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 12:49:58 +00:00
TUN-9511: Add metrics for virtual DNS origin
Closes TUN-9511
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"github.com/urfave/cli/v2/altsrc"
|
"github.com/urfave/cli/v2/altsrc"
|
||||||
@@ -229,14 +230,15 @@ func prepareTunnelConfig(
|
|||||||
}, log)
|
}, log)
|
||||||
|
|
||||||
// Setup DNS Resolver Service
|
// Setup DNS Resolver Service
|
||||||
|
originMetrics := origins.NewMetrics(prometheus.DefaultRegisterer)
|
||||||
dnsResolverAddrs := c.StringSlice(flags.VirtualDNSServiceResolverAddresses)
|
dnsResolverAddrs := c.StringSlice(flags.VirtualDNSServiceResolverAddresses)
|
||||||
dnsService := origins.NewDNSResolverService(origins.NewDNSDialer(), log)
|
dnsService := origins.NewDNSResolverService(origins.NewDNSDialer(), log, originMetrics)
|
||||||
if len(dnsResolverAddrs) > 0 {
|
if len(dnsResolverAddrs) > 0 {
|
||||||
addrs, err := parseResolverAddrPorts(dnsResolverAddrs)
|
addrs, err := parseResolverAddrPorts(dnsResolverAddrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("invalid %s provided: %w", flags.VirtualDNSServiceResolverAddresses, err)
|
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})
|
originDialerService.AddReservedService(dnsService, []netip.AddrPort{origins.VirtualDNSServiceAddr})
|
||||||
|
|
||||||
|
@@ -51,31 +51,35 @@ type DNSResolverService struct {
|
|||||||
dialer ingress.OriginDialer
|
dialer ingress.OriginDialer
|
||||||
resolver peekResolver
|
resolver peekResolver
|
||||||
logger *zerolog.Logger
|
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{
|
return &DNSResolverService{
|
||||||
addresses: []netip.AddrPort{defaultResolverAddr},
|
addresses: []netip.AddrPort{defaultResolverAddr},
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
resolver: &resolver{dialFunc: net.Dial},
|
resolver: &resolver{dialFunc: net.Dial},
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
metrics: metrics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStaticDNSResolverService(resolverAddrs []netip.AddrPort, dialer ingress.OriginDialer, logger *zerolog.Logger) *DNSResolverService {
|
func NewStaticDNSResolverService(resolverAddrs []netip.AddrPort, dialer ingress.OriginDialer, logger *zerolog.Logger, metrics Metrics) *DNSResolverService {
|
||||||
s := NewDNSResolverService(dialer, logger)
|
s := NewDNSResolverService(dialer, logger, metrics)
|
||||||
s.addresses = resolverAddrs
|
s.addresses = resolverAddrs
|
||||||
s.static = true
|
s.static = true
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DNSResolverService) DialTCP(ctx context.Context, _ netip.AddrPort) (net.Conn, error) {
|
func (s *DNSResolverService) DialTCP(ctx context.Context, _ netip.AddrPort) (net.Conn, error) {
|
||||||
|
s.metrics.IncrementDNSTCPRequests()
|
||||||
dest := s.getAddress()
|
dest := s.getAddress()
|
||||||
// The dialer ignores the provided address because the request will instead go to the local DNS resolver.
|
// The dialer ignores the provided address because the request will instead go to the local DNS resolver.
|
||||||
return s.dialer.DialTCP(ctx, dest)
|
return s.dialer.DialTCP(ctx, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DNSResolverService) DialUDP(_ netip.AddrPort) (net.Conn, error) {
|
func (s *DNSResolverService) DialUDP(_ netip.AddrPort) (net.Conn, error) {
|
||||||
|
s.metrics.IncrementDNSUDPRequests()
|
||||||
dest := s.getAddress()
|
dest := s.getAddress()
|
||||||
// The dialer ignores the provided address because the request will instead go to the local DNS resolver.
|
// The dialer ignores the provided address because the request will instead go to the local DNS resolver.
|
||||||
return s.dialer.DialUDP(dest)
|
return s.dialer.DialUDP(dest)
|
||||||
|
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
func TestDNSResolver_DefaultResolver(t *testing.T) {
|
func TestDNSResolver_DefaultResolver(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
service := NewDNSResolverService(NewDNSDialer(), &log)
|
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
|
||||||
mockResolver := &mockPeekResolver{
|
mockResolver := &mockPeekResolver{
|
||||||
address: "127.0.0.2:53",
|
address: "127.0.0.2:53",
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ func TestDNSResolver_DefaultResolver(t *testing.T) {
|
|||||||
func TestStaticDNSResolver_DefaultResolver(t *testing.T) {
|
func TestStaticDNSResolver_DefaultResolver(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
addresses := []netip.AddrPort{netip.MustParseAddrPort("1.1.1.1:53"), netip.MustParseAddrPort("1.0.0.1:53")}
|
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{
|
mockResolver := &mockPeekResolver{
|
||||||
address: "127.0.0.2:53",
|
address: "127.0.0.2:53",
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ func TestStaticDNSResolver_DefaultResolver(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
|
func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
service := NewDNSResolverService(NewDNSDialer(), &log)
|
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
|
||||||
|
|
||||||
mockResolver := &mockPeekResolver{}
|
mockResolver := &mockPeekResolver{}
|
||||||
service.resolver = mockResolver
|
service.resolver = mockResolver
|
||||||
@@ -64,7 +64,7 @@ func TestDNSResolver_UpdateResolverAddress(t *testing.T) {
|
|||||||
func TestStaticDNSResolver_RefreshLoopExits(t *testing.T) {
|
func TestStaticDNSResolver_RefreshLoopExits(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
addresses := []netip.AddrPort{netip.MustParseAddrPort("1.1.1.1:53"), netip.MustParseAddrPort("1.0.0.1:53")}
|
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{
|
mockResolver := &mockPeekResolver{
|
||||||
address: "127.0.0.2:53",
|
address: "127.0.0.2:53",
|
||||||
@@ -85,7 +85,7 @@ func TestStaticDNSResolver_RefreshLoopExits(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
|
func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
service := NewDNSResolverService(NewDNSDialer(), &log)
|
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
|
||||||
mockResolver := &mockPeekResolver{}
|
mockResolver := &mockPeekResolver{}
|
||||||
service.resolver = mockResolver
|
service.resolver = mockResolver
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ func TestDNSResolver_UpdateResolverAddressInvalid(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSResolver_UpdateResolverErrorIgnored(t *testing.T) {
|
func TestDNSResolver_UpdateResolverErrorIgnored(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
service := NewDNSResolverService(NewDNSDialer(), &log)
|
service := NewDNSResolverService(NewDNSDialer(), &log, &noopMetrics{})
|
||||||
resolverErr := errors.New("test resolver error")
|
resolverErr := errors.New("test resolver error")
|
||||||
mockResolver := &mockPeekResolver{err: resolverErr}
|
mockResolver := &mockPeekResolver{err: resolverErr}
|
||||||
service.resolver = mockResolver
|
service.resolver = mockResolver
|
||||||
@@ -126,7 +126,7 @@ func TestDNSResolver_UpdateResolverErrorIgnored(t *testing.T) {
|
|||||||
func TestDNSResolver_DialUDPUsesResolvedAddress(t *testing.T) {
|
func TestDNSResolver_DialUDPUsesResolvedAddress(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
mockDialer := &mockDialer{expected: defaultResolverAddr}
|
mockDialer := &mockDialer{expected: defaultResolverAddr}
|
||||||
service := NewDNSResolverService(mockDialer, &log)
|
service := NewDNSResolverService(mockDialer, &log, &noopMetrics{})
|
||||||
mockResolver := &mockPeekResolver{}
|
mockResolver := &mockPeekResolver{}
|
||||||
service.resolver = mockResolver
|
service.resolver = mockResolver
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ func TestDNSResolver_DialUDPUsesResolvedAddress(t *testing.T) {
|
|||||||
func TestDNSResolver_DialTCPUsesResolvedAddress(t *testing.T) {
|
func TestDNSResolver_DialTCPUsesResolvedAddress(t *testing.T) {
|
||||||
log := zerolog.Nop()
|
log := zerolog.Nop()
|
||||||
mockDialer := &mockDialer{expected: defaultResolverAddr}
|
mockDialer := &mockDialer{expected: defaultResolverAddr}
|
||||||
service := NewDNSResolverService(mockDialer, &log)
|
service := NewDNSResolverService(mockDialer, &log, &noopMetrics{})
|
||||||
mockResolver := &mockPeekResolver{}
|
mockResolver := &mockPeekResolver{}
|
||||||
service.resolver = mockResolver
|
service.resolver = mockResolver
|
||||||
|
|
||||||
|
40
ingress/origins/metrics.go
Normal file
40
ingress/origins/metrics.go
Normal 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
|
||||||
|
}
|
6
ingress/origins/metrics_test.go
Normal file
6
ingress/origins/metrics_test.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package origins
|
||||||
|
|
||||||
|
type noopMetrics struct{}
|
||||||
|
|
||||||
|
func (noopMetrics) IncrementDNSUDPRequests() {}
|
||||||
|
func (noopMetrics) IncrementDNSTCPRequests() {}
|
Reference in New Issue
Block a user