github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/metric/emitter/newrelic_test.go (about)

     1  package emitter_test
     2  
     3  import (
     4  	"compress/gzip"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"time"
    10  
    11  	"code.cloudfoundry.org/lager"
    12  	"github.com/pf-qiu/concourse/v6/atc/metric"
    13  	"github.com/pf-qiu/concourse/v6/atc/metric/emitter"
    14  
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/ginkgo/extensions/table"
    17  	. "github.com/onsi/gomega"
    18  	. "github.com/onsi/gomega/ghttp"
    19  )
    20  
    21  var _ = Describe("NewRelicEmitter", func() {
    22  
    23  	var (
    24  		testEmitter emitter.NewRelicEmitter
    25  		server      *Server
    26  		client      *http.Client
    27  		testEvent   metric.Event
    28  		testLogger  lager.Logger
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		testEvent = metric.Event{
    33  			Name:  "build started",
    34  			Value: 1,
    35  		}
    36  
    37  		testLogger = lager.NewLogger("newrelic")
    38  
    39  		server = NewServer()
    40  
    41  		client = &http.Client{
    42  			Transport: &http.Transport{},
    43  			Timeout:   time.Minute,
    44  		}
    45  	})
    46  
    47  	AfterEach(func() {
    48  		server.Close()
    49  	})
    50  
    51  	Context("Emits metrics", func() {
    52  		Context("when batch size is 2", func() {
    53  			BeforeEach(func() {
    54  				testEmitter = emitter.NewRelicEmitter{
    55  					NewRelicBatch: make([]emitter.NewRelicEvent, 0),
    56  					BatchDuration: 100 * time.Second,
    57  					BatchSize:     2,
    58  					LastEmitTime:  time.Now(),
    59  					Url:           server.URL(),
    60  					Client:        client,
    61  				}
    62  			})
    63  			It("should write one batch to NewRelic", func() {
    64  				server.RouteToHandler(http.MethodPost, "/", verifyEvents(2))
    65  				for i := 0; i < 3; i++ {
    66  					testEmitter.Emit(testLogger, testEvent)
    67  				}
    68  				Eventually(server.ReceivedRequests).Should(HaveLen(1))
    69  				Expect(testEmitter.NewRelicBatch).To(HaveLen(1))
    70  			})
    71  			It("should write two batches to NewRelic", func() {
    72  				server.RouteToHandler(http.MethodPost, "/", verifyEvents(2))
    73  				server.RouteToHandler(http.MethodPost, "/", verifyEvents(2))
    74  				for i := 0; i < 4; i++ {
    75  					testEmitter.Emit(testLogger, testEvent)
    76  				}
    77  				Eventually(server.ReceivedRequests).Should(HaveLen(2))
    78  				Expect(testEmitter.NewRelicBatch).To(HaveLen(0))
    79  			})
    80  			It("should write no batches to NewRelic", func() {
    81  				testEmitter.Emit(testLogger, testEvent)
    82  
    83  				time.Sleep(500 * time.Millisecond)
    84  				Eventually(server.ReceivedRequests).Should(HaveLen(0))
    85  				Expect(testEmitter.NewRelicBatch).To(HaveLen(1))
    86  			})
    87  		})
    88  		Context("when batch duration is 1 millisecond", func() {
    89  			BeforeEach(func() {
    90  				testEmitter = emitter.NewRelicEmitter{
    91  					NewRelicBatch: make([]emitter.NewRelicEvent, 0),
    92  					BatchDuration: 1 * time.Millisecond,
    93  					BatchSize:     100,
    94  					LastEmitTime:  time.Now(),
    95  					Url:           server.URL(),
    96  					Client:        client,
    97  				}
    98  			})
    99  			It("should write one batch to NewRelic", func() {
   100  				server.RouteToHandler(http.MethodPost, "/", verifyEvents(1))
   101  				time.Sleep(1 * time.Millisecond)
   102  				testEmitter.Emit(testLogger, testEvent)
   103  				Eventually(server.ReceivedRequests).Should(HaveLen(1))
   104  				Expect(testEmitter.NewRelicBatch).To(HaveLen(0))
   105  			})
   106  			It("should write two batches to NewRelic", func() {
   107  				server.RouteToHandler(http.MethodPost, "/", verifyEvents(1))
   108  				server.RouteToHandler(http.MethodPost, "/", verifyEvents(1))
   109  				for i := 0; i < 2; i++ {
   110  					time.Sleep(1 * time.Millisecond)
   111  					testEmitter.Emit(testLogger, testEvent)
   112  				}
   113  				Eventually(server.ReceivedRequests).Should(HaveLen(2))
   114  				Expect(testEmitter.NewRelicBatch).To(HaveLen(0))
   115  			})
   116  			It("should write no batches to NewRelic", func() {
   117  				testEmitter.Emit(testLogger, testEvent)
   118  				Eventually(server.ReceivedRequests).Should(HaveLen(0))
   119  				Expect(testEmitter.NewRelicBatch).To(HaveLen(1))
   120  
   121  			})
   122  		})
   123  
   124  		DescribeTable("Compression", func(compressionState bool, expectedEncoding string) {
   125  			testEmitter = emitter.NewRelicEmitter{
   126  				NewRelicBatch:      make([]emitter.NewRelicEvent, 0),
   127  				BatchDuration:      100 * time.Second,
   128  				BatchSize:          1,
   129  				LastEmitTime:       time.Now(),
   130  				Url:                server.URL(),
   131  				Client:             client,
   132  				DisableCompression: compressionState,
   133  			}
   134  
   135  			server.RouteToHandler(http.MethodPost, "/", verifyEvents(1))
   136  
   137  			testEmitter.Emit(testLogger, testEvent)
   138  			Eventually(server.ReceivedRequests).Should(HaveLen(1))
   139  			request := (server.ReceivedRequests())[0]
   140  			Expect(request.Header.Get("Content-Encoding")).To(Equal(expectedEncoding))
   141  		},
   142  			Entry("is enabled", false, "gzip"),
   143  			Entry("is disabled", true, ""),
   144  		)
   145  	})
   146  
   147  	Context("NewRelicConfiguration", func() {
   148  		It("sends events to configured endpoint", func() {
   149  			config := &emitter.NewRelicConfig{
   150  				AccountID: "123456",
   151  				APIKey:    "eu019347923874648573934074",
   152  				Url:       server.URL(),
   153  			}
   154  
   155  			server.RouteToHandler(http.MethodPost, "/v1/accounts/123456/events", verifyEvents(1))
   156  
   157  			e, _ := config.NewEmitter()
   158  			e.Emit(testLogger, testEvent)
   159  
   160  			newRelicEmitter := e.(*emitter.NewRelicEmitter)
   161  			Expect(newRelicEmitter.Url).To(Equal(fmt.Sprintf("%s/v1/accounts/123456/events", server.URL())))
   162  			Eventually(server.ReceivedRequests).Should(HaveLen(1))
   163  		})
   164  	})
   165  })
   166  
   167  func verifyEvents(expectedEvents int) http.HandlerFunc {
   168  	return func(writer http.ResponseWriter, request *http.Request) {
   169  		var (
   170  			givenBody []byte
   171  			err       error
   172  		)
   173  
   174  		if request.Header.Get("Content-Encoding") == "gzip" {
   175  			reader, err := gzip.NewReader(request.Body)
   176  			Expect(err).To(Not(HaveOccurred()))
   177  			givenBody, err = ioutil.ReadAll(reader)
   178  			Expect(err).To(Not(HaveOccurred()))
   179  		} else {
   180  			givenBody, err = ioutil.ReadAll(request.Body)
   181  			Expect(err).To(Not(HaveOccurred()))
   182  		}
   183  
   184  		var events []emitter.NewRelicEvent
   185  		err = json.Unmarshal(givenBody, &events)
   186  		Expect(err).To(Not(HaveOccurred()))
   187  
   188  		Expect(len(events)).To(BeNumerically("==", expectedEvents))
   189  
   190  		for _, event := range events {
   191  			Expect(event["eventType"]).To(Equal("build_started"))
   192  			Expect(event["value"]).To(Equal(float64(1)))
   193  		}
   194  
   195  		writer.WriteHeader(http.StatusOK)
   196  	}
   197  }