public async Task Trace_Header() { string traceId = TraceIdFactory.Create().NextId(); ulong spanId = SpanIdFactory.Create().NextId(); string testId = Utils.GetTestId(); var startTime = Timestamp.FromDateTime(DateTime.UtcNow); var builder = new WebHostBuilder().UseStartup <TraceTestNoBufferLowQpsApplication>(); using (var server = new TestServer(builder)) { var client = server.CreateClient(); var header = TraceHeaderContext.Create(traceId, spanId, shouldTrace: true); client.DefaultRequestHeaders.Add(TraceHeaderContext.TraceHeader, header.ToString()); await client.GetAsync($"/Trace/Trace/{testId}"); } var spanName = TraceController.GetMessage(nameof(TraceController.Trace), testId); var trace = _polling.GetTrace(spanName, startTime); Assert.NotNull(trace); Assert.Equal(traceId, trace.TraceId); Assert.Equal(2, trace.Spans.Count); var span = trace.Spans.First(s => s.Name.StartsWith("/Trace")); Assert.Equal(spanId, span.ParentSpanId); }
public async Task Trace_Header() { string traceId = _traceIdFactory.NextId(); ulong spanId = _spanIdFactory.NextId(); var uri = $"/Trace/{nameof(TraceController.Trace)}/{_testId}"; var childSpanName = EntryData.GetMessage(nameof(TraceController.Trace), _testId); using (var server = new TestServer(new WebHostBuilder().UseStartup <TraceTestNoBufferLowQpsApplication>())) using (var client = server.CreateClient()) { var header = TraceHeaderContext.Create(traceId, spanId, shouldTrace: true); client.DefaultRequestHeaders.Add(TraceHeaderContext.TraceHeader, header.ToString()); var response = await client.GetAsync(uri); var trace = _polling.GetTrace(uri, _startTime); TraceEntryVerifiers.AssertParentChildSpan(trace, uri, childSpanName); Assert.Equal(traceId, trace.TraceId); var parentSpan = trace.Spans.First(s => s.Name == uri); Assert.Equal(spanId, parentSpan.ParentSpanId); Assert.True(response.Headers.Contains(TraceHeaderContext.TraceHeader)); var returnedHeader = response.Headers.GetValues(TraceHeaderContext.TraceHeader).Single(); var headerContext = TraceHeaderContext.FromHeader(returnedHeader); Assert.Equal(traceId, headerContext.TraceId); Assert.Equal(spanId, headerContext.SpanId); Assert.True(headerContext.ShouldTrace); } }
public void Log_Trace() { string traceId = "105445aa7843bc8bf206b12000100f00"; string fullTraceName = TraceTarget.ForProject(ProjectId).GetFullTraceName(traceId); Predicate <IEnumerable <LogEntry> > matcher = logEntries => { LogEntry entry = logEntries.Single(); return(entry.LogName == new LogName(ProjectId, BaseLogName).ToString() && entry.Trace == fullTraceName); }; var tracerContext = TraceHeaderContext.Create(traceId, 81237123, null); HeaderDictionary dict = new HeaderDictionary(); dict[TraceHeaderContext.TraceHeader] = tracerContext.ToString(); var mockServiceProvider = new Mock <IServiceProvider>(); var mockAccessor = new Mock <IHttpContextAccessor>(); var mockContext = new Mock <HttpContext>(); var mockRequest = new Mock <HttpRequest>(); mockServiceProvider.Setup(sp => sp.GetService(typeof(IHttpContextAccessor))).Returns(mockAccessor.Object); mockAccessor.Setup(a => a.HttpContext).Returns(mockContext.Object); mockContext.Setup(c => c.Request).Returns(mockRequest.Object); mockRequest.Setup(r => r.Headers).Returns(dict); var mockConsumer = new Mock <IConsumer <LogEntry> >(); mockConsumer.Setup(c => c.Receive(Match.Create(matcher))); var logger = GetLogger(mockConsumer.Object, LogLevel.Information, serviceProvider: mockServiceProvider.Object, logName: BaseLogName); logger.Log(LogLevel.Error, 0, LogMessage, s_exception, Formatter); mockConsumer.VerifyAll(); }
public async Task Trace_Header() { string traceId = TraceIdFactory.Create().NextId(); ulong spanId = SpanIdFactory.Create().NextId(); string testId = Utils.GetTestId(); var startTime = Timestamp.FromDateTime(DateTime.UtcNow); var client = _noBufferLowQps.CreateClient(); var header = TraceHeaderContext.Create(traceId, spanId, shouldTrace: true); client.DefaultRequestHeaders.Add(TraceHeaderContext.TraceHeader, header.ToString()); var response = await client.GetAsync($"/Trace/Trace/{testId}"); var spanName = TraceController.GetMessage(nameof(TraceController.Trace), testId); var trace = _polling.GetTrace(spanName, startTime); Assert.NotNull(trace); Assert.Equal(traceId, trace.TraceId); Assert.Equal(2, trace.Spans.Count); var span = trace.Spans.First(s => s.Name.StartsWith("/Trace")); Assert.Equal(spanId, span.ParentSpanId); Assert.True(response.Headers.Contains(TraceHeaderContext.TraceHeader)); var returnedHeader = response.Headers.GetValues(TraceHeaderContext.TraceHeader).Single(); var headerContext = TraceHeaderContext.FromHeader(returnedHeader); Assert.Equal(traceId, headerContext.TraceId); Assert.Equal(spanId, headerContext.SpanId); Assert.True(headerContext.ShouldTrace); }
public async Task Logging_Trace_FromHeader_Implicit() { string traceId = s_traceIdFactory.NextId(); ulong spanId = s_spanIdFactory.NextId(); string testId = IdGenerator.FromGuid(); using (var server = GetTestServer <NoBufferWarningLoggerTestApplication>()) using (var client = server.CreateClient()) { client.DefaultRequestHeaders.Add(TraceHeaderContext.TraceHeader, TraceHeaderContext.Create(traceId, spanId, true).ToString()); await client.GetAsync($"/Main/Critical/{testId}"); } _fixture.AddValidator(testId, results => { // We only have one log entry. LogEntry entry = Assert.Single(results); // And the resource name of the trace associated to it points to the trace // we specified on the header. Assert.Contains(TestEnvironment.GetTestProjectId(), entry.Trace); Assert.Contains(traceId, entry.Trace); // Let's get our trace. var trace = s_tracePolling.GetTrace(traceId); Assert.NotNull(trace); // The span associated to our entry needs to be part of that trace. // (We created this span on the middleware to encompass the whole request) var entrySpan = Assert.Single(trace.Spans, s => EntryData.SpanIdToHex(s.SpanId) == entry.SpanId); // And its parent needs to be the span specified in the header Assert.Equal(spanId, entrySpan.ParentSpanId); }); }
public async Task Logging_Trace_FromHeader_MultipleSpans() { string traceId = s_traceIdFactory.NextId(); ulong spanId = s_spanIdFactory.NextId(); string testId = IdGenerator.FromGuid(); var builder = new WebHostBuilder().UseStartup <NoBufferWarningLoggerTestApplication>(); using (var server = new TestServer(builder)) using (var client = server.CreateClient()) { client.DefaultRequestHeaders.Add(TraceHeaderContext.TraceHeader, TraceHeaderContext.Create(traceId, spanId, true).ToString()); await client.GetAsync($"/Main/{nameof(MainController.LogsInDifferentSpans)}/{testId}"); } _fixture.AddValidator(testId, results => { // Span: span-1 // Log: span-1 // Span: span-1-2 // Log: span-1-2 // Span: span-2 // Log: span-2 string projectId = TestEnvironment.GetTestProjectId(); // We have 3 logs. Assert.Equal(3, results.Count); // And the resource name of the trace associated to all of them points to the trace // we specified on the header. Assert.DoesNotContain(results, entry => !entry.Trace.Contains(projectId)); Assert.DoesNotContain(results, entry => !entry.Trace.Contains(traceId)); // Let's get our trace. var trace = s_tracePolling.GetTrace(traceId); Assert.NotNull(trace); // Let's check that all the entries are associated to the correct spans. var logEntry1 = Assert.Single(results, e => e.JsonPayload.Fields["message"].StringValue.EndsWith("log-1")); var logEntry12 = Assert.Single(results, e => e.JsonPayload.Fields["message"].StringValue.EndsWith("log-1-2")); var logEntry2 = Assert.Single(results, e => e.JsonPayload.Fields["message"].StringValue.EndsWith("log-2")); var span1 = Assert.Single(trace.Spans, s => EntryData.SpanIdToHex(s.SpanId) == logEntry1.SpanId); Assert.EndsWith("span-1", span1.Name); var span12 = Assert.Single(trace.Spans, s => EntryData.SpanIdToHex(s.SpanId) == logEntry12.SpanId); Assert.EndsWith("span-1-2", span12.Name); var span2 = Assert.Single(trace.Spans, s => EntryData.SpanIdToHex(s.SpanId) == logEntry2.SpanId); Assert.EndsWith("span-2", span2.Name); // Let's check that the spans are correctly created and descend from the span we specified in the header. // span-1-2 is a child of span-1 Assert.Equal(span12.ParentSpanId, span1.SpanId); // span-1 and span-2 have the same parent Assert.Equal(span1.ParentSpanId, span2.ParentSpanId); // The grandparent of span-1 and span-2 is the span we specified on the header. var parentSpan = Assert.Single(trace.Spans, s => s.SpanId == span1.ParentSpanId); Assert.Equal(spanId, parentSpan.ParentSpanId); }); }
public void Create() { var context = TraceHeaderContext.Create(TraceId, SpanId, true); Assert.Equal(SpanId, context.SpanId); Assert.Equal(TraceId, context.TraceId); Assert.True(context.ShouldTrace); }
/// <summary> /// Invokes the next <see cref="RequestDelegate"/> and traces the time /// taken for the next delegate to run, reporting the results to the /// Stackdriver Trace API. /// </summary> /// <param name="httpContext">The current HTTP context.</param> /// <param name="traceHeaderContext">Information from the current request header. Must not be null.</param> public async Task Invoke(HttpContext httpContext, TraceHeaderContext traceHeaderContext) { GaxPreconditions.CheckNotNull(traceHeaderContext, nameof(traceHeaderContext)); // Create a tracer for the given request and set it on the context manager so // the tracer can be used in other places. var tracer = _tracerFactory(traceHeaderContext); ContextTracerManager.SetCurrentTracer(tracer); if (tracer.GetCurrentTraceId() == null) { await _next(httpContext).ConfigureAwait(false); } else { if (traceHeaderContext.TraceId != null) { // Set the trace updated trace header on the response. var updatedHeaderContext = TraceHeaderContext.Create( tracer.GetCurrentTraceId(), tracer.GetCurrentSpanId() ?? 0, true); httpContext.Response.Headers.Add( TraceHeaderContext.TraceHeader, updatedHeaderContext.ToString()); } // Trace the delegate and annotate it with information from the current // HTTP context. var traceName = await _nameProvider.GetTraceNameAsync(httpContext).ConfigureAwait(false); var span = tracer.StartSpan(traceName); try { await _next(httpContext).ConfigureAwait(false); } catch (Exception exception) { try { StackTrace stackTrace = new StackTrace(exception, true); tracer.SetStackTrace(stackTrace); } catch (Exception innerException) { throw new AggregateException(innerException, exception); } throw; } finally { tracer.AnnotateSpan(Labels.AgentLabel); tracer.AnnotateSpan(Labels.FromHttpContext(httpContext)); span.Dispose(); } } }
public void ToStringTest() { var context = TraceHeaderContext.Create(TraceId, SpanId, true); Assert.Equal($"{TraceId}/{SpanId};o=1", context.ToString()); context = TraceHeaderContext.Create(TraceId, SpanId, null); Assert.Equal($"{TraceId}/{SpanId};", context.ToString()); context = TraceHeaderContext.Create(TraceId, SpanId, false); Assert.Equal($"{TraceId}/{SpanId};o=0", context.ToString()); context = TraceHeaderContext.Create(null, null, false); Assert.Equal("/;o=0", context.ToString()); }
/// <summary> /// Invokes the next <see cref="RequestDelegate"/> and traces the time /// taken for the next delegate to run, reporting the results to the /// Stackdriver Trace API. /// </summary> /// <param name="httpContext">The current http context.</param> /// <param name="traceHeaderContext">Information from the current requrest header. Cannot be null.</param> public async Task Invoke(HttpContext httpContext, TraceHeaderContext traceHeaderContext) { GaxPreconditions.CheckNotNull(traceHeaderContext, nameof(traceHeaderContext)); // Create a tracer for the given request and set it on the HttpContext so // the tracer can be used in other places. var tracer = _tracerFactory.CreateTracer(traceHeaderContext); ContextTracerManager.SetCurrentTracer(_accessor, tracer); if (tracer.GetCurrentTraceId() == null) { await _next(httpContext).ConfigureAwait(false); } else { if (traceHeaderContext.TraceId != null) { // Set the trace updated trace header on the response. var updatedHeaderContext = TraceHeaderContext.Create( tracer.GetCurrentTraceId(), tracer.GetCurrentSpanId() ?? 0, true); httpContext.Response.Headers.Add( TraceHeaderContext.TraceHeader, updatedHeaderContext.ToString()); } // Trace the delegate and annotate it with information from the current // http context. tracer.StartSpan(httpContext.Request.Path); try { await _next(httpContext).ConfigureAwait(false); } catch (Exception e) { StackTrace stackTrace = new StackTrace(e, true); tracer.SetStackTrace(stackTrace); throw; } finally { tracer.AnnotateSpan(Labels.AgentLabel); tracer.AnnotateSpan(Labels.FromHttpContext(httpContext)); tracer.EndSpan(); } } }
public void CreateManagedTracer() { var context = TraceHeaderContext.Create(null, null, false); var tracerFactoryMock = new Mock <IManagedTracerFactory>(); tracerFactoryMock.Setup(f => f.CreateTracer(context)).Returns(NullManagedTracer.Instance); var mockProvider = new Mock <IServiceProvider>(); mockProvider.Setup(p => p.GetService(typeof(TraceHeaderContext))).Returns(context); mockProvider.Setup(p => p.GetService(typeof(IManagedTracerFactory))).Returns(tracerFactoryMock.Object); var tracer = CloudTraceExtension.CreateManagedTracer(mockProvider.Object); Assert.IsType(typeof(NullManagedTracer), tracer); tracerFactoryMock.VerifyAll(); mockProvider.VerifyAll(); }
public async Task Logging_Trace() { string traceId = "105445aa7843bc8bf206b12000100f00"; string testId = Utils.GetTestId(); DateTime startTime = DateTime.UtcNow; var builder = new WebHostBuilder().UseStartup <NoBufferWarningLoggerTestApplication>(); using (var server = new TestServer(builder)) using (var client = server.CreateClient()) { client.DefaultRequestHeaders.Add(TraceHeaderContext.TraceHeader, TraceHeaderContext.Create(traceId, 81237123, null).ToString()); await client.GetAsync($"/Main/Critical/{testId}"); var results = _polling.GetEntries(startTime, testId, 1, LogSeverity.Critical); Assert.Contains(Utils.GetProjectIdFromEnvironment(), results.Single().Trace); Assert.Contains(traceId, results.Single().Trace); } }
public void CreateManagedTracer() { var accessor = new HttpContextAccessor(); accessor.HttpContext = new DefaultHttpContext(); var context = TraceHeaderContext.Create(null, null, false); var tracerFactoryMock = new Mock <IManagedTracerFactory>(); tracerFactoryMock.Setup(f => f.CreateTracer(context)).Returns(NullManagedTracer.Instance); var mockProvider = new Mock <IServiceProvider>(); mockProvider.Setup(p => p.GetService(typeof(TraceHeaderContext))).Returns(context); mockProvider.Setup(p => p.GetService(typeof(IManagedTracerFactory))).Returns(tracerFactoryMock.Object); mockProvider.Setup(p => p.GetService(typeof(IHttpContextAccessor))).Returns(accessor); var tracer = CloudTraceExtension.CreateManagedTracer(mockProvider.Object); Assert.IsType(typeof(NullManagedTracer), tracer); Assert.Equal(tracer, accessor.HttpContext.Items[CloudTraceExtension.TraceKey]); tracerFactoryMock.VerifyAll(); mockProvider.VerifyAll(); }
/// <summary> /// Propagates Google trace context information to the response. /// Used by default if user code has not specified a propagator of their own. /// </summary> internal static void PropagateGoogleTraceHeaders(HttpResponse response, ITraceContext traceContext) { var googleHeader = TraceHeaderContext.Create(traceContext.TraceId, traceContext.SpanId ?? 0, traceContext.ShouldTrace); response.Headers.Add(TraceHeaderContext.TraceHeader, googleHeader.ToString()); }
private static void GoogleTraceContextEmitter(HttpRequestHeaders headers, string traceId, ulong?spanId, bool?shouldTrace) => // To mimic incoming requests with the Google trace header. headers.Add(TraceHeaderContext.TraceHeader, TraceHeaderContext.Create(traceId, spanId, shouldTrace).ToString());