/* Wraps the RoundTrip function of the given RoundTripper. Will provide accounting metrics for the http.Request / http.Response life-cycle Callers of RoundTrip are responsible for setting the ‘X-CF-RequestID’ field in the request header if they have one. Callers are also responsible for setting the ‘X-CF-ApplicationID’ and ‘X-CF-InstanceIndex’ fields in the request header if they are known. */ func (irt *instrumentedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { requestId, err := GenerateUuid() if err != nil { log.Printf("failed to generated request ID: %v\n", err) requestId = &uuid.UUID{} } httpStart := factories.NewHttpStart(req, events.PeerType_Client, requestId) parentRequestId, err := uuid.ParseHex(req.Header.Get("X-CF-RequestID")) if err == nil { httpStart.ParentRequestId = factories.NewUUID(parentRequestId) } req.Header.Set("X-CF-RequestID", requestId.String()) err = irt.emitter.Emit(httpStart) if err != nil { log.Printf("failed to emit start event: %v\n", err) } resp, roundTripErr := irt.roundTripper.RoundTrip(req) var httpStop *events.HttpStop if roundTripErr != nil { httpStop = factories.NewHttpStop(req, 0, 0, events.PeerType_Client, requestId) } else { httpStop = factories.NewHttpStop(req, resp.StatusCode, resp.ContentLength, events.PeerType_Client, requestId) } err = irt.emitter.Emit(httpStop) if err != nil { log.Printf("failed to emit stop event: %v\n", err) } return resp, roundTripErr }
BeforeEach(func() { applicationId, _ = uuid.NewV4() requestId, _ = uuid.NewV4() req, _ = http.NewRequest("GET", "http://foo.example.com/", nil) req.RemoteAddr = "127.0.0.1" req.Header.Set("User-Agent", "our-testing-client") }) Describe("NewHttpStart", func() { Context("without an application ID or instanceIndex", func() { It("should set appropriate fields", func() { expectedStartEvent := &events.HttpStart{ RequestId: factories.NewUUID(requestId), PeerType: events.PeerType_Server.Enum(), Method: events.HttpStart_GET.Enum(), Uri: proto.String("foo.example.com/"), RemoteAddress: proto.String("127.0.0.1"), UserAgent: proto.String("our-testing-client"), } startEvent := factories.NewHttpStart(req, events.PeerType_Server, requestId) Expect(startEvent.GetTimestamp()).ToNot(BeZero()) startEvent.Timestamp = nil Expect(startEvent).To(Equal(expectedStartEvent)) }) })
Expect(fakeEmitter.Messages[0].Event).To(BeAssignableToTypeOf(new(events.HttpStart))) Expect(fakeEmitter.Messages[0].Origin).To(Equal("testRoundtripper/42")) }) Context("if request ID already exists", func() { var existingRequestId *uuid.UUID BeforeEach(func() { existingRequestId, _ = uuid.NewV4() req.Header.Set("X-CF-RequestID", existingRequestId.String()) }) It("should emit the existing request ID as the parent request ID", func() { rt.RoundTrip(req) startEvent := fakeEmitter.Messages[0].Event.(*events.HttpStart) Expect(startEvent.GetParentRequestId()).To(Equal(factories.NewUUID(existingRequestId))) }) }) Context("if round tripper returns an error", func() { It("should emit a stop event with blank response fields", func() { fakeRoundTripper.FakeError = errors.New("fakeEmitter error") rt.RoundTrip(req) Expect(fakeEmitter.Messages[1].Event).To(BeAssignableToTypeOf(new(events.HttpStop))) stopEvent := fakeEmitter.Messages[1].Event.(*events.HttpStop) Expect(stopEvent.GetStatusCode()).To(BeNumerically("==", 0)) Expect(stopEvent.GetContentLength()).To(BeNumerically("==", 0)) }) })
type unknownEvent struct{} func (*unknownEvent) ProtoMessage() {} var _ = Describe("EventFormatter", func() { Describe("wrap", func() { var origin string BeforeEach(func() { origin = "testEventFormatter/42" }) It("should work with HttpStart events", func() { id, _ := uuid.NewV4() testEvent := &events.HttpStart{RequestId: factories.NewUUID(id)} envelope, err := emitter.Wrap(testEvent, origin) Expect(err).To(BeNil()) Expect(envelope.GetEventType()).To(Equal(events.Envelope_HttpStart)) Expect(envelope.GetHttpStart()).To(Equal(testEvent)) }) It("should work with HttpStop events", func() { id, _ := uuid.NewV4() testEvent := &events.HttpStop{RequestId: factories.NewUUID(id)} envelope, err := emitter.Wrap(testEvent, origin) Expect(err).To(BeNil()) Expect(envelope.GetEventType()).To(Equal(events.Envelope_HttpStop)) Expect(envelope.GetHttpStop()).To(Equal(testEvent))