Skip to content

Commit

Permalink
refactor(dslx): allow running w/o measurexlite as the backend (#1376)
Browse files Browse the repository at this point in the history
Summary of the changes:

* rename `ConnPool` (`struct`) to `Runtime` (`interface`) and retain the
same functionality;

* introduce a "minimal" runtime that does not collect observations along
with a measurexlite runtime;

* use the "runtime" to carry the logger and other bits of information
that it seems more rational to keep into the runtime rather than keeping
inside each pipeline stage result (I also did this in the richer-input
PoC);

* make sure `measurexlite`'s `Trace` can be fully accessed through an
interface.

Closes ooni/probe#2580
  • Loading branch information
bassosimone authored Oct 20, 2023
1 parent aa0deff commit 2da2e4d
Show file tree
Hide file tree
Showing 37 changed files with 921 additions and 762 deletions.
42 changes: 0 additions & 42 deletions internal/dslx/connpool.go

This file was deleted.

100 changes: 0 additions & 100 deletions internal/dslx/connpool_test.go

This file was deleted.

112 changes: 26 additions & 86 deletions internal/dslx/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ package dslx

import (
"context"
"sync/atomic"
"time"

"github.com/ooni/probe-cli/v3/internal/logx"
"github.com/ooni/probe-cli/v3/internal/measurexlite"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
Expand All @@ -21,47 +19,20 @@ type DomainName string
// DNSLookupOption is an option you can pass to NewDomainToResolve.
type DNSLookupOption func(*DomainToResolve)

// DNSLookupOptionIDGenerator configures a specific ID generator.
// See DomainToResolve docs for more information.
func DNSLookupOptionIDGenerator(value *atomic.Int64) DNSLookupOption {
return func(dis *DomainToResolve) {
dis.IDGenerator = value
}
}

// DNSLookupOptionLogger configures a specific logger.
// See DomainToResolve docs for more information.
func DNSLookupOptionLogger(value model.Logger) DNSLookupOption {
return func(dis *DomainToResolve) {
dis.Logger = value
}
}

// DNSLookupOptionTags allows to set tags to tag observations.
func DNSLookupOptionTags(value ...string) DNSLookupOption {
return func(dis *DomainToResolve) {
dis.Tags = append(dis.Tags, value...)
}
}

// DNSLookupOptionZeroTime configures the measurement's zero time.
// See DomainToResolve docs for more information.
func DNSLookupOptionZeroTime(value time.Time) DNSLookupOption {
return func(dis *DomainToResolve) {
dis.ZeroTime = value
}
}

// NewDomainToResolve creates input for performing DNS lookups. The only mandatory
// argument is the domain name to resolve. You can also supply optional
// values by passing options to this function.
func NewDomainToResolve(domain DomainName, options ...DNSLookupOption) *DomainToResolve {
state := &DomainToResolve{
Domain: string(domain),
IDGenerator: &atomic.Int64{},
Logger: model.DiscardLogger,
Tags: []string{},
ZeroTime: time.Now(),
Domain: string(domain),
Tags: []string{},
}
for _, option := range options {
option(state)
Expand All @@ -79,25 +50,8 @@ type DomainToResolve struct {
// Domain is the MANDATORY domain name to lookup.
Domain string

// IDGenerator is the MANDATORY ID generator. We will use this field
// to assign unique IDs to distinct sub-measurements. The default
// construction implemented by NewDomainToResolve creates a new generator
// that starts counting from zero, leading to the first trace having
// one as its index.
IDGenerator *atomic.Int64

// Logger is the MANDATORY logger to use. The default construction
// implemented by NewDomainToResolve uses model.DiscardLogger.
Logger model.Logger

// Tags contains OPTIONAL tags to tag observations.
Tags []string

// ZeroTime is the MANDATORY zero time of the measurement. We will
// use this field as the zero value to compute relative elapsed times
// when generating measurements. The default construction by
// NewDomainToResolve initializes this field with the current time.
ZeroTime time.Time
}

// ResolvedAddresses contains the results of DNS lookups. To initialize
Expand All @@ -110,47 +64,36 @@ type ResolvedAddresses struct {
// from the value inside the DomainToResolve.
Domain string

// IDGenerator is the ID generator. We inherit this field
// from the value inside the DomainToResolve.
IDGenerator *atomic.Int64

// Logger is the logger to use. We inherit this field
// from the value inside the DomainToResolve.
Logger model.Logger

// Trace is the trace we're currently using. This struct is
// created by the various Apply functions using values inside
// the DomainToResolve to initialize the Trace.
Trace *measurexlite.Trace

// ZeroTime is the zero time of the measurement. We inherit this field
// from the value inside the DomainToResolve.
ZeroTime time.Time
Trace Trace
}

// DNSLookupGetaddrinfo returns a function that resolves a domain name to
// IP addresses using libc's getaddrinfo function.
func DNSLookupGetaddrinfo() Func[*DomainToResolve, *Maybe[*ResolvedAddresses]] {
return &dnsLookupGetaddrinfoFunc{}
func DNSLookupGetaddrinfo(rt Runtime) Func[*DomainToResolve, *Maybe[*ResolvedAddresses]] {
return &dnsLookupGetaddrinfoFunc{nil, rt}
}

// dnsLookupGetaddrinfoFunc is the function returned by DNSLookupGetaddrinfo.
type dnsLookupGetaddrinfoFunc struct {
resolver model.Resolver // for testing
rt Runtime
}

// Apply implements Func.
func (f *dnsLookupGetaddrinfoFunc) Apply(
ctx context.Context, input *DomainToResolve) *Maybe[*ResolvedAddresses] {

// create trace
trace := measurexlite.NewTrace(input.IDGenerator.Add(1), input.ZeroTime, input.Tags...)
trace := f.rt.NewTrace(f.rt.IDGenerator().Add(1), f.rt.ZeroTime(), input.Tags...)

// start the operation logger
ol := logx.NewOperationLogger(
input.Logger,
f.rt.Logger(),
"[#%d] DNSLookup[getaddrinfo] %s",
trace.Index,
trace.Index(),
input.Domain,
)

Expand All @@ -161,7 +104,7 @@ func (f *dnsLookupGetaddrinfoFunc) Apply(

resolver := f.resolver
if resolver == nil {
resolver = trace.NewStdlibResolver(input.Logger)
resolver = trace.NewStdlibResolver(f.rt.Logger())
}

// lookup
Expand All @@ -171,12 +114,9 @@ func (f *dnsLookupGetaddrinfoFunc) Apply(
ol.Stop(err)

state := &ResolvedAddresses{
Addresses: addrs, // maybe empty
Domain: input.Domain,
IDGenerator: input.IDGenerator,
Logger: input.Logger,
Trace: trace,
ZeroTime: input.ZeroTime,
Addresses: addrs, // maybe empty
Domain: input.Domain,
Trace: trace,
}

return &Maybe[*ResolvedAddresses]{
Expand All @@ -189,9 +129,11 @@ func (f *dnsLookupGetaddrinfoFunc) Apply(

// DNSLookupUDP returns a function that resolves a domain name to
// IP addresses using the given DNS-over-UDP resolver.
func DNSLookupUDP(resolver string) Func[*DomainToResolve, *Maybe[*ResolvedAddresses]] {
func DNSLookupUDP(rt Runtime, resolver string) Func[*DomainToResolve, *Maybe[*ResolvedAddresses]] {
return &dnsLookupUDPFunc{
Resolver: resolver,
Resolver: resolver,
mockResolver: nil,
rt: rt,
}
}

Expand All @@ -200,20 +142,21 @@ type dnsLookupUDPFunc struct {
// Resolver is the MANDATORY endpointed of the resolver to use.
Resolver string
mockResolver model.Resolver // for testing
rt Runtime
}

// Apply implements Func.
func (f *dnsLookupUDPFunc) Apply(
ctx context.Context, input *DomainToResolve) *Maybe[*ResolvedAddresses] {

// create trace
trace := measurexlite.NewTrace(input.IDGenerator.Add(1), input.ZeroTime, input.Tags...)
trace := f.rt.NewTrace(f.rt.IDGenerator().Add(1), f.rt.ZeroTime(), input.Tags...)

// start the operation logger
ol := logx.NewOperationLogger(
input.Logger,
f.rt.Logger(),
"[#%d] DNSLookup[%s/udp] %s",
trace.Index,
trace.Index(),
f.Resolver,
input.Domain,
)
Expand All @@ -226,8 +169,8 @@ func (f *dnsLookupUDPFunc) Apply(
resolver := f.mockResolver
if resolver == nil {
resolver = trace.NewParallelUDPResolver(
input.Logger,
netxlite.NewDialerWithoutResolver(input.Logger),
f.rt.Logger(),
trace.NewDialerWithoutResolver(f.rt.Logger()),
f.Resolver,
)
}
Expand All @@ -239,12 +182,9 @@ func (f *dnsLookupUDPFunc) Apply(
ol.Stop(err)

state := &ResolvedAddresses{
Addresses: addrs, // maybe empty
Domain: input.Domain,
IDGenerator: input.IDGenerator,
Logger: input.Logger,
Trace: trace,
ZeroTime: input.ZeroTime,
Addresses: addrs, // maybe empty
Domain: input.Domain,
Trace: trace,
}

return &Maybe[*ResolvedAddresses]{
Expand Down
Loading

0 comments on commit 2da2e4d

Please sign in to comment.