using Microsoft.AspNetCore.Mvc.Filters; using PostSharp.Patterns.Diagnostics; using System; using System.Collections.Generic; using System.Net; using System.Threading.Tasks; using static PostSharp.Patterns.Diagnostics.SemanticMessageBuilder; namespace MicroserviceExample { [Log(AttributeExclude = true)] public class LoggingActionFilter : IAsyncActionFilter { private static readonly LogSource logger = LogSource.Get(); public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // Read the Request-Id header so we can assign it to the activity. string parentOperationId = context.HttpContext.Request.Headers["Request-Id"]; OpenActivityOptions options = default; // Set the parent id. if (!string.IsNullOrEmpty(parentOperationId)) { options.SyntheticParentId = parentOperationId; } else { options.IsSyntheticRootId = true; } // Process cross-context properties (aka baggage). string correlationContext = context.HttpContext.Request.Headers["Correlation-Context"]; if (!string.IsNullOrEmpty(correlationContext)) { options.Properties = ParseCorrelationContext(correlationContext)?.ToArray(); } var request = context.HttpContext.Request; using (var activity = logger.Default.OpenActivity(Semantic("Request", ("Path", request.Path), ("Query", request.QueryString), ("Method", request.Method)), options)) { try { await next(); var response = context.HttpContext.Response; if (response.StatusCode >= (int) HttpStatusCode.OK && response.StatusCode <= 299) { // Success. activity.SetOutcome(LogLevel.Info, Semantic("Success", ("StatusCode", response.StatusCode))); } else { // Failure. activity.SetOutcome(LogLevel.Warning, Semantic("Failure", ("StatusCode", response.StatusCode))); } } catch (Exception e) { activity.SetException(e); } } } private static List<LoggingProperty> ParseCorrelationContext(string correlationContext) { var properties = new List<LoggingProperty>(); foreach (var pair in correlationContext.Split(',', StringSplitOptions.RemoveEmptyEntries)) { var posOfEqual = pair.IndexOf('='); if (posOfEqual <= 0) { continue; } var propertyName = pair.Substring(0, posOfEqual); var propertyValue = pair.Substring(posOfEqual + 1); properties.Add(new LoggingProperty(propertyName, propertyValue) { IsBaggage = true }); } return properties; } } }