commit fe3356a54dccebe5d474d67068f817ef69f5c099 Author: Cecylia Bocovich cohosh@torproject.org Date: Wed Jun 12 10:14:21 2019 -0400
Unit tests for metrics code
Added unit tests for metrics logging. Refactored the logMetrics() function to allow for easier testing --- broker/metrics.go | 33 ++++++---- broker/snowflake-broker_test.go | 129 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 13 deletions(-)
diff --git a/broker/metrics.go b/broker/metrics.go index b03c6db..5ac4192 100644 --- a/broker/metrics.go +++ b/broker/metrics.go @@ -116,25 +116,32 @@ func NewMetrics(metricsLogger *log.Logger) (*Metrics, error) { return m, nil }
+// Logs metrics in intervals specified by metricsResolution func (m *Metrics) logMetrics() { - heartbeat := time.Tick(metricsResolution) for range heartbeat { - m.logger.Println("snowflake-stats-end", time.Now().UTC().Format("2006-01-02 15:04:05"), "(", int(metricsResolution.Seconds()), "s)") - m.logger.Println("snowflake-ips", m.countryStats.Display()) - m.logger.Println("snowflake-idle-count", binCount(m.proxyIdleCount)) - m.logger.Println("client-denied-count", binCount(m.clientDeniedCount)) - m.logger.Println("client-snowflake-match-count", binCount(m.clientProxyMatchCount)) - - //restore all metrics to original values - m.proxyIdleCount = 0 - m.clientDeniedCount = 0 - m.clientProxyMatchCount = 0 - m.countryStats.counts = make(map[string]int) - m.countryStats.ips = make(map[string]bool) + m.printMetrics() + m.zeroMetrics() } }
+func (m *Metrics) printMetrics() { + m.logger.Println("snowflake-stats-end", time.Now().UTC().Format("2006-01-02 15:04:05"), "(", int(metricsResolution.Seconds()), "s)") + m.logger.Println("snowflake-ips", m.countryStats.Display()) + m.logger.Println("snowflake-idle-count", binCount(m.proxyIdleCount)) + m.logger.Println("client-denied-count", binCount(m.clientDeniedCount)) + m.logger.Println("client-snowflake-match-count", binCount(m.clientProxyMatchCount)) +} + +// Restores all metrics to original values +func (m *Metrics) zeroMetrics() { + m.proxyIdleCount = 0 + m.clientDeniedCount = 0 + m.clientProxyMatchCount = 0 + m.countryStats.counts = make(map[string]int) + m.countryStats.ips = make(map[string]bool) +} + // Rounds up a count to the nearest multiple of 8. func binCount(count int) int { return int((math.Ceil(float64(count) / 8)) * 8) diff --git a/broker/snowflake-broker_test.go b/broker/snowflake-broker_test.go index 03aa2b4..021122e 100644 --- a/broker/snowflake-broker_test.go +++ b/broker/snowflake-broker_test.go @@ -11,6 +11,7 @@ import ( "net/http/httptest" "os" "testing" + "time" )
func NullLogger() *log.Logger { @@ -390,3 +391,131 @@ func TestGeoip(t *testing.T) {
}) } + +func TestMetrics(t *testing.T) { + + Convey("Test metrics...", t, func() { + done := make(chan bool) + buf := new(bytes.Buffer) + ctx := NewBrokerContext(log.New(buf, "", 0)) + + err := ctx.metrics.LoadGeoipDatabases("test_geoip", "test_geoip6") + So(err, ShouldEqual, nil) + + //Test addition of proxy polls + Convey("for proxy polls", func() { + w := httptest.NewRecorder() + data := bytes.NewReader([]byte("test")) + r, err := http.NewRequest("POST", "snowflake.broker/proxy", data) + r.Header.Set("X-Session-ID", "test") + r.RemoteAddr = "129.97.208.23:8888" //CA geoip + So(err, ShouldBeNil) + go func(ctx *BrokerContext) { + proxyPolls(ctx, w, r) + done <- true + }(ctx) + p := <-ctx.proxyPolls //manually unblock poll + p.offerChannel <- nil + <-done + + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips CA=1,\nsnowflake-idle-count 8\nclient-denied-count 0\nclient-snowflake-match-count 0\n") + }) + + //Test addition of client failures + Convey("for no proxies available", func() { + w := httptest.NewRecorder() + data := bytes.NewReader([]byte("test")) + r, err := http.NewRequest("POST", "snowflake.broker/client", data) + So(err, ShouldBeNil) + + clientOffers(ctx, w, r) + + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips \nsnowflake-idle-count 0\nclient-denied-count 8\nclient-snowflake-match-count 0\n") + + // Test reset + buf.Reset() + ctx.metrics.zeroMetrics() + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips \nsnowflake-idle-count 0\nclient-denied-count 0\nclient-snowflake-match-count 0\n") + }) + //Test addition of client matches + Convey("for client-proxy match", func() { + w := httptest.NewRecorder() + data := bytes.NewReader([]byte("test")) + r, err := http.NewRequest("POST", "snowflake.broker/client", data) + So(err, ShouldBeNil) + + // Prepare a fake proxy to respond with. + snowflake := ctx.AddSnowflake("fake") + go func() { + clientOffers(ctx, w, r) + done <- true + }() + offer := <-snowflake.offerChannel + So(offer, ShouldResemble, []byte("test")) + snowflake.answerChannel <- []byte("fake answer") + <-done + + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips \nsnowflake-idle-count 0\nclient-denied-count 0\nclient-snowflake-match-count 8\n") + }) + //Test rounding boundary + Convey("binning boundary", func() { + w := httptest.NewRecorder() + data := bytes.NewReader([]byte("test")) + r, err := http.NewRequest("POST", "snowflake.broker/client", data) + So(err, ShouldBeNil) + + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + clientOffers(ctx, w, r) + + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips \nsnowflake-idle-count 0\nclient-denied-count 8\nclient-snowflake-match-count 0\n") + + clientOffers(ctx, w, r) + buf.Reset() + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips \nsnowflake-idle-count 0\nclient-denied-count 16\nclient-snowflake-match-count 0\n") + }) + + //Test unique ip + Convey("proxy counts by unique ip", func() { + w := httptest.NewRecorder() + data := bytes.NewReader([]byte("test")) + r, err := http.NewRequest("POST", "snowflake.broker/proxy", data) + r.Header.Set("X-Session-ID", "test") + r.RemoteAddr = "129.97.208.23:8888" //CA geoip + So(err, ShouldBeNil) + go func(ctx *BrokerContext) { + proxyPolls(ctx, w, r) + done <- true + }(ctx) + p := <-ctx.proxyPolls //manually unblock poll + p.offerChannel <- nil + <-done + + data = bytes.NewReader([]byte("test")) + r, err = http.NewRequest("POST", "snowflake.broker/proxy", data) + r.Header.Set("X-Session-ID", "test") + r.RemoteAddr = "129.97.208.23:8888" //CA geoip + go func(ctx *BrokerContext) { + proxyPolls(ctx, w, r) + done <- true + }(ctx) + p = <-ctx.proxyPolls //manually unblock poll + p.offerChannel <- nil + <-done + + ctx.metrics.printMetrics() + So(buf.String(), ShouldResemble, "snowflake-stats-end "+time.Now().UTC().Format("2006-01-02 15:04:05")+" ( 86400 s)\nsnowflake-ips CA=1,\nsnowflake-idle-count 8\nclient-denied-count 0\nclient-snowflake-match-count 0\n") + }) + }) +}