我有以下例外:
public class InvalidStatusCodeException : Exception
{
public HttpStatusCode ReceivedStatusCode { get; set; }
public string ApiUrl { get; set; }
public InvalidStatusCodeException(HttpStatusCode receivedStatusCode, string apiUrl)
{
ReceivedStatusCode = receivedStatusCode;
ApiUrl = apiUrl;
}
}
在某些情况下扔掉它:
string url = "api/group/1/getAll";
var response = await _client.GetAsync(url);
if (!response.IsSuccessStatusCode)
throw new InvalidStatusCodeException(response.StatusCode, url);
如果我捕获并记录此异常:
catch(InvalidStatusCodeException status_ex)
{
string error = $"Invalid Status code for request: '{status_ex.ApiUrl}', received code: {status_ex.ReceivedStatusCode}";
log.LogError(status_ex, error, "InvalidStatusCode");
}
我看不到自定义属性(ReceivedStatusCode、ApiUrl)的值,只能在错误消息中查看详细信息。
如果我根本没有捕获此异常并且异常正在自动记录,那么根本无法查看详细信息。
有什么方法可以在不额外捕获异常的情况下查看这些自定义属性?
您可以使用结构日志记录的概念,将命名常量记录为自定义属性。
catch(InvalidStatusCodeException status_ex)
{
log.LogError(status_ex, "Invalid Status code for request: '{ApiUrl}', received code: {ReceivedStatusCode}", status_ex.ApiUrl, status_ex.ReceivedStatusCode);
}
上述日志将在应用程序洞察日志中添加
ApiUrl
和 ReceivedStatusCode
作为自定义属性。
更新
您不需要抛出并捕获异常。您可以登录
if (response.IsSuccessStatusCode)
的else块,如下所示:
if (response.IsSuccessStatusCode)
{
}
else
{
log.LogError(status_ex, "Invalid Status code for request: '{ApiUrl}', received code: {ReceivedStatusCode}",
apiUrl, response.StatusCode);
}
记录自定义属性的其他方式是通过 Logging Scope(检查this)和通过 TelemetryInitializer(检查this)
向底座添加消息
Exception
public class InvalidStatusCodeException : Exception
{
public HttpStatusCode ReceivedStatusCode { get; set; }
public string ApiUrl { get; set; }
public InvalidStatusCodeException(HttpStatusCode receivedStatusCode, string apiUrl)
: base($"Invalid Status code for request: '{apiUrl}', received code: {receivedStatusCode}")
{
ReceivedStatusCode = receivedStatusCode;
ApiUrl = apiUrl;
}
}
您可以为此编写一个自定义的中间件。有3个步骤:
第 1 步:自定义您要捕获的遥测数据:
public class CustomTelemetryMiddleware
{
private readonly RequestDelegate _next;
public CustomTelemetryMiddleware(RequestDelegate next)
{
_next = next;
}
// https://github.com/microsoft/ApplicationInsights-aspnetcore/issues/686#issuecomment-530353448
public async Task Invoke(HttpContext context)
{
var requestTelemetry = context.Features.Get<RequestTelemetry>();
if (requestTelemetry != null)
{
var request = context.Request;
// add items to show up in Request Properties:
requestTelemetry.Context.User.Id = context.User.Identity.Name;
// add items to show up in Custom Properties:
requestTelemetry.Properties.Add("PayingCustomer", "Yes");
/* Capture the request body as a Custom Property
*/
if (request?.Body?.CanRead == true)
{
request.EnableBuffering();
var bodySize = (int)(request.ContentLength ?? request.Body.Length);
if (bodySize > 0)
{
request.Body.Position = 0;
byte[] body;
using (var ms = new MemoryStream(bodySize))
{
await request.Body.CopyToAsync(ms);
body = ms.ToArray();
}
request.Body.Position = 0;
var requestBodyString = Encoding.UTF8.GetString(body);
requestTelemetry.Properties.Add("RequestBody", requestBodyString);
}
}
}
await _next(context);
}
}
第2步,注册:
public static class CustomTelemetryMiddlewareExtensions
{
public static IApplicationBuilder UseCustomTelemetry(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CustomTelemetryMiddleware>();
}
}
最后,第 3 步,在 Startup.cs 中注册它
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider)
{
// put this towards the end of your pipeline
app.UseCustomTelemetry();
}