Аспект в функции Azure для корреляции Application Insight - PullRequest
0 голосов
/ 19 октября 2018

Я написал много функций Azure (Http, ServiceBus, EventHub и триггер CosmosDB).Для ведения журнала приложений я реализовал свой собственный класс Logger, который создает объект TelemetryClient для загрузки журнала в Application Insight.

Я вижу все свои журналы трассировки, исключений и исключений в Application Insight, ноЯ не могу сопоставить без OperationName и OperationId

Теперь я вручную вызываю TelemetryClient StartOperation и StopOperation длясоздать OperationId.

AzureFunction

[FunctionName("AlertEventStoreFunction")]
    public static async Task Run([EventHubTrigger("%AlertEventHub%", Connection = "AlertEventHubConnection", ConsumerGroup = "cg1")]EventData eventMessage,
        [Inject]IEventService eventService, [Inject]ILog log)
    {
        log.StartOperation("AlertEventStoreFunction");
        try
        {                
            log.Info($"Event PartitionKey {eventMessage.PartitionKey}, Offset {eventMessage.Offset} and SequenceNumber {eventMessage.SequenceNumber}");
            string message = Encoding.UTF8.GetString(eventMessage.GetBytes());
            log.Verbose(message);
            await eventService.SaveAlertEventAsync(message);
        }
        catch (Exception ex)
        {
            log.Error(ex.Message, ex);
        }
        finally
        {
            log.StopOperation();
        }
    }

Logger Class

public class Log : ILog
{
    private static TelemetryClient telemetryClient = new TelemetryClient() { InstrumentationKey = ConfigurationManager.AppSettings["InstrumentationKey"] };
    private IOperationHolder<RequestTelemetry> operation;
    private bool status = true;

    public TelemetryClient TelemetryClient
    {
        get
        {
            return telemetryClient;
        }
    }

    /// <summary>
    /// This method will start new session for particular request, we can correlate each log by Operation_Id
    /// </summary>
    /// <param name="functionName">function name</param>
    public void StartOperation(string functionName)
    {
        RequestTelemetry requestTelemetry = new RequestTelemetry { Name = functionName };
        this.operation = telemetryClient.StartOperation(requestTelemetry);
        telemetryClient.TrackTrace($"{functionName} trigger");
    }

    /// <summary>
    /// this method will close session
    /// </summary>
    public void StopOperation()
    {
        telemetryClient.StopOperation(this.operation);
        this.operation.Telemetry.Success = status;
    }

    public void Error(string message, Exception ex = null)
    {
        telemetryClient.TrackTrace(message, SeverityLevel.Error);
        if (ex != null)
            telemetryClient.TrackException(ex);
        status = false;
    }

    public void Info(string message)
    {
        telemetryClient.TrackTrace(message, SeverityLevel.Information);
    }

    public void Verbose(string message)
    {
        telemetryClient.TrackTrace(message, SeverityLevel.Verbose);
    }

    public void Warning(string message)
    {
        telemetryClient.TrackTrace(message, SeverityLevel.Warning);
    }
}

Я не хочу помещать блок try-catch в каждую функцию, поэтому я создал Aspect (AOP) с использованием postsharp, он работал, как и ожидалось, но бесплатная версия позволяет работать только с 10 функциями.

Я не вижу другой хорошей замены postsharp (пробовал sprint.net, Cauldron.Interception и т. д.)

Вместо этого кода, что я могу сделать, чтобы создать корреляцию (OperationId)?

1 Ответ

0 голосов
/ 20 октября 2018

У меня есть Postsharp альтернатива "MrAdvice", новая версия не имеет никакой зависимости

public class LoggerAspect : Attribute, IMethodAdvice
{
    private ILog log;
    private IOperationHolder<RequestTelemetry> operation;

    public void Advise(MethodAdviceContext context)
    {
        try
        {
            log = LogManager.GetLogger();
            RequestTelemetry requestTelemetry = new RequestTelemetry { Name = context.TargetType.Name };
            operation = log.TelemetryClient.StartOperation(requestTelemetry);
            operation.Telemetry.Success = true;

            context.Proceed(); // this calls the original method
        }
        catch (Exception ex)
        {
            operation.Telemetry.Success = false;
            log.Error(ex.Message, ex);
        }
        finally
        {
            log.TelemetryClient.StopOperation(operation);
        }
    }
}

Все еще открыта для лучших предложений.

...