public async Task FlushTwice()
        {
            var w = new AgentWriter(_api.Object, statsd: null);
            await w.FlushAndCloseAsync();

            await w.FlushAndCloseAsync();
        }
        public async Task FlushTwice()
        {
            var w = new AgentWriter(_api.Object, new NullMetrics());
            await w.FlushAndCloseAsync();

            await w.FlushAndCloseAsync();
        }
Beispiel #3
0
        public async Task FlushTwice(bool synchronousSend)
        {
            var api = new Mock <IApi>();
            var w   = new AgentWriter(api.Object, statsd: null, synchronousSend);
            await w.FlushAndCloseAsync();

            await w.FlushAndCloseAsync();
        }
        public Task FaultyApi()
        {
            // The flush thread should be able to recover from an error when calling the API
            // Also, it should free the faulty buffer
            var api   = new Mock <IApi>();
            var agent = new AgentWriter(api.Object, statsd: null);

            var mutex = new ManualResetEventSlim();

            agent.Flushed += () => mutex.Set();

            api.Setup(a => a.SendTracesAsync(It.IsAny <ArraySegment <byte> >(), It.IsAny <int>()))
            .Returns(() =>
            {
                throw new InvalidOperationException();
            });

            agent.WriteTrace(CreateTrace(1));

            mutex.Wait();

            Assert.True(agent.ActiveBuffer == agent.FrontBuffer);
            Assert.True(agent.FrontBuffer.IsEmpty);
            Assert.True(agent.BackBuffer.IsEmpty);

            return(agent.FlushAndCloseAsync());
        }
        public Task SwitchBuffer()
        {
            // Make sure that the agent is able to switch to the secondary buffer when the primary is full/busy
            var api   = new Mock <IApi>();
            var agent = new AgentWriter(api.Object, statsd: null);

            var barrier = new Barrier(2);

            api.Setup(a => a.SendTracesAsync(It.IsAny <ArraySegment <byte> >(), It.IsAny <int>()))
            .Callback(() =>
            {
                barrier.SignalAndWait();
                barrier.SignalAndWait();
            })
            .Returns(Task.FromResult(true));

            agent.WriteTrace(CreateTrace(1));

            // Wait for the flush operation
            barrier.SignalAndWait();

            // At this point, the flush thread is stuck in Api.SendTracesAsync, and the frontBuffer should be active and locked
            Assert.True(agent.ActiveBuffer == agent.FrontBuffer);
            Assert.True(agent.FrontBuffer.IsLocked);
            Assert.Equal(1, agent.FrontBuffer.TraceCount);
            Assert.Equal(1, agent.FrontBuffer.SpanCount);

            var mutex = new ManualResetEventSlim();

            agent.WriteTrace(CreateTrace(2));

            // Wait for the trace to be dequeued
            WaitForDequeue(agent);

            // Since the frontBuffer was locked, the buffers should have been swapped
            Assert.True(agent.ActiveBuffer == agent.BackBuffer);
            Assert.Equal(1, agent.BackBuffer.TraceCount);
            Assert.Equal(2, agent.BackBuffer.SpanCount);

            // Unblock the flush thread
            barrier.SignalAndWait();

            // Wait for the next flush operation
            barrier.SignalAndWait();

            // Back buffer should still be active and being flushed
            Assert.True(agent.ActiveBuffer == agent.BackBuffer);
            Assert.True(agent.BackBuffer.IsLocked);
            Assert.False(agent.FrontBuffer.IsLocked);

            // Unblock and exit
            barrier.Dispose();
            return(agent.FlushAndCloseAsync());
        }
        public async Task AddsTraceKeepRateMetricToRootSpan()
        {
            // Traces should be dropped when both buffers are full
            var calculator = new MovingAverageKeepRateCalculator(windowSize: 10, Timeout.InfiniteTimeSpan);

            var tracer = new Mock <IDatadogTracer>();

            tracer.Setup(x => x.DefaultServiceName).Returns("Default");
            var traceContext    = new TraceContext(tracer.Object);
            var rootSpanContext = new SpanContext(null, traceContext, null);
            var rootSpan        = new Span(rootSpanContext, DateTimeOffset.UtcNow);
            var childSpan       = new Span(new SpanContext(rootSpanContext, traceContext, null), DateTimeOffset.UtcNow);

            traceContext.AddSpan(rootSpan);
            traceContext.AddSpan(childSpan);
            var trace       = new[] { rootSpan, childSpan };
            var sizeOfTrace = ComputeSizeOfTrace(trace);

            // Make the buffer size big enough for a single trace
            var api = new Mock <IApi>();

            api.Setup(x => x.SendTracesAsync(It.IsAny <ArraySegment <byte> >(), It.IsAny <int>()))
            .ReturnsAsync(() => true);
            var agent = new AgentWriter(api.Object, statsd: null, calculator, automaticFlush: false, maxBufferSize: (sizeOfTrace * 2) + SpanBuffer.HeaderSize - 1, batchInterval: 100);

            // Fill both buffers
            agent.WriteTrace(trace);
            agent.WriteTrace(trace);

            // Drop one
            agent.WriteTrace(trace);
            await agent.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API

            // Write another one
            agent.WriteTrace(trace);
            await agent.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API

            api.Verify();
            api.Invocations.Clear();

            // Write trace and update keep rate
            calculator.UpdateBucket();
            agent.WriteTrace(trace);
            await agent.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API

            const double expectedTraceKeepRate = 0.75;

            rootSpan.SetMetric(Metrics.TracesKeepRate, expectedTraceKeepRate);
            var expectedData = Vendors.MessagePack.MessagePackSerializer.Serialize(trace, new FormatterResolverWrapper(SpanFormatterResolver.Instance));
            await agent.FlushAndCloseAsync();

            api.Verify(x => x.SendTracesAsync(It.Is <ArraySegment <byte> >(y => Equals(y, expectedData)), It.Is <int>(i => i == 1)), Times.Once);
        }
        public async Task WriteTrace_2Traces_SendToApi()
        {
            var trace         = new[] { new Span(new SpanContext(1, 1), DateTimeOffset.UtcNow) };
            var expectedData1 = Vendors.MessagePack.MessagePackSerializer.Serialize(trace, new FormatterResolverWrapper(SpanFormatterResolver.Instance));

            _agentWriter.WriteTrace(trace);
            await _agentWriter.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API

            _api.Verify(x => x.SendTracesAsync(It.Is <ArraySegment <byte> >(y => Equals(y, expectedData1)), It.Is <int>(i => i == 1)), Times.Once);

            _api.Invocations.Clear();

            trace = new[] { new Span(new SpanContext(2, 2), DateTimeOffset.UtcNow) };
            var expectedData2 = Vendors.MessagePack.MessagePackSerializer.Serialize(trace, new FormatterResolverWrapper(SpanFormatterResolver.Instance));

            _agentWriter.WriteTrace(trace);
            await _agentWriter.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API

            _api.Verify(x => x.SendTracesAsync(It.Is <ArraySegment <byte> >(y => Equals(y, expectedData2)), It.Is <int>(i => i == 1)), Times.Once);

            await _agentWriter.FlushAndCloseAsync();
        }
        public Task WakeUpSerializationTask()
        {
            var agent = new AgentWriter(Mock.Of <IApi>(), statsd: null, batchInterval: 0);

            // To reduce flackyness, first we make sure the serialization thread is started
            WaitForDequeue(agent);

            // Wait for the serialization thread to go to sleep
            while (true)
            {
                if (!WaitForDequeue(agent, wakeUpThread: false, delay: 500))
                {
                    break;
                }
            }

            // Serialization thread is asleep, makes sure it wakes up when enqueuing a trace
            agent.WriteTrace(CreateTrace(1));
            Assert.True(WaitForDequeue(agent));

            return(agent.FlushAndCloseAsync());
        }
 public Task FlushAndCloseAsync()
 {
     return(_agentWriter.FlushAndCloseAsync());
 }