我尝试为ServiceStack api中的所有传入请求分配全局请求/跟踪ID。我通过添加以下预请求过滤器解决了这个问题:
PreRequestFilters.Add((request, response) =>
{
var requestId = Guid.NewGuid();
request.Items["RequestId"] = requestId;
});
哪一项都运行得很好 - 我可以在我的自定义ServiceStack服务运行器和所有内容中看到请求ID。
当我希望将此请求ID写入我的日志时,会出现问题。我使用的是Nlog,并创建了以下自定义布局渲染器:
public class RequestIdLayoutRenderer : LayoutRenderer
{
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
if (ServiceStackHost.Instance == null) return;
var request = ServiceStackHost.Instance.TryGetCurrentRequest();
if (request == null) return;
object requestId;
if (!request.Items.TryGetValue("RequestId", out requestId)) return;
builder.Append(requestId);
}
}
问题是:当返回request
时,Items
集合仅包含默认的ServiceStack元素AspSessionIDManagerInitializeRequestCalled
。
我的问题是:这是预期的行为,如果是,那么我该如何检索Items
集合"外部" ServiceStack范围?
有没有更好的方法来共享此请求ID,以便NLog可以接收它?
我已经在Nlog中尝试了MappedDiagnosticsContext
,但由于奇怪的原因,一些日志条目缺少RequestId,所以这是为了避免使用上下文。
Windows 10 Update 1上的ServiceStack版本为4.0.52和.net版本4. Nlog版本4.
答案 0 :(得分:2)
ServiceStack ASP.NET IRequest
保留了最初源自但与基础ASP.NET请求分离的字典项的本地副本。如果要在ServiceStack请求的上下文之外共享数据,但在同一个ASP.NET请求中,可以使用HttpContext.Current
单例,例如:
PreRequestFilters.Add((request, response) =>
{
var requestId = Guid.NewGuid();
HttpContext.Current.Items["RequestId"] = requestId;
//Alternative API:
//var aspReq = (HttpRequestBase)request.OriginalRequest;
//aspReq.Items["RequestId"] = requestId;
});