})

	Describe("ConvergeTasks", func() {
		const (
			taskGuid  = "some-guid"
			taskGuid2 = "some-other-guid"
			domain    = "some-domain"
			cellId    = "cell-id"
		)

		JustBeforeEach(func() {
			etcdDB.ConvergeTasks(logger, kickTasksDuration, expirePendingTaskDuration, expireCompletedTaskDuration)
		})

		It("bumps the convergence counter", func() {
			Expect(sender.GetCounter("ConvergenceTaskRuns")).To(Equal(uint64(1)))
		})

		It("reports the duration that it took to converge", func() {
			reportedDuration := sender.GetValue("ConvergenceTaskDuration")
			Expect(reportedDuration.Unit).To(Equal("nanos"))
			Expect(reportedDuration.Value).NotTo(BeZero())
		})

		It("emits -1 metrics", func() {
			Expect(sender.GetValue("TasksPending").Value).To(Equal(float64(-1)))
			Expect(sender.GetValue("TasksRunning").Value).To(Equal(float64(-1)))
			Expect(sender.GetValue("TasksCompleted").Value).To(Equal(float64(-1)))
			Expect(sender.GetValue("TasksResolving").Value).To(Equal(float64(-1)))
		})
Beispiel #2
0
				EventType: events.Envelope_LogMessage.Enum(),
				LogMessage: &events.LogMessage{
					Message:     []byte{4, 5, 6},
					MessageType: events.LogMessage_OUT.Enum(),
					Timestamp:   proto.Int64(123),
					AppId:       proto.String("fake-app-id"),
				},
			}))
		})

		It("does not put an envelope on the output channel if there is unmarshal error", func() {
			unmarshaller.Write([]byte{1, 2, 3})
			Expect(writer.Events).To(BeEmpty())
		})
	})

	Context("metrics", func() {
		BeforeEach(func() {
			unmarshaller = legacyunmarshaller.New(&writer, loggertesthelper.Logger())
			fakeSender = fake.NewFakeMetricSender()
			batcher := metricbatcher.New(fakeSender, time.Millisecond)
			metrics.Initialize(fakeSender, batcher)
		})

		It("emits an unmarshal error counter", func() {
			unmarshaller.Write([]byte{1, 2, 3})
			Eventually(func() uint64 { return fakeSender.GetCounter("legacyUnmarshaller.unmarshalErrors") }).Should(BeEquivalentTo(1))
		})
	})
})
	BeforeEach(func() {
		fakeMetricSender = fake.NewFakeMetricSender()
		metrics.Initialize(fakeMetricSender)
	})

	It("delegates SendValue", func() {
		metrics.SendValue("metric", 42.42, "answers")

		Expect(fakeMetricSender.GetValue("metric").Value).To(Equal(42.42))
		Expect(fakeMetricSender.GetValue("metric").Unit).To(Equal("answers"))
	})

	It("delegates IncrementCounter", func() {
		metrics.IncrementCounter("count")

		Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(1))

		metrics.IncrementCounter("count")

		Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(2))
	})

	It("delegates AddToCounter", func() {
		metrics.AddToCounter("count", 5)

		Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(5))

		metrics.AddToCounter("count", 10)

		Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(15))
	})
Beispiel #4
0
			It("responds with 202", func() {
				Expect(responseRecorder.Code).To(Equal(http.StatusAccepted))
			})

			It("logs with the correct session nesting", func() {
				Expect(logger.TestSink.LogMessages()).To(Equal([]string{
					"test.request.serving",
					"test.request.task-auction-handler.create.submitted",
					"test.request.done",
				}))
			})

			It("sends the correct metrics", func() {
				Expect(sender.GetValue("RequestLatency").Value).To(BeNumerically(">", 0))
				Expect(sender.GetCounter("RequestCount")).To(BeEquivalentTo(1))
			})
		})
	})

	Describe("LRP Handler", func() {
		Context("with a valid LRPStart", func() {
			BeforeEach(func() {
				starts := []auctioneer.LRPStartRequest{{
					Indices: []int{2},

					Domain:      "tests",
					ProcessGuid: "some-guid",

					Resource: rep.Resource{
						RootFs:   "docker:///docker.com/docker",
						reportedDuration := sender.GetValue("VolmanMountDuration")
						Expect(reportedDuration.Unit).To(Equal("nanos"))
						Expect(reportedDuration.Value).NotTo(BeZero())
						reportedDuration = sender.GetValue("VolmanMountDurationForfakedriver")
						Expect(reportedDuration.Unit).To(Equal("nanos"))
						Expect(reportedDuration.Value).NotTo(BeZero())
					})

					It("should increment error count on mount failure", func() {
						mountResponse := voldriver.MountResponse{Err: "an error"}
						fakeDriver.MountReturns(mountResponse)

						volumeId := "fake-volume"
						client.Mount(logger, "fakedriver", volumeId, map[string]interface{}{"volume_id": volumeId})
						Expect(sender.GetCounter("VolmanMountErrors")).To(Equal(uint64(1)))
					})

				})
			})

			Context("umount", func() {
				It("should be able to unmount", func() {
					volumeId := "fake-volume"

					err := client.Unmount(logger, "fakedriver", volumeId)
					Expect(err).NotTo(HaveOccurred())
					Expect(fakeDriver.UnmountCallCount()).To(Equal(1))
					Expect(fakeDriver.RemoveCallCount()).To(Equal(0))
				})
		Context("when a staging request is received for a registered backend", func() {
			var stagingRequest cc_messages.StagingRequestFromCC

			BeforeEach(func() {
				stagingRequest = cc_messages.StagingRequestFromCC{
					AppId:     "myapp",
					Lifecycle: "fake-backend",
				}

				var err error
				stagingRequestJson, err = json.Marshal(stagingRequest)
				Expect(err).NotTo(HaveOccurred())
			})

			It("increments the counter to track arriving staging messages", func() {
				Expect(fakeMetricSender.GetCounter("StagingStartRequestsReceived")).To(Equal(uint64(1)))
			})

			It("returns an Accepted response", func() {
				Expect(responseRecorder.Code).To(Equal(http.StatusAccepted))
			})

			It("builds a staging recipe", func() {
				Expect(fakeBackend.BuildRecipeCallCount()).To(Equal(1))

				guid, request := fakeBackend.BuildRecipeArgsForCall(0)
				Expect(guid).To(Equal("a-staging-guid"))
				Expect(request).To(Equal(stagingRequest))
			})

			Context("when the recipe was built successfully", func() {
				table.SetRoutesReturns(dummyMessagesToEmit)

				nextEvent.Store(EventHolder{models.NewDesiredLRPCreatedEvent(desiredLRP)})
			})

			It("should set the routes on the table", func() {
				Eventually(table.SetRoutesCallCount).Should(Equal(1))

				key, routes := table.SetRoutesArgsForCall(0)
				Expect(key).To(Equal(expectedRoutingKey))
				Expect(routes).To(Equal(routing_table.Routes{Hostnames: expectedRoutes, LogGuid: logGuid, RouteServiceUrl: expectedRouteServiceUrl}))
			})

			It("sends a 'routes registered' metric", func() {
				Eventually(func() uint64 {
					return fakeMetricSender.GetCounter("RoutesRegistered")
				}).Should(BeEquivalentTo(2))
			})

			It("sends a 'routes unregistered' metric", func() {
				Eventually(func() uint64 {
					return fakeMetricSender.GetCounter("RoutesUnRegistered")
				}).Should(BeEquivalentTo(0))
			})

			It("should emit whatever the table tells it to emit", func() {
				Eventually(emitter.EmitCallCount).Should(Equal(2))
				messagesToEmit := emitter.EmitArgsForCall(1)
				Expect(messagesToEmit).To(Equal(dummyMessagesToEmit))
			})
Beispiel #8
0
		It("writes message to client", func() {
			byteWriter.WriteOutput.sentLength <- len(prefixedMessage)
			bytesWritten, err := batcher.Write(messageBytes)
			Expect(err).ToNot(HaveOccurred())
			Expect(bytesWritten).To(Equal(len(messageBytes)))
			Expect(byteWriter.WriteInput.message).To(Receive(Equal(prefixedMessage)))
		})

		It("sends a sentMessages metric", func() {
			close(byteWriter.WriteOutput.sentLength)
			_, err := batcher.Write(messageBytes)
			Expect(err).ToNot(HaveOccurred())

			Eventually(byteWriter.WriteInput.message).Should(Receive(Equal(prefixedMessage)))
			Eventually(func() uint64 { return sender.GetCounter("DopplerForwarder.sentMessages") }).Should(BeEquivalentTo(1))
		})

		Context("the weighted writer errors once", func() {
			BeforeEach(func() {
				byteWriter.WriteOutput.sentLength <- 0
				byteWriter.WriteOutput.err = make(chan error, 1)
				byteWriter.WriteOutput.err <- errors.New("boom")
			})

			JustBeforeEach(func() {
				byteWriter.WriteOutput.sentLength <- len(prefixedMessage)
				close(byteWriter.WriteOutput.err)
			})

			It("retries", func() {
	})

	Context("udp client", func() {
		BeforeEach(func() {
			client.SchemeReturns("udp")
		})

		It("marshals, signs, writes and emits metrics", func() {
			bytes, err := proto.Marshal(envelope)
			Expect(err).NotTo(HaveOccurred())
			bytes = signature.SignMessage(bytes, sharedSecret)

			forwarder.Write(envelope)

			Expect(client.WriteArgsForCall(0)).To(Equal(bytes))
			Eventually(func() uint64 { return sender.GetCounter("DopplerForwarder.sentMessages") }).Should(BeEquivalentTo(1))
			Expect(sender.GetCounter("dropsondeMarshaller.logMessageMarshalled")).To(BeEquivalentTo(1))
		})

		Context("when writes fail", func() {
			BeforeEach(func() {
				client.WriteReturns(0, errors.New("boom"))
			})

			It("does not increment message count or sentMessages", func() {
				forwarder.Write(envelope)

				Consistently(func() uint64 { return sender.GetCounter("DopplerForwarder.sentMessages") }).Should(BeZero())
				Expect(sender.GetCounter("dropsondeMarshaller.LogMessageMarshalled")).To(BeZero())
			})
		})
				Origin:     proto.String("fake-origin-1"),
				EventType:  events.Envelope_LogMessage.Enum(),
				LogMessage: factories.NewLogMessage(events.LogMessage_OUT, "message", "appid", "sourceType"),
			}
			message, _ = proto.Marshal(envelope)

			marshaller.Write(envelope)
		})

		It("marshals envelopes into bytes", func() {
			Expect(writer.Data()).Should(HaveLen(1))
			outputMessage := writer.Data()[0]
			Expect(outputMessage).To(Equal(message))
		})

		It("emits a metric", func() {
			Eventually(func() uint64 { return fakeMetricSender.GetCounter("dropsondeMarshaller.logMessageMarshalled") }).Should(BeEquivalentTo(1))
		})
	})

	Context("invalid envelope", func() {
		It("emits a dropsonde marshal error counter", func() {
			envelope := &events.Envelope{}

			marshaller.Write(envelope)

			Eventually(func() uint64 { return fakeMetricSender.GetCounter("dropsondeMarshaller.marshalErrors") }).Should(BeEquivalentTo(1))
		})
	})
})
					Expect(metric.Value).To(Equal(uint64(1)))
				case "sentByteCount":
					Expect(metric.Value).To(Equal(uint64(21)))
				case "receivedMessageCount":
					Expect(metric.Value).To(Equal(uint64(1)))
				case "receivedByteCount":
					Expect(metric.Value).To(Equal(uint64(21)))
				default:
					Fail("Got an invalid metric name: " + metric.Name)
				}
			}
		})

		It("sends metrics using dropsonde", func() {
			Expect(fakeMetricSender.GetValue("currentBufferCount")).To(Equal(fake.Metric{Value: 0, Unit: "Msg"}))
			Expect(fakeMetricSender.GetCounter("sentMessageCount")).To(BeEquivalentTo(1))
			Expect(fakeMetricSender.GetCounter("sentByteCount")).To(BeEquivalentTo(21))
			Expect(fakeMetricSender.GetCounter("receivedMessageCount")).To(BeEquivalentTo(1))
			Expect(fakeMetricSender.GetCounter("receivedByteCount")).To(BeEquivalentTo(21))
		})
	})

	It("doesn't send empty data", func() {
		bufferSize := 4096
		firstMessage := []byte("")
		secondMessage := []byte("hi")

		loggregatorClient.Send(firstMessage)
		loggregatorClient.Send(secondMessage)

		buffer := make([]byte, bufferSize)
Beispiel #12
0
			protocol = "tcp"
		})

		It("counts the number of bytes sent", func() {
			// subtract a magic number three from the message length to make sure
			// we report the bytes sent by the client, not just the len of the
			// message given to it
			sentLength := len(message) - 3
			client.WriteOutput.sentLength <- sentLength
			client.WriteOutput.err <- nil

			err := wrapper.Write(client, message)
			Expect(err).NotTo(HaveOccurred())

			Eventually(func() uint64 {
				return sender.GetCounter("tcp.sentByteCount")
			}).Should(BeEquivalentTo(sentLength))
		})

		It("counts the number of messages sent", func() {
			client.WriteOutput.sentLength <- len(message)
			client.WriteOutput.err <- nil
			err := wrapper.Write(client, message)
			Expect(err).NotTo(HaveOccurred())

			Eventually(func() uint64 {
				return sender.GetCounter("tcp.sentMessageCount")
			}).Should(BeEquivalentTo(1))

			client.WriteOutput.sentLength <- len(message)
			client.WriteOutput.err <- nil
				}
			})

			JustBeforeEach(func() {
				marshaller.SetWriter(nil)
			})

			It("does not panic", func() {
				Expect(func() {
					marshaller.Write(envelope)
				}).ToNot(Panic())
			})

			It("counts messages written while byteWriter was nil", func() {
				marshaller.Write(envelope)
				Eventually(func() uint64 { return sender.GetCounter("dropsondeMarshaller.nilByteWriterWrites") }).Should(BeEquivalentTo(1))
			})
		})

		Context("with an invalid envelope", func() {
			BeforeEach(func() {
				envelope = &events.Envelope{}
				close(writer.WriteOutput.SentLength)
				close(writer.WriteOutput.Err)
			})

			It("counts marshal errors", func() {
				marshaller.Write(envelope)
				Eventually(func() uint64 { return sender.GetCounter("dropsondeMarshaller.marshalErrors") }).Should(BeEquivalentTo(1))
			})
Beispiel #14
0
			BeforeEach(func() {
				close(byteWriter.WriteOutput.SentLength)

				// close enough
				infinity := 10
				byteWriter.WriteOutput.Err = make(chan error, infinity)
				for i := 0; i < infinity; i++ {
					byteWriter.WriteOutput.Err <- errors.New("To INFINITY (but not beyond)")
				}
			})

			It("increments the dropped message counter", func() {
				batcher.Write(messageBytes)

				Eventually(droppedCounter.DropInput.Count).Should(Receive(BeNumerically("==", 1)))
				Consistently(func() uint64 { return sender.GetCounter("DopplerForwarder.sentMessages") }).Should(BeEquivalentTo(0))
			})
		})
	})

	Context("message smaller than buffer size", func() {
		var twoMessageOutput []byte

		BeforeEach(func() {
			for uint64(len(messageBytes)) < bufferSize/2 {
				messageBytes = append(messageBytes, messageBytes...)
			}
		})

		JustBeforeEach(func() {
			twoMessageOutput = append(prefixedMessage, prefixedMessage...)
			Consistently(func() int { return len(mockWriter.Events) }).Should(Equal(0))
		})
	})

	Context("metrics", func() {
		var fakeSender *fake.FakeMetricSender

		BeforeEach(func() {
			fakeSender = fake.NewFakeMetricSender()
			batcher := metricbatcher.New(fakeSender, time.Millisecond)
			metrics.Initialize(fakeSender, batcher)
		})

		var eventuallyExpectMetric = func(name string, value uint64) {
			Eventually(func() uint64 {
				return fakeSender.GetCounter("MessageAggregator." + name)
			}).Should(Equal(value), fmt.Sprintf("Metric %s was incorrect", name))
		}

		It("emits a HTTP start counter", func() {
			messageAggregator.Write(createStartMessage(123, events.PeerType_Client))
			eventuallyExpectMetric("httpStartReceived", 1)
		})

		It("emits a HTTP stop counter", func() {
			messageAggregator.Write(createStopMessage(123, events.PeerType_Client))
			eventuallyExpectMetric("httpStopReceived", 1)
		})

		It("emits a HTTP StartStop counter", func() {
			messageAggregator.Write(createStartMessage(123, events.PeerType_Client))
			lagertest.NewTestLogger("test"),
			reportInterval,
			&etcdOptions,
			fakeClock,
		))
	})

	AfterEach(func() {
		pmn.Signal(os.Interrupt)
		Eventually(pmn.Wait(), 2*time.Second).Should(Receive())
	})

	Context("when the metron notifier starts up", func() {
		It("should emit an event that BBS has started", func() {
			Eventually(func() uint64 {
				return sender.GetCounter("BBSMasterElected")
			}).Should(Equal(uint64(1)))
		})
	})

	Context("when the report interval elapses", func() {
		JustBeforeEach(func() {
			fakeClock.Increment(reportInterval)
		})

		Context("when the etcd cluster is around", func() {
			var (
				etcd1 *ghttp.Server
				etcd2 *ghttp.Server
				etcd3 *ghttp.Server
			)
		message, err = proto.Marshal(envelope)
		Expect(err).NotTo(HaveOccurred())

	})

	It("counts the number of bytes sent", func() {
		// Make sure the counter counts the sent byte count,
		// instead of len(message)
		sentLength := len(message) - 3
		client.WriteOutput.sentLength <- sentLength
		client.WriteOutput.err <- nil

		err := udpWrapper.Write(client, message)
		Expect(err).NotTo(HaveOccurred())
		Eventually(func() uint64 {
			return sender.GetCounter("udp.sentByteCount")
		}).Should(BeEquivalentTo(sentLength))
	})

	It("counts the number of messages sent", func() {
		client.WriteOutput.sentLength <- len(message)
		client.WriteOutput.err <- nil

		err := udpWrapper.Write(client, message)
		Expect(err).NotTo(HaveOccurred())
		Eventually(func() uint64 {
			return sender.GetCounter("udp.sentMessageCount")
		}).Should(BeEquivalentTo(1))
		Eventually(func() uint64 {
			return sender.GetCounter("DopplerForwarder.sentMessages")
		}).Should(BeEquivalentTo(1))
		It("creates the desired LRP", func() {
			Expect(fakeBBS.DesireLRPCallCount()).To(Equal(1))

			Expect(fakeBBS.DesiredLRPByProcessGuidCallCount()).To(Equal(1))
			Expect(fakeBBS.DesireLRPArgsForCall(0)).To(Equal(newlyDesiredLRP))

			Expect(buildpackBuilder.BuildArgsForCall(0)).To(Equal(&desireAppRequest))
		})

		It("responds with 202 Accepted", func() {
			Expect(responseRecorder.Code).To(Equal(http.StatusAccepted))
		})

		It("increments the desired LRPs counter", func() {
			Expect(metricSender.GetCounter("LRPsDesired")).To(Equal(uint64(1)))
		})

		Context("when the bbs fails", func() {
			BeforeEach(func() {
				fakeBBS.DesireLRPReturns(errors.New("oh no"))
			})

			It("responds with a ServiceUnavailabe error", func() {
				Expect(responseRecorder.Code).To(Equal(http.StatusServiceUnavailable))
			})
		})

		Context("when the bbs fails with a Conflict error", func() {
			BeforeEach(func() {
				fakeBBS.DesireLRPStub = func(_ *models.DesiredLRP) error {
				var err error
				backendResponseJson, err = json.Marshal(backendResponse)
				Expect(err).NotTo(HaveOccurred())
			})

			It("posts the response builder's result to CC", func() {
				Expect(fakeCCClient.StagingCompleteCallCount()).To(Equal(1))
				guid, payload, _ := fakeCCClient.StagingCompleteArgsForCall(0)
				Expect(guid).To(Equal("the-task-guid"))
				Expect(payload).To(Equal(backendResponseJson))
			})

			Context("when the CC request succeeds", func() {
				It("increments the staging success counter", func() {
					Expect(metricSender.GetCounter("StagingRequestsSucceeded")).To(BeEquivalentTo(1))
				})

				It("emits the time it took to stage succesfully", func() {
					Expect(metricSender.GetValue("StagingRequestSucceededDuration")).To(Equal(fake.Metric{
						Value: float64(stagingDurationNano),
						Unit:  "nanos",
					}))

				})

				It("returns a 200", func() {
					Expect(responseRecorder.Code).To(Equal(200))
				})
			})
var _ = Describe("MetricBatcher", func() {
	var (
		fakeMetricSender *fake.FakeMetricSender
		metricBatcher    *metricbatcher.MetricBatcher
	)

	BeforeEach(func() {
		fakeMetricSender = fake.NewFakeMetricSender()
		metricBatcher = metricbatcher.New(fakeMetricSender, 50*time.Millisecond)
	})

	Describe("BatchIncrementCounter", func() {
		It("batches and then sends a single metric", func() {
			metricBatcher.BatchIncrementCounter("count")
			Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(0)) // should not increment.

			metricBatcher.BatchIncrementCounter("count")
			metricBatcher.BatchIncrementCounter("count")

			time.Sleep(75 * time.Millisecond)
			Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(3)) // should update counter only when time out

			metricBatcher.BatchIncrementCounter("count")
			metricBatcher.BatchIncrementCounter("count")
			Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(3)) // should update counter only when time out

			time.Sleep(75 * time.Millisecond)
			Expect(fakeMetricSender.GetCounter("count")).To(BeEquivalentTo(5)) // should update counter only when time out
		})
		BeforeEach(func() {
			client.SchemeReturns("udp")
		})

		It("counts the number of bytes sent", func() {
			bytes, err := proto.Marshal(envelope)
			Expect(err).NotTo(HaveOccurred())

			client.WriteReturns(len(bytes), nil)

			n := uint32(len(bytes))

			forwarder.Write(envelope)

			Eventually(func() uint64 {
				return sender.GetCounter("udp.sentByteCount")
			}).Should(BeEquivalentTo(n))
		})

		It("counts the number of messages sent", func() {
			forwarder.Write(envelope)

			Eventually(func() uint64 {
				return sender.GetCounter("udp.sentMessageCount")
			}).Should(BeEquivalentTo(1))
		})

		It("increments transmitErrorCount if client write fails", func() {
			err := errors.New("Client Write Failed")
			client.WriteReturns(0, err)
						AuctionRecord: auctiontypes.AuctionRecord{PlacementError: rep.ErrorInsufficientResources.Error()},
					},
					{
						LRP:           rep.NewLRP(models.NewActualLRPKey("incompatible-stacks", 0, "domain"), resource),
						AuctionRecord: auctiontypes.AuctionRecord{PlacementError: auctiontypes.ErrorCellMismatch.Error()},
					},
				},
				FailedTasks: []auctiontypes.TaskAuction{
					{
						Task:          rep.NewTask("failed-task", "domain", resource),
						AuctionRecord: auctiontypes.AuctionRecord{PlacementError: rep.ErrorInsufficientResources.Error()},
					},
				},
			})

			Expect(metricSender.GetCounter("AuctioneerLRPAuctionsStarted")).To(BeNumerically("==", 1))
			Expect(metricSender.GetCounter("AuctioneerTaskAuctionsStarted")).To(BeNumerically("==", 1))
			Expect(metricSender.GetCounter("AuctioneerLRPAuctionsFailed")).To(BeNumerically("==", 2))
			Expect(metricSender.GetCounter("AuctioneerTaskAuctionsFailed")).To(BeNumerically("==", 1))
		})
	})

	Describe("FetchStatesCompleted", func() {
		It("should adjust the metric counters", func() {
			delegate.FetchStatesCompleted(1 * time.Second)

			sentMetric := metricSender.GetValue("AuctioneerFetchStatesDuration")
			Expect(sentMetric.Value).To(Equal(1e+09))
			Expect(sentMetric.Unit).To(Equal("nanos"))
		})
	})
Beispiel #23
0
		)

		BeforeEach(func() {
			sender = fake.NewFakeMetricSender()
			dropsonde_metrics.Initialize(sender, nil)

			handler = func(w http.ResponseWriter, r *http.Request) { time.Sleep(10) }
			handler = middleware.RequestCountWrap(handler)
		})

		It("reports call count", func() {
			handler.ServeHTTP(nil, nil)
			handler.ServeHTTP(nil, nil)
			handler.ServeHTTP(nil, nil)

			Expect(sender.GetCounter("RequestCount")).To(Equal(uint64(3)))
		})
	})

	Describe("LogWrap", func() {
		var (
			logger              *lagertest.TestLogger
			loggableHandlerFunc middleware.LoggableHandlerFunc
		)

		BeforeEach(func() {
			logger = lagertest.NewTestLogger("test-session")
			logger.RegisterSink(lager.NewWriterSink(GinkgoWriter, lager.DEBUG))
			loggableHandlerFunc = func(logger lager.Logger, w http.ResponseWriter, r *http.Request) {
				logger = logger.Session("logger-group")
				logger.Info("written-in-loggable-handler")
			Expect(mockWriter.Events[0]).To(Equal(event))
		})

		It("returns an error when it can't unmarshal", func() {
			message = []byte("Bad Message")
			unmarshaller.Write(message)

			Expect(mockWriter.Events).To(HaveLen(0))
		})
	})

	Context("metrics", func() {
		It("emits unmarshal errors", func() {
			_, err := unmarshaller.UnmarshallMessage([]byte("illegal envelope"))
			Expect(err).To(HaveOccurred())
			Eventually(func() uint64 { return fakeSender.GetCounter("dropsondeUnmarshaller.unmarshalErrors") }).Should(BeEquivalentTo(1))
		})

		It("emits unknown event types", func() {
			unknownEventTypeMessage := &events.Envelope{
				Origin:    proto.String("fake-origin-2"),
				EventType: events.Envelope_EventType(2000).Enum(),
				ValueMetric: &events.ValueMetric{
					Name:  proto.String("fake-metric-name"),
					Value: proto.Float64(42),
					Unit:  proto.String("fake-unit"),
				},
			}
			message, err := proto.Marshal(unknownEventTypeMessage)
			Expect(err).ToNot(HaveOccurred())
	It("marshals envelopes into bytes", func() {
		envelope := &events.Envelope{
			Origin:     proto.String("fake-origin-1"),
			EventType:  events.Envelope_LogMessage.Enum(),
			LogMessage: factories.NewLogMessage(events.LogMessage_OUT, "message", "appid", "sourceType"),
		}
		message, _ := proto.Marshal(envelope)

		inputChan <- envelope
		outputMessage := <-outputChan
		Expect(outputMessage).To(Equal(message))
	})

	Context("metrics", func() {
		var eventuallyExpectCounter = func(name string, value uint64) {
			Eventually(func() uint64 { return fakeSender.GetCounter(name) }).Should(BeEquivalentTo(value))
		}

		It("emits a marshal error counter", func() {
			envelope := &events.Envelope{}

			inputChan <- envelope
			eventuallyExpectCounter("dropsondeMarshaller.marshalErrors", 1)
		})

		It("emits a value metric counter", func() {
			envelope := &events.Envelope{
				Origin:      proto.String("fake-origin-3"),
				EventType:   events.Envelope_ValueMetric.Enum(),
				ValueMetric: factories.NewValueMetric("value-name", 1.0, "units"),
			}
					Expect(uaaClient.FetchTokenArgsForCall(0)).To(BeTrue())
					Expect(uaaClient.FetchTokenArgsForCall(1)).To(BeFalse())
					Expect(client.RoutesCallCount()).To(Equal(2))
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(Equal("unauthorized"))
				})
			})
		})

		Context("When the token fetcher returns an error", func() {
			BeforeEach(func() {
				uaaClient.FetchTokenReturns(nil, errors.New("token fetcher error"))
			})

			It("returns an error", func() {
				currentTokenFetchErrors := sender.GetCounter(TokenFetchErrors)
				err := fetcher.FetchRoutes()
				Expect(err).To(HaveOccurred())
				Expect(uaaClient.FetchTokenCallCount()).To(Equal(1))
				Expect(registry.RegisterCallCount()).To(Equal(0))
				Eventually(func() uint64 {
					return sender.GetCounter(TokenFetchErrors)
				}).Should(BeNumerically(">", currentTokenFetchErrors))
			})
		})
	})

	Describe("Run", func() {
		BeforeEach(func() {
			uaaClient.FetchTokenReturns(token, nil)
			client.RoutesReturns(response, nil)
	var req *http.Request
	var endpoint *route.Endpoint
	var sender *fake.FakeMetricSender

	BeforeEach(func() {
		metricsReporter = metrics.NewMetricsReporter()
		req, _ = http.NewRequest("GET", "https://example.com", nil)
		endpoint = route.NewEndpoint("someId", "host", 2222, "privateId", "2", map[string]string{}, 30, "", models.ModificationTag{})
		sender = fake.NewFakeMetricSender()
		batcher := metricbatcher.New(sender, time.Millisecond)
		dropsondeMetrics.Initialize(sender, batcher)
	})

	It("increments the bad_requests metric", func() {
		metricsReporter.CaptureBadRequest(req)
		Eventually(func() uint64 { return sender.GetCounter("rejected_requests") }).Should(BeEquivalentTo(1))

		metricsReporter.CaptureBadRequest(req)
		Eventually(func() uint64 { return sender.GetCounter("rejected_requests") }).Should(BeEquivalentTo(2))
	})

	It("increments the bad_gateway metric", func() {
		metricsReporter.CaptureBadGateway(req)
		Eventually(func() uint64 { return sender.GetCounter("bad_gateways") }).Should(BeEquivalentTo(1))

		metricsReporter.CaptureBadGateway(req)
		Eventually(func() uint64 { return sender.GetCounter("bad_gateways") }).Should(BeEquivalentTo(2))
	})

	Context("increments the request metrics", func() {
		It("increments the total requests metric", func() {
			_, err = connection.Write([]byte(otherData))
			Expect(err).NotTo(HaveOccurred())

			Eventually(writer.Data).Should(HaveLen(2))

			data = string(writer.Data()[1])
			Expect(data).To(Equal(otherData))
		})

		It("emits metrics related to data sent in on udp connection", func(done Done) {
			expectedData := "Some Data"
			otherData := "More stuff"
			connection, err := net.Dial("udp", address)
			dataByteCount := len(otherData + expectedData)

			_, err = connection.Write([]byte(expectedData))
			Expect(err).NotTo(HaveOccurred())

			_, err = connection.Write([]byte(otherData))
			Expect(err).NotTo(HaveOccurred())

			Eventually(writer.Data).Should(HaveLen(2))

			Eventually(func() uint64 { return fakeMetricSender.GetCounter("networkReader.receivedMessageCount") }).Should(BeEquivalentTo(2))
			Eventually(func() uint64 { return fakeMetricSender.GetCounter("networkReader.receivedByteCount") }).Should(BeEquivalentTo(dataByteCount))

			close(done)
		}, 2)
	})
})
		})

		It("emits missing LRP metrics", func() {
			sqlDB.ConvergeLRPs(logger, cellSet)
			Expect(sender.GetValue("LRPsMissing").Value).To(Equal(float64(17)))
		})

		It("emits extra LRP metrics", func() {
			sqlDB.ConvergeLRPs(logger, cellSet)
			Expect(sender.GetValue("LRPsExtra").Value).To(Equal(float64(2)))
		})
	})

	Describe("convergence counters", func() {
		It("bumps the convergence counter", func() {
			Expect(sender.GetCounter("ConvergenceLRPRuns")).To(Equal(uint64(0)))
			sqlDB.ConvergeLRPs(logger, models.CellSet{})
			Expect(sender.GetCounter("ConvergenceLRPRuns")).To(Equal(uint64(1)))
			sqlDB.ConvergeLRPs(logger, models.CellSet{})
			Expect(sender.GetCounter("ConvergenceLRPRuns")).To(Equal(uint64(2)))
		})

		It("reports the duration that it took to converge", func() {
			sqlDB.ConvergeLRPs(logger, models.CellSet{})

			reportedDuration := sender.GetValue("ConvergenceLRPDuration")
			Expect(reportedDuration.Unit).To(Equal("nanos"))
			Expect(reportedDuration.Value).NotTo(BeZero())
		})
	})