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