Идентификатор операции при использовании Application Insight - PullRequest
0 голосов
/ 06 февраля 2019

Я предоставляю своей конечной точке идентификатор корреляции:

enter image description here

Затем я читаю этот идентификатор из HttpContext.Request.Headers и использую его какmy telemetry.Context.Operation.Id.

Это работает, но когда я просматриваю свой журнал, у меня появляется дополнительная запись, которая автоматически генерируется платформой.Эта запись имеет свой собственный идентификатор.Как я могу убедиться, что платформа использует один и тот же идентификатор?

enter image description here

Так я настраиваю службу

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Users.Api.Services;
using Users.Api.Utility;
using Users.Services.Implementations;
using Users.Services.Interfaces;
using Users.Sql;
using Users.Utility;
using Packages.Api.Filters;
using Packages.Audit;
using Swashbuckle.AspNetCore.Swagger;

namespace Users.Api
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Dependency injection
            services.AddAutoMapper();

            services.AddDbContext<UsersContext>(
               builder => builder.UseSqlServer(Environment.GetEnvironmentVariable("Connectionstring")));

            services.AddScoped<IUserService, UserService>();
            services.AddScoped<IIdentityService, IdentityService>();
            services.AddScoped<IServiceBusCommunicator, ServiceBusCommunicator>();
            services.AddScoped<IGraphClient, GraphClient>();
            services.AddScoped<IClaimsHarvester, ClaimsHarvester>();
            services.AddScoped<IUserRepository, UserRepository>();

            services.AddSingleton<HttpClient>();
            services.AddSingleton<EndpointConfiguration>();
            services.AddSingleton<GraphConfiguration>();
            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddScoped<IAuditLogClient, AuditLogClient>();

            var clientId = Environment.GetEnvironmentVariable("Authentication:AzureAd:ClientId");
            var tenant = Environment.GetEnvironmentVariable("Authentication:AzureAd:Tenant");
            var signInPolicyId = Environment.GetEnvironmentVariable("Authentication:AzureAd:SignInPolicyId");
            var authority = $"https://login.microsoftonline.com/tfp/{tenant}/{signInPolicyId}/v2.0/";

            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;

                }).AddJwtBearer(bearerOptions =>
                {
                    bearerOptions.Authority = authority;
                    bearerOptions.Audience = clientId;
                    bearerOptions.Events = new JwtBearerEvents
                    {
                        OnAuthenticationFailed = AuthenticationFailed
                    };
                });

            services.AddMvc();

            services.AddSwaggerGen(
                options =>
                {
                    options.SwaggerDoc("v1", new Info { Title = "Users API", Version = "v1" });
                });

            services.ConfigureSwaggerGen(options =>
            {
                options.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
                options.OperationFilter<CorrelationHeaderParameterOperationFilter>();
                options.OperationFilter<XTotalCountHeaderParameterOperationFilter>();
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app,
            IHostingEnvironment env,
            ILoggerFactory loggerFactory,
            ContextInitializer contextInitializer)
        {
            if (env.IsDevelopment())
            {
               // loggerFactory.AddConsole(Configuration.GetSection("Logging"));
               // loggerFactory.AddDebug();
                app.UseDeveloperExceptionPage();
            }

            app.UseAuthentication();
            app.UseMvc();

            app.UseSwagger();
            app.UseSwaggerUI(
                c =>
                {
                    c.SwaggerEndpoint($"{Environment.GetEnvironmentVariable("ServiceFabric:UniqueUrlPath")}/swagger/v1/swagger.json", "Contacts API V1");
                });

            // Seed default values
            contextInitializer.Seed();
        }

        private Task AuthenticationFailed(AuthenticationFailedContext arg)
        {
            // For debugging purposes only!
            var s = $"AuthenticationFailed: {arg.Exception.Message}";
            arg.Response.ContentLength = s.Length;
            arg.Response.Body.Write(Encoding.UTF8.GetBytes(s), 0, s.Length);
            return Task.FromResult(0);
        }
    }
}

1 Ответ

0 голосов
/ 07 февраля 2019

Обычно это не поддерживается ApplicationInsights.

Вы все еще можете этого достичь, но вам нужно написать собственную коллекцию запросов.

Вам необходимо удалить RequestTelemetryTrackingModule из контейнера DI и добавьте свое пользовательское промежуточное ПО, которое отслеживает запросы.

Что не будет работать с этим подходом (код ниже):

  • сценарии, когда вы используете разныеинструментальные ключи для этого сервиса и вышестоящих сервисов.Вы можете проверить, как он обрабатывается в AppInsights SDK (установить requestTelemetry.Source и заголовок ответа )

  • корреляция с информационными трассами, испускаемымиAspNetCore.

  • обычно, имя телеметрии запроса содержит маршрут, а не путь, вам может понадобиться выяснить это

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplicationInsightsTelemetry("ikey");
            var requestModule =
                services.FirstOrDefault(sd => sd.ImplementationType == typeof(RequestTrackingTelemetryModule));
            if (requestModule != null)
            {
                services.Remove(requestModule);
            }

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, TelemetryClient client)
        {
            app.UseMiddleware<RequestMiddleware>(client);
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }

    public class RequestMiddleware
    {
        private readonly RequestDelegate next;
        private readonly TelemetryClient telemetryClient;

        public RequestMiddleware(
            RequestDelegate next,
            TelemetryClient telemetryClient)
        {
            this.telemetryClient = telemetryClient;
            this.next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var activity = new Activity("request");
            if (context.Request.Headers.TryGetValue("x-my-correlation-id", out var val))
            {
                activity.SetParentId(val);
            }

            using (var request = telemetryClient.StartOperation<RequestTelemetry>(activity))
            {
                request.Telemetry.Url = context.Request.GetUri();
                request.Telemetry.Context.Operation.Name = $"{context.Request.Method} {context.Request.Path.Value}";
                request.Telemetry.Name = $"{context.Request.Method} {context.Request.Path.Value}";

                try
                {
                    await next.Invoke(context).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    telemetryClient.TrackException(e);
                    request.Telemetry.Success = false;
                    throw;
                }
                finally
                {
                    if (context.Response != null)
                    {
                        request.Telemetry.ResponseCode = context.Response.StatusCode.ToString();
                        request.Telemetry.Success = context.Response.StatusCode < 400;
                    }
                    else
                    {
                        request.Telemetry.Success = false;
                    }
                }
            }
        }
    }
...