Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor([email protected]): improve logging clarity #964

Merged
merged 4 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions internal/experiment/webconnectivity/analysiscore.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,38 +109,38 @@ func (tk *TestKeys) analysisToplevel(logger model.Logger) {
tk.Blocking = "dns"
tk.Accessible = false
logger.Warnf(
"ANOMALY: flags=%d accessible=%+v, blocking=%+v",
"ANOMALY: flags=%d, accessible=%+v, blocking=%+v",
tk.BlockingFlags, tk.Accessible, tk.Blocking,
)

case (tk.BlockingFlags & analysisFlagTCPIPBlocking) != 0:
tk.Blocking = "tcp_ip"
tk.Accessible = false
logger.Warnf(
"ANOMALY: flags=%d accessible=%+v, blocking=%+v",
"ANOMALY: flags=%d, accessible=%+v, blocking=%+v",
tk.BlockingFlags, tk.Accessible, tk.Blocking,
)

case (tk.BlockingFlags & (analysisFlagTLSBlocking | analysisFlagHTTPBlocking)) != 0:
tk.Blocking = "http-failure"
tk.Accessible = false
logger.Warnf("ANOMALY: flags=%d accessible=%+v, blocking=%+v",
logger.Warnf("ANOMALY: flags=%d, accessible=%+v, blocking=%+v",
tk.BlockingFlags, tk.Accessible, tk.Blocking,
)

case (tk.BlockingFlags & analysisFlagHTTPDiff) != 0:
tk.Blocking = "http-diff"
tk.Accessible = false
logger.Warnf(
"ANOMALY: flags=%d accessible=%+v, blocking=%+v",
"ANOMALY: flags=%d, accessible=%+v, blocking=%+v",
tk.BlockingFlags, tk.Accessible, tk.Blocking,
)

case tk.BlockingFlags == analysisFlagSuccess:
tk.Blocking = false
tk.Accessible = true
logger.Infof(
"ACCESSIBLE: flags=%d accessible=%+v, blocking=%+v",
"ACCESSIBLE: flags=%d, accessible=%+v, blocking=%+v",
tk.BlockingFlags, tk.Accessible, tk.Blocking,
)

Expand Down
81 changes: 67 additions & 14 deletions internal/experiment/webconnectivity/analysisdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const (
func (tk *TestKeys) analysisDNSToplevel(logger model.Logger) {
tk.analysisDNSExperimentFailure()
tk.analysisDNSBogon(logger)
tk.analysisDNSDuplicateResponses(logger)
tk.analysisDNSUnexpectedFailure(logger)
tk.analysisDNSUnexpectedAddrs(logger)
if tk.DNSFlags != 0 {
Expand All @@ -70,6 +71,15 @@ func (tk *TestKeys) analysisDNSToplevel(logger model.Logger) {
}
}

// analysisDNSDuplicateResponses checks whether we received duplicate
// replies for DNS-over-UDP queries, which is very unexpected.
func (tk *TestKeys) analysisDNSDuplicateResponses(logger model.Logger) {
if length := len(tk.DNSDuplicateResponses); length > 0 {
// TODO(bassosimone): write algorithm to analyze this
logger.Warnf("DNS: got %d unexpected late/duplicate DNS responses", length)
}
}

// analysisDNSExperimentFailure sets the legacy DNSExperimentFailure field.
func (tk *TestKeys) analysisDNSExperimentFailure() {
for _, query := range tk.Queries {
Expand Down Expand Up @@ -106,13 +116,23 @@ func (tk *TestKeys) analysisDNSBogon(logger model.Logger) {
switch answer.AnswerType {
case "A":
if net.ParseIP(answer.IPv4) != nil && netxlite.IsBogon(answer.IPv4) {
logger.Warnf("DNS: BOGON %s in #%d", answer.IPv4, query.TransactionID)
logger.Warnf(
"DNS: got BOGON answer %s for domain %s (see #%d)",
answer.IPv4,
query.Hostname,
query.TransactionID,
)
tk.DNSFlags |= AnalysisDNSBogon
// continue processing so we print all the bogons we have
}
case "AAAA":
if net.ParseIP(answer.IPv6) != nil && netxlite.IsBogon(answer.IPv6) {
logger.Warnf("DNS: BOGON %s in #%d", answer.IPv6, query.TransactionID)
logger.Warnf(
"DNS: got BOGON answer %s for domain %s (see #%d)",
answer.IPv6,
query.Hostname,
query.TransactionID,
)
tk.DNSFlags |= AnalysisDNSBogon
// continue processing so we print all the bogons we have
}
Expand Down Expand Up @@ -255,7 +275,7 @@ func (tk *TestKeys) analysisDNSUnexpectedAddrs(logger model.Logger) {
// if the probe has not collected any addr for the same domain, it's
// definitely suspicious and counts as a difference
if len(probeAddrs) <= 0 {
logger.Warnf("DNS: no IP address resolved by the probe")
logger.Warnf("DNS: the probe did not resolve any IP address")
tk.DNSFlags |= AnalysisDNSUnexpectedAddrs
return
}
Expand All @@ -266,26 +286,34 @@ func (tk *TestKeys) analysisDNSUnexpectedAddrs(logger model.Logger) {
if len(differentAddrs) <= 0 {
return
}
for _, addr := range differentAddrs {
logger.Infof("DNS: address %s: not resolved by TH", addr)
}

// now, let's exclude the differentAddrs for which we successfully
// completed a TLS handshake: those should be good addrs
withoutHandshake := tk.findAddrsWithoutTLSHandshake(domain, differentAddrs)
if len(withoutHandshake) <= 0 {
return
}
for _, addr := range withoutHandshake {
logger.Infof("DNS: address %s: cannot confirm using TLS handshake", addr)
}

// as a last resort, accept the addresses without an handshake whose
// ASN overlaps with ASNs resolved by the TH
differentASNs := tk.analysisDNSDiffASN(withoutHandshake, thAddrs)
differentASNs := tk.analysisDNSDiffASN(logger, withoutHandshake, thAddrs)
if len(differentASNs) <= 0 {
return
}

// otherwise, conclude we have unexpected probe addrs
logger.Warnf(
"DNSDiff: differentAddrs: %+v; withoutHandshake: %+v; differentASNs: %+v",
differentAddrs, withoutHandshake, differentASNs,
)
for addr, asn := range differentASNs {
logger.Warnf(
"DNS: address %s has unexpected AS%d and we cannot use TLS to confirm it",
addr, asn,
)
}
tk.DNSFlags |= AnalysisDNSUnexpectedAddrs
}

Expand All @@ -298,6 +326,10 @@ func (tk *TestKeys) analysisDNSDiffAddrs(probeAddrs, thAddrs []string) (diff []s
)
mapping := make(map[string]int)
for _, addr := range probeAddrs {
if net.ParseIP(addr) != nil && netxlite.IsBogon(addr) {
// we can exclude bogons from the analysis because we already analyzed them
continue
}
mapping[addr] |= inProbe
}
for _, addr := range thAddrs {
Expand All @@ -313,23 +345,44 @@ func (tk *TestKeys) analysisDNSDiffAddrs(probeAddrs, thAddrs []string) (diff []s

// analysisDNSDiffASN returns whether there are IP addresses in the probe's
// list with different ASNs from the ones in the TH's list.
func (tk *TestKeys) analysisDNSDiffASN(probeAddrs, thAddrs []string) (asns []uint) {
func (tk *TestKeys) analysisDNSDiffASN(
logger model.Logger,
probeAddrs,
thAddrs []string,
) (result map[string]uint) {
const (
inProbe = 1 << iota
inTH
)
mapping := make(map[uint]int)
logger.Debugf("DNS: probeAddrs %+v, thAddrs %+v", probeAddrs, thAddrs)
uniqueAddrs := make(map[string]uint)
asnToFlags := make(map[uint]int)
for _, addr := range probeAddrs {
asn, _, _ := geoipx.LookupASN(addr)
mapping[asn] |= inProbe // including the zero ASN that means unknown
asnToFlags[asn] |= inProbe // including the zero ASN that means unknown
uniqueAddrs[addr] = asn
}
for _, addr := range thAddrs {
asn, _, _ := geoipx.LookupASN(addr)
mapping[asn] |= inTH // including the zero ASN that means unknown
asnToFlags[asn] |= inTH // including the zero ASN that means unknown
uniqueAddrs[addr] = asn
}
for addr, asn := range uniqueAddrs {
logger.Infof("DNS: addr %s has AS%d", addr, asn)
}
for asn, where := range mapping {
probeOnlyASNs := make(map[uint]bool)
for asn, where := range asnToFlags {
if (where & inTH) == 0 {
asns = append(asns, asn)
probeOnlyASNs[asn] = true
}
}
for asn := range probeOnlyASNs {
logger.Infof("DNS: AS%d: only seen by probe", asn)
}
result = make(map[string]uint)
for addr, asn := range uniqueAddrs {
if probeOnlyASNs[asn] {
result[addr] = asn
}
}
return
Expand Down
4 changes: 2 additions & 2 deletions internal/experiment/webconnectivity/analysishttpcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ func (tk *TestKeys) analysisHTTPToplevel(logger model.Logger) {
netxlite.FailureEOFError:
tk.BlockingFlags |= analysisFlagHTTPBlocking
logger.Warnf(
"HTTP: endpoint %s is blocked (see #%d): %s",
"HTTP: unexpected failure %s for %s (see #%d)",
*failure,
finalRequest.Address,
finalRequest.TransactionID,
*failure,
)
default:
// leave this case for ooni/pipeline
Expand Down
5 changes: 5 additions & 0 deletions internal/experiment/webconnectivity/analysishttpdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (tk *TestKeys) analysisHTTPDiff(logger model.Logger,
tk.BlockingFlags |= analysisFlagSuccess
return
}
logger.Infof("HTTP: body length: MISMATCH (see #%d)", probe.TransactionID)
if tk.HeadersMatch != nil && *tk.HeadersMatch {
logger.Infof(
"HTTP: statusCodeMatch && headersMatch => #%d is successful",
Expand All @@ -61,6 +62,7 @@ func (tk *TestKeys) analysisHTTPDiff(logger model.Logger,
tk.BlockingFlags |= analysisFlagSuccess
return
}
logger.Infof("HTTP: uncommon headers: MISMATCH (see #%d)", probe.TransactionID)
if tk.TitleMatch != nil && *tk.TitleMatch {
logger.Infof(
"HTTP: statusCodeMatch && titleMatch => #%d is successful",
Expand All @@ -69,6 +71,9 @@ func (tk *TestKeys) analysisHTTPDiff(logger model.Logger,
tk.BlockingFlags |= analysisFlagSuccess
return
}
logger.Infof("HTTP: title: MISMATCH (see #%d)", probe.TransactionID)
} else {
logger.Infof("HTTP: status code: MISMATCH (see #%d)", probe.TransactionID)
}

tk.BlockingFlags |= analysisFlagHTTPDiff
Expand Down
4 changes: 2 additions & 2 deletions internal/experiment/webconnectivity/analysistcpip.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ func (tk *TestKeys) analysisTCPIPToplevel(logger model.Logger) {
continue
}
logger.Warnf(
"TCP/IP: endpoint %s is blocked (see #%d): %s",
"TCP/IP: unexpected failure %s for %s (see #%d)",
*failure,
epnt,
entry.TransactionID,
*failure,
)
entry.Status.Blocked = &istrue
tk.BlockingFlags |= analysisFlagTCPIPBlocking
Expand Down
4 changes: 2 additions & 2 deletions internal/experiment/webconnectivity/analysistls.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ func (tk *TestKeys) analysisTLSToplevel(logger model.Logger) {
continue
}
logger.Warnf(
"TLS: endpoint %s is blocked (see #%d): %s",
"TLS: unexpected failure %s for %s (see #%d)",
*failure,
epnt,
entry.TransactionID,
*failure,
)
tk.BlockingFlags |= analysisFlagTLSBlocking
}
Expand Down
3 changes: 0 additions & 3 deletions internal/experiment/webconnectivity/dnsresolvers.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,6 @@ func (t *DNSResolvers) waitForLateReplies(parentCtx context.Context, trace *meas
defer t.WaitGroup.Done()
const lateTimeout = 500 * time.Millisecond
events := trace.DelayedDNSResponseWithTimeout(parentCtx, lateTimeout)
if length := len(events); length > 0 {
t.Logger.Warnf("got %d late DNS replies", length)
}
t.TestKeys.AppendDNSLateReplies(events...)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/experiment/webconnectivity/measurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (m *Measurer) ExperimentName() string {

// ExperimentVersion implements model.ExperimentMeasurer.
func (m *Measurer) ExperimentVersion() string {
return "0.5.16"
return "0.5.17"
}

// Run implements model.ExperimentMeasurer.
Expand Down
8 changes: 4 additions & 4 deletions internal/experiment/webconnectivity/testkeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ type TestKeys struct {
// Do53 contains ancillary observations collected by Do53 resolvers.
Do53 *TestKeysDo53 `json:"x_do53"`

// DNSLateReplies contains late replies we didn't expect to receive from
// DNSDuplicateResponses contains late/duplicate responses we didn't expect to receive from
// a resolver (which may raise eyebrows if they're different).
DNSLateReplies []*model.ArchivalDNSLookupResult `json:"x_dns_late_replies"`
DNSDuplicateResponses []*model.ArchivalDNSLookupResult `json:"x_dns_duplicate_responses"`

// Queries contains DNS queries.
Queries []*model.ArchivalDNSLookupResult `json:"queries"`
Expand Down Expand Up @@ -202,7 +202,7 @@ func (tk *TestKeys) AppendNetworkEvents(v ...*model.ArchivalNetworkEvent) {
// AppendDNSLateReplies appends to DNSLateReplies.
func (tk *TestKeys) AppendDNSLateReplies(v ...*model.ArchivalDNSLookupResult) {
tk.mu.Lock()
tk.DNSLateReplies = append(tk.DNSLateReplies, v...)
tk.DNSDuplicateResponses = append(tk.DNSDuplicateResponses, v...)
tk.mu.Unlock()
}

Expand Down Expand Up @@ -325,7 +325,7 @@ func NewTestKeys() *TestKeys {
NetworkEvents: []*model.ArchivalNetworkEvent{},
Queries: []*model.ArchivalDNSLookupResult{},
},
DNSLateReplies: []*model.ArchivalDNSLookupResult{},
DNSDuplicateResponses: []*model.ArchivalDNSLookupResult{},
Queries: []*model.ArchivalDNSLookupResult{},
Requests: []*model.ArchivalHTTPRequestResult{},
TCPConnect: []*model.ArchivalTCPConnectResult{},
Expand Down