0

我希望我们的分布式事件日志具有适当的相关性。对于我们的 Web 应用程序,这似乎是自动的。来自我们的应用服务 API 之一的相关日志示例:

在此处输入图像描述

但是,对于我们的其他(非 ASP、非 WebApp)服务,我们使用 Log4Net 和 App Insights appender,我们的日志不相关。我在这里尝试了以下说明:https ://docs.microsoft.com/en-us/azure/azure-monitor/app/correlation

即使在为每个操作添加了唯一的 operation_Id 属性之后,我们也没有看到日志相关性(我也尝试过“Operation Id”)。无相关日志条目的示例: 在此处输入图像描述

任何有关如何使用 log4net 实现此目的的帮助将不胜感激。

干杯!

4

1 回答 1

1

跨服务相关 ID 主要通过标头传播。当为 Web 应用程序启用 AI 时,它会从传入标头中读取 ID/上下文,然后使用适当的 ID/上下文更新传出标头。在服务中,使用 Activity 对象跟踪操作,发出的每个遥测数据都将与此 Activity 相关联,从而共享必要的关联 ID。

在服务总线/事件中心通信的情况下,最新版本也支持传播(ID/上下文作为元数据传播)。

如果服务不是基于 Web 的并且 AI 自动关联传播不起作用,您可能需要手动从某些元数据中获取传入的 ID 信息(如果有),恢复/启动 Activity,使用此 Activity 启动 AI 操作。当在该活动范围内生成遥测项目时,它将获得正确的 ID,并将成为总体跟踪的一部分。这样,如果遥测是从在 AI 操作上下文范围内执行的 Log4net 跟踪生成的,那么该遥测应该获得正确的 ID。

从标头访问相关性的代码示例:

public class ApplicationInsightsMiddleware : OwinMiddleware
{
    // you may create a new TelemetryConfiguration instance, reuse one you already have
    // or fetch the instance created by Application Insights SDK.
    private readonly TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.CreateDefault();
    private readonly TelemetryClient telemetryClient = new TelemetryClient(telemetryConfiguration);

    public ApplicationInsightsMiddleware(OwinMiddleware next) : base(next) {}

    public override async Task Invoke(IOwinContext context)
    {
        // Let's create and start RequestTelemetry.
        var requestTelemetry = new RequestTelemetry
        {
            Name = $"{context.Request.Method} {context.Request.Uri.GetLeftPart(UriPartial.Path)}"
        };

        // If there is a Request-Id received from the upstream service, set the telemetry context accordingly.
        if (context.Request.Headers.ContainsKey("Request-Id"))
        {
            var requestId = context.Request.Headers.Get("Request-Id");
            // Get the operation ID from the Request-Id (if you follow the HTTP Protocol for Correlation).
            requestTelemetry.Context.Operation.Id = GetOperationId(requestId);
            requestTelemetry.Context.Operation.ParentId = requestId;
        }

        // StartOperation is a helper method that allows correlation of 
        // current operations with nested operations/telemetry
        // and initializes start time and duration on telemetry items.
        var operation = telemetryClient.StartOperation(requestTelemetry);

        // Process the request.
        try
        {
            await Next.Invoke(context);
        }
        catch (Exception e)
        {
            requestTelemetry.Success = false;
            telemetryClient.TrackException(e);
            throw;
        }
        finally
        {
            // Update status code and success as appropriate.
            if (context.Response != null)
            {
                requestTelemetry.ResponseCode = context.Response.StatusCode.ToString();
                requestTelemetry.Success = context.Response.StatusCode >= 200 && context.Response.StatusCode <= 299;
            }
            else
            {
                requestTelemetry.Success = false;
            }

            // Now it's time to stop the operation (and track telemetry).
            telemetryClient.StopOperation(operation);
        }
    }

    public static string GetOperationId(string id)
    {
        // Returns the root ID from the '|' to the first '.' if any.
        int rootEnd = id.IndexOf('.');
        if (rootEnd < 0)
            rootEnd = id.Length;

        int rootStart = id[0] == '|' ? 1 : 0;
        return id.Substring(rootStart, rootEnd - rootStart);
    }
}

单独进行手动关联操作跟踪的代码示例:

async Task BackgroundTask()
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>(taskName);
    operation.Telemetry.Type = "Background";
    try
    {
        int progress = 0;
        while (progress < 100)
        {
            // Process the task.
            telemetryClient.TrackTrace($"done {progress++}%");
        }
        // Update status code and success as appropriate.
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        // Update status code and success as appropriate.
        throw;
    }
    finally
    {
        telemetryClient.StopOperation(operation);
    }
}

请注意,最新版本的 Application Insights SDK 正在切换到 W3C 相关标准,因此根据 W3C 规范,标头名称和预期格式会有所不同

于 2019-12-05T01:47:46.563 回答