将Hangfire作业记录到Application Insights并将活动与操作ID相关联

彭多·保罗

我觉得这应该比事实简单得多,或者我只是想得太多。

我有一个.NET Core 3.1 Web API应用程序,该应用程序使用HangFire在后台处理某些作业。我还配置了Application Insights以从.NET Core API记录遥测。

我可以在Application Insights中看到记录事件和相关性遥测数据。但是,每个事件/日志/依赖项都是根据唯一的OperationId和Parent ID记录的。

我正在尝试确定如何确保针对在后台作业中排队的原始请求的OperationId和/或父ID记录已记录的任何活动或在后台作业的上下文中使用的任何依赖项。

当我排队一个作业时,我可以获取传入的HTTP请求的当前OperationId,然后将其与该作业一起推入HangFire队列。然后执行作业时,我可以取回该OperationId。然后,我需要做的是使OperationID在作业执行的整个上下文/生命周期中都可用,以便将其附加到发送给Application Insightd的任何遥测中。

我以为我可以创建一个IJobContext接口,可以将其注入执行作业的类中。在这种情况下,我可以推送OperationID。然后,我可以创建一个ITelemetryInitializer,它也将IJobContext作为依赖项。然后,我可以在ITelemetryInitializer中设置要发送到Application Insights的遥测的OperationID和ParentId。这是一些简单的代码:

public class HangFirePanelMessageQueue : IMessageQueue
{
    private readonly MessageProcessor _messageProcessor;
    private readonly IHangFireJobContext _jobContext;
    private readonly TelemetryClient _telemetryClient;

    public HangFirePanelMessageQueue(MessageProcessor panelMessageProcessor,
        IIoTMessageSerializer iotHubMessageSerialiser,
        IHangFireJobContext jobContext, TelemetryClient telemetryClient)
    {
        _messageProcessor = panelMessageProcessor;
        _jobContext = jobContext;
        _telemetryClient = telemetryClient;
    }

    public async Task ProcessQueuedMessage(string message, string operationId)
    {
        var iotMessage = _iotHubMessageSerialiser.GetMessage(message);

        _jobContext?.Set(iotMessage.CorrelationID, iotMessage.MessageID);

        await _messageProcessor.ProcessMessage(iotMessage);
    }

    public Task QueueMessageForProcessing(string message)
    {
        var dummyTrace = new TraceTelemetry("Queuing message for processing", SeverityLevel.Information);
        _telemetryClient.TrackTrace(dummyTrace);
        string opId = dummyTrace.Context.Operation.Id;

        BackgroundJob.Enqueue(() =>
        ProcessQueuedMessage(message, opId));

        return Task.CompletedTask;
    }
}

IJobContext看起来像这样:

public interface IHangFireJobContext
{
    bool Initialised { get; }

    string OperationId { get; }

    string JobId { get; }

    void Set(string operationId, string jobId);
}

然后,我将拥有一个ITelemetryInitializer来丰富任何ITelemetry:

public class EnrichBackgroundJobTelemetry : ITelemetryInitializer
{
    private readonly IHangFireJobContext jobContext;

    public EnrichBackgroundJobTelemetry(IHangFireJobContext jobContext)
    {
        this.jobContext = jobContext;
    }

    public void Initialize(ITelemetry telemetry)
    {
        if (!jobContext.Initialised)
        {
            return;
        }

        telemetry.Context.Operation.Id = jobContext.OperationId;
    }
}

但是,我遇到的问题是ITelemetryInitializer是一个单例,因此将使用IHangFireJobContext对其实例化一次,然后再对其进行后续的HangFire作业都不会进行更新。

我确实找到了https://github.com/skwasjer/Hangfire.Correlate项目,该项目扩展了https://github.com/skwasjer/Correlate关联创建一个关联上下文,可以通过类似于IHttpContextAccessor的ICorrelationContextAccessor进行访问。

但是,Correlate的脚注状态为“请考虑.NET Core 3现在已经内置了对W3C TraceContext(blog)的支持,并且还有其他分布式跟踪库,其功能比Correlate更多。” 其中将Application Insights列为更高级的分布式跟踪的替代方法之一。

那么,有谁能帮助我了解在HangFire作业的上下文中创建到Application Insights的任何遥测信息时,我该如何丰富它们?我认为正确的答案是使用ITelemetryInitializer并在该ITelemetry项上填充OperationId,但是,我不确定要向ITelemetryInitialzer中注入什么依赖关系才能访问HangFire作业上下文。

彼得·邦斯

当我排队一个作业时,我可以获取传入的HTTP请求的当前OperationId,然后将其与该作业一起推入HangFire队列。

因此,我是否正确地说您有一个控制器操作将工作推向停火状态?如果是这样,您可以在控制器方法内部进行操作,获取操作ID并将其传递给作业。使用该操作ID使用操作ID开始新操作。该操作以及在该操作期间生成的所有遥测将被链接到原始请求。

我没有进行hangfire集成,但是下面的代码显示了总体思路:一些工作在后台排队等待完成,并且应该链接到有关遥测的请求:

        [HttpGet("/api/demo5")]
        public ActionResult TrackWorker()
        {
            var requestTelemetry = HttpContext.Features.Get<RequestTelemetry>();

            _taskQueue.QueueBackgroundWorkItem(async ct =>
            {
                using(var op = _telemetryClient.StartOperation<DependencyTelemetry>("QueuedWork", requestTelemetry.Context.Operation.Id))
                {
                    _ = await new HttpClient().GetStringAsync("http://blank.org");

                    await Task.Delay(250);
                    op.Telemetry.ResultCode = "200";
                    op.Telemetry.Success = true;
                }
            });

            return Accepted();
        }

完整的示例可以在这里找到

在此处输入图片说明

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将玩家ID与交易相关联?

来自分类Dev

将玩家ID与交易相关联?

来自分类Dev

从Docker容器将数据记录到Azure Application Insights

来自分类Dev

如何将图片与商品ID相关联

来自分类Dev

将数据框列与上一个活动相关联

来自分类Dev

将 Rails 活动模型与两个不同的模型相关联

来自分类Dev

使用grep将ping命令中的ttl与操作系统相关联

来自分类Dev

在Ruby on Rails Admin上按ID将记录与相同模型的其他记录相关联

来自分类Dev

在Ruby on Rails Admin上按ID将记录与相同模型的其他记录相关联

来自分类Dev

将App与Epub格式相关联

来自分类Dev

将修订与Redmine问题相关联

来自分类Dev

将Braintree PaymentMethod与地址相关联

来自分类Dev

将NServiceBus Saga与ConversationId相关联

来自分类Dev

将按钮与Enter键相关联

来自分类Dev

CakePhp将评论与帖子相关联

来自分类Dev

将信息框与图像相关联

来自分类Dev

将组合的索引与值相关联

来自分类Dev

将特定索引与向量相关联

来自分类Dev

Firebase - 将图片与用户相关联?

来自分类Dev

如何将动态添加的输入字段与父元素/ id相关联?

来自分类Dev

如何将多个ID与MS SQL Server中的单个行相关联?

来自分类Dev

如何将传单标记与数据库中的对象ID相关联

来自分类Dev

将div标签放置在其他标签之上,并将位置与另一个div相关联

来自分类Dev

删除与某个子值相关联的整个记录

来自分类Dev

如何将鳄梨酱记录文件与历史连接记录相关联

来自分类Dev

禁用Azure DevOps功能,其中讨论中的#ID将两个工作项相关联?

来自分类Dev

将运算结果与哈希图值相关联

来自分类Dev

将aiohttp请求与其响应相关联

来自分类Dev

将“外部”类模型与flask sqlalchemy相关联

Related 相关文章

热门标签

归档