public void EndSpan_NoAvailableSpan() { var tracer = SimpleManagedTracer.Create(UnusedConsumer, CreateTrace()); Assert.Throws <InvalidOperationException>(() => tracer.EndSpan()); }
public void GetCurrentTraceId() { var tracer = SimpleManagedTracer.Create(UnusedConsumer, ProjectId, TraceId); Assert.Equal(tracer.GetCurrentTraceId(), TraceId); }
public void GetCurrentSpanId_NoSpan() { var tracer = SimpleManagedTracer.Create(UnusedConsumer, ProjectId, TraceId); Assert.Null(tracer.GetCurrentSpanId()); }
public void SetStackTrace_NoAvailableSpan() { var tracer = SimpleManagedTracer.Create(UnusedConsumer, ProjectId, TraceId); Assert.Throws <InvalidOperationException>(() => tracer.SetStackTrace(EmptyStackTrace)); }
public void AnnotateSpan_NoAvailableSpan() { var tracer = SimpleManagedTracer.Create(UnusedConsumer, ProjectId, TraceId); Assert.Throws <InvalidOperationException>(() => tracer.AnnotateSpan(EmptyDictionary)); }
public async Task MultipleSpans_Threads_Started_During_Span() { var mockConsumer = new Mock <IConsumer <TraceProto> >(); var tracer = SimpleManagedTracer.Create(mockConsumer.Object, ProjectId, TraceId); Predicate <IEnumerable <TraceProto> > rootMatcher = t => { var spans = t.Single().Spans; return(spans.Count == 1 && IsValidSpan(spans[0], "root")); }; ulong rootId = 0; mockConsumer .Setup(c => c.Receive(Match.Create(rootMatcher))) .Callback <IEnumerable <TraceProto> >(t => rootId = t.Single().Spans[0].SpanId); var childThreadsReleased = new ManualResetEventSlim(initialState: false); var startedChildSpans = 0; Func <string, string, Task> op = async(childName, grandchildName) => { childThreadsReleased.Wait(); using (tracer.StartSpan(childName)) { Interlocked.Increment(ref startedChildSpans); await Task.Yield(); using (tracer.StartSpan(grandchildName)) { await Task.Yield(); } do { await Task.Yield(); // Don't allow the span to close until both are started to make sure we only // get a single Receive call below instead of two. Interlocked has no way to // explicitly force read from main memory, but this hack will "attempt" to // update the count and always fail, returning the actual value from main // memory. } while (Interlocked.CompareExchange(ref startedChildSpans, -1, -1) < 2); } }; Task t1; Task t2; using (tracer.StartSpan("root")) { t1 = Task.Run(() => op("child-one", "grandchild-one").Wait()); t2 = Task.Run(() => op("child-two", "grandchild-two").Wait()); } Predicate <IEnumerable <TraceProto> > childMatcher = t => { // Verify that even though the child spans were started after the root span was ended, they // still have it as a parent since it was opened when their tasks were created. var spans = t.Single().Spans.OrderBy(s => s.Name).ToList(); var childOneId = spans[0].SpanId; var childTwoId = spans[1].SpanId; return(spans.Count == 4 && IsValidSpan(spans[0], "child-one", parentId: rootId) && IsValidSpan(spans[1], "child-two", parentId: rootId) && IsValidSpan(spans[2], "grandchild-one", parentId: childOneId) && IsValidSpan(spans[3], "grandchild-two", parentId: childTwoId)); }; mockConsumer.Setup(c => c.Receive(Match.Create(childMatcher))); childThreadsReleased.Set(); await Task.WhenAll(t1, t2); mockConsumer.VerifyAll(); }
private SimpleManagedTracer CreateSimpleManagedTracer(IConsumer <TraceProto> consumer) => SimpleManagedTracer.Create(consumer, _projectId, _traceIdFactory.NextId(), null);
private IManagedTracer CreateSimpleManagedTracer(IConsumer <TraceProto> consumer) => SimpleManagedTracer.Create(consumer, TestEnvironment.GetTestProjectId(), _traceIdFactory.NextId(), null);