Добавление метаданных к трассировкам в функциях Azure - PullRequest
0 голосов
/ 05 ноября 2019

У меня есть функция Azure (.NET core 2.0), которая запускается на каждом PR в репозитории ADO. Я хотел бы добавить PR-ID в качестве метаданных к каждой трассировке, зарегистрированной функцией Azure. (Я просматриваю журналы, используя таблицу traces в экземпляре Insights приложения Azure)

Функция Azure регистрирует трассировки с помощью:

public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, ILogger log, ExecutionContext context)
{
  logger.LogInformation("Trace Message");
}

Как добавить дополнительные метаданные к каждой трассе?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Да, это возможно.

Вариант 1: Использование инициализатора телеметрии с помощью AsyncLocal :

    public class CustomTelemetryInitializer : ITelemetryInitializer
    {
        public static AsyncLocal<string> MyValue = new AsyncLocal<string>();

        public void Initialize(ITelemetry telemetry)
        {
            if (telemetry is ISupportProperties propertyItem)
            {
                propertyItem.Properties["myProp"] = MyValue.Value;
            }
        }
    }

Вы можетеустановите значение AsyncLocal в функции следующим образом:

        [FunctionName("Function")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req,
            ILogger log)
        {
            var name = req.Query["name"];

            CustomTelemetryInitializer.MyValue.Value = name;

            log.LogInformation("C# HTTP trigger function processed a request.");

            return new OkObjectResult($"Hello, {name}");
        }

При запуске функции вы можете увидеть информацию на портале:

enter image description here

Вы можете найти весь код в этом репо

Теперь, обращаясь к вашим комментариям. Да, вам нужно что-то дополнительное. Экземпляр ITelemetryInitializer необходимо зарегистрировать с помощью внедрения зависимостей. Это делается в классе Startup, как указано в документации :

    using Microsoft.ApplicationInsights.Extensibility;
    using Microsoft.Azure.Functions.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection;

    [assembly: FunctionsStartup(typeof(FunctionApp.Startup))]

    namespace FunctionApp
    {
        public class Startup : FunctionsStartup
        {
            public override void Configure(IFunctionsHostBuilder builder)
            {
                builder.Services.AddSingleton<ITelemetryInitializer, CustomTelemetryInitializer>();
                builder.Services.AddLogging();
            }
        }
    }

После регистрации SDK Application Insights будет использовать CustomTelemetryInitializer.

Опция 2 Другая опция не включает какой-либо TelemetryInitializer, но вы можете добавить только свойства к сгенерированному RequestTelemetry, который добавляется интеграцией Azure Function App Insights. Это делается с использованием факта, что текущий TelemetryRequest хранится в HttpContext:

       [FunctionName("Function")]
        public static IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req,
            ILogger log)
        {
            var name = req.Query["name"];

            CustomTelemetryInitializer.MyValue.Value = name;

            log.LogInformation("C# HTTP trigger function processed a request.");

            var telemetryItem = req.HttpContext.Features.Get<RequestTelemetry>();
            telemetryItem.Properties["SetInFunc"] = name;

            return new OkObjectResult($"Hello, {name}");
        }

Это также будет отображаться на портале:

enter image description here

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

union (traces), (requests), (dependencies), (customEvents), (exceptions)
| extend itemType = iif(itemType == 'availabilityResult',itemType,iif(itemType == 'customEvent',itemType,iif(itemType == 'dependency',itemType,iif(itemType == 'pageView',itemType,iif(itemType == 'request',itemType,iif(itemType == 'trace',itemType,iif(itemType == 'exception',itemType,"")))))))
| extend prop = customDimensions.SetInFunc
| where ((itemType == 'trace' or (itemType == 'request' or (itemType == 'pageView' or (itemType == 'customEvent' or (itemType == 'exception' or (itemType == 'dependency' or itemType == 'availabilityResult')))))))
| top 101 by timestamp desc

покажет:

enter image description here

Вся телеметрия, исходящая из одного вызова, будет иметь одинаковый operation_Id.

1 голос
/ 06 ноября 2019

Это можно реализовать с помощью Инициализатор ITelemetry , вы можете добавить пользовательское измерение к указанной телеметрии, как только для запроса.

1.Установите следующие пакеты nuget:

Microsoft.ApplicationInsights, version 2.11.0

Microsoft.NET.Sdk.Functions, version 1.0.29

2. Ниже приведен мой тестовый код.

[assembly: WebJobsStartup(typeof(FunctionApp54.MyStartup))]
namespace FunctionApp54
{

    internal class MyTelemetryInitializer : ITelemetryInitializer
    {
        public void Initialize(ITelemetry telemetry)
        {

            //use telemetry is RequestTelemetry to make sure only add to request
            if (telemetry != null && telemetry is RequestTelemetry && !telemetry.Context.GlobalProperties.ContainsKey("testpro"))
            {
                telemetry.Context.GlobalProperties.Add("testpro", "testvalue");
            }
        }
    }

    public class MyStartup : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {
            builder.Services.AddSingleton<ITelemetryInitializer, MyTelemetryInitializer>();

        }
    }

    public static class Function2
    {


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

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

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

            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
        }
    }
}

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...