我在ASP.NETMVC5和6上有一些旧的应用程序,我想完成一些类似ASP.NETCore所做的自动W3C跟踪ID传播的功能。(例如,阅读传入的traceparent
请求标头,相应地设置Activity.Current属性。将值存储在请求上下文中并不理想,因为它不会自动对其他任务可用,但这将是一个很好的开始)。
我想有一些中间件,在每个控制器之前运行并设置Activity。要创建这个中间件,我需要使用OWIN吗?或者在ASP.NET MVC中有一些内置的东西,我可以使用它来运行代码,以便在将请求提交给控制器方法之前读取请求?
我尝试设置一个OWIN中间件来尝试设置Activity.Current属性和OwinContext。我不知道我做得对不对,但是Activity.Current
总是null,控制器中的Request.GetOwinContext()
调用也总是null,即使我可以在它从OWIN中间件传递到控制器之前看到值,并且线程ID在Startup.cs中的lambda函数和ValuesController.Get方法中是相同的。
看起来OWIN中间件甚至在控制器被调用之前就已经退出了,也许这就是原因吧?
// Startup.cs
using Microsoft.Owin;
using Owin;
using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
using System.Web.Http;
[assembly: OwinStartup(typeof(ActivityDemo.Startup))]
namespace ActivityDemo
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
app.Use(async (ctx, next) =>
{
ActivityContext activityCtx = default;
string traceparent = ctx.Request.Headers.Get("traceparent");
if (traceparent != null)
{
try
{
string tracestate = ctx.Request.Headers.Get("tracestate");
ActivityContext.TryParse(traceparent, tracestate, out activityCtx);
}
catch { }
}
// We depend on the activity being set (for logging with Serilog),
// so create one manually even if no one is listening to the
// ActivitySource.
Activity activity = new Activity("ReceiveHttpRequest").SetParentId(traceparent).Start();
// ctx.Request.Set("traceparent", traceparent);
ctx.Environment["traceparent"] = traceparent;
var current = Activity.Current; // inserted to inspect with debugger
await next();
});
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
// app.Run();
}
}
}
// ValuesController.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace ActivityDemo.Controllers
{
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
var activity = Activity.Current;
var owinContext = Request.GetOwinContext(); // inserted to inspect with debugger, always `null`
var owinEnv = Request.GetOwinEnvironment(); // inserted to inspect with debugger, always `null`
return new string[] { "value1", "value2", Activity.Current?.TraceId.ToString() };
}
}
}
这只是我尝试的第一件事我对非OWIN解决方案也持开放态度。
1条答案
按热度按时间bjp0bcyl1#
我想我找到了!
1.将
System.Diagnostics.DiagnosticSource
和System.Reactive.Core
包添加到ASP.NET项目中。1.创建一个新文件
App_Start\DiagnosticsConfig.cs
,包含以下内容:1.解析
Global.Asax.cs
的traceparent
头Application_BeginRequest()
和Application_EndRequest()
方法。另外,注册侦听器。之后,您应该将
Activity.Current
设置为Controller代码/日志的传入traceparent
头,并且来自System.Net.Http
的传出请求将自动开始一个新的span。