summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--constants/constants.go9
-rw-r--r--lgc/lgc.go72
-rw-r--r--networkQuality.go81
-rw-r--r--timeoutat/timeoutat.go9
-rw-r--r--utilities/utilities.go23
5 files changed, 122 insertions, 72 deletions
diff --git a/constants/constants.go b/constants/constants.go
index 1a060dd..02038a3 100644
--- a/constants/constants.go
+++ b/constants/constants.go
@@ -31,3 +31,12 @@ var (
// The default URL for the config host.
DefaultConfigHost string = "networkquality.example.com"
)
+
+type DebugLevel int8
+
+const (
+ NoDebug DebugLevel = iota
+ Debug
+ Warn
+ Error
+)
diff --git a/lgc/lgc.go b/lgc/lgc.go
index 30d316a..5cf6078 100644
--- a/lgc/lgc.go
+++ b/lgc/lgc.go
@@ -25,6 +25,7 @@ import (
"sync/atomic"
"time"
+ "github.com/network-quality/goresponsiveness/constants"
"github.com/network-quality/goresponsiveness/utilities"
"golang.org/x/net/http2"
)
@@ -37,7 +38,7 @@ var GenerateConnectionId func() uint64 = func() func() uint64 {
}()
type LoadGeneratingConnection interface {
- Start(context.Context, bool) bool
+ Start(context.Context, constants.DebugLevel) bool
Transferred() uint64
Client() *http.Client
IsValid() bool
@@ -64,7 +65,7 @@ type LoadGeneratingConnectionDownload struct {
Path string
downloaded uint64
client *http.Client
- debug bool
+ debug constants.DebugLevel
valid bool
KeyLogger io.Writer
clientId uint64
@@ -79,7 +80,7 @@ func generateHttpTimingTracer(
DNSStart: func(dnsStartInfo httptrace.DNSStartInfo) {
lgd.stats.dnsStartTime = time.Now()
lgd.stats.dnsStart = dnsStartInfo
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf(
"DNS Start for %v: %v\n",
lgd.ClientId(),
@@ -90,13 +91,13 @@ func generateHttpTimingTracer(
DNSDone: func(dnsDoneInfo httptrace.DNSDoneInfo) {
lgd.stats.dnsCompleteTime = time.Now()
lgd.stats.dnsDone = dnsDoneInfo
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf("DNS Done for %v: %v\n", lgd.ClientId(), dnsDoneInfo)
}
},
ConnectStart: func(network, address string) {
lgd.stats.connectStartTime = time.Now()
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf(
"TCP Start of %v: %v: %v\n",
lgd.ClientId(),
@@ -107,7 +108,7 @@ func generateHttpTimingTracer(
},
ConnectDone: func(network, address string, err error) {
lgd.stats.connectCompleteTime = time.Now()
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf(
"TCP Done for %v: %v: %v (%v)\n",
lgd.ClientId(),
@@ -119,7 +120,7 @@ func generateHttpTimingTracer(
},
GetConn: func(hostPort string) {
lgd.stats.getConnectionStartTime = time.Now()
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf(
"GetConn host port for %v: %v\n",
lgd.ClientId(),
@@ -133,7 +134,7 @@ func generateHttpTimingTracer(
}
lgd.stats.connInfo = connInfo
lgd.stats.getConnectionCompleteTime = time.Now()
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf(
"GetConn host port for %v: %v\n",
lgd.ClientId(),
@@ -143,14 +144,14 @@ func generateHttpTimingTracer(
},
TLSHandshakeStart: func() {
lgd.stats.tlsStartTime = time.Now()
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf("TLSHandshakeStart for %v\n", lgd.ClientId())
}
},
TLSHandshakeDone: func(tlsConnState tls.ConnectionState, err error) {
lgd.stats.tlsCompleteTime = time.Now()
lgd.stats.tlsConnInfo = tlsConnState
- if lgd.debug {
+ if utilities.IsDebug(lgd.debug) {
fmt.Printf(
"TLSHandshakeDone for %v: %v\n",
lgd.ClientId(),
@@ -168,7 +169,7 @@ func (lbd *LoadGeneratingConnectionDownload) ClientId() uint64 {
func (lbd *LoadGeneratingConnectionDownload) Transferred() uint64 {
transferred := atomic.LoadUint64(&lbd.downloaded)
- if lbd.debug {
+ if utilities.IsDebug(lbd.debug) {
fmt.Printf("download: Transferred: %v\n", transferred)
}
return transferred
@@ -195,14 +196,15 @@ func (cr *countingReader) Read(p []byte) (n int, err error) {
func (lbd *LoadGeneratingConnectionDownload) Start(
ctx context.Context,
- debug bool,
+ debug constants.DebugLevel,
) bool {
lbd.downloaded = 0
lbd.clientId = GenerateConnectionId()
transport := http2.Transport{}
+ transport.TLSClientConfig = &tls.Config{}
if !utilities.IsInterfaceNil(lbd.KeyLogger) {
- if debug {
+ if utilities.IsDebug(lbd.debug) {
fmt.Printf(
"Using an SSL Key Logger for this load-generating download.\n",
)
@@ -215,18 +217,16 @@ func (lbd *LoadGeneratingConnectionDownload) Start(
// depend on whether the url contains
// https:// or http://:
// https://github.com/golang/go/blob/7ca6902c171b336d98adbb103d701a013229c806/src/net/http/transport.go#L74
- transport.TLSClientConfig = &tls.Config{
- KeyLogWriter: lbd.KeyLogger,
- InsecureSkipVerify: true,
- }
+ transport.TLSClientConfig.KeyLogWriter = lbd.KeyLogger
}
+ transport.TLSClientConfig.InsecureSkipVerify = true
lbd.client = &http.Client{Transport: &transport}
lbd.debug = debug
lbd.valid = true
lbd.tracer = generateHttpTimingTracer(lbd)
- if debug {
+ if utilities.IsDebug(debug) {
fmt.Printf(
"Started a load-generating download (id: %v).\n",
lbd.clientId,
@@ -240,22 +240,28 @@ func (lbd *LoadGeneratingConnectionDownload) IsValid() bool {
}
func (lbd *LoadGeneratingConnectionDownload) doDownload(ctx context.Context) {
- newRequest, err := http.NewRequestWithContext(
+ var request *http.Request = nil
+ var get *http.Response = nil
+ var err error = nil
+
+ if request, err = http.NewRequestWithContext(
httptrace.WithClientTrace(ctx, lbd.tracer),
"GET",
lbd.Path,
nil,
- )
+ ); err != nil {
+ lbd.valid = false
+ return
+ }
- get, err := lbd.client.Do(newRequest)
- if err != nil {
+ if get, err = lbd.client.Do(request); err != nil {
lbd.valid = false
return
}
cr := &countingReader{n: &lbd.downloaded, ctx: ctx, readable: get.Body}
_, _ = io.Copy(ioutil.Discard, cr)
get.Body.Close()
- if lbd.debug {
+ if utilities.IsDebug(lbd.debug) {
fmt.Printf("Ending a load-generating download.\n")
}
}
@@ -264,7 +270,7 @@ type LoadGeneratingConnectionUpload struct {
Path string
uploaded uint64
client *http.Client
- debug bool
+ debug constants.DebugLevel
valid bool
KeyLogger io.Writer
clientId uint64
@@ -276,7 +282,7 @@ func (lbu *LoadGeneratingConnectionUpload) ClientId() uint64 {
func (lbu *LoadGeneratingConnectionUpload) Transferred() uint64 {
transferred := atomic.LoadUint64(&lbu.uploaded)
- if lbu.debug {
+ if utilities.IsDebug(lbu.debug) {
fmt.Printf("upload: Transferred: %v\n", transferred)
}
return transferred
@@ -314,9 +320,10 @@ func (lbu *LoadGeneratingConnectionUpload) doUpload(ctx context.Context) bool {
if resp, err = lbu.client.Post(lbu.Path, "application/octet-stream", s); err != nil {
lbu.valid = false
+ return false
}
resp.Body.Close()
- if lbu.debug {
+ if utilities.IsDebug(lbu.debug) {
fmt.Printf("Ending a load-generating upload.\n")
}
return true
@@ -324,7 +331,7 @@ func (lbu *LoadGeneratingConnectionUpload) doUpload(ctx context.Context) bool {
func (lbu *LoadGeneratingConnectionUpload) Start(
ctx context.Context,
- debug bool,
+ debug constants.DebugLevel,
) bool {
lbu.uploaded = 0
lbu.clientId = GenerateConnectionId()
@@ -332,24 +339,23 @@ func (lbu *LoadGeneratingConnectionUpload) Start(
// See above for the rationale of doing http2.Transport{} here
// to ensure that we are using h2.
transport := http2.Transport{}
+ transport.TLSClientConfig = &tls.Config{}
if !utilities.IsInterfaceNil(lbu.KeyLogger) {
- if debug {
+ if utilities.IsDebug(lbu.debug) {
fmt.Printf(
"Using an SSL Key Logger for this load-generating upload.\n",
)
}
- transport.TLSClientConfig = &tls.Config{
- KeyLogWriter: lbu.KeyLogger,
- InsecureSkipVerify: true,
- }
+ transport.TLSClientConfig.KeyLogWriter = lbu.KeyLogger
}
+ transport.TLSClientConfig.InsecureSkipVerify = true
lbu.client = &http.Client{Transport: &transport}
lbu.debug = debug
lbu.valid = true
- if debug {
+ if utilities.IsDebug(lbu.debug) {
fmt.Printf("Started a load-generating upload (id: %v).\n", lbu.clientId)
}
go lbu.doUpload(ctx)
diff --git a/networkQuality.go b/networkQuality.go
index d450bf4..a7c7756 100644
--- a/networkQuality.go
+++ b/networkQuality.go
@@ -57,7 +57,11 @@ var (
"config",
"path on the server to the configuration endpoint.",
)
- debug = flag.Bool("debug", constants.DefaultDebug, "Enable debugging.")
+ debugCliFlag = flag.Bool(
+ "debug",
+ constants.DefaultDebug,
+ "Enable debugging.",
+ )
timeout = flag.Int(
"timeout",
constants.DefaultTestTime,
@@ -201,7 +205,7 @@ func addFlows(
lgcs *[]lgc.LoadGeneratingConnection,
lgcsPreviousTransferred *[]uint64,
lgcGenerator func() lgc.LoadGeneratingConnection,
- debug bool,
+ debug constants.DebugLevel,
) {
for i := uint64(0); i < toAdd; i++ {
*lgcs = append(*lgcs, lgcGenerator())
@@ -222,11 +226,12 @@ type SaturationResult struct {
}
type Debugging struct {
+ Level constants.DebugLevel
Prefix string
}
-func NewDebugging(prefix string) *Debugging {
- return &Debugging{Prefix: prefix}
+func NewDebugging(level constants.DebugLevel, prefix string) *Debugging {
+ return &Debugging{Level: level, Prefix: prefix}
}
func (d *Debugging) String() string {
@@ -251,7 +256,7 @@ func saturate(
&lgcs,
&lgcsPreviousTransferred,
lgcGenerator,
- debug != nil,
+ debug.Level,
)
previousFlowIncreaseIteration := uint64(0)
@@ -281,7 +286,7 @@ func saturate(
now := time.Now()
// At each 1-second interval
if nextSampleStartTime.Sub(now) > 0 {
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf(
"%v: Sleeping until %v\n",
debug,
@@ -300,7 +305,7 @@ func saturate(
allInvalid := true
for i := range lgcs {
if !lgcs[i].IsValid() {
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf(
"%v: Load-generating connection with id %d is invalid ... skipping.\n",
debug,
@@ -319,7 +324,7 @@ func saturate(
// For some reason, all the lgcs are invalid. This likely means that
// the network/server went away.
if allInvalid {
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf(
"%v: All lgcs were invalid. Assuming that network/server went away.\n",
debug,
@@ -339,7 +344,7 @@ func saturate(
previousMovingAverage,
)
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf(
"%v: Instantaneous goodput: %f MB.\n",
debug,
@@ -377,7 +382,7 @@ func saturate(
if (currentIteration - previousFlowIncreaseIteration) > uint64(
constants.MovingAverageStabilitySpan,
) {
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf(
"%v: Adding flows because we are unsaturated and waited a while.\n",
debug,
@@ -389,31 +394,31 @@ func saturate(
&lgcs,
&lgcsPreviousTransferred,
lgcGenerator,
- debug != nil,
+ debug.Level,
)
previousFlowIncreaseIteration = currentIteration
} else {
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf("%v: We are unsaturated, but it still too early to add anything.\n", debug)
}
}
} else { // Else, network reached saturation for the current flow count.
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf("%v: Network reached saturation with current flow count.\n", debug)
}
// If new flows added and for 4 seconds the moving average
// throughput did not change: network reached stable saturation
if (currentIteration-previousFlowIncreaseIteration) < uint64(constants.MovingAverageStabilitySpan) && movingAverageAverage.AllSequentialIncreasesLessThan(float64(5)) {
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf("%v: New flows added within the last four seconds and the moving-average average is consistent!\n", debug)
}
break
} else {
// Else, add four more flows
- if debug != nil {
+ if utilities.IsDebug(debug.Level) {
fmt.Printf("%v: New flows to add to try to increase our saturation!\n", debug)
}
- addFlows(saturationCtx, constants.AdditiveNumberOfLoadGeneratingConnections, &lgcs, &lgcsPreviousTransferred, lgcGenerator, debug != nil)
+ addFlows(saturationCtx, constants.AdditiveNumberOfLoadGeneratingConnections, &lgcs, &lgcsPreviousTransferred, lgcGenerator, debug.Level)
previousFlowIncreaseIteration = currentIteration
}
}
@@ -435,6 +440,11 @@ func main() {
context.Background(),
)
config := &Config{}
+ var debugLevel constants.DebugLevel = constants.Error
+
+ if *debugCliFlag {
+ debugLevel = constants.Debug
+ }
if err := config.Get(configHostPort, *configPath); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
@@ -449,16 +459,16 @@ func main() {
)
return
}
- if *debug {
+ if utilities.IsDebug(debugLevel) {
fmt.Printf("Configuration: %s\n", config)
}
timeoutChannel := timeoutat.TimeoutAt(
operatingCtx,
timeoutAbsoluteTime,
- *debug,
+ debugLevel,
)
- if *debug {
+ if utilities.IsDebug(debugLevel) {
fmt.Printf("Test will end earlier than %v\n", timeoutAbsoluteTime)
}
@@ -495,7 +505,7 @@ func main() {
fmt.Printf("Could not seek to the end of the key file: %v!\n", err)
sslKeyFileConcurrentWriter = nil
} else {
- if *debug {
+ if utilities.IsDebug(debugLevel) {
fmt.Printf("Doing SSL key logging through file %v\n", *sslKeyFileName)
}
sslKeyFileConcurrentWriter = ccw.NewConcurrentFileWriter(sslKeyFileHandle)
@@ -519,7 +529,7 @@ func main() {
var downloadDebugging *Debugging = nil
var uploadDebugging *Debugging = nil
- if *debug {
+ if utilities.IsDebug(debugLevel) {
downloadDebugging = &Debugging{Prefix: "download"}
uploadDebugging = &Debugging{Prefix: "upload"}
}
@@ -548,7 +558,7 @@ func main() {
case downloadSaturation = <-downloadSaturationChannel:
{
downloadSaturated = true
- if *debug {
+ if *debugCliFlag {
fmt.Printf(
"################# download is %s saturated (%fMBps, %d flows)!\n",
utilities.Conditional(
@@ -564,7 +574,7 @@ func main() {
case uploadSaturation = <-uploadSaturationChannel:
{
uploadSaturated = true
- if *debug {
+ if *debugCliFlag {
fmt.Printf(
"################# upload is %s saturated (%fMBps, %d flows)!\n",
utilities.Conditional(
@@ -588,7 +598,7 @@ func main() {
"Error: Saturation could not be completed in time and no provisional rates could be accessed. Test failed.\n",
)
cancelOperatingCtx()
- if *debug {
+ if *debugCliFlag {
time.Sleep(constants.CooldownPeriod)
}
return
@@ -605,9 +615,9 @@ func main() {
timeoutChannel = timeoutat.TimeoutAt(
operatingCtx,
timeoutAbsoluteTime,
- *debug,
+ debugLevel,
)
- if *debug {
+ if *debugCliFlag {
fmt.Printf(
"################# timeout reaching saturation!\n",
)
@@ -625,7 +635,7 @@ func main() {
timeoutChannel = timeoutat.TimeoutAt(
operatingCtx,
timeoutAbsoluteTime,
- *debug,
+ debugLevel,
)
}
@@ -643,10 +653,10 @@ func main() {
downloadSaturation.lgcs,
)
if !downloadSaturation.lgcs[randomlgcsIndex].IsValid() {
- if *debug {
+ if *debugCliFlag {
fmt.Printf(
"%v: The randomly selected download lgc (with id %d) was invalid. Skipping.\n",
- debug,
+ debugCliFlag,
downloadSaturation.lgcs[randomlgcsIndex].ClientId(),
)
}
@@ -655,7 +665,7 @@ func main() {
// invalid connections and never
// do the select below
if time.Since(timeoutAbsoluteTime) > 0 {
- if *debug {
+ if *debugCliFlag {
fmt.Printf(
"Pathologically could not find valid lgcs to use for measurement.\n",
)
@@ -666,12 +676,11 @@ func main() {
}
newTransport := http2.Transport{}
+ newTransport.TLSClientConfig = &tls.Config{}
if sslKeyFileConcurrentWriter != nil {
- newTransport.TLSClientConfig = &tls.Config{
- KeyLogWriter: sslKeyFileConcurrentWriter,
- InsecureSkipVerify: true,
- }
+ newTransport.TLSClientConfig.KeyLogWriter = sslKeyFileConcurrentWriter
}
+ newTransport.TLSClientConfig.InsecureSkipVerify = true
newClient := http.Client{Transport: &newTransport}
select {
@@ -691,7 +700,7 @@ func main() {
// We know that we have a good Sequential RTT.
totalRTsCount += uint64(sequentialRTTimes.RoundTripCount)
totalRTTimes += sequentialRTTimes.Delay.Seconds()
- if *debug {
+ if *debugCliFlag {
fmt.Printf(
"sequentialRTTsTime: %v\n",
sequentialRTTimes.Delay.Seconds(),
@@ -740,7 +749,7 @@ func main() {
}
cancelOperatingCtx()
- if *debug {
+ if *debugCliFlag {
fmt.Printf("In debugging mode, we will cool down.\n")
time.Sleep(constants.CooldownPeriod)
fmt.Printf("Done cooling down.\n")
diff --git a/timeoutat/timeoutat.go b/timeoutat/timeoutat.go
index 0e13a9f..eac57f2 100644
--- a/timeoutat/timeoutat.go
+++ b/timeoutat/timeoutat.go
@@ -18,17 +18,20 @@ import (
"context"
"fmt"
"time"
+
+ "github.com/network-quality/goresponsiveness/constants"
+ "github.com/network-quality/goresponsiveness/utilities"
)
func TimeoutAt(
ctx context.Context,
when time.Time,
- debug bool,
+ debug constants.DebugLevel,
) (response chan interface{}) {
response = make(chan interface{})
go func(ctx context.Context) {
go func() {
- if debug {
+ if utilities.IsDebug(debug) {
fmt.Printf("Timeout expected to end at %v\n", when)
}
select {
@@ -36,7 +39,7 @@ func TimeoutAt(
case <-ctx.Done():
}
response <- struct{}{}
- if debug {
+ if utilities.IsDebug(debug) {
fmt.Printf("Timeout ended at %v\n", time.Now())
}
}()
diff --git a/utilities/utilities.go b/utilities/utilities.go
index 46d5766..b8e416c 100644
--- a/utilities/utilities.go
+++ b/utilities/utilities.go
@@ -22,6 +22,8 @@ import (
"os"
"reflect"
"time"
+
+ "github.com/network-quality/goresponsiveness/constants"
)
func IsInterfaceNil(ifc interface{}) bool {
@@ -121,3 +123,24 @@ func SeekForAppend(file *os.File) (err error) {
_, err = file.Seek(0, 2)
return
}
+
+func IsDebug(level constants.DebugLevel) bool {
+ if level <= constants.Debug {
+ return true
+ }
+ return false
+}
+
+func IsWarn(level constants.DebugLevel) bool {
+ if level <= constants.Warn {
+ return true
+ }
+ return false
+}
+
+func IsError(level constants.DebugLevel) bool {
+ if level <= constants.Error {
+ return true
+ }
+ return false
+}