Context("write returns an error", func() {
			BeforeEach(func() {
				client.WriteStub = func([]byte) (int, error) {
					switch client.WriteCallCount() {
					case 2:
						return 0, errors.New("write failure")
					default:
						return 0, nil
					}
				}
				forwarder.Write(envelope)
			})

			It("closes the client", func() {
				Eventually(func() int { return client.CloseCallCount() }).Should(Equal(1))
			})

			It("does not increment the marshallErrors metric", func() {
				Consistently(func() uint64 { return sender.GetCounter("dropsondeMarshaller.marshalErrors") }).Should(BeZero())
			})

			It("only increments retryCount metric and not other metrics", func() {
				Eventually(func() uint64 { return sender.GetCounter("tls.sentMessageCount") }).Should(BeZero())
				Eventually(func() uint64 { return sender.GetCounter("tls.sentByteCount") }).Should(BeZero())
				Eventually(func() uint64 { return sender.GetCounter("DopplerForwarder.sentMessages") }).Should(BeZero())
				Eventually(func() uint64 { return sender.GetCounter("dropsondeMarshaller.LogMessageMarshalled") }).Should(BeZero())
				Eventually(func() uint64 { return sender.GetCounter("tls.retryCount") }).Should(BeEquivalentTo(1))
			})

			It("resends the same message upon retry", func() {
			var fakeClient *fakeclient.FakeClient

			BeforeEach(func() {
				fakeClient = newFakeClient("udp", "host:port")
				clientFactory.newClient = func(string) (clientpool.Client, error) {
					return fakeClient, nil
				}
			})

			It("the client is stopped", func() {
				s := map[string]string{
					"a": "udp://host:port",
				}

				pool.Set(s, nil)
				Expect(fakeClient.CloseCallCount()).To(Equal(0))
				pool.Set(nil, nil)
				Expect(fakeClient.CloseCallCount()).To(Equal(1))
			})
		})

		Context("with identical server data", func() {
			var clientFactoryCallCount int

			BeforeEach(func() {
				clientFactoryCallCount = 0
				defaultNewClient := clientFactory.newClient
				clientFactory.newClient = func(url string) (clientpool.Client, error) {
					clientFactoryCallCount++
					return defaultNewClient(url)
				}
			Expect(client.WriteArgsForCall(0)).To(Equal(buffer.Bytes()))
			Expect(client.WriteArgsForCall(1)).To(Equal(bytes))

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

		Context("with a network error", func() {
			BeforeEach(func() {
				client.WriteReturns(0, &net.OpError{Op: "dial", Err: errors.New("boom")})

				forwarder.Write(envelope)
			})

			It("closes the client", func() {
				Expect(client.CloseCallCount()).To(Equal(1))
			})

			It("increments the marshallErrors metric", func() {
				Consistently(func() uint64 { return sender.GetCounter("dropsondeMarshaller.marshalErrors") }).Should(BeZero())
			})

			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())
			})
		})

		Context("with a non-network error", func() {