/// <summary> /// Adds the needed services for Google Cloud Tracing. Used with <see cref="UseGoogleTrace"/>. /// </summary> /// <param name="services">The service collection. Cannot be null.</param> /// <param name="projectId">The Google Cloud Platform project ID. Cannot be null.</param> /// <param name="config">Optional trace configuration, if unset the default will be used.</param> /// <param name="client">Optional Trace client, if unset the default will be used.</param> /// <param name="traceOverridePredicate">Optional function to trace requests. If the trace header is not set /// then this function will be called to determine if a given request should be traced. This will /// not override trace headers. If the function returns true the request will be traced, if false /// is returned the trace will not be traced and if null is returned it will not affect the /// trace decision.</param> public static void AddGoogleTrace( this IServiceCollection services, string projectId, TraceConfiguration config = null, TraceServiceClient client = null, Func <HttpRequest, bool?> traceOverridePredicate = null) { GaxPreconditions.CheckNotNull(services, nameof(services)); GaxPreconditions.CheckNotNull(projectId, nameof(projectId)); client = client ?? TraceServiceClient.Create(); config = config ?? TraceConfiguration.Create(); var traceIdFactory = TraceIdFactory.Create(); var consumer = ConsumerFactory <TraceProto> .GetConsumer( new GrpcTraceConsumer(client), MessageSizer <TraceProto> .GetSize, config.BufferOptions); var tracerFactory = new ManagedTracerFactory(projectId, consumer, RateLimitingTraceOptionsFactory.Create(config), traceIdFactory); services.AddSingleton <IManagedTracerFactory>(tracerFactory); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton(CreateTraceHeaderPropagatingHandler); services.AddSingleton(new ShouldTraceRequest(traceOverridePredicate)); services.AddSingleton(traceIdFactory); services.AddScoped(CreateTraceHeaderContext); services.AddScoped(CreateManagedTracer); }
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.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); }
private IServiceProvider CreateProviderForTraceHeaderContext(string traceHeader) { var context = new DefaultHttpContext(); var request = context.Request; request.Headers[TraceHeaderContext.TraceHeader] = traceHeader; var accessor = new HttpContextAccessor { HttpContext = context }; var traceIdFactory = TraceIdFactory.Create(); Mock <IServiceProvider> mockProvider = new Mock <IServiceProvider>(); mockProvider.Setup(p => p.GetService(typeof(IHttpContextAccessor))).Returns(accessor); mockProvider.Setup(p => p.GetService(typeof(TraceDecisionPredicate))).Returns( TraceDecisionPredicate.Default); mockProvider.Setup(p => p.GetService(typeof(TraceIdFactory))).Returns(traceIdFactory); return(mockProvider.Object); }
/// <summary> /// Create an <see cref="IServiceProvider"/> to be used during tests of /// <see cref="CloudTraceExtension.CreateTraceHeaderContext(IServiceProvider)"/>. /// It will set up an <see cref="IHttpContextAccessor"/> with the passed in trace header, /// a <see cref="ShouldTraceRequest"/> with the passed in should trace function and a /// <see cref="TraceIdFactory"/>. /// </summary> private IServiceProvider CreateProviderForTraceHeaderContext( string traceHeader, Func <HttpRequest, bool?> shouldTraceFunc = null) { var context = new DefaultHttpContext(); var request = new DefaultHttpRequest(context); request.Headers[TraceHeaderContext.TraceHeader] = traceHeader; var accessor = new HttpContextAccessor(); accessor.HttpContext = context; var traceIdFactory = TraceIdFactory.Create(); Mock <IServiceProvider> mockProvider = new Mock <IServiceProvider>(); mockProvider.Setup(p => p.GetService(typeof(IHttpContextAccessor))).Returns(accessor); mockProvider.Setup(p => p.GetService(typeof(ShouldTraceRequest))).Returns( new ShouldTraceRequest(shouldTraceFunc)); mockProvider.Setup(p => p.GetService(typeof(TraceIdFactory))).Returns(traceIdFactory); return(mockProvider.Object); }
public async Task Traces_CustomTraceContext() { var uri = $"/TraceSamples/{nameof(TraceSamplesController.TraceHelloWorld)}/{_testId}"; var traceId = TraceIdFactory.Create().NextId(); using var server = GetTestServer <CustomTraceContextTestApplication.Startup>(); using var client = server.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Get, uri) { Headers = { { "custom_trace_id", traceId } } }; var response = await client.SendAsync(request); var trace = s_polling.GetTrace(uri, _startTime); TraceEntryVerifiers.AssertParentChildSpan(trace, uri, _testId); TraceEntryVerifiers.AssertSpanLabelsContains( trace.Spans.First(s => s.Name == uri), TraceEntryData.HttpGetSuccessLabels); Assert.False(response.Headers.Contains(TraceHeaderContext.TraceHeader)); Assert.Equal(traceId, trace.TraceId); Assert.True(response.Headers.Contains("custom_trace_id")); }
private static ITraceContext GetTraceContextFromIncomingRequest() => new SimpleTraceContext(TraceIdFactory.Create().NextId(), null, true);
/// <summary> /// Adds the needed services for Google Cloud Tracing. Used with <see cref="UseGoogleTrace"/>. /// </summary> /// <param name="services">The service collection. Cannot be null.</param> /// <param name="projectId">The Google Cloud Platform project ID. Cannot be null.</param> /// <param name="config">Optional trace configuration, if unset the default will be used.</param> /// <param name="clientTask">Optional task which produces the Trace client, if /// unset the default will be used.</param> public static void AddGoogleTrace( this IServiceCollection services, string projectId, TraceConfiguration config = null, Task <TraceServiceClient> clientTask = null) { GaxPreconditions.CheckNotNull(services, nameof(services)); GaxPreconditions.CheckNotNull(projectId, nameof(projectId)); clientTask = clientTask ?? TraceServiceClient.CreateAsync(); config = config ?? TraceConfiguration.Create(); IConsumer <TraceProto> consumer = ConsumerFactory <TraceProto> .GetConsumer( new GrpcTraceConsumer(clientTask), MessageSizer <TraceProto> .GetSize, config.BufferOptions); var tracerFactory = new ManagedTracerFactory(projectId, consumer, RateLimitingTraceOptionsFactory.Create(config), TraceIdFactory.Create()); services.AddSingleton <IManagedTracerFactory>(tracerFactory); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddScoped(CreateTraceHeaderContext); services.AddScoped(CreateManagedTracer); }
/// <summary> /// Adds the needed services for Google Cloud Tracing. Used with <see cref="UseGoogleTrace"/>. /// </summary> /// <param name="services">The service collection. Cannot be null.</param> /// /// <param name="setupAction">Action to set up options. Cannot be null.</param> public static void AddGoogleTrace( this IServiceCollection services, Action <TraceServiceOptions> setupAction) { GaxPreconditions.CheckNotNull(services, nameof(services)); GaxPreconditions.CheckNotNull(setupAction, nameof(setupAction)); var serviceOptions = new TraceServiceOptions(); setupAction(serviceOptions); var client = serviceOptions.Client ?? TraceServiceClient.Create(); var options = serviceOptions.Options ?? TraceOptions.Create(); var traceFallbackPredicate = serviceOptions.TraceFallbackPredicate ?? TraceDecisionPredicate.Default; var projectId = CommonUtils.GetAndCheckProjectId(serviceOptions.ProjectId); var consumer = ConsumerFactory <TraceProto> .GetConsumer( new GrpcTraceConsumer(client), MessageSizer <TraceProto> .GetSize, options.BufferOptions, options.RetryOptions); var tracerFactory = new ManagedTracerFactory(projectId, consumer, RateLimitingTraceOptionsFactory.Create(options), TraceIdFactory.Create()); services.AddScoped(CreateTraceHeaderContext); services.AddSingleton <IManagedTracerFactory>(tracerFactory); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton(CreateManagedTracer); services.AddSingleton(CreateTraceHeaderPropagatingHandler); services.AddSingleton(traceFallbackPredicate); }
/// <summary> /// Adds the needed services for Google Cloud Tracing. Used with <see cref="UseGoogleTrace"/>. /// </summary> /// <param name="services">The service collection. Cannot be null.</param> /// <param name="projectId">Optional if running on Google App Engine or Google Compute Engine. /// The Google Cloud Platform project ID. If unspecified and running on GAE or GCE the project ID will be /// detected from the platform.</param> /// <param name="config">Optional trace configuration, if unset the default will be used.</param> /// <param name="client">Optional Trace client, if unset the default will be used.</param> /// <param name="traceFallbackPredicate">Optional function to trace requests. If the trace header is not set /// then this function will be called to determine if a given request should be traced. This will /// not override trace headers.</param> public static void AddGoogleTrace( this IServiceCollection services, string projectId = null, TraceConfiguration config = null, TraceServiceClient client = null, TraceDecisionPredicate traceFallbackPredicate = null) { GaxPreconditions.CheckNotNull(services, nameof(services)); client = client ?? TraceServiceClient.Create(); config = config ?? TraceConfiguration.Create(); traceFallbackPredicate = traceFallbackPredicate ?? TraceDecisionPredicate.Default; projectId = CommonUtils.GetAndCheckProjectId(projectId); var consumer = ConsumerFactory <TraceProto> .GetConsumer( new GrpcTraceConsumer(client), MessageSizer <TraceProto> .GetSize, config.BufferOptions); var tracerFactory = new ManagedTracerFactory(projectId, consumer, RateLimitingTraceOptionsFactory.Create(config), TraceIdFactory.Create()); services.AddScoped(CreateTraceHeaderContext); services.AddSingleton <IManagedTracerFactory>(tracerFactory); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton(CreateManagedTracer); services.AddSingleton(CreateTraceHeaderPropagatingHandler); services.AddSingleton(traceFallbackPredicate); }