Skip to main content

Troubleshooting & FAQ

Common Issues​

Schema does not compile after upgrading to v10.0.1​

Cause: The property Schema on HttpRequestLogTemplate was misspelled and has been renamed to Scheme (the correct HTTP term) in v10.0.1.

Fix: Rename all references from Schema to Scheme:

// ❌ v10.0.0
var requestLog = new HttpRequestLogTemplate
{
Schema = context.Request.Scheme,
};

// ✅ v10.0.1
var requestLog = new HttpRequestLogTemplate
{
Scheme = context.Request.Scheme,
};

Duration expects a formatted string, not a number​

Cause: HttpResponseLogTemplate.Duration is a string?. An earlier 10.0.1 preview exposed it as double?, but that change was reverted before the 10.0.1 packages were published — the shipped property has always been string?. Code that assigns a double (e.g., duration.TotalMilliseconds) will not compile.

Fix: Assign a pre-formatted string. The built-in consumers format it as "{milliseconds} ms":

// ❌ Does not compile — Duration is string?
var responseLog = new HttpResponseLogTemplate
{
Duration = duration.TotalMilliseconds,
};

// ✅
var responseLog = new HttpResponseLogTemplate
{
Duration = $"{duration.TotalMilliseconds} ms",
};

RequestId / TraceIdentifier do not exist after upgrading to v10.0.2​

Cause: These properties were removed from BaseHttpLogTemplate in v10.0.2. The built-in consumers (LoggingMiddleware in RA.Utilities.Api, RequestResponseLoggingHandler in RA.Utilities.Integrations) no longer populate them — request correlation is now carried by the logging scope instead of being duplicated on every template.

Fix: Remove references to the removed properties. For correlation, rely on scopes/enrichers: LoggingMiddleware enriches every entry it writes with an x-request-id scope value, and RA.Utilities.Logging.Core provides a RequestIdEnricher for Serilog. Custom consumers can wrap the call in their own scope:

using (_logger.BeginScope(new Dictionary<string, object> { [LoggingConstants.XRequestId] = requestId }))
{
// log templates written in this scope carry the correlation id
}

The constant LoggingConstants.XRequestId (value "x-request-id") remains available from RA.Utilities.Logging.Shared.Constants for consistent header name references.

Request and response logs show different RequestedOn timestamps​

Cause: In v10.0.0, RequestedOn was a computed property (=> DateTime.UtcNow) that evaluated at serialization time, so request and response logs got different timestamps.

Fix: Upgrade to v10.0.1 where RequestedOn is a settable property that defaults to DateTime.UtcNow at construction time. If you need the exact request time, set it explicitly when creating the log template.

LoggingConstants type or namespace not found​

Cause: The LoggingConstants class (in namespace RA.Utilities.Logging.Shared.Constants) was added in v10.0.1 and provides the canonical header name XRequestId. If your project isn't referencing it, you may get a compile error.

Fix: Add the using directive:

using RA.Utilities.Logging.Shared.Constants;

Known Limitations​

  • Multi-valued HTTP headers are flattened: RequestHeaders and ResponseHeaders use IDictionary<string, string>, which collapses multi-valued headers (e.g., Set-Cookie) into a single string via .ToString(). The original array of values is not preserved.
  • RequestBody/ResponseBody is object?: The body type is untyped, and the content type (e.g., application/json, text/plain) is not captured on the log template. If you need the content type in your logs, capture it separately.
  • ToString() may fail on cyclic object graphs: BaseHttpLogTemplate.ToString() calls JsonSerializer.Serialize(this) with default options. If a request or response body contains a cyclic reference, serialization will throw. Consider logging via Serilog's {@LogTemplate} destructuring instead, which handles cycles gracefully.
  • No built-in body truncation: Large request or response bodies are logged in their entirety. The built-in consumers buffer the full body into memory via EnableBuffering() / ReadBodyAsync(). For high-throughput APIs with large payloads, consider implementing body size limits or sampling in your own middleware.

Performance Tips​

  • Use ILogger.IsEnabled() guards: The built-in LoggingMiddleware checks _logger.IsEnabled(LogLevel.Information) before constructing log templates. Follow this pattern in custom consumers to avoid allocating log objects when the log level is disabled.
  • Prefer {@LogTemplate} destructuring over .ToString(): Serilog's structured logging with {@RequestLog} captures the object graph natively without the intermediate JSON string allocation.
  • LoggingConstants.XRequestId is a const: It is inlined at compile time with zero runtime cost. Use it instead of the magic string "x-request-id".