/// <summary>
        /// Adds the needed services for Google Cloud Tracing. Used with <see cref="UseGoogleTrace"/>.
        /// </summary>
        /// <param name="services">The service collection. Must not be null.</param>
        /// <param name="setupAction">Action to set up options. Must not be null.</param>
        /// <remarks>
        /// If <see cref="RetryOptions.ExceptionHandling"/> is set to <see cref="ExceptionHandling.Propagate"/>
        /// and the <see cref="RequestDelegate"/> executed by this middleware throws ad exception and this
        /// diagnostics library also throws an exception trying to report it and <see cref="AggregateException"/>
        /// with both exceptions will be thrown.  Otherwise only the exception from the <see cref="RequestDelegate"/>
        /// will be thrown.
        /// </remarks>
        public static IServiceCollection 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 = Project.GetAndCheckProjectId(serviceOptions.ProjectId);

            var consumer      = ManagedTracer.CreateConsumer(client, options);
            var tracerFactory = ManagedTracer.CreateTracerFactory(projectId, consumer, options);

            services.AddScoped(CreateTraceHeaderContext);
            services.AddSingleton(tracerFactory);
            services.AddHttpContextAccessor();
            services.AddSingleton(ManagedTracer.CreateDelegatingTracer(ContextTracerManager.GetCurrentTracer));
            services.AddTransient <ICloudTraceNameProvider, DefaultCloudTraceNameProvider>();

            // On .Net Standard 2.0 or higher, we can use the System.Net.Http.IHttpClientFactory defined in Microsoft.Extensions.Http,
            // for which we need a DelagatingHandler with no InnerHandler set. This is the recommended way.
            // It should be registered as follows.
            services.AddTransient(sp => new UnchainedTraceHeaderPropagatingHandler(ContextTracerManager.GetCurrentTracer));
            // This is to be used for explicitly creating an HttpClient instance. Valid for all platforms.
            services.AddSingleton(new TraceHeaderPropagatingHandler(ContextTracerManager.GetCurrentTracer));

            return(services.AddSingleton(traceFallbackPredicate));
        }
        public static IServiceCollection AddGoogleTrace(
            this IServiceCollection services, Action <TraceServiceOptions> setupAction)
        {
            GaxPreconditions.CheckNotNull(services, nameof(services));
            GaxPreconditions.CheckNotNull(setupAction, nameof(setupAction));

            var serviceOptions = new TraceServiceOptions();

            setupAction(serviceOptions);

            services.AddGoogleTraceForAspNetCore(false, new AspNetCoreTraceOptions
            {
                TraceFallbackPredicate = serviceOptions.TraceFallbackPredicate,
                ServiceOptions         = new Common.TraceServiceOptions
                {
                    Client    = serviceOptions.Client,
                    Options   = serviceOptions.Options,
                    ProjectId = serviceOptions.ProjectId
                }
            });

            // This is to be used for explicitly creating an HttpClient instance. Valid for all platforms but subject to
            // issues with HttpClient lifetime as described in
            // https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests.
            // Although TraceHeaderPropagatingHandler supports a custom trace context propagator, we don't support it here by default.
            // The context propagator may be transient or scoped, in which case we'd have to register the TraceHeaderPropagatingHandler
            // as transient or scoped respectively. We don't know how to do that, and we don't want to do transient by default because
            // of the lifecycle issues described on the link above.
            // We use TryAdd so that user code may add their own TraceHeaderPropagatingHandler.
            // Obsolete: We are targeting netstastandard2.0 so user code can use the preferred UnchainedTraceHeaderPropagatingHandler.
            services.TryAddSingleton(new TraceHeaderPropagatingHandler(ContextTracerManager.GetCurrentTracer));

            return(services);
        }
Exemple #3
0
        /// <summary>
        /// Adds the needed services for Google Cloud Tracing. Used with <see cref="UseGoogleTrace"/>.
        /// </summary>
        /// <param name="services">The service collection. Must not be null.</param>
        /// <param name="setupAction">Action to set up options. Must not be null.</param>
        /// <remarks>
        /// If <see cref="RetryOptions.ExceptionHandling"/> is set to <see cref="ExceptionHandling.Propagate"/>
        /// and the <see cref="RequestDelegate"/> executed by this middleware throws ad exception and this
        /// diagnostics library also throws an exception trying to report it and <see cref="AggregateException"/>
        /// with both exceptions will be thrown.  Otherwise only the exception from the <see cref="RequestDelegate"/>
        /// will be thrown.
        /// </remarks>
        public static IServiceCollection AddGoogleTrace(
            this IServiceCollection services, Action <TraceServiceOptions> setupAction)
        {
            GaxPreconditions.CheckNotNull(services, nameof(services));
            GaxPreconditions.CheckNotNull(setupAction, nameof(setupAction));

            var serviceOptions = new TraceServiceOptions();

            setupAction(serviceOptions);

            services.AddGoogleTrace((Common.TraceServiceOptions commonOptions) =>
            {
                commonOptions.ProjectId = serviceOptions.ProjectId;
                commonOptions.Options   = serviceOptions.Options;
                commonOptions.Client    = serviceOptions.Client;
            });

            var traceFallbackPredicate = serviceOptions.TraceFallbackPredicate ?? TraceDecisionPredicate.Default;

            // We use TryAdd... here to allow user code to inject their own trace context provider
            // and matching trace context response propagator. We use Google trace header otherwise.
            services.TryAddGoogleTraceContextProvider();
            services.TryAddSingleton <Action <HttpResponse, ITraceContext> >(PropagateGoogleTraceHeaders);

            // Obsolete: Adding this for backwards compatibility in case someone is using the old factory type.
            // The new and prefered factory type is Func<ITraceContext, IManagedTracer>.
            services.AddSingleton <Func <TraceHeaderContext, IManagedTracer> >(sp => sp.GetRequiredService <Func <ITraceContext, IManagedTracer> >());

            services.AddHttpContextAccessor();
            services.AddTransient <ICloudTraceNameProvider, DefaultCloudTraceNameProvider>();

            // This is to be used for explicitly creating an HttpClient instance. Valid for all platforms but subject to
            // issues with HttpClient lifetime as described in
            // https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests.
            // Although TraceHeaderPropagatingHandler supports a custom trace context propagator, we don't support it here by default.
            // The context propagator may be transient or scoped, in which case we'd have to register the TraceHeaderPropagatingHandler
            // as transient or scoped respectively. We don't know how to do that, and we don't want to do transient by default because
            // of the lifecycle issues described on the link above.
            // We use TryAdd so that user code may add their own TraceHeaderPropagatingHandler.
            // Obsolete: We are targeting netstastandard2.0 so user code can use the preferred UnchainedTraceHeaderPropagatingHandler.
            services.TryAddSingleton(new TraceHeaderPropagatingHandler(ContextTracerManager.GetCurrentTracer));

            return(services.AddSingleton(traceFallbackPredicate));
        }