Skip to content

Commit

Permalink
bootstrap: slog
Browse files Browse the repository at this point in the history
  • Loading branch information
Mizzick committed Jun 26, 2024
1 parent 5702d07 commit d292051
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 69 deletions.
4 changes: 2 additions & 2 deletions internal/bootstrap/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestResolveDialContext(t *testing.T) {
dialContext, err := bootstrap.ResolveDialContext(
&url.URL{Host: netutil.JoinHostPort(hostname, port)},
testTimeout,
bootstrap.NewParallelResolver([]bootstrap.Resolver{r}, l),
bootstrap.ParallelResolver{r},
tc.preferIPv6,
l,
)
Expand Down Expand Up @@ -134,7 +134,7 @@ func TestResolveDialContext(t *testing.T) {
dialContext, err := bootstrap.ResolveDialContext(
&url.URL{Host: netutil.JoinHostPort(hostname, port)},
testTimeout,
bootstrap.NewParallelResolver([]bootstrap.Resolver{r}, l),
bootstrap.ParallelResolver{r},
false,
l,
)
Expand Down
72 changes: 18 additions & 54 deletions internal/bootstrap/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package bootstrap

import (
"context"
"log/slog"
"net"
"net/netip"
"slices"
"time"

"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/logutil/slogutil"
)

Expand All @@ -24,50 +24,38 @@ type Resolver interface {
// type check
var _ Resolver = &net.Resolver{}

// ParallelResolver operates a slice of resolvers that are queried concurrently.
// The first successful response is returned.
type ParallelResolver struct {
logger *slog.Logger
resolvers []Resolver
}

// NewParallelResolver returns new properly initialized [ParallelResolver]. l
// must not be nil.
func NewParallelResolver(resolvers []Resolver, l *slog.Logger) (r *ParallelResolver) {
return &ParallelResolver{
logger: l,
resolvers: resolvers,
}
}
// ParallelResolver is a slice of resolvers that are queried concurrently. The
// first successful response is returned.
type ParallelResolver []Resolver

// type check
var _ Resolver = (*ParallelResolver)(nil)
var _ Resolver = ParallelResolver(nil)

// LookupNetIP implements the [Resolver] interface for ParallelResolver.
func (r ParallelResolver) LookupNetIP(
ctx context.Context,
network Network,
host string,
) (addrs []netip.Addr, err error) {
resolversNum := len(r.resolvers)
resolversNum := len(r)
switch resolversNum {
case 0:
return nil, ErrNoResolvers
case 1:
return lookup(ctx, r.resolvers[0], r.logger, network, host)
return lookup(ctx, r[0], network, host)
default:
// Go on.
}

// Size of channel must accommodate results of lookups from all resolvers,
// sending into channel will block otherwise.
ch := make(chan any, resolversNum)
for _, rslv := range r.resolvers {
go lookupAsync(ctx, rslv, r.logger, network, host, ch)
for _, rslv := range r {
go lookupAsync(ctx, rslv, network, host, ch)
}

var errs []error
for range r.resolvers {
for range r {
switch result := <-ch; result := result.(type) {
case error:
errs = append(errs, result)
Expand All @@ -80,55 +68,31 @@ func (r ParallelResolver) LookupNetIP(
}

// lookupAsync performs a lookup for ip of host with r and sends the result into
// resCh. It is intended to be used as a goroutine. l must not be nil.
func lookupAsync(
ctx context.Context,
r Resolver,
l *slog.Logger,
network string,
host string,
resCh chan<- any,
) {
defer slogutil.RecoverAndLog(ctx, l)
// resCh. It is intended to be used as a goroutine.
func lookupAsync(ctx context.Context, r Resolver, network, host string, resCh chan<- any) {
defer slogutil.RecoverAndLog(ctx, slogutil.NewDiscardLogger())

addrs, err := lookup(ctx, r, l, network, host)
addrs, err := lookup(ctx, r, network, host)
if err != nil {
resCh <- err
} else {
resCh <- addrs
}
}

// lookup tries to lookup ip of host with r. l must not be nil.
// lookup tries to lookup ip of host with r.
//
// TODO(e.burkov): Get rid of this function? It only wraps the actual lookup
// with dubious logging.
func lookup(
ctx context.Context,
r Resolver,
l *slog.Logger,
network string,
host string,
) (addrs []netip.Addr, err error) {
func lookup(ctx context.Context, r Resolver, network, host string) (addrs []netip.Addr, err error) {
start := time.Now()
addrs, err = r.LookupNetIP(ctx, network, host)
elapsed := time.Since(start)

if err != nil {
l.DebugContext(
ctx,
"lookup failed",
"host", host,
"elapsed", elapsed,
slogutil.KeyError, err,
)
log.Debug("parallel lookup: lookup for %s failed in %s: %s", host, elapsed, err)
} else {
l.DebugContext(ctx,
"lookup succeeded",
"host", host,
"elapsed", elapsed,
"addrs", addrs,
)
log.Debug("parallel lookup: lookup for %s succeeded in %s: %s", host, elapsed, addrs)
}

return addrs, err
Expand Down
27 changes: 16 additions & 11 deletions internal/bootstrap/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"testing"

"github.com/AdguardTeam/dnsproxy/internal/bootstrap"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
Expand All @@ -31,11 +30,8 @@ func (r *testResolver) LookupNetIP(
func TestLookupParallel(t *testing.T) {
const hostname = "host.name"

l := slogutil.NewDiscardLogger()

t.Run("no_resolvers", func(t *testing.T) {
r := bootstrap.NewParallelResolver(nil, l)
addrs, err := r.LookupNetIP(context.Background(), "ip", "")
addrs, err := bootstrap.ParallelResolver(nil).LookupNetIP(context.Background(), "ip", "")
assert.ErrorIs(t, err, bootstrap.ErrNoResolvers)
assert.Nil(t, addrs)
})
Expand All @@ -53,8 +49,11 @@ func TestLookupParallel(t *testing.T) {
}

t.Run("one_resolver", func(t *testing.T) {
r := bootstrap.NewParallelResolver([]bootstrap.Resolver{immediate}, l)
addrs, err := r.LookupNetIP(context.Background(), "ip", hostname)
addrs, err := bootstrap.ParallelResolver{immediate}.LookupNetIP(
context.Background(),
"ip",
hostname,
)
require.NoError(t, err)

assert.Equal(t, hostAddrs, addrs)
Expand All @@ -73,8 +72,11 @@ func TestLookupParallel(t *testing.T) {
},
}

r := bootstrap.NewParallelResolver([]bootstrap.Resolver{immediate, delayed}, l)
addrs, err := r.LookupNetIP(context.Background(), "ip", hostname)
addrs, err := bootstrap.ParallelResolver{immediate, delayed}.LookupNetIP(
context.Background(),
"ip",
hostname,
)
require.NoError(t, err)
testutil.RequireSend(t, delayCh, struct{}{}, testTimeout)

Expand All @@ -92,8 +94,11 @@ func TestLookupParallel(t *testing.T) {
},
}

p := bootstrap.NewParallelResolver([]bootstrap.Resolver{r, r, r}, l)
addrs, err := p.LookupNetIP(context.Background(), "ip", hostname)
addrs, err := bootstrap.ParallelResolver{r, r, r}.LookupNetIP(
context.Background(),
"ip",
hostname,
)
testutil.AssertErrorMsg(t, wantErrMsg, err)
assert.Nil(t, addrs)
})
Expand Down
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"syscall"
"time"

"github.com/AdguardTeam/dnsproxy/internal/bootstrap"
proxynetutil "github.com/AdguardTeam/dnsproxy/internal/netutil"
"github.com/AdguardTeam/dnsproxy/internal/version"
"github.com/AdguardTeam/dnsproxy/proxy"
Expand Down Expand Up @@ -603,7 +602,7 @@ func initBootstrap(
case 1:
return resolvers[0], nil
default:
return bootstrap.NewParallelResolver(resolvers, l.With(slogutil.KeyPrefix, "resolver")), nil
return upstream.ParallelResolver(resolvers), nil
}
}

Expand Down

0 comments on commit d292051

Please sign in to comment.