Browse Source

OpenTelemetry support. (#747)

pull/748/head
Sebastian Stehle 4 years ago
committed by GitHub
parent
commit
fd4b2ba5d0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 100
      backend/Squidex.ruleset
  2. 41
      backend/extensions/Squidex.Extensions/APM/ApplicationInsights/ApplicationInsightsPlugin.cs
  3. 36
      backend/extensions/Squidex.Extensions/APM/ApplicationInsights/RoleNameTelemetryInitializer.cs
  4. 82
      backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs
  5. 35
      backend/extensions/Squidex.Extensions/APM/Otlp/OtlpPlugin.cs
  6. 39
      backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverExceptionHandler.cs
  7. 37
      backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverPlugin.cs
  8. 43
      backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverSeverityLogAppender.cs
  9. 10
      backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
  10. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
  11. 7
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs
  12. 11
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs
  13. 15
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs
  14. 11
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs
  15. 15
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs
  16. 11
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
  17. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
  18. 19
      backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs
  19. 3
      backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs
  20. 3
      backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetLoader.cs
  21. 3
      backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryParser.cs
  22. 19
      backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs
  23. 16
      backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs
  24. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs
  25. 3
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentLoader.cs
  26. 3
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs
  27. 9
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs
  28. 5
      backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs
  29. 3
      backend/src/Squidex.Domain.Apps.Entities/Rules/Queries/RuleEnricher.cs
  30. 11
      backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs
  31. 2
      backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
  32. 2
      backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
  33. 2
      backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
  34. 7
      backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Reader.cs
  35. 5
      backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Writer.cs
  36. 4
      backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
  37. 11
      backend/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs
  38. 5
      backend/src/Squidex.Infrastructure/Orleans/J{T}.cs
  39. 10
      backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
  40. 33
      backend/src/Squidex.Infrastructure/Telemetry.cs
  41. 4
      backend/src/Squidex.Web/ETagExtensions.cs
  42. 3
      backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs
  43. 2
      backend/src/Squidex.Web/Pipeline/CachingManager.cs
  44. 6
      backend/src/Squidex.Web/Pipeline/MeasureResultFilter.cs
  45. 2
      backend/src/Squidex.Web/Pipeline/RequestLogOptions.cs
  46. 59
      backend/src/Squidex.Web/Pipeline/RequestLogPerformanceMiddleware.cs
  47. 11
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
  48. 1
      backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs
  49. 8
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
  50. 32
      backend/src/Squidex/Config/Domain/TelemetryServices.cs
  51. 24
      backend/src/Squidex/Squidex.csproj
  52. 1
      backend/src/Squidex/Startup.cs
  53. 1299
      backend/src/Squidex/appsettings.json

100
backend/Squidex.ruleset

@ -1,100 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Squidex Rules" Description="Squidex Rules" ToolsVersion="14.0">
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1002" Action="Error" />
<Rule Id="SA1003" Action="Error" />
<Rule Id="SA1008" Action="None" />
<Rule Id="SA1009" Action="None" />
<Rule Id="SA1012" Action="Error" />
<Rule Id="SA1013" Action="Error" />
<Rule Id="SA1025" Action="Error" />
<Rule Id="SA1026" Action="Error" />
<Rule Id="SA1028" Action="Error" />
<Rule Id="SA1000" Action="Error" />
<Rule Id="SA1001" Action="Error" />
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1004" Action="Error" />
<Rule Id="SA1107" Action="None" />
<Rule Id="SA1010" Action="Error" />
<Rule Id="SA1111" Action="None" />
<Rule Id="SA1116" Action="None" />
<Rule Id="SA1117" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1119" Action="None" />
<Rule Id="SA1122" Action="Error" />
<Rule Id="SA1127" Action="None" />
<Rule Id="SA1128" Action="Error" />
<Rule Id="SA1129" Action="Error" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1201" Action="None" />
<Rule Id="SA1202" Action="None" />
<Rule Id="SA1203" Action="Error" />
<Rule Id="SA1204" Action="None" />
<Rule Id="SA1208" Action="Error" />
<Rule Id="SA1210" Action="Error" />
<Rule Id="SA1214" Action="Error" />
<Rule Id="SA1306" Action="Error" />
<Rule Id="SA1311" Action="Error" />
<Rule Id="SA1400" Action="Error" />
<Rule Id="SA1401" Action="Error" />
<Rule Id="SA1402" Action="None" />
<Rule Id="SA1407" Action="Error" />
<Rule Id="SA1408" Action="None" />
<Rule Id="SA1502" Action="Error" />
<Rule Id="SA1504" Action="Error" />
<Rule Id="SA1505" Action="Error" />
<Rule Id="SA1507" Action="Error" />
<Rule Id="SA1508" Action="Error" />
<Rule Id="SA1518" Action="Error" />
<Rule Id="SA1512" Action="None" />
<Rule Id="SA1513" Action="Error" />
<Rule Id="SA1515" Action="None" />
<Rule Id="SA1516" Action="None" />
<Rule Id="SA1600" Action="None" />
<Rule Id="SA1612" Action="None" />
<Rule Id="SA1615" Action="None" />
<Rule Id="SA1623" Action="None" />
<Rule Id="SA1633" Action="Error" />
<Rule Id="SA1649" Action="Error" />
<Rule Id="SA1634" Action="None" />
<Rule Id="SA1635" Action="None" />
<Rule Id="SA1652" Action="None" />
<Rule Id="SA1404" Action="None" />
<Rule Id="SA1601" Action="None" />
<Rule Id="SA1413" Action="None" />
<Rule Id="SA0001" Action="None" />
<Rule Id="SA1602" Action="None" />
</Rules>
<Rules AnalyzerId="RefactoringEssentials" RuleNamespace="RefactoringEssentials">
<Rule Id="RECS0061" Action="Error" />
<Rule Id="RECS0017" Action="Error" />
<Rule Id="RECS0060" Action="Error" />
<Rule Id="RECS0062" Action="Error" />
<Rule Id="RECS0063" Action="Error" />
<Rule Id="RECS0064" Action="Error" />
<Rule Id="RECS0133" Action="Error" />
<Rule Id="REVB0145" Action="None" />
<Rule Id="RECS0002" Action="Error" />
<Rule Id="RECS0154" Action="None" />
<Rule Id="RECS0146" Action="Error" />
<Rule Id="RECS0026" Action="Error" />
<Rule Id="RECS0145" Action="None" />
<Rule Id="RECS0129" Action="None" />
<Rule Id="RECS0070" Action="None" />
</Rules>
<Rules AnalyzerId="Roslyn.Core" RuleNamespace="Roslyn.Core">
<Rule Id="AD0001" Action="None" />
</Rules>
<Rules AnalyzerId="Roslyn.Core" RuleNamespace="Microsoft.CodeAnalysis.Diagnostics">
<Rule Id="IDE0070" Action="None" />
<Rule Id="IDE0032" Action="None" />
<Rule Id="IDE0042" Action="None" />
<Rule Id="IDE0090" Action="None" />
</Rules>
<Rules AnalyzerId="Microsoft.AspNetCore.Mvc.Api.Analyzers" RuleNamespace="Microsoft.AspNetCore.Mvc.Api.Analyzers">
<Rule Id="API1000" Action="Error" />
<Rule Id="API1001" Action="Error" />
<Rule Id="API1002" Action="Error" />
<Rule Id="API1003" Action="Error" />
</Rules>
</RuleSet>

41
backend/extensions/Squidex.Extensions/APM/ApplicationInsights/ApplicationInsightsPlugin.cs

@ -5,46 +5,27 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Azure.Monitor.OpenTelemetry.Exporter;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Squidex.Infrastructure.Plugins;
using Squidex.Log;
namespace Squidex.Extensions.APM.ApplicationInsights
{
public sealed class ApplicationInsightsPlugin : IPlugin, IStartupFilter
public sealed class ApplicationInsightsPlugin : IPlugin
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
var client = builder.ApplicationServices.GetRequiredService<TelemetryClient>();
Profiler.SpanStarted += session =>
{
session.Listen(client.StartOperation<RequestTelemetry>(session.Key));
};
next(builder);
};
}
public void ConfigureServices(IServiceCollection services, IConfiguration config)
{
var isEnabled = config.GetValue<bool>("logging:applicationInsights");
if (isEnabled)
services.AddOpenTelemetryTracing(builder =>
{
services.AddSingleton<IStartupFilter>(this);
services.AddApplicationInsightsTelemetry();
services.AddSingleton<ITelemetryInitializer, RoleNameTelemetryInitializer>();
}
if (config.GetValue<bool>("logging:applicationInsights:enabled"))
{
builder.AddAzureMonitorTraceExporter(options =>
{
config.GetSection("logging:applicationInsights").Bind(options);
});
}
});
}
}
}

36
backend/extensions/Squidex.Extensions/APM/ApplicationInsights/RoleNameTelemetryInitializer.cs

@ -1,36 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Extensions.Configuration;
namespace Squidex.Extensions.APM.ApplicationInsights
{
public sealed class RoleNameTelemetryInitializer : ITelemetryInitializer
{
private readonly string roleName;
public RoleNameTelemetryInitializer(IConfiguration configuration)
{
roleName = configuration.GetValue<string>("logging:roleName");
if (string.IsNullOrWhiteSpace(roleName))
{
roleName = "Squidex";
}
}
public void Initialize(ITelemetry telemetry)
{
if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName))
{
telemetry.Context.Cloud.RoleName = roleName;
}
}
}
}

82
backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs

@ -1,82 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Datadog.Trace;
using Datadog.Trace.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Squidex.Infrastructure.Plugins;
using Squidex.Log;
namespace Squidex.Extensions.APM.Datadog
{
public sealed class DatadogPlugin : IPlugin, IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder.Use(async (context, next) =>
{
using (var scope = Tracer.Instance.StartActive(context.Request.Path))
{
try
{
scope.Span.SetTag("http.method", context.Request.Method);
await next();
}
catch (Exception ex)
{
scope.Span.SetException(ex);
throw;
}
finally
{
scope.Span.SetTag("http.status_code", context.Response.StatusCode.ToString());
}
}
});
next(builder);
};
}
public void ConfigureServices(IServiceCollection services, IConfiguration config)
{
var isEnabled = config.GetValue<bool>("logging:datadog");
if (isEnabled)
{
services.AddSingleton<IStartupFilter>(this);
SetupTracer();
SetupProfiler();
}
}
private static void SetupProfiler()
{
Profiler.SpanStarted += session =>
{
session.Listen(Tracer.Instance.StartActive(session.Key));
};
}
private static void SetupTracer()
{
var settings = TracerSettings.FromDefaultSources();
settings.ServiceName = "squidex";
Tracer.Instance = new Tracer(settings);
}
}
}

35
backend/extensions/Squidex.Extensions/APM/Otlp/OtlpPlugin.cs

@ -0,0 +1,35 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Trace;
using Squidex.Infrastructure.Plugins;
namespace Squidex.Extensions.APM.Datadog
{
public sealed class OtlpPlugin : IPlugin
{
public void ConfigureServices(IServiceCollection services, IConfiguration config)
{
services.AddOpenTelemetryTracing(builder =>
{
if (config.GetValue<bool>("logging:otlp:enabled"))
{
// See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
builder.AddOtlpExporter(options =>
{
config.GetSection("logging:otlp").Bind(options);
});
}
});
}
}
}

39
backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverExceptionHandler.cs

@ -0,0 +1,39 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Google.Cloud.Diagnostics.AspNetCore;
using Microsoft.AspNetCore.Http;
using Squidex.Infrastructure;
using Squidex.Log;
namespace Squidex.Extensions.APM.Stackdriver
{
internal class StackdriverExceptionHandler : ILogAppender
{
private readonly DefaultHttpContext fallbackContext = new DefaultHttpContext();
private readonly IExceptionLogger logger;
private readonly IHttpContextAccessor httpContextAccessor;
public StackdriverExceptionHandler(IExceptionLogger logger, IHttpContextAccessor httpContextAccessor)
{
this.logger = logger;
this.httpContextAccessor = httpContextAccessor;
}
public void Append(IObjectWriter writer, SemanticLogLevel logLevel, Exception exception)
{
if (exception != null && exception is not DomainException)
{
var httpContext = httpContextAccessor.HttpContext;
logger.Log(exception, httpContext ?? fallbackContext);
}
}
}
}

37
backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverPlugin.cs

@ -0,0 +1,37 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Trace;
using Squidex.Infrastructure.Plugins;
using Squidex.Log;
namespace Squidex.Extensions.APM.Stackdriver
{
public sealed class StackdriverPlugin : IPlugin
{
public void ConfigureServices(IServiceCollection services, IConfiguration config)
{
services.AddOpenTelemetryTracing(builder =>
{
if (config.GetValue<bool>("logging:stackdriver:enabled"))
{
var projectId = config.GetValue<string>("logging:stackdriver:projectId");
builder.UseStackdriverExporter(projectId);
services.AddSingleton<ILogAppender,
StackdriverSeverityLogAppender>();
services.AddSingleton<ILogAppender,
StackdriverExceptionHandler>();
}
});
}
}
}

43
backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverSeverityLogAppender.cs

@ -0,0 +1,43 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Squidex.Log;
namespace Squidex.Extensions.APM.Stackdriver
{
public sealed class StackdriverSeverityLogAppender : ILogAppender
{
public void Append(IObjectWriter writer, SemanticLogLevel logLevel, Exception exception)
{
var severity = GetSeverity(logLevel);
writer.WriteProperty(nameof(severity), severity);
}
private static string GetSeverity(SemanticLogLevel logLevel)
{
switch (logLevel)
{
case SemanticLogLevel.Trace:
return "DEBUG";
case SemanticLogLevel.Debug:
return "DEBUG";
case SemanticLogLevel.Information:
return "INFO";
case SemanticLogLevel.Warning:
return "WARNING";
case SemanticLogLevel.Error:
return "ERROR";
case SemanticLogLevel.Fatal:
return "CRITICAL";
default:
return "DEFAULT";
}
}
}
}

10
backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj

@ -13,16 +13,20 @@
<PackageReference Include="Confluent.Kafka" Version="1.7.0" />
<PackageReference Include="Confluent.SchemaRegistry.Serdes" Version="1.3.0" />
<PackageReference Include="CoreTweet" Version="1.0.0.483" />
<PackageReference Include="Datadog.Trace" Version="1.27.1" />
<PackageReference Include="Elasticsearch.Net" Version="7.13.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.17.0" />
<PackageReference Include="Elasticsearch.Net" Version="7.14.1" />
<PackageReference Include="Google.Cloud.Diagnostics.AspNetCore" Version="4.0.0" />
<PackageReference Include="Google.Cloud.Logging.V2" Version="3.3.0" />
<PackageReference Include="Microsoft.Azure.CognitiveServices.Vision.ComputerVision" Version="7.0.0" />
<PackageReference Include="Microsoft.Azure.SignalR.Management" Version="1.9.2" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Microsoft.OData.Core" Version="7.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NodaTime" Version="3.0.5" />
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.0.0-beta.2" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.2.0-alpha1" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc7" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.OpenTelemetry.Exporter.Stackdriver" Version="0.0.0-alpha.0.97" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />

2
backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj

@ -20,7 +20,7 @@
<PackageReference Include="GeoJSON.Net" Version="1.2.19" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Microsoft.OData.Core" Version="7.9.0" />
<PackageReference Include="NJsonSchema" Version="10.4.4" />
<PackageReference Include="NJsonSchema" Version="10.5.2" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.Jint" Version="3.0.0-beta-0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />

7
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs

@ -14,7 +14,6 @@ using Squidex.Domain.Apps.Entities.Assets;
using Squidex.Domain.Apps.Entities.Assets.Repositories;
using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
@ -46,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IResultList<IAssetFolderEntity>> QueryAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>("QueryAsyncByQuery"))
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>("QueryAsyncByQuery"))
{
var filter = BuildFilter(appId, parentId);
@ -61,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var filter = BuildFilter(appId, parentId);
@ -78,7 +77,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IAssetFolderEntity?> FindAssetFolderAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
var documentId = DomainId.Combine(appId, id);

11
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs

@ -17,7 +17,6 @@ using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.States;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
@ -25,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
async Task<(AssetFolderDomainObject.State Value, bool Valid, long Version)> ISnapshotStore<AssetFolderDomainObject.State>.ReadAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
var existing =
await Collection.Find(x => x.DocumentId == key)
@ -42,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetFolderDomainObject.State>.WriteAsync(DomainId key, AssetFolderDomainObject.State value, long oldVersion, long newVersion)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
var entity = Map(value);
@ -52,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetFolderDomainObject.State>.WriteManyAsync(IEnumerable<(DomainId Key, AssetFolderDomainObject.State Value, long Version)> snapshots)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
var updates = snapshots.Select(Map).Select(x =>
new ReplaceOneModel<MongoAssetFolderEntity>(
@ -74,7 +73,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetFolderDomainObject.State>.ReadAllAsync(Func<AssetFolderDomainObject.State, long, Task> callback,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
await Collection.Find(new BsonDocument(), Batching.Options).ForEachAsync(x => callback(Map(x), x.Version), ct);
}
@ -82,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetFolderDomainObject.State>.RemoveAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
await Collection.DeleteOneAsync(x => x.DocumentId == key);
}

15
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs

@ -18,7 +18,6 @@ using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.MongoDb.Queries;
using Squidex.Infrastructure.Translations;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
@ -91,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IResultList<IAssetEntity>> QueryAsync(DomainId appId, DomainId? parentId, Q q,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>("QueryAsyncByQuery"))
using (Telemetry.Activities.StartMethod<MongoAssetRepository>("QueryAsyncByQuery"))
{
try
{
@ -153,7 +152,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IReadOnlyList<DomainId>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>("QueryAsyncByIds"))
using (Telemetry.Activities.StartMethod<MongoAssetRepository>("QueryAsyncByIds"))
{
var assetEntities =
await Collection.Find(BuildFilter(appId, ids)).Only(x => x.Id)
@ -168,7 +167,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var assetEntities =
await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.ParentId == parentId).Only(x => x.Id)
@ -183,7 +182,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IAssetEntity?> FindAssetByHashAsync(DomainId appId, string hash, string fileName, long fileSize,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var assetEntity =
await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.FileHash == hash && x.FileName == fileName && x.FileSize == fileSize)
@ -196,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IAssetEntity?> FindAssetBySlugAsync(DomainId appId, string slug,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var assetEntity =
await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.Slug == slug)
@ -209,7 +208,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IAssetEntity?> FindAssetAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var documentId = DomainId.Combine(appId, id);
@ -224,7 +223,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task<IAssetEntity?> FindAssetAsync(DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var assetEntity =
await Collection.Find(x => x.Id == id && !x.IsDeleted)

11
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs

@ -17,7 +17,6 @@ using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.States;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
@ -25,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
async Task<(AssetDomainObject.State Value, bool Valid, long Version)> ISnapshotStore<AssetDomainObject.State>.ReadAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var existing =
await Collection.Find(x => x.DocumentId == key)
@ -42,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetDomainObject.State>.WriteAsync(DomainId key, AssetDomainObject.State value, long oldVersion, long newVersion)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
var entity = Map(value);
@ -52,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetDomainObject.State>.WriteManyAsync(IEnumerable<(DomainId Key, AssetDomainObject.State Value, long Version)> snapshots)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetFolderRepository>())
{
var updates = snapshots.Select(Map).Select(x =>
new ReplaceOneModel<MongoAssetEntity>(
@ -74,7 +73,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetDomainObject.State>.ReadAllAsync(Func<AssetDomainObject.State, long, Task> callback,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
await Collection.Find(new BsonDocument(), Batching.Options).ForEachAsync(x => callback(Map(x), x.Version), ct);
}
@ -82,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore<AssetDomainObject.State>.RemoveAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
using (Telemetry.Activities.StartMethod<MongoAssetRepository>())
{
await Collection.DeleteOneAsync(x => x.DocumentId == key);
}

15
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs

@ -20,7 +20,6 @@ using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Queries;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
@ -107,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
if (q.Ids != null && q.Ids.Count > 0)
{
@ -136,7 +135,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
if (q.Ids != null && q.Ids.Count > 0)
{
@ -160,7 +159,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task<IContentEntity?> FindContentAsync(ISchemaEntity schema, DomainId id,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
return await queryBdId.QueryAsync(schema, id, ct);
}
@ -169,7 +168,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
await queryScheduled.QueryAsync(now, callback, ct);
}
@ -178,7 +177,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
return await queryByIds.QueryIdsAsync(appId, ids, ct);
}
@ -187,7 +186,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
return await queryByQuery.QueryIdsAsync(appId, schemaId, filterNode, ct);
}
@ -196,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
return await queryReferrers.CheckExistsAsync(appId, contentId, ct);
}

11
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs

@ -15,7 +15,6 @@ using Squidex.Domain.Apps.Entities.Contents.DomainObject;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.States;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
@ -29,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task<(ContentDomainObject.State Value, bool Valid, long Version)> ISnapshotStore<ContentDomainObject.State>.ReadAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
var version = await collectionAll.FindVersionAsync(key);
@ -39,7 +38,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore<ContentDomainObject.State>.ClearAsync()
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
await collectionAll.ClearAsync();
await collectionPublished.ClearAsync();
@ -48,7 +47,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore<ContentDomainObject.State>.RemoveAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
await collectionAll.RemoveAsync(key);
await collectionPublished.RemoveAsync(key);
@ -57,7 +56,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore<ContentDomainObject.State>.WriteAsync(DomainId key, ContentDomainObject.State value, long oldVersion, long newVersion)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
if (value.SchemaId.Id == DomainId.Empty)
{
@ -72,7 +71,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore<ContentDomainObject.State>.WriteManyAsync(IEnumerable<(DomainId Key, ContentDomainObject.State Value, long Version)> snapshots)
{
using (Profiler.TraceMethod<MongoContentRepository>())
using (Telemetry.Activities.StartMethod<MongoContentRepository>())
{
var entitiesPublished = new List<MongoContentEntity>();
var entitiesAll = new List<MongoContentEntity>();

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj

@ -17,7 +17,7 @@
<ProjectReference Include="..\Squidex.Domain.Apps.Entities\Squidex.Domain.Apps.Entities.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.12.4" />
<PackageReference Include="MongoDB.Driver" Version="2.13.1" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />

19
backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -19,7 +19,6 @@ using Squidex.Infrastructure.Orleans;
using Squidex.Infrastructure.Security;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
using Squidex.Log;
using Squidex.Shared;
using Squidex.Text;
@ -77,7 +76,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task<List<IAppEntity>> GetAppsAsync()
{
using (Profiler.TraceMethod<AppsIndex>())
using (Telemetry.Activities.StartMethod<AppsIndex>())
{
var ids = await GetAppIdsAsync();
@ -91,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task<List<IAppEntity>> GetAppsForUserAsync(string userId, PermissionSet permissions)
{
using (Profiler.TraceMethod<AppsIndex>())
using (Telemetry.Activities.StartMethod<AppsIndex>())
{
var ids =
await Task.WhenAll(
@ -109,7 +108,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task<IAppEntity?> GetAppByNameAsync(string name, bool canCache = false)
{
using (Profiler.TraceMethod<AppsIndex>())
using (Telemetry.Activities.StartMethod<AppsIndex>())
{
if (canCache)
{
@ -132,7 +131,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task<IAppEntity?> GetAppAsync(DomainId appId, bool canCache)
{
using (Profiler.TraceMethod<AppsIndex>())
using (Telemetry.Activities.StartMethod<AppsIndex>())
{
if (canCache)
{
@ -155,7 +154,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task<List<DomainId>> GetAppIdsByUserAsync(string userId)
{
using (Profiler.TraceMethod<AppProvider>())
using (Telemetry.Activities.StartMethod<AppProvider>())
{
return await grainFactory.GetGrain<IAppsByUserIndexGrain>(userId).GetIdsAsync();
}
@ -163,7 +162,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task<List<DomainId>> GetAppIdsAsync()
{
using (Profiler.TraceMethod<AppProvider>())
using (Telemetry.Activities.StartMethod<AppProvider>())
{
return await grainFactory.GetGrain<IAppsByNameIndexGrain>(SingleGrain.Id).GetIdsAsync();
}
@ -171,7 +170,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task<List<DomainId>> GetAppIdsAsync(string[] names)
{
using (Profiler.TraceMethod<AppProvider>())
using (Telemetry.Activities.StartMethod<AppProvider>())
{
return await grainFactory.GetGrain<IAppsByNameIndexGrain>(SingleGrain.Id).GetIdsAsync(names);
}
@ -179,7 +178,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task<DomainId> GetAppIdAsync(string name)
{
using (Profiler.TraceMethod<AppProvider>())
using (Telemetry.Activities.StartMethod<AppProvider>())
{
return await grainFactory.GetGrain<IAppsByNameIndexGrain>(SingleGrain.Id).GetIdAsync(name);
}

3
backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs

@ -14,7 +14,6 @@ using Squidex.Domain.Apps.Core.Tags;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Caching;
using Squidex.Infrastructure.Reflection;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
@ -48,7 +47,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
Guard.NotNull(assets, nameof(assets));
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetEnricher>())
using (Telemetry.Activities.StartMethod<AssetEnricher>())
{
var results = assets.Select(x => SimpleMapper.Map(x, new AssetEntity())).ToList();

3
backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetLoader.cs

@ -9,7 +9,6 @@ using System.Threading.Tasks;
using Orleans;
using Squidex.Domain.Apps.Entities.Assets.DomainObject;
using Squidex.Infrastructure;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
@ -24,7 +23,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
public async Task<IAssetEntity?> GetAsync(DomainId appId, DomainId id, long version)
{
using (Profiler.TraceMethod<AssetLoader>())
using (Telemetry.Activities.StartMethod<AssetLoader>())
{
var key = DomainId.Combine(appId, id);

3
backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryParser.cs

@ -21,7 +21,6 @@ using Squidex.Infrastructure.Queries.Json;
using Squidex.Infrastructure.Queries.OData;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
using Squidex.Log;
using Squidex.Text;
namespace Squidex.Domain.Apps.Entities.Assets.Queries
@ -48,7 +47,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
Guard.NotNull(context, nameof(context));
Guard.NotNull(q, nameof(q));
using (Profiler.TraceMethod<AssetQueryParser>())
using (Telemetry.Activities.StartMethod<AssetQueryParser>())
{
var query = ParseClrQuery(q);

19
backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs

@ -12,7 +12,6 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Squidex.Domain.Apps.Entities.Assets.Repositories;
using Squidex.Infrastructure;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
@ -45,7 +44,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
public async Task<IReadOnlyList<IAssetFolderEntity>> FindAssetFolderAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
var result = new List<IAssetFolderEntity>();
@ -71,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
public async Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
var assetFolders = await QueryFoldersCoreAsync(appId, parentId, ct);
@ -82,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
public async Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(Context context, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
var assetFolders = await QueryFoldersCoreAsync(context, parentId, ct);
@ -95,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
var asset = await FindByHashCoreAsync(context, hash, fileName, fileSize, ct);
@ -113,7 +112,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
var asset = await FindBySlugCoreAsync(context, slug, ct);
@ -131,7 +130,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
var asset = await FindCoreAsync(id, ct);
@ -149,7 +148,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
IAssetEntity? asset;
@ -181,7 +180,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
return EmptyAssets;
}
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
q = await queryParser.ParseAsync(context, q);
@ -215,7 +214,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
private async Task<IReadOnlyList<IEnrichedAssetEntity>> TransformCoreAsync(Context context, IEnumerable<IAssetEntity> assets,
CancellationToken ct)
{
using (Profiler.TraceMethod<AssetQueryService>())
using (Telemetry.Activities.StartMethod<AssetQueryService>())
{
return await assetEnricher.EnrichAsync(assets, context, ct);
}

16
backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs

@ -136,7 +136,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
jobUrl: CurrentJob.Url.ToString()
);
using (Profiler.StartSession())
using (Telemetry.Activities.StartActivity("RestoreBackup"))
{
try
{
@ -156,14 +156,14 @@ namespace Squidex.Domain.Apps.Entities.Backup
{
await reader.CheckCompatibilityAsync();
using (Profiler.Trace("ReadEvents"))
using (Telemetry.Activities.StartActivity("ReadEvents"))
{
await ReadEventsAsync(reader, handlers);
}
foreach (var handler in handlers)
{
using (Profiler.TraceMethod(handler.GetType(), nameof(IBackupHandler.RestoreAsync)))
using (Telemetry.Activities.StartMethod(handler.GetType(), nameof(IBackupHandler.RestoreAsync)))
{
await handler.RestoreAsync(runningContext);
}
@ -173,7 +173,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
foreach (var handler in handlers)
{
using (Profiler.TraceMethod(handler.GetType(), nameof(IBackupHandler.CompleteRestoreAsync)))
using (Telemetry.Activities.StartMethod(handler.GetType(), nameof(IBackupHandler.CompleteRestoreAsync)))
{
await handler.CompleteRestoreAsync(runningContext);
}
@ -194,8 +194,6 @@ namespace Squidex.Domain.Apps.Entities.Backup
w.WriteProperty("status", "completed");
w.WriteProperty("operationId", ctx.jobId);
w.WriteProperty("url", ctx.jobUrl);
Profiler.Session?.Write(w);
});
}
catch (Exception ex)
@ -223,8 +221,6 @@ namespace Squidex.Domain.Apps.Entities.Backup
w.WriteProperty("status", "failed");
w.WriteProperty("operationId", ctx.jobId);
w.WriteProperty("url", ctx.jobUrl);
Profiler.Session?.Write(w);
});
}
finally
@ -294,7 +290,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
private async Task<IBackupReader> DownloadAsync()
{
using (Profiler.Trace("Download"))
using (Telemetry.Activities.StartActivity("Download"))
{
Log("Downloading Backup");
@ -421,7 +417,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
{
var userMapping = new UserMapping(CurrentJob.Actor);
using (Profiler.Trace("CreateUsers"))
using (Telemetry.Activities.StartActivity("CreateUsers"))
{
Log("Creating Users");

5
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs

@ -13,7 +13,6 @@ using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
@ -51,7 +50,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
private async Task<IReadOnlyList<IEnrichedContentEntity>> EnrichInternalAsync(IEnumerable<IContentEntity> contents, bool cloneData, Context context,
CancellationToken ct)
{
using (Profiler.TraceMethod<ContentEnricher>())
using (Telemetry.Activities.StartMethod<ContentEnricher>())
{
var results = new List<ContentEntity>();
@ -102,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
ct.ThrowIfCancellationRequested();
using (Profiler.TraceMethod(step.ToString()!))
using (Telemetry.Activities.StartMethod(step.ToString()!))
{
await step.EnrichAsync(context, results, GetSchema, ct);
}

3
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentLoader.cs

@ -9,7 +9,6 @@ using System.Threading.Tasks;
using Orleans;
using Squidex.Domain.Apps.Entities.Contents.DomainObject;
using Squidex.Infrastructure;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
@ -24,7 +23,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
public async Task<IContentEntity?> GetAsync(DomainId appId, DomainId id, long version)
{
using (Profiler.TraceMethod<ContentLoader>())
using (Telemetry.Activities.StartMethod<ContentLoader>())
{
var key = DomainId.Combine(appId, id).ToString();

3
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs

@ -28,7 +28,6 @@ using Squidex.Infrastructure.Queries.Json;
using Squidex.Infrastructure.Queries.OData;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
using Squidex.Log;
using Squidex.Text;
namespace Squidex.Domain.Apps.Entities.Contents.Queries
@ -59,7 +58,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
Guard.NotNull(context, nameof(context));
Guard.NotNull(q, nameof(q));
using (Profiler.TraceMethod<ContentQueryParser>())
using (Telemetry.Activities.StartMethod<ContentQueryParser>())
{
var query = await ParseClrQueryAsync(context, q, schema);

9
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs

@ -16,7 +16,6 @@ using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Security;
using Squidex.Infrastructure.Translations;
using Squidex.Log;
using Squidex.Shared;
using Squidex.Shared.Identity;
@ -53,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<ContentQueryService>())
using (Telemetry.Activities.StartMethod<ContentQueryService>())
{
var schema = await GetSchemaOrThrowAsync(context, schemaIdOrName);
@ -82,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<ContentQueryService>())
using (Telemetry.Activities.StartMethod<ContentQueryService>())
{
if (q == null)
{
@ -114,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<ContentQueryService>())
using (Telemetry.Activities.StartMethod<ContentQueryService>())
{
if (q == null)
{
@ -160,7 +159,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
private async Task<IReadOnlyList<IEnrichedContentEntity>> TransformCoreAsync(Context context, IEnumerable<IContentEntity> contents,
CancellationToken ct)
{
using (Profiler.TraceMethod<ContentQueryService>())
using (Telemetry.Activities.StartMethod<ContentQueryService>())
{
return await contentEnricher.EnrichAsync(contents, context, ct);
}

5
backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs

@ -13,7 +13,6 @@ using Squidex.Domain.Apps.Entities.Rules.Commands;
using Squidex.Domain.Apps.Entities.Rules.DomainObject;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Rules.Indexes
{
@ -33,7 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
public async Task<List<IRuleEntity>> GetRulesAsync(DomainId appId)
{
using (Profiler.TraceMethod<RulesIndex>())
using (Telemetry.Activities.StartMethod<RulesIndex>())
{
var ids = await GetRuleIdsAsync(appId);
@ -47,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
private async Task<List<DomainId>> GetRuleIdsAsync(DomainId appId)
{
using (Profiler.TraceMethod<RulesIndex>())
using (Telemetry.Activities.StartMethod<RulesIndex>())
{
return await Index(appId).GetIdsAsync();
}

3
backend/src/Squidex.Domain.Apps.Entities/Rules/Queries/RuleEnricher.cs

@ -12,7 +12,6 @@ using Squidex.Domain.Apps.Entities.Rules.Repositories;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Caching;
using Squidex.Infrastructure.Reflection;
using Squidex.Log;
namespace Squidex.Domain.Apps.Entities.Rules.Queries
{
@ -42,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Queries
Guard.NotNull(rules, nameof(rules));
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<RuleEnricher>())
using (Telemetry.Activities.StartMethod<RuleEnricher>())
{
var results = new List<RuleEntity>();

11
backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs

@ -17,7 +17,6 @@ using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
using Squidex.Log;
using Squidex.Text;
namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
@ -41,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public async Task<List<ISchemaEntity>> GetSchemasAsync(DomainId appId)
{
using (Profiler.TraceMethod<SchemasIndex>())
using (Telemetry.Activities.StartMethod<SchemasIndex>())
{
var ids = await GetSchemaIdsAsync(appId);
@ -55,7 +54,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public async Task<ISchemaEntity?> GetSchemaByNameAsync(DomainId appId, string name, bool canCache)
{
using (Profiler.TraceMethod<SchemasIndex>())
using (Telemetry.Activities.StartMethod<SchemasIndex>())
{
var cacheKey = GetCacheKey(appId, name);
@ -80,7 +79,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public async Task<ISchemaEntity?> GetSchemaAsync(DomainId appId, DomainId id, bool canCache)
{
using (Profiler.TraceMethod<SchemasIndex>())
using (Telemetry.Activities.StartMethod<SchemasIndex>())
{
var cacheKey = GetCacheKey(appId, id);
@ -105,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
private async Task<DomainId> GetSchemaIdAsync(DomainId appId, string name)
{
using (Profiler.TraceMethod<SchemasIndex>())
using (Telemetry.Activities.StartMethod<SchemasIndex>())
{
return await Index(appId).GetIdAsync(name);
}
@ -113,7 +112,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
private async Task<List<DomainId>> GetSchemaIdsAsync(DomainId appId)
{
using (Profiler.TraceMethod<SchemasIndex>())
using (Telemetry.Activities.StartMethod<SchemasIndex>())
{
return await Index(appId).GetIdsAsync();
}

2
backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj

@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="27.1.1" />
<PackageReference Include="Elasticsearch.Net" Version="7.13.2" />
<PackageReference Include="Elasticsearch.Net" Version="7.14.1" />
<PackageReference Include="Equals.Fody" Version="4.0.1" PrivateAssets="all" />
<PackageReference Include="Fody" Version="6.5.2">
<PrivateAssets>all</PrivateAssets>

2
backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj

@ -19,7 +19,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.12.4" />
<PackageReference Include="MongoDB.Driver" Version="2.13.1" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />

2
backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj

@ -17,7 +17,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="IdentityModel" Version="5.1.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.7" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.9" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />

7
backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Reader.cs

@ -14,7 +14,6 @@ using System.Threading.Tasks;
using MongoDB.Driver;
using NodaTime;
using Squidex.Infrastructure.MongoDb;
using Squidex.Log;
using EventFilter = MongoDB.Driver.FilterDefinition<Squidex.Infrastructure.EventSourcing.MongoEventCommit>;
namespace Squidex.Infrastructure.EventSourcing
@ -48,7 +47,7 @@ namespace Squidex.Infrastructure.EventSourcing
return EmptyEvents;
}
using (Profiler.TraceMethod<MongoEventStore>())
using (Telemetry.Activities.StartMethod<MongoEventStore>())
{
var commits =
await Collection.Find(
@ -65,7 +64,7 @@ namespace Squidex.Infrastructure.EventSourcing
{
Guard.NotNullOrEmpty(streamName, nameof(streamName));
using (Profiler.TraceMethod<MongoEventStore>())
using (Telemetry.Activities.StartMethod<MongoEventStore>())
{
var commits =
await Collection.Find(
@ -84,7 +83,7 @@ namespace Squidex.Infrastructure.EventSourcing
{
Guard.NotNull(streamNames, nameof(streamNames));
using (Profiler.TraceMethod<MongoEventStore>())
using (Telemetry.Activities.StartMethod<MongoEventStore>())
{
var position = EtagVersion.Empty;

5
backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Writer.cs

@ -10,7 +10,6 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using Squidex.Log;
namespace Squidex.Infrastructure.EventSourcing
{
@ -40,7 +39,7 @@ namespace Squidex.Infrastructure.EventSourcing
Guard.LessThan(events.Count, MaxCommitSize, "events.Count");
Guard.GreaterEquals(expectedVersion, EtagVersion.Any, nameof(expectedVersion));
using (Profiler.TraceMethod<MongoEventStore>())
using (Telemetry.Activities.StartMethod<MongoEventStore>())
{
if (events.Count == 0)
{
@ -102,7 +101,7 @@ namespace Squidex.Infrastructure.EventSourcing
{
Guard.NotNull(commits, nameof(commits));
using (Profiler.TraceMethod<MongoEventStore>())
using (Telemetry.Activities.StartMethod<MongoEventStore>())
{
var writes = new List<WriteModel<MongoEventCommit>>();

4
backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj

@ -13,8 +13,8 @@
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.12.4" />
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.12.4" />
<PackageReference Include="MongoDB.Driver" Version="2.13.1" />
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.13.1" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="5.0.0" />

11
backend/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs

@ -14,7 +14,6 @@ using MongoDB.Bson;
using MongoDB.Driver;
using Newtonsoft.Json;
using Squidex.Infrastructure.MongoDb;
using Squidex.Log;
namespace Squidex.Infrastructure.States
{
@ -45,7 +44,7 @@ namespace Squidex.Infrastructure.States
public async Task<(T Value, bool Valid, long Version)> ReadAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoSnapshotStore<T>>())
using (Telemetry.Activities.StartMethod<MongoSnapshotStore<T>>())
{
var existing =
await Collection.Find(x => x.DocumentId.Equals(key))
@ -62,7 +61,7 @@ namespace Squidex.Infrastructure.States
public async Task WriteAsync(DomainId key, T value, long oldVersion, long newVersion)
{
using (Profiler.TraceMethod<MongoSnapshotStore<T>>())
using (Telemetry.Activities.StartMethod<MongoSnapshotStore<T>>())
{
await Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u.Set(x => x.Doc, value));
}
@ -70,7 +69,7 @@ namespace Squidex.Infrastructure.States
public Task WriteManyAsync(IEnumerable<(DomainId Key, T Value, long Version)> snapshots)
{
using (Profiler.TraceMethod<MongoSnapshotStore<T>>())
using (Telemetry.Activities.StartMethod<MongoSnapshotStore<T>>())
{
var writes = snapshots.Select(x => new ReplaceOneModel<MongoState<T>>(
Filter.Eq(y => y.DocumentId, x.Key),
@ -96,7 +95,7 @@ namespace Squidex.Infrastructure.States
public async Task ReadAllAsync(Func<T, long, Task> callback,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoSnapshotStore<T>>())
using (Telemetry.Activities.StartMethod<MongoSnapshotStore<T>>())
{
await Collection.Find(new BsonDocument(), options: Batching.Options).ForEachAsync(x => callback(x.Doc, x.Version), ct);
}
@ -104,7 +103,7 @@ namespace Squidex.Infrastructure.States
public async Task RemoveAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoSnapshotStore<T>>())
using (Telemetry.Activities.StartMethod<MongoSnapshotStore<T>>())
{
await Collection.DeleteOneAsync(x => x.DocumentId.Equals(key));
}

5
backend/src/Squidex.Infrastructure/Orleans/J{T}.cs

@ -12,7 +12,6 @@ using Orleans.CodeGeneration;
using Orleans.Concurrency;
using Orleans.Serialization;
using Squidex.Infrastructure.Json;
using Squidex.Log;
#pragma warning disable IDE0060 // Remove unused parameter
@ -57,7 +56,7 @@ namespace Squidex.Infrastructure.Orleans
[SerializerMethod]
public static void Serialize(object? input, ISerializationContext context, Type? expected)
{
using (Profiler.TraceMethod(nameof(J)))
using (Telemetry.Activities.StartMethod(nameof(J)))
{
var jsonSerializer = GetSerializer(context);
@ -70,7 +69,7 @@ namespace Squidex.Infrastructure.Orleans
[DeserializerMethod]
public static object? Deserialize(Type expected, IDeserializationContext context)
{
using (Profiler.TraceMethod(nameof(J)))
using (Telemetry.Activities.StartMethod(nameof(J)))
{
var jsonSerializer = GetSerializer(context);

10
backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj

@ -10,11 +10,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GeoJSON.Net" Version="1.2.19" />
<PackageReference Include="MailKit" Version="2.13.0" />
<PackageReference Include="MailKit" Version="2.14.0" />
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="5.0.7" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.1.2" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="5.0.9" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.1.3" />
<PackageReference Include="Microsoft.OData.Core" Version="7.9.0" />
<PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.4.3">
<PrivateAssets>all</PrivateAssets>
@ -23,12 +23,12 @@
<PackageReference Include="Microsoft.Orleans.Core" Version="3.4.3" />
<PackageReference Include="Microsoft.Orleans.OrleansRuntime" Version="3.4.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NJsonSchema" Version="10.4.4" />
<PackageReference Include="NJsonSchema" Version="10.5.2" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.Assets" Version="1.8.0" />
<PackageReference Include="Squidex.Caching" Version="1.8.0" />
<PackageReference Include="Squidex.Hosting.Abstractions" Version="1.9.0" />
<PackageReference Include="Squidex.Log" Version="1.4.0" />
<PackageReference Include="Squidex.Log" Version="1.5.0" />
<PackageReference Include="Squidex.Text" Version="1.7.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />

33
backend/src/Squidex.Infrastructure/Telemetry.cs

@ -0,0 +1,33 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Squidex.Infrastructure
{
public static class Telemetry
{
public static readonly ActivitySource Activities = new ActivitySource("Notifo");
public static Activity? StartMethod(this ActivitySource activity, Type type, [CallerMemberName] string? memberName = null)
{
return activity.StartActivity($"{type.Name}/{memberName}");
}
public static Activity? StartMethod<T>(this ActivitySource activity, [CallerMemberName] string? memberName = null)
{
return activity.StartActivity($"{typeof(T).Name}/{memberName}");
}
public static Activity? StartMethod(this ActivitySource activity, string objectName, [CallerMemberName] string? memberName = null)
{
return activity.StartActivity($"{objectName}/{memberName}");
}
}
}

4
backend/src/Squidex.Web/ETagExtensions.cs

@ -19,7 +19,7 @@ namespace Squidex.Web
{
public static string ToEtag<T>(this IReadOnlyList<T> items) where T : IEntity, IEntityWithVersion
{
using (Profiler.Trace("CalculateEtag"))
using (Telemetry.Activities.StartActivity("CalculateEtag"))
{
var hash = Create(items, 0);
@ -29,7 +29,7 @@ namespace Squidex.Web
public static string ToEtag<T>(this IResultList<T> entities) where T : IEntity, IEntityWithVersion
{
using (Profiler.Trace("CalculateEtag"))
using (Telemetry.Activities.StartActivity("CalculateEtag"))
{
var hash = Create(entities, entities.Total);

3
backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Squidex.Domain.Apps.Entities.Apps.Plans;
using Squidex.Infrastructure;
using Squidex.Log;
namespace Squidex.Web.Pipeline
@ -48,7 +49,7 @@ namespace Squidex.Web.Pipeline
{
if (FilterDefinition.Costs > 0)
{
using (Profiler.Trace("CheckUsage"))
using (Telemetry.Activities.StartActivity("CheckUsage"))
{
var (_, clientId) = context.HttpContext.User.GetClient();

2
backend/src/Squidex.Web/Pipeline/CachingManager.cs

@ -99,7 +99,7 @@ namespace Squidex.Web.Pipeline
{
if (hasDependency && !response.Headers.ContainsKey(HeaderNames.ETag))
{
using (Profiler.Trace("CalculateEtag"))
using (Telemetry.Activities.StartActivity("CalculateEtag"))
{
var cacheBuffer = hasher.GetHashAndReset();
var cacheString = BitConverter.ToString(cacheBuffer).Replace("-", string.Empty).ToUpperInvariant();

6
backend/src/Squidex.Web/Pipeline/MeasureResultFilter.cs

@ -7,7 +7,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using Squidex.Log;
using Squidex.Infrastructure;
namespace Squidex.Web.Pipeline
{
@ -15,7 +15,7 @@ namespace Squidex.Web.Pipeline
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
using (Profiler.Trace("ExecuteAction"))
using (Telemetry.Activities.StartActivity("ExecuteAction"))
{
await next();
}
@ -23,7 +23,7 @@ namespace Squidex.Web.Pipeline
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
using (Profiler.Trace("ExecuteResult"))
using (Telemetry.Activities.StartActivity("ExecuteResult"))
{
await next();
}

2
backend/src/Squidex.Web/Pipeline/RequestLogOptions.cs

@ -10,7 +10,5 @@ namespace Squidex.Web.Pipeline
public sealed class RequestLogOptions
{
public bool LogRequests { get; set; }
public bool LogProfiler { get; set; }
}
}

59
backend/src/Squidex.Web/Pipeline/RequestLogPerformanceMiddleware.cs

@ -28,44 +28,23 @@ namespace Squidex.Web.Pipeline
public async Task InvokeAsync(HttpContext context, ISemanticLog log)
{
var shouldStartSession = requestLogOptions.LogRequests || Profiler.HasListener;
if (requestLogOptions.LogRequests || shouldStartSession)
if (requestLogOptions.LogRequests)
{
var session =
shouldStartSession ?
Profiler.StartSession() :
default;
var watch =
requestLogOptions.LogRequests ?
ValueStopwatch.StartNew() :
default;
var watch = ValueStopwatch.StartNew();
using (session)
try
{
try
{
await next(context);
}
finally
{
if (requestLogOptions.LogRequests)
{
var elapsedMs = watch.Stop();
log.LogInformation((elapsedMs, context), (ctx, w) =>
{
if (requestLogOptions.LogProfiler)
{
Profiler.Session?.Write(w);
}
await next(context);
}
finally
{
var elapsedMs = watch.Stop();
w.WriteObject("filters", ctx.context, LogFilters);
w.WriteProperty("elapsedRequestMs", ctx.elapsedMs);
});
}
}
log.LogInformation((elapsedMs, context), (ctx, w) =>
{
w.WriteObject("filters", ctx.context, LogFilters);
w.WriteProperty("elapsedRequestMs", ctx.elapsedMs);
});
}
}
else
@ -74,33 +53,33 @@ namespace Squidex.Web.Pipeline
}
}
private static void LogFilters(HttpContext httpContext, IObjectWriter c)
private static void LogFilters(HttpContext httpContext, IObjectWriter obj)
{
var app = httpContext.Context().App;
if (app != null)
{
c.WriteProperty("appId", app.Id.ToString());
c.WriteProperty("appName", app.Name);
obj.WriteProperty("appId", app.Id.ToString());
obj.WriteProperty("appName", app.Name);
}
var userId = httpContext.User.OpenIdSubject();
if (!string.IsNullOrWhiteSpace(userId))
{
c.WriteProperty(nameof(userId), userId);
obj.WriteProperty(nameof(userId), userId);
}
var clientId = httpContext.User.OpenIdClientId();
if (!string.IsNullOrWhiteSpace(clientId))
{
c.WriteProperty(nameof(clientId), clientId);
obj.WriteProperty(nameof(clientId), clientId);
}
var costs = httpContext.Features.Get<IApiCostsFeature>()?.Costs ?? 0;
c.WriteProperty(nameof(costs), costs);
obj.WriteProperty(nameof(costs), costs);
}
}
}

11
backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs

@ -18,12 +18,11 @@ using Squidex.Assets;
using Squidex.Domain.Apps.Entities;
using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.Apps.Plans;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Security;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
using Squidex.Log;
using Squidex.Shared;
using Squidex.Web;
@ -267,25 +266,25 @@ namespace Squidex.Areas.Api.Controllers.Apps
}
catch (AssetNotFoundException)
{
using (Profiler.Trace("Resize"))
using (Telemetry.Activities.StartActivity("Resize"))
{
using (var sourceStream = GetTempStream())
{
using (var destinationStream = GetTempStream())
{
using (Profiler.Trace("ResizeDownload"))
using (Telemetry.Activities.StartActivity("ResizeDownload"))
{
await appImageStore.DownloadAsync(App.Id, sourceStream);
sourceStream.Position = 0;
}
using (Profiler.Trace("ResizeImage"))
using (Telemetry.Activities.StartActivity("ResizeImage"))
{
await assetThumbnailGenerator.CreateThumbnailAsync(sourceStream, destinationStream, ResizeOptions);
destinationStream.Position = 0;
}
using (Profiler.Trace("ResizeUpload"))
using (Telemetry.Activities.StartActivity("ResizeUpload"))
{
await assetStore.UploadAsync(resizedAsset, destinationStream);
destinationStream.Position = 0;

1
backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs

@ -15,7 +15,6 @@ using Squidex.Areas.Api.Controllers.Plans;
using Squidex.Areas.Api.Controllers.Rules;
using Squidex.Areas.Api.Controllers.Schemas;
using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Apps.Plans;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Reflection;

8
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs

@ -203,19 +203,19 @@ namespace Squidex.Areas.Api.Controllers.Assets
{
var suffix = resizeOptions.ToString();
using (Profiler.Trace("Resize"))
using (Telemetry.Activities.StartActivity("Resize"))
{
using (var sourceStream = GetTempStream())
{
using (var destinationStream = GetTempStream())
{
using (Profiler.Trace("ResizeDownload"))
using (Telemetry.Activities.StartActivity("ResizeDownload"))
{
await assetFileStore.DownloadAsync(asset.AppId.Id, asset.Id, asset.FileVersion, null, sourceStream);
sourceStream.Position = 0;
}
using (Profiler.Trace("ResizeImage"))
using (Telemetry.Activities.StartActivity("ResizeImage"))
{
try
{
@ -231,7 +231,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
try
{
using (Profiler.Trace("ResizeUpload"))
using (Telemetry.Activities.StartActivity("ResizeUpload"))
{
await assetFileStore.UploadAsync(asset.AppId.Id, asset.Id, asset.FileVersion, suffix, destinationStream, overwrite);
destinationStream.Position = 0;

32
backend/src/Squidex/Config/Domain/TelemetryServices.cs

@ -0,0 +1,32 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
namespace Squidex.Config.Domain
{
public static class TelemetryServices
{
public static void AddSquidexTelemetry(this IServiceCollection services)
{
services.AddOpenTelemetryTracing(builder =>
{
builder.SetResourceBuilder(
ResourceBuilder.CreateDefault()
.AddService("Squidex", "Squidex",
typeof(TelemetryServices).Assembly.GetName().Version!.ToString()));
builder.AddSource("Squidex");
builder.AddAspNetCoreInstrumentation();
builder.AddHttpClientInstrumentation();
});
}
}
}

24
backend/src/Squidex/Squidex.csproj

@ -32,16 +32,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.GitHub" Version="5.0.8" />
<PackageReference Include="AspNet.Security.OAuth.GitHub" Version="5.0.9" />
<PackageReference Include="GraphQL.DataLoader" Version="4.5.0" />
<PackageReference Include="GraphQL.Server.Core" Version="5.0.2" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore.NewtonsoftJson" Version="5.0.2" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore.SystemTextJson" Version="5.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="5.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="5.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.9" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.RulesetToEditorconfigConverter" Version="3.0.0" />
<PackageReference Include="Microsoft.Data.Edm" Version="5.8.4" />
@ -50,18 +50,20 @@
<PackageReference Include="Microsoft.Orleans.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="Microsoft.Orleans.Hosting.Kubernetes" Version="3.4.3" />
<PackageReference Include="Microsoft.Orleans.OrleansRuntime" Version="3.4.3" />
<PackageReference Include="MongoDB.Driver" Version="2.12.4" />
<PackageReference Include="Namotion.Reflection" Version="1.0.23" />
<PackageReference Include="MongoDB.Driver" Version="2.13.1" />
<PackageReference Include="Namotion.Reflection" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NJsonSchema" Version="10.4.4" />
<PackageReference Include="NJsonSchema" Version="10.5.2" />
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.0.0" />
<PackageReference Include="NSwag.AspNetCore" Version="13.11.3" />
<PackageReference Include="NSwag.AspNetCore" Version="13.13.2" />
<PackageReference Include="OpenCover" Version="4.7.1221" PrivateAssets="all" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc7" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc7" />
<PackageReference Include="Orleans.Providers.MongoDB" Version="3.3.1" />
<PackageReference Include="OrleansDashboard" Version="3.5.2" />
<PackageReference Include="OrleansDashboard.EmbeddedAssets" Version="3.5.2" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="ReportGenerator" Version="4.8.11" PrivateAssets="all" />
<PackageReference Include="ReportGenerator" Version="4.8.12" PrivateAssets="all" />
<PackageReference Include="Squidex.Assets.Azure" Version="1.8.0" />
<PackageReference Include="Squidex.Assets.GoogleCloud" Version="1.8.0" />
<PackageReference Include="Squidex.Assets.FTP" Version="1.8.0" />

1
backend/src/Squidex/Startup.cs

@ -68,6 +68,7 @@ namespace Squidex
services.AddSquidexSerializers();
services.AddSquidexStoreServices(config);
services.AddSquidexSubscriptions(config);
services.AddSquidexTelemetry();
services.AddSquidexTranslation(config);
services.AddSquidexUsageTracking(config);
}

1299
backend/src/Squidex/appsettings.json

File diff suppressed because it is too large
Loading…
Cancel
Save