diff --git a/backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs b/backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs index c678f6cf7..44c60205a 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs @@ -25,9 +25,14 @@ namespace Squidex.Domain.Apps.Entities.Apps private const string FieldAuthUserId = "AuthUserId"; private const string FieldBytes = "Bytes"; private const string FieldCosts = "Costs"; + private const string FieldCacheStatus = "CacheStatus"; + private const string FieldCacheServer = "CacheServer"; + private const string FieldCacheTTL = "CacheTTL"; + private const string FieldCacheHits = "CacheHits"; private const string FieldRequestElapsedMs = "RequestElapsedMs"; private const string FieldRequestMethod = "RequestMethod"; private const string FieldRequestPath = "RequestPath"; + private const string FieldStatusCode = "StatusCode"; private const string FieldTimestamp = "Timestamp"; private static readonly CsvConfiguration CsvConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) @@ -64,10 +69,15 @@ namespace Squidex.Domain.Apps.Entities.Apps Append(storedRequest, FieldAuthClientId, request.UserClientId); Append(storedRequest, FieldAuthUserId, request.UserId); Append(storedRequest, FieldBytes, request.Bytes); + Append(storedRequest, FieldCacheHits, request.CacheHits); + Append(storedRequest, FieldCacheServer, request.CacheServer); + Append(storedRequest, FieldCacheStatus, request.CacheStatus); + Append(storedRequest, FieldCacheTTL, request.CacheTTL); Append(storedRequest, FieldCosts, request.Costs); Append(storedRequest, FieldRequestElapsedMs, request.ElapsedMs); Append(storedRequest, FieldRequestMethod, request.RequestMethod); Append(storedRequest, FieldRequestPath, request.RequestPath); + Append(storedRequest, FieldStatusCode, request.StatusCode); return requestLogStore.LogAsync(storedRequest); } @@ -90,6 +100,11 @@ namespace Squidex.Domain.Apps.Entities.Apps csv.WriteField(FieldAuthClientId); csv.WriteField(FieldAuthUserId); csv.WriteField(FieldBytes); + csv.WriteField(FieldCacheHits); + csv.WriteField(FieldCacheServer); + csv.WriteField(FieldCacheStatus); + csv.WriteField(FieldCacheTTL); + csv.WriteField(FieldStatusCode); await csv.NextRecordAsync(); @@ -102,7 +117,12 @@ namespace Squidex.Domain.Apps.Entities.Apps csv.WriteField(GetDouble(request, FieldCosts)); csv.WriteField(GetString(request, FieldAuthClientId)); csv.WriteField(GetString(request, FieldAuthUserId)); - csv.WriteField(GetString(request, FieldBytes)); + csv.WriteField(GetLong(request, FieldBytes)); + csv.WriteField(GetLong(request, FieldCacheHits)); + csv.WriteField(GetString(request, FieldCacheServer)); + csv.WriteField(GetString(request, FieldCacheStatus)); + csv.WriteField(GetLong(request, FieldCacheTTL)); + csv.WriteField(GetLong(request, FieldStatusCode)); await csv.NextRecordAsync(); }, appId.ToString(), fromDate, toDate, ct); @@ -122,29 +142,39 @@ namespace Squidex.Domain.Apps.Entities.Apps } } - private static void Append(Request request, string key, double value) + private static void Append(Request request, string key, object? value) { - request.Properties[key] = value.ToString(CultureInfo.InvariantCulture); + if (value != null) + { + Append(request, key, Convert.ToString(value, CultureInfo.InvariantCulture)); + } } - private static void Append(Request request, string key, long value) + private static string? GetString(Request request, string key) { - request.Properties[key] = value.ToString(CultureInfo.InvariantCulture); + return request.Properties.GetValueOrDefault(key, string.Empty); } - private static string GetString(Request request, string key) + private static double? GetDouble(Request request, string key) { - return request.Properties.GetValueOrDefault(key, string.Empty)!; + if (request.Properties.TryGetValue(key, out var value) && + double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; + } + + return null; } - private static double GetDouble(Request request, string key) + private static long? GetLong(Request request, string key) { - if (request.Properties.TryGetValue(key, out var value) && double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + if (request.Properties.TryGetValue(key, out var value) && + long.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { return result; } - return 0; + return null; } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Apps/RequestLog.cs b/backend/src/Squidex.Domain.Apps.Entities/Apps/RequestLog.cs index f737d90c2..e0f75b043 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Apps/RequestLog.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Apps/RequestLog.cs @@ -21,6 +21,16 @@ namespace Squidex.Domain.Apps.Entities.Apps public string? UserClientId; + public int StatusCode; + + public string? CacheServer; + + public string? CacheStatus; + + public int? CacheHits; + + public int? CacheTTL; + public long ElapsedMs; public long Bytes; diff --git a/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs b/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs index 108678699..0bbbea0f5 100644 --- a/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs +++ b/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs @@ -60,11 +60,14 @@ namespace Squidex.Web.Pipeline var request = default(RequestLog); request.Bytes = bytes; + request.CacheStatus = "MISS"; + request.CacheHits = 0; request.Costs = context.Features.Get()?.Costs ?? 0; request.ElapsedMs = watch.Stop(); request.RequestMethod = context.Request.Method; request.RequestPath = context.Request.Path; request.Timestamp = clock.GetCurrentInstant(); + request.StatusCode = context.Response.StatusCode; request.UserId = context.User.OpenIdSubject(); request.UserClientId = clientId; diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DefaultAppLogStoreTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DefaultAppLogStoreTests.cs index 95cd357a9..fe1eb7234 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DefaultAppLogStoreTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/DefaultAppLogStoreTests.cs @@ -52,10 +52,15 @@ namespace Squidex.Domain.Apps.Entities.Apps var request = default(RequestLog); request.Bytes = 1024; + request.CacheHits = 10; + request.CacheServer = "server-fra"; + request.CacheStatus = "MISS"; + request.CacheTTL = 3600; request.Costs = 1.5; request.ElapsedMs = 120; request.RequestMethod = "GET"; request.RequestPath = "/my-path"; + request.StatusCode = 200; request.Timestamp = default; request.UserClientId = "frontend"; request.UserId = "user1"; @@ -64,17 +69,21 @@ namespace Squidex.Domain.Apps.Entities.Apps Assert.NotNull(recordedRequest); - Assert.Contains(request.Bytes.ToString(CultureInfo.InvariantCulture), recordedRequest!.Properties.Values); - Assert.Contains(request.Costs.ToString(CultureInfo.InvariantCulture), recordedRequest!.Properties.Values); - Assert.Contains(request.ElapsedMs.ToString(), recordedRequest!.Properties.Values); - Assert.Contains(request.RequestMethod, recordedRequest!.Properties.Values); - Assert.Contains(request.RequestPath, recordedRequest!.Properties.Values); - Assert.Contains(request.UserClientId, recordedRequest!.Properties.Values); - Assert.Contains(request.UserId, recordedRequest!.Properties.Values); + Contains(request.Bytes, recordedRequest); + Contains(request.CacheHits, recordedRequest); + Contains(request.CacheServer, recordedRequest); + Contains(request.CacheStatus, recordedRequest); + Contains(request.CacheTTL, recordedRequest); + Contains(request.ElapsedMs.ToString(), recordedRequest); + Contains(request.RequestMethod, recordedRequest); + Contains(request.RequestPath, recordedRequest); + Contains(request.StatusCode, recordedRequest); + Contains(request.UserClientId, recordedRequest); + Contains(request.UserId, recordedRequest); } [Fact] - public async Task Should_create_some_stream() + public async Task Should_write_to_stream() { var dateFrom = DateTime.UtcNow.Date.AddDays(-30); var dateTo = DateTime.UtcNow.Date; @@ -111,6 +120,16 @@ namespace Squidex.Domain.Apps.Entities.Apps Assert.Equal(5, lines); } + private static void Contains(string value, Request? request) + { + Assert.Contains(value, request!.Properties.Values); + } + + private static void Contains(object value, Request? request) + { + Assert.Contains(Convert.ToString(value, CultureInfo.InvariantCulture), request!.Properties.Values); + } + private static Request CreateRecord() { return new Request { Properties = new Dictionary() };