Application Insights с несколькими приложениями - PullRequest
0 голосов
/ 13 марта 2020

У меня есть Application Insights, который регистрирует трассировки от службы приложений и функции приложения (один ресурс для 2 функций). Мне нужно отфильтровать трассировки в соответствии с ресурсом (служба приложения или функция приложения) и, если возможно, для функции приложения, функция которой фактически регистрирует данные. Глядя на следы, я вижу следующий список свойств:

enter image description here

Я подумал найти имя ресурса в свойстве appName, вместо этого есть имя ресурса Application Insights, которое для меня бесполезно, поскольку все эти трассировки происходят от этого ресурса.

Примечание. Мне не нравится обходной путь для установки префикса в сообщении для фильтрации трасс.

ОБНОВЛЕНИЕ

Я последовал советам Питера Бонса и создал совершенно новый проект Function V3. Базовая c версия проекта работала также без инициализатора телеметрии, я имею в виду, что свойство Cloud_RoleName было правильно заполнено. Затем я добавил свои изменения, чтобы адаптировать пример кода, и обнаружил, что проблема возникает, когда я внедряю новый клиент телеметрии. Я знаю, что не рекомендуется вручную вводить TelemetryClient в функцию приложения, но мне абсолютно необходимо отправить пользовательское событие в Application Insights, и, насколько я знаю, это невозможно с интерфейсом ILogger, используемым по умолчанию в функции приложения.

Startup.cs

public class Startup : FunctionsStartup
{
    private TelemetryConfiguration telemetryConfiguration;

    public override void Configure(IFunctionsHostBuilder builder)
    {
        var localRoot = Environment.GetEnvironmentVariable("AzureWebJobsScriptRoot");
        var azureRoot = $"{Environment.GetEnvironmentVariable("HOME")}/site/wwwroot";

        var configBuilder = new ConfigurationBuilder()
            .SetBasePath(localRoot ?? azureRoot)
            .AddEnvironmentVariables()
            .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true);

        var configuration = configBuilder.Build();

        if (builder != null)
        {
            this.ConfigureServices(builder.Services, configuration);
        }
    }

    private void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<ITelemetryInitializer>(x => new CustomTelemetryInitializer(configuration["appFunctionName"]));
        telemetryConfiguration = new TelemetryConfiguration(configuration["APPINSIGHTS_INSTRUMENTATIONKEY"]);
        telemetryConfiguration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
        var telemetryClient = new TelemetryClient(telemetryConfiguration);
        services.AddSingleton(telemetryClient);

        services.AddSingleton<ISampleInterface, SampleService>();
    }
}

CustomTelemetryInitializer.cs

public class CustomTelemetryInitializer : ITelemetryInitializer
{
    private readonly string roleName;

    public CustomTelemetryInitializer(string roleName)
    {
        this.roleName = roleName;
    }

    public void Initialize(ITelemetry telemetry)
    {
        if (string.IsNullOrEmpty(telemetry?.Context?.Cloud?.RoleName))
        {
            telemetry.Context.Cloud.RoleName = roleName;
        }
    }
}

SampleService.cs

public class SampleService : ISampleInterface
{
    private TelemetryClient telemetryClient;

    public SampleService(TelemetryClient telemetryClient)
    {
        this.telemetryClient = telemetryClient;
    }

    public void TestAppInsights()
    {
        telemetryClient.TrackEvent("Sample Custom Event with init");
        telemetryClient.TrackTrace("Sample Custom Trace with init");
    }
}

Function.cs

public class Function1
{
    private ISampleInterface service;
    public Function1(ISampleInterface service)
    {
        this.service = service;
    }

    [FunctionName("Function1")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request with init.");

        this.service.TestAppInsights();

        string name = req.Query["name"];

        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        name = name ?? data?.name;

        string responseMessage = string.IsNullOrEmpty(name)
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
            : $"Hello, {name}. This HTTP triggered function executed successfully.";

        return new OkObjectResult(responseMessage);
    }
}

1 Ответ

0 голосов
/ 13 марта 2020

Как насчет проверки свойства cloud_RoleName, доступного для всей телеметрии? По умолчанию в качестве значения будет указано имя веб-приложения или функции (включая имена слотов).

В противном случае, если вы хотите добавить пользовательские свойства или изменить свойства для всей телеметрии в одном месте, вы можете использовать инициализатор телеметрии как продемонстрировано здесь :

using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;

namespace CustomInitializer.Telemetry
{
    public class MyTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(ITelemetry telemetry)
        {
            telemetry.Context.Cloud.RoleName = "HttpTriggered";
        }
    }
}

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

enter image description here

Другое дело

[...] но я абсолютно необходимо отправить пользовательское событие в Application Insights и, насколько я знаю, это невозможно с интерфейсом ILogger, используемым по умолчанию в функции приложения.

Обратите внимание, что вы можете перенаправить вывод, используя ILogger интерфейс к Application Insights. Это будет отображаться как след.

...