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 FlushBothBuffers()
        {
            // When the back buffer is full, both buffers should be flushed
            var api = new Mock <IApi>();

            var sizeOfTrace = ComputeSizeOfTrace(CreateTrace(1));

            // Make the buffer size big enough for a single trace
            var agent = new AgentWriter(api.Object, statsd: null, automaticFlush: false, maxBufferSize: (sizeOfTrace * 2) + SpanBuffer.HeaderSize - 1);

            agent.WriteTrace(CreateTrace(1));
            agent.WriteTrace(CreateTrace(1));

            Assert.True(agent.ActiveBuffer == agent.BackBuffer);
            Assert.True(agent.FrontBuffer.IsFull);
            Assert.Equal(1, agent.FrontBuffer.TraceCount);
            Assert.False(agent.BackBuffer.IsFull);
            Assert.Equal(1, agent.BackBuffer.TraceCount);

            await agent.FlushTracesAsync();

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

            api.Verify(a => a.SendTracesAsync(It.IsAny <ArraySegment <byte> >(), 1), Times.Exactly(2));
        }
示例#3
0
        public async Task WriteTrace_2Traces_SendToApi()
        {
            // TODO:bertrand it is too complicated to setup such a simple test
            var trace = new[] { new Span(_spanContext, start: null) };

            _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 <Span[][]>(y => y.Single().Equals(trace))), Times.Once);

            trace = new[] { new Span(_spanContext, start: null) };
            _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 <Span[][]>(y => y.Single().Equals(trace))), Times.Once);
        }
        public void AgentWriterEnqueueFlushTasks()
        {
            var api         = new Mock <IApi>();
            var agentWriter = new AgentWriter(api.Object, statsd: null, automaticFlush: false);
            var flushTcs    = new TaskCompletionSource <bool>();
            int invocation  = 0;

            api.Setup(i => i.SendTracesAsync(It.IsAny <ArraySegment <byte> >(), It.IsAny <int>()))
            .Returns(() =>
            {
                // One for the front buffer, one for the back buffer
                if (Interlocked.Increment(ref invocation) <= 2)
                {
                    return(flushTcs.Task);
                }

                return(Task.FromResult(true));
            });

            var trace = new ArraySegment <Span>(new[] { new Span(new SpanContext(1, 1), DateTimeOffset.UtcNow) });

            // Write trace to the front buffer
            agentWriter.WriteTrace(trace);

            // Flush front buffer
            var firstFlush = agentWriter.FlushTracesAsync();

            // This will swap to the back buffer due front buffer is blocked.
            agentWriter.WriteTrace(trace);

            // Flush the second buffer
            var secondFlush = agentWriter.FlushTracesAsync();

            // This trace will force other buffer swap and then a drop because both buffers are blocked
            agentWriter.WriteTrace(trace);

            // This will try to flush the front buffer again.
            var thirdFlush = agentWriter.FlushTracesAsync();

            // Third flush should wait for the first flush to complete.
            Assert.False(thirdFlush.IsCompleted);
        }
        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 FlushTracesAsync()
 {
     return(_agentWriter.FlushTracesAsync());
 }