summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc/lgc.go18
-rw-r--r--rpm/rpm.go31
-rw-r--r--traceable/traceable_test.go153
3 files changed, 180 insertions, 22 deletions
diff --git a/lgc/lgc.go b/lgc/lgc.go
index b32721b..b0694db 100644
--- a/lgc/lgc.go
+++ b/lgc/lgc.go
@@ -279,14 +279,7 @@ func (lgd *LoadGeneratingConnectionDownload) Start(
)
}
- // Later, when the doDownload function attempts to add a tracer to the http request,
- // it will be associated with the context. Multiple tracers associated with the same
- // context will make it impossible to disambiguate the events. In other words, if there
- // are multiple tracers associated with the same context, *all* the tracers get invoked
- // every time that an event happens on a request with any of them! So, we will make a
- // unique context so that there is a one-to-one correspondence between tracers and requests.
- downloadCtx, _ := context.WithCancel(parentCtx)
- go lgd.doDownload(downloadCtx)
+ go lgd.doDownload(parentCtx)
return true
}
@@ -432,14 +425,7 @@ func (lgu *LoadGeneratingConnectionUpload) Start(
fmt.Printf("Started a load-generating upload (id: %v).\n", lgu.clientId)
}
- // Later, when the doUpload function attempts to add a tracer to the http request,
- // it will be associated with the context. Multiple tracers associated with the same
- // context will make it impossible to disambiguate the events. In other words, if there
- // are multiple tracers associated with the same context, *all* the tracers get invoked
- // every time that an event happens on a request with any of them! So, we will make a
- // unique context so that there is a one-to-one correspondence between tracers and requests.
- uploadCtx, _ := context.WithCancel(parentCtx)
- go lgu.doUpload(uploadCtx)
+ go lgu.doUpload(parentCtx)
return true
}
diff --git a/rpm/rpm.go b/rpm/rpm.go
index 07121a6..cee308f 100644
--- a/rpm/rpm.go
+++ b/rpm/rpm.go
@@ -53,12 +53,17 @@ type LGDataCollectionResult struct {
DataPoints []DataPoint
}
-func LGProbe(parentProbeCtx context.Context, connection lgc.LoadGeneratingConnection, lgProbeUrl string, result *chan DataPoint, debugging *debug.DebugWithPrefix) error {
- probeCtx, _ := context.WithCancel(parentProbeCtx)
+func LGProbe(
+ parentProbeCtx context.Context,
+ connection lgc.LoadGeneratingConnection,
+ lgProbeUrl string,
+ result *chan DataPoint,
+ debugging *debug.DebugWithPrefix,
+) error {
probeTracer := NewProbeTracer(connection.Client(), true, debugging)
time_before_probe := time.Now()
probe_req, err := http.NewRequestWithContext(
- httptrace.WithClientTrace(probeCtx, probeTracer.trace),
+ httptrace.WithClientTrace(parentProbeCtx, probeTracer.trace),
"GET",
lgProbeUrl,
nil,
@@ -109,9 +114,16 @@ func LGProbe(parentProbeCtx context.Context, connection lgc.LoadGeneratingConnec
*result <- DataPoint{RoundTripCount: 1, Duration: totalDelay}
return nil
- /////////////
}
-func LGProber(proberCtx context.Context, defaultConnection lgc.LoadGeneratingConnection, altConnections *[]lgc.LoadGeneratingConnection, url string, interval time.Duration, debugging *debug.DebugWithPrefix) (points chan DataPoint) {
+
+func LGProber(
+ proberCtx context.Context,
+ defaultConnection lgc.LoadGeneratingConnection,
+ altConnections *[]lgc.LoadGeneratingConnection,
+ url string,
+ interval time.Duration,
+ debugging *debug.DebugWithPrefix,
+) (points chan DataPoint) {
points = make(chan DataPoint)
go func() {
@@ -149,7 +161,14 @@ func LGCollectData(
lgProbeConfiguration := lgProbeConfigurationGenerator()
- LGProber(lgDataCollectionCtx, lgcs[0], &lgcs, lgProbeConfiguration.URL, time.Duration(100*time.Millisecond), debugging)
+ LGProber(
+ lgDataCollectionCtx,
+ lgcs[0],
+ &lgcs,
+ lgProbeConfiguration.URL,
+ time.Duration(100*time.Millisecond),
+ debugging,
+ )
previousFlowIncreaseInterval := uint64(0)
previousMovingAverage := float64(0)
diff --git a/traceable/traceable_test.go b/traceable/traceable_test.go
new file mode 100644
index 0000000..e0fcb04
--- /dev/null
+++ b/traceable/traceable_test.go
@@ -0,0 +1,153 @@
+package traceable
+
+import (
+ "context"
+ "crypto/tls"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptrace"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "time"
+
+ "github.com/network-quality/goresponsiveness/debug"
+)
+
+type CountingTraceable struct {
+ Counter *uint64
+}
+
+func (lgd *CountingTraceable) SetDnsStartTimeInfo(
+ now time.Time,
+ dnsStartInfo httptrace.DNSStartInfo,
+) {
+
+}
+
+func (lgd *CountingTraceable) SetDnsDoneTimeInfo(
+ now time.Time,
+ dnsDoneInfo httptrace.DNSDoneInfo,
+) {
+
+}
+
+func (lgd *CountingTraceable) SetConnectStartTime(
+ now time.Time,
+) {
+
+}
+
+func (lgd *CountingTraceable) SetConnectDoneTimeError(
+ now time.Time,
+ err error,
+) {
+
+}
+
+func (lgd *CountingTraceable) SetGetConnTime(now time.Time) {
+}
+
+func (lgd *CountingTraceable) SetGotConnTimeInfo(
+ now time.Time,
+ gotConnInfo httptrace.GotConnInfo,
+) {
+ atomic.AddUint64(lgd.Counter, 1)
+}
+
+func (lgd *CountingTraceable) SetTLSHandshakeStartTime(
+ now time.Time,
+) {
+}
+
+func (lgd *CountingTraceable) SetTLSHandshakeDoneTimeState(
+ now time.Time,
+ connectionState tls.ConnectionState,
+) {
+}
+
+func (lgd *CountingTraceable) SetHttpWroteRequestTimeInfo(
+ now time.Time,
+ info httptrace.WroteRequestInfo,
+) {
+}
+
+func (lgd *CountingTraceable) SetHttpResponseReadyTime(
+ now time.Time,
+) {
+}
+
+// Ensure that two different http client request tracers started with the same context
+// do not compose and receive each other's callbacks.
+func TestDuplicativeTraceables(t *testing.T) {
+
+ singleCtx, singleCtxCancel_ := context.WithCancel(context.Background())
+ defer singleCtxCancel_()
+
+ client := http.Client{}
+
+ counterA := new(uint64)
+ countingTracerA := CountingTraceable{Counter: counterA}
+ counterB := new(uint64)
+ countingTracerB := CountingTraceable{Counter: counterB}
+
+ debugging := debug.NewDebugWithPrefix(debug.Debug, "TestDuplicativeTraceables")
+ request_a, err := http.NewRequestWithContext(
+ httptrace.WithClientTrace(
+ singleCtx,
+ GenerateHttpTimingTracer(&countingTracerA, debugging.Level),
+ ),
+ "GET",
+ "https://www.google.com/",
+ nil,
+ )
+ if err != nil {
+ t.Fatalf("Failed to create request A to GET google.com")
+ }
+ request_b, err := http.NewRequestWithContext(
+ httptrace.WithClientTrace(
+ singleCtx,
+ GenerateHttpTimingTracer(&countingTracerB, debugging.Level),
+ ),
+ "GET",
+ "https://www.google.com/",
+ nil,
+ )
+ if err != nil {
+ t.Fatalf("Failed to create request B to GET google.com")
+ }
+
+ requestWg := new(sync.WaitGroup)
+
+ requestWg.Add(2)
+ go func() {
+ defer requestWg.Done()
+ get, err := client.Do(request_a)
+ if err != nil {
+ return
+ }
+ _, _ = io.Copy(ioutil.Discard, get.Body)
+ get.Body.Close()
+ }()
+ go func() {
+ defer requestWg.Done()
+ get, err := client.Do(request_b)
+ if err != nil {
+ return
+ }
+ _, _ = io.Copy(ioutil.Discard, get.Body)
+ get.Body.Close()
+ }()
+
+ requestWg.Wait()
+
+ if !(*counterA == 1 && *counterB == 1) {
+ t.Fatalf(
+ "Two separate tracers received overlapping callbacks on each other's http requests: (counterA: %d, counterB: %d)",
+ *counterA,
+ *counterB,
+ )
+ }
+
+}