diff --git a/backend/Squidex.ruleset b/backend/Squidex.ruleset
deleted file mode 100644
index e56b72abe..000000000
--- a/backend/Squidex.ruleset
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/backend/extensions/Squidex.Extensions/APM/ApplicationInsights/ApplicationInsightsPlugin.cs b/backend/extensions/Squidex.Extensions/APM/ApplicationInsights/ApplicationInsightsPlugin.cs
index ad9bca6a2..4ee785de1 100644
--- a/backend/extensions/Squidex.Extensions/APM/ApplicationInsights/ApplicationInsightsPlugin.cs
+++ b/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 Configure(Action next)
- {
- return builder =>
- {
- var client = builder.ApplicationServices.GetRequiredService();
-
- Profiler.SpanStarted += session =>
- {
- session.Listen(client.StartOperation(session.Key));
- };
-
- next(builder);
- };
- }
-
public void ConfigureServices(IServiceCollection services, IConfiguration config)
{
- var isEnabled = config.GetValue("logging:applicationInsights");
-
- if (isEnabled)
+ services.AddOpenTelemetryTracing(builder =>
{
- services.AddSingleton(this);
- services.AddApplicationInsightsTelemetry();
- services.AddSingleton();
- }
+ if (config.GetValue("logging:applicationInsights:enabled"))
+ {
+ builder.AddAzureMonitorTraceExporter(options =>
+ {
+ config.GetSection("logging:applicationInsights").Bind(options);
+ });
+ }
+ });
}
}
}
diff --git a/backend/extensions/Squidex.Extensions/APM/ApplicationInsights/RoleNameTelemetryInitializer.cs b/backend/extensions/Squidex.Extensions/APM/ApplicationInsights/RoleNameTelemetryInitializer.cs
deleted file mode 100644
index 22107f4cd..000000000
--- a/backend/extensions/Squidex.Extensions/APM/ApplicationInsights/RoleNameTelemetryInitializer.cs
+++ /dev/null
@@ -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("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;
- }
- }
- }
-}
diff --git a/backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs b/backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs
deleted file mode 100644
index d5fd577b1..000000000
--- a/backend/extensions/Squidex.Extensions/APM/Datadog/DatadogPlugin.cs
+++ /dev/null
@@ -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 Configure(Action 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("logging:datadog");
-
- if (isEnabled)
- {
- services.AddSingleton(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);
- }
- }
-}
diff --git a/backend/extensions/Squidex.Extensions/APM/Otlp/OtlpPlugin.cs b/backend/extensions/Squidex.Extensions/APM/Otlp/OtlpPlugin.cs
new file mode 100644
index 000000000..caf4ae0ff
--- /dev/null
+++ b/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("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);
+ });
+ }
+ });
+ }
+ }
+}
diff --git a/backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverExceptionHandler.cs b/backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverExceptionHandler.cs
new file mode 100644
index 000000000..bec3acbc0
--- /dev/null
+++ b/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);
+ }
+ }
+ }
+}
diff --git a/backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverPlugin.cs b/backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverPlugin.cs
new file mode 100644
index 000000000..c4bf69c28
--- /dev/null
+++ b/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("logging:stackdriver:enabled"))
+ {
+ var projectId = config.GetValue("logging:stackdriver:projectId");
+
+ builder.UseStackdriverExporter(projectId);
+
+ services.AddSingleton();
+
+ services.AddSingleton();
+ }
+ });
+ }
+ }
+}
diff --git a/backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverSeverityLogAppender.cs b/backend/extensions/Squidex.Extensions/APM/Stackdriver/StackdriverSeverityLogAppender.cs
new file mode 100644
index 000000000..b12567eca
--- /dev/null
+++ b/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";
+ }
+ }
+ }
+}
diff --git a/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj b/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
index 580759a0b..47a5e967b 100644
--- a/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
+++ b/backend/extensions/Squidex.Extensions/Squidex.Extensions.csproj
@@ -13,16 +13,20 @@
-
-
-
+
+
+
+
+
+
+
diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj b/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
index 4f3e2bd98..b9ca82aab 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
+++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs
index 7c5f8a4bc..c58f3cbb5 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs
+++ b/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> QueryAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod("QueryAsyncByQuery"))
+ using (Telemetry.Activities.StartMethod("QueryAsyncByQuery"))
{
var filter = BuildFilter(appId, parentId);
@@ -61,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task> QueryChildIdsAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var filter = BuildFilter(appId, parentId);
@@ -78,7 +77,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task FindAssetFolderAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var documentId = DomainId.Combine(appId, id);
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs
index 3918da039..74e1286a7 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs
+++ b/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.ReadAsync(DomainId key)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var existing =
await Collection.Find(x => x.DocumentId == key)
@@ -42,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore.WriteAsync(DomainId key, AssetFolderDomainObject.State value, long oldVersion, long newVersion)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var entity = Map(value);
@@ -52,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore.WriteManyAsync(IEnumerable<(DomainId Key, AssetFolderDomainObject.State Value, long Version)> snapshots)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var updates = snapshots.Select(Map).Select(x =>
new ReplaceOneModel(
@@ -74,7 +73,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore.ReadAllAsync(Func callback,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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.RemoveAsync(DomainId key)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
await Collection.DeleteOneAsync(x => x.DocumentId == key);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs
index 9f7f4ee2f..5031a2c71 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs
+++ b/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> QueryAsync(DomainId appId, DomainId? parentId, Q q,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod("QueryAsyncByQuery"))
+ using (Telemetry.Activities.StartMethod("QueryAsyncByQuery"))
{
try
{
@@ -153,7 +152,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task> QueryIdsAsync(DomainId appId, HashSet ids,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod("QueryAsyncByIds"))
+ using (Telemetry.Activities.StartMethod("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> QueryChildIdsAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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 FindAssetByHashAsync(DomainId appId, string hash, string fileName, long fileSize,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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 FindAssetBySlugAsync(DomainId appId, string slug,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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 FindAssetAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var documentId = DomainId.Combine(appId, id);
@@ -224,7 +223,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public async Task FindAssetAsync(DomainId id,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var assetEntity =
await Collection.Find(x => x.Id == id && !x.IsDeleted)
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs
index ecbaecda2..198ffd8d8 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs
+++ b/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.ReadAsync(DomainId key)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var existing =
await Collection.Find(x => x.DocumentId == key)
@@ -42,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore.WriteAsync(DomainId key, AssetDomainObject.State value, long oldVersion, long newVersion)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var entity = Map(value);
@@ -52,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore.WriteManyAsync(IEnumerable<(DomainId Key, AssetDomainObject.State Value, long Version)> snapshots)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var updates = snapshots.Select(Map).Select(x =>
new ReplaceOneModel(
@@ -74,7 +73,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
async Task ISnapshotStore.ReadAllAsync(Func callback,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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.RemoveAsync(DomainId key)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
await Collection.DeleteOneAsync(x => x.DocumentId == key);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs
index 6844ed91b..ea61cec8d 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs
+++ b/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> QueryAsync(IAppEntity app, List schemas, Q q,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
if (q.Ids != null && q.Ids.Count > 0)
{
@@ -136,7 +135,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
if (q.Ids != null && q.Ids.Count > 0)
{
@@ -160,7 +159,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task FindContentAsync(ISchemaEntity schema, DomainId id,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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 callback,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
await queryScheduled.QueryAsync(now, callback, ct);
}
@@ -178,7 +177,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task> QueryIdsAsync(DomainId appId, HashSet ids,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await queryByIds.QueryIdsAsync(appId, ids, ct);
}
@@ -187,7 +186,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode filterNode,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await queryByQuery.QueryIdsAsync(appId, schemaId, filterNode, ct);
}
@@ -196,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public async Task HasReferrersAsync(DomainId appId, DomainId contentId,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await queryReferrers.CheckExistsAsync(appId, contentId, ct);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
index bfe46f45e..fbd153cdb 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
+++ b/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.ReadAsync(DomainId key)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var version = await collectionAll.FindVersionAsync(key);
@@ -39,7 +38,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore.ClearAsync()
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
await collectionAll.ClearAsync();
await collectionPublished.ClearAsync();
@@ -48,7 +47,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore.RemoveAsync(DomainId key)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
await collectionAll.RemoveAsync(key);
await collectionPublished.RemoveAsync(key);
@@ -57,7 +56,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore.WriteAsync(DomainId key, ContentDomainObject.State value, long oldVersion, long newVersion)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
if (value.SchemaId.Id == DomainId.Empty)
{
@@ -72,7 +71,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
async Task ISnapshotStore.WriteManyAsync(IEnumerable<(DomainId Key, ContentDomainObject.State Value, long Version)> snapshots)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var entitiesPublished = new List();
var entitiesAll = new List();
diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
index cc50ada9c..ce81d17ca 100644
--- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
+++ b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Squidex.Domain.Apps.Entities.MongoDb.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs b/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs
index 995007747..0c383653b 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs
+++ b/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> GetAppsAsync()
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var ids = await GetAppIdsAsync();
@@ -91,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task> GetAppsForUserAsync(string userId, PermissionSet permissions)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var ids =
await Task.WhenAll(
@@ -109,7 +108,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task GetAppByNameAsync(string name, bool canCache = false)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
if (canCache)
{
@@ -132,7 +131,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public async Task GetAppAsync(DomainId appId, bool canCache)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
if (canCache)
{
@@ -155,7 +154,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task> GetAppIdsByUserAsync(string userId)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await grainFactory.GetGrain(userId).GetIdsAsync();
}
@@ -163,7 +162,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task> GetAppIdsAsync()
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await grainFactory.GetGrain(SingleGrain.Id).GetIdsAsync();
}
@@ -171,7 +170,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task> GetAppIdsAsync(string[] names)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await grainFactory.GetGrain(SingleGrain.Id).GetIdsAsync(names);
}
@@ -179,7 +178,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
private async Task GetAppIdAsync(string name)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await grainFactory.GetGrain(SingleGrain.Id).GetIdAsync(name);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs
index 58a749372..edcffc1c1 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs
+++ b/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())
+ using (Telemetry.Activities.StartMethod())
{
var results = assets.Select(x => SimpleMapper.Map(x, new AssetEntity())).ToList();
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetLoader.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetLoader.cs
index 1fada21ec..95b03276a 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetLoader.cs
+++ b/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 GetAsync(DomainId appId, DomainId id, long version)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var key = DomainId.Combine(appId, id);
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryParser.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryParser.cs
index d4496dcce..9715d1916 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryParser.cs
+++ b/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())
+ using (Telemetry.Activities.StartMethod())
{
var query = ParseClrQuery(q);
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs
index f4ed509e7..e88330785 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs
+++ b/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> FindAssetFolderAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var result = new List();
@@ -71,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
public async Task> QueryAssetFoldersAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var assetFolders = await QueryFoldersCoreAsync(appId, parentId, ct);
@@ -82,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
public async Task> QueryAssetFoldersAsync(Context context, DomainId parentId,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
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())
+ using (Telemetry.Activities.StartMethod())
{
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())
+ using (Telemetry.Activities.StartMethod())
{
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())
+ using (Telemetry.Activities.StartMethod())
{
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())
+ using (Telemetry.Activities.StartMethod())
{
IAssetEntity? asset;
@@ -181,7 +180,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
return EmptyAssets;
}
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
q = await queryParser.ParseAsync(context, q);
@@ -215,7 +214,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
private async Task> TransformCoreAsync(Context context, IEnumerable assets,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await assetEnricher.EnrichAsync(assets, context, ct);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs b/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs
index 7146a16f9..de2f2a81d 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs
+++ b/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 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");
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs
index d97bd59f8..faa1c0fd5 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs
+++ b/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> EnrichInternalAsync(IEnumerable contents, bool cloneData, Context context,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var results = new List();
@@ -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);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentLoader.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentLoader.cs
index def19558c..33e23dcd9 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentLoader.cs
+++ b/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 GetAsync(DomainId appId, DomainId id, long version)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var key = DomainId.Combine(appId, id).ToString();
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs
index 212612ffe..105673a8e 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryParser.cs
+++ b/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())
+ using (Telemetry.Activities.StartMethod())
{
var query = await ParseClrQueryAsync(context, q, schema);
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs
index c430b46c5..e7cbe2c56 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs
+++ b/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())
+ using (Telemetry.Activities.StartMethod())
{
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())
+ using (Telemetry.Activities.StartMethod())
{
if (q == null)
{
@@ -114,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
Guard.NotNull(context, nameof(context));
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
if (q == null)
{
@@ -160,7 +159,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
private async Task> TransformCoreAsync(Context context, IEnumerable contents,
CancellationToken ct)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await contentEnricher.EnrichAsync(contents, context, ct);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs b/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs
index 737322d39..abb6d0634 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs
+++ b/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> GetRulesAsync(DomainId appId)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var ids = await GetRuleIdsAsync(appId);
@@ -47,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
private async Task> GetRuleIdsAsync(DomainId appId)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await Index(appId).GetIdsAsync();
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Rules/Queries/RuleEnricher.cs b/backend/src/Squidex.Domain.Apps.Entities/Rules/Queries/RuleEnricher.cs
index b4b1b2598..7dbdc5d7f 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Rules/Queries/RuleEnricher.cs
+++ b/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())
+ using (Telemetry.Activities.StartMethod())
{
var results = new List();
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs b/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs
index f7d86dedb..53adf6b23 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs
+++ b/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> GetSchemasAsync(DomainId appId)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var ids = await GetSchemaIdsAsync(appId);
@@ -55,7 +54,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public async Task GetSchemaByNameAsync(DomainId appId, string name, bool canCache)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var cacheKey = GetCacheKey(appId, name);
@@ -80,7 +79,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public async Task GetSchemaAsync(DomainId appId, DomainId id, bool canCache)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var cacheKey = GetCacheKey(appId, id);
@@ -105,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
private async Task GetSchemaIdAsync(DomainId appId, string name)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await Index(appId).GetIdAsync(name);
}
@@ -113,7 +112,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
private async Task> GetSchemaIdsAsync(DomainId appId)
{
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
return await Index(appId).GetIdsAsync();
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj b/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
index 1841176ed..199b24c30 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
+++ b/backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
@@ -18,7 +18,7 @@
-
+
all
diff --git a/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj b/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
index bfd397200..ecf15442e 100644
--- a/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
+++ b/backend/src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj b/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
index 153ad5b31..49dac07fb 100644
--- a/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
+++ b/backend/src/Squidex.Domain.Users/Squidex.Domain.Users.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Reader.cs b/backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Reader.cs
index 9143d59d5..f4a86c082 100644
--- a/backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Reader.cs
+++ b/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;
namespace Squidex.Infrastructure.EventSourcing
@@ -48,7 +47,7 @@ namespace Squidex.Infrastructure.EventSourcing
return EmptyEvents;
}
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var commits =
await Collection.Find(
@@ -65,7 +64,7 @@ namespace Squidex.Infrastructure.EventSourcing
{
Guard.NotNullOrEmpty(streamName, nameof(streamName));
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var commits =
await Collection.Find(
@@ -84,7 +83,7 @@ namespace Squidex.Infrastructure.EventSourcing
{
Guard.NotNull(streamNames, nameof(streamNames));
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var position = EtagVersion.Empty;
diff --git a/backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Writer.cs b/backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Writer.cs
index bc4234e9e..eb58942b4 100644
--- a/backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore_Writer.cs
+++ b/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())
+ using (Telemetry.Activities.StartMethod())
{
if (events.Count == 0)
{
@@ -102,7 +101,7 @@ namespace Squidex.Infrastructure.EventSourcing
{
Guard.NotNull(commits, nameof(commits));
- using (Profiler.TraceMethod())
+ using (Telemetry.Activities.StartMethod())
{
var writes = new List>();
diff --git a/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj b/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
index ba8b59a5a..58c4a2330 100644
--- a/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
+++ b/backend/src/Squidex.Infrastructure.MongoDb/Squidex.Infrastructure.MongoDb.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/backend/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs b/backend/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs
index 616bacdaa..23cbe71bd 100644
--- a/backend/src/Squidex.Infrastructure.MongoDb/States/MongoSnapshotStore.cs
+++ b/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>())
+ using (Telemetry.Activities.StartMethod>())
{
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>())
+ using (Telemetry.Activities.StartMethod>())
{
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>())
+ using (Telemetry.Activities.StartMethod>())
{
var writes = snapshots.Select(x => new ReplaceOneModel>(
Filter.Eq(y => y.DocumentId, x.Key),
@@ -96,7 +95,7 @@ namespace Squidex.Infrastructure.States
public async Task ReadAllAsync(Func callback,
CancellationToken ct = default)
{
- using (Profiler.TraceMethod>())
+ using (Telemetry.Activities.StartMethod>())
{
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>())
+ using (Telemetry.Activities.StartMethod>())
{
await Collection.DeleteOneAsync(x => x.DocumentId.Equals(key));
}
diff --git a/backend/src/Squidex.Infrastructure/Orleans/J{T}.cs b/backend/src/Squidex.Infrastructure/Orleans/J{T}.cs
index 6e0d74791..2d13c1596 100644
--- a/backend/src/Squidex.Infrastructure/Orleans/J{T}.cs
+++ b/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);
diff --git a/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj b/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
index 9ea21eb73..8695875e0 100644
--- a/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
+++ b/backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
@@ -10,11 +10,11 @@
-
+
-
-
+
+
all
@@ -23,12 +23,12 @@
-
+
-
+
diff --git a/backend/src/Squidex.Infrastructure/Telemetry.cs b/backend/src/Squidex.Infrastructure/Telemetry.cs
new file mode 100644
index 000000000..59cd58489
--- /dev/null
+++ b/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(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}");
+ }
+ }
+}
diff --git a/backend/src/Squidex.Web/ETagExtensions.cs b/backend/src/Squidex.Web/ETagExtensions.cs
index 47e84866e..8df1a45aa 100644
--- a/backend/src/Squidex.Web/ETagExtensions.cs
+++ b/backend/src/Squidex.Web/ETagExtensions.cs
@@ -19,7 +19,7 @@ namespace Squidex.Web
{
public static string ToEtag(this IReadOnlyList 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(this IResultList entities) where T : IEntity, IEntityWithVersion
{
- using (Profiler.Trace("CalculateEtag"))
+ using (Telemetry.Activities.StartActivity("CalculateEtag"))
{
var hash = Create(entities, entities.Total);
diff --git a/backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs b/backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs
index 0730999ef..4b8796bb4 100644
--- a/backend/src/Squidex.Web/Pipeline/ApiCostsFilter.cs
+++ b/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();
diff --git a/backend/src/Squidex.Web/Pipeline/CachingManager.cs b/backend/src/Squidex.Web/Pipeline/CachingManager.cs
index 35e71dbfe..a6d696d6e 100644
--- a/backend/src/Squidex.Web/Pipeline/CachingManager.cs
+++ b/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();
diff --git a/backend/src/Squidex.Web/Pipeline/MeasureResultFilter.cs b/backend/src/Squidex.Web/Pipeline/MeasureResultFilter.cs
index 81302f034..c1f1c6add 100644
--- a/backend/src/Squidex.Web/Pipeline/MeasureResultFilter.cs
+++ b/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();
}
diff --git a/backend/src/Squidex.Web/Pipeline/RequestLogOptions.cs b/backend/src/Squidex.Web/Pipeline/RequestLogOptions.cs
index 85ffadf04..e15eea34d 100644
--- a/backend/src/Squidex.Web/Pipeline/RequestLogOptions.cs
+++ b/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; }
}
}
diff --git a/backend/src/Squidex.Web/Pipeline/RequestLogPerformanceMiddleware.cs b/backend/src/Squidex.Web/Pipeline/RequestLogPerformanceMiddleware.cs
index 20bf145c9..ac3757e6d 100644
--- a/backend/src/Squidex.Web/Pipeline/RequestLogPerformanceMiddleware.cs
+++ b/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()?.Costs ?? 0;
- c.WriteProperty(nameof(costs), costs);
+ obj.WriteProperty(nameof(costs), costs);
}
}
}
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
index 843059eb5..f65ecbe08 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
+++ b/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;
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs
index 9a47b8b90..8f9c851e9 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs
+++ b/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;
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
index c0e1b143a..de881cbe9 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
+++ b/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;
diff --git a/backend/src/Squidex/Config/Domain/TelemetryServices.cs b/backend/src/Squidex/Config/Domain/TelemetryServices.cs
new file mode 100644
index 000000000..da524a005
--- /dev/null
+++ b/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();
+ });
+ }
+ }
+}
diff --git a/backend/src/Squidex/Squidex.csproj b/backend/src/Squidex/Squidex.csproj
index 259b10948..31c6742ad 100644
--- a/backend/src/Squidex/Squidex.csproj
+++ b/backend/src/Squidex/Squidex.csproj
@@ -32,16 +32,16 @@
-
+
-
-
-
-
-
+
+
+
+
+
@@ -50,18 +50,20 @@
-
-
+
+
-
+
-
+
+
+
-
+
diff --git a/backend/src/Squidex/Startup.cs b/backend/src/Squidex/Startup.cs
index db87f9677..7748339b0 100644
--- a/backend/src/Squidex/Startup.cs
+++ b/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);
}
diff --git a/backend/src/Squidex/appsettings.json b/backend/src/Squidex/appsettings.json
index a3756d711..a61a797ca 100644
--- a/backend/src/Squidex/appsettings.json
+++ b/backend/src/Squidex/appsettings.json
@@ -1,785 +1,546 @@
{
- "mode": {
- /*
- * Use this flag to set Squidex to readonly, e.g. when you deploy a second instance for migration.
- */
- "isReadonly": false
- },
-
- "urls": {
- /*
- * Set the base url of your application, to generate correct urls in background process.
- */
- "baseUrl": "https://localhost:5001",
-
- /*
- * The base path when running Squidex behind a reverse proxy like nginx under a subfolder / subpath.
- */
- "basePath": "",
-
- /*
- * Set it to true to redirect the user from http to https permanently.
- */
- "enforceHttps": false,
-
- /*
- * Set it to true to return a 400 if the host does not match.
- */
- "enforceHost": false,
-
- /*
- * A list of known proxies to make forward headers safer.
- */
- "knownProxies": [],
-
- /*
- * Set it to true to use the X-Forwarded- headers for host name and scheme.
- */
- "enableForwardHeaders": true,
-
- /*
- * A list of trusted hosts for redirects.
- */
- "trustedHosted": []
- },
-
- "fullText": {
- /*
- * Define the type of the full text store.
- *
- * Supported: elastic (ElasticSearch). Default: MongoDB
- */
- "type": "default",
- "elastic": {
- /*
- * The configuration to your elastic search cluster.
- *
- * Read More: https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-configuration.html
- */
- "configuration": "http://localhost:9200",
- /*
- * The name of the index.
- */
- "indexName": "squidex"
- }
- },
-
- /*
- * Define optional paths to plugins.
- */
- "plugins": [
- "Squidex.Extensions.dll"
- ],
-
- "caching": {
- /*
- * Set to true, to use strong etags.
- */
- "strongETag": false,
-
- /*
- * Restrict the surrogate keys to the number of characters.
- */
- "maxSurrogateKeysSize": 0,
-
- "replicated": {
- /*
- * Set to true to enable a replicated cache for app, schemas and rules. Increases performance but reduces consistency.
- */
- "enable": true
- }
- },
-
- "languages": {
- /*
- * Use custom languages where the key is the language code and the value is the english name.
- */
- "custom": ""
- },
-
- "rules": {
- /*
- * The timeout to execute rule actions.
- */
- "executionTimeoutInSeconds": 10
- },
-
- "ui": {
- /*
- * Regex suggestions for the UI
- */
- "regexSuggestions": {
- // Regex for emails.
- "Email": "^[a-zA-Z0-9.!#$%&’*+\\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$",
- // Regex for phone numbers.
- "Phone": "^\\(*\\+*[1-9]{0,3}\\)*-*[1-9]{0,3}[-. /]*\\(*[2-9]\\d{2}\\)*[-. /]*\\d{3}[-. /]*\\d{4} *e*x*t*\\.* *\\d{0,4}$",
- // Regex for slugs (e.g. hello-world).
- "Slug": "^[a-z0-9]+(\\-[a-z0-9]+)*$",
- // Regex for urls.
- "Url": "^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:\\/?#%[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
+ "mode": {
+ // Use this flag to set Squidex to readonly, e.g. when you deploy a second instance for migration.
+ "isReadonly": false
},
- /*
- * True if only admins should be able to create apps.
- */
- "onlyAdminsCanCreateApps": false,
-
- "map": {
- /*
- * Define the type of the geolocation service.
- *
- * Supported: GoogleMaps, OSM
- */
- "type": "OSM",
- "googleMaps": {
- /*
- * The optional google maps API key. CREATE YOUR OWN PLEASE.
- */
- "key": "AIzaSyB_Z8l3nwUxZhMJykiDUJy6bSHXXlwcYMg"
- }
+ "urls": {
+ // Set the base url of your application, to generate correct urls in background process.
+ "baseUrl": "https://localhost:5001",
+
+ // The base path when running Squidex behind a reverse proxy like nginx under a subfolder / subpath.
+ "basePath": "",
+
+ // Set it to true to redirect the user from http to https permanently.
+ "enforceHttps": false,
+
+ // Set it to true to return a 400 if the host does not match.
+ "enforceHost": false,
+
+ // A list of known proxies to make forward headers safer.
+ "knownProxies": [],
+
+ // Set it to true to use the X-Forwarded- headers for host name and scheme.
+ "enableForwardHeaders": true,
+
+ // A list of trusted hosts for redirects.
+ "trustedHosted": []
},
- /*
- * Redirect to login automatically.
- */
- "redirectToLogin": false,
-
- /*
- * Hide the news dialog.
- */
- "hideNews": false,
-
- /*
- * Hide all onboarding tooltips and dialogs.
- */
- "hideOnboarding": false,
-
- /*
- * Hide the today and now button.
- */
- "hideDateButtons": false,
-
- /*
- * Hide the Local/UTC button
- */
- "hideDateTimeModeButton": false,
-
- /*
- * Show the exposed values as information on the apps overview page.
- */
- "showInfo": false,
-
- /*
- * The number of content items for dropdown selector.
- */
- "referencesDropdownItemCount": 100,
-
- "google": {
- /*
- * The Google analytics ID.
- */
- "analyticsId": "UA-99989790-2"
- }
- },
-
- "email": {
- "smtp": {
- /*
- * The host name to your email server.
- */
- "server": "",
-
- /*
- * The sender email address.
- */
- "sender": "hello@squidex.io",
-
- /*
- * The username to authenticate to your email server.
- */
- "username": "",
-
- /*
- * The password to authenticate to your email server.
- */
- "password": "",
-
- /*
- * Always use SSL if possible.
- */
- "enableSsl": true,
-
- /*
- * The port to your email server.
- */
- "port": 587
+ "fullText": {
+ // Define the type of the full text store.
+ //
+ // SUPPORTED: elastic (ElasticSearch), default. Default: default
+ "type": "default",
+
+ "elastic": {
+ // he configuration to your elastic search cluster.
+ //
+ // Read More: https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-configuration.html
+ "configuration": "http://localhost:9200",
+ // The name of the index.
+ "indexName": "squidex"
+ }
},
- "notifications": {
- /*
- * The email subject when a new user is added as contributor.
- */
- "newUserSubject": "You have been invited to join Project $APP_NAME at Squidex CMS",
-
- /*
- * The email body when a new user is added as contributor.
- */
- "newUserBody": "Welcome to Squidex\r\nDear User,\r\n\r\n$ASSIGNER_NAME ($ASSIGNER_EMAIL) has invited you to join Project (also called an App) $APP_NAME at Squidex Headless CMS. Login with your Github, Google or Microsoft credentials to create a new user account and start editing content now.\r\n\r\nThank you very much,\r\nThe Squidex Team\r\n\r\n<> [$UI_URL]",
-
- /*
- * The email subject when an existing user is added as contributor.
- */
- "existingUserSubject": "[Squidex CMS] You have been invited to join App $APP_NAME",
-
- /*
- * The email body when an existing user is added as contributor.
- */
- "existingUserBody": "Dear User,\r\n\r\n$ASSIGNER_NAME ($ASSIGNER_EMAIL) has invited you to join App $APP_NAME at Squidex Headless CMS.\r\n\r\nLogin or reload the Management UI to see the App.\r\n\r\nThank you very much,\r\nThe Squidex Team\r\n\r\n<> [$UI_URL]",
-
- /*
- * The email subject when app usage reached
- */
- "usageSubject": "[Squidex CMS] You you are about to reach your usage limit for App $APP_NAME",
-
- /*
- * The email body when app usage reached
- */
- "usageBody": "Dear User,\r\n\r\nYou you are about to reach your usage limit for App $APP_NAME at Squidex Headless CMS.\r\n\r\nYou have already used $API_CALLS of your monthy limit of $API_CALLS_LIMIT API calls.\r\n\r\nPlease check your clients or upgrade your plan!\r\n\r\n<> [$UI_URL]"
- }
- },
-
- /*
- * Configure notifo if you want to have support for custom notifications.
- */
- "notifo": {
- /*
- * The id of the app in notifo.
- */
- "appId": "",
- /*
- * The API key for your app in notifo.
- */
- "apiKey": "",
- /*
- * The API URL.
- */
- "apiUrl": "https://app.notifo.io"
- },
-
- "robots": {
- /*
- * The text for the robots.txt file
- */
- "text": "User-agent: *\nAllow: /api/assets/*"
- },
-
- "healthz": {
- "gc": {
- /*
- * The maximum number of megabyte that the process can consume until it is marked as not healthy.
- */
- "threshold": 4096
- }
- },
-
- "contents": {
- /*
- * The default page size if not specified by a query.
- */
- "defaultPageSize": 200,
-
- /*
- * The maximum number of items to return for each query.
- *
- * Warning: Use pagination and not large number of items.
- */
- "maxResults": 200,
-
- /*
- * The timeout when searching for single items in the database.
- */
- "timeoutFind": "00:00:01",
-
- /*
- * The timeout when searching for multiple items in the database.
- */
- "timeoutQuery": "00:00:05"
- },
-
- "assets": {
- /*
- * The default page size if not specified by a query.
- */
- "defaultPageSize": 200,
-
- /*
- * The maximum number of items to return for each query.
- *
- * Warning: Use pagination and not large number of items.
- */
- "maxResults": 200,
-
- /*
- * The maximum file size in bytes. Default: 5MB
- */
- "maxSize": 5242880,
-
- /*
- * True to delete assets recursively.
- */
- "deleteRecursive": true,
-
- /*
- * True to delete assets files permanently.
- */
- "deletePermanent": false,
-
- /*
- * The timeout when searching for single items in the database.
- */
- "timeoutFind": "00:00:01",
-
- /*
- * The timeout when searching for multiple items in the database.
- */
- "timeoutQuery": "00:00:05",
-
- /*
- * Create one folder per app.
- *
- * WARNING: If you change this parameter, previous assets are not available anymore.
- */
- "folderPerApp": false
- },
-
- "logging": {
- /*
- * The log level.
- *
- * Trace, Debug, Information, Warning, Error, Fatal
- */
- "level": "Information",
-
- /*
- * Setting the flag to true, enables well formatteds json logs.
- */
- "human": true,
-
- /*
- * Set to true, to use colors.
- */
- "colors": true,
-
- /*
- * Set to false to disable logging of http requests.
- */
- "logRequests": true,
-
- /*
- * Set to true to enable logging of profiler information.
- */
- "logProfiler": false,
-
- /*
- * False to disable the log store.
- */
- "storeEnabled": true,
-
- /*
- * The number of days request log items will be stored.
- */
- "storeRetentationInDays": 90,
-
- /*
- * True, to enable datadog integration.
- */
- "datadog": false,
-
- /*
- * True, to enable application insights integraon.
- */
- "applicationInsights": false
- },
-
- "assetStore": {
- /*
- * Define the type of the read store.
- *
- * Supported: Folder (local folder), MongoDb (GridFS), GoogleCloud (hosted in Google Cloud only), AzureBlob, AmazonS3, FTP (not recommended).
- */
- "type": "Folder",
- "folder": {
- /*
- * The relative or absolute path to the folder to store the assets.
- */
- "path": "Assets"
+
+ // Define optional paths to plugins.
+ "plugins": [
+ "Squidex.Extensions.dll"
+ ],
+
+ "caching": {
+ // Set to true, to use strong etags.
+ "strongETag": false,
+
+ // Restrict the surrogate keys to the number of characters.
+ "maxSurrogateKeysSize": 0,
+
+ "replicated": {
+ // Set to true to enable a replicated cache for app, schemas and rules. Increases performance but reduces consistency.
+ "enable": true
+ }
+ },
+
+ "languages": {
+ // Use custom languages where the key is the language code and the value is the english name.
+ "custom": ""
+ },
+
+ "rules": {
+ // The timeout to execute rule actions.
+ "executionTimeoutInSeconds": 10
+ },
+
+ "ui": {
+ // Regex suggestions for the UI
+ "regexSuggestions": {
+ // Regex for emails.
+ "Email": "^[a-zA-Z0-9.!#$%&’*+\\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$",
+ // Regex for phone numbers.
+ "Phone": "^\\(*\\+*[1-9]{0,3}\\)*-*[1-9]{0,3}[-. /]*\\(*[2-9]\\d{2}\\)*[-. /]*\\d{3}[-. /]*\\d{4} *e*x*t*\\.* *\\d{0,4}$",
+ // Regex for slugs (e.g. hello-world).
+ "Slug": "^[a-z0-9]+(\\-[a-z0-9]+)*$",
+ // Regex for urls.
+ "Url": "^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:\\/?#%[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
+ },
+
+ // True if only admins should be able to create apps.
+ "onlyAdminsCanCreateApps": false,
+
+ "map": {
+ // Define the type of the geolocation service.
+ //
+ // SUPPORTED: GoogleMaps, OSM
+ "type": "OSM",
+
+ "googleMaps": {
+ // The optional google maps API key. CREATE YOUR OWN PLEASE.
+ "key": "AIzaSyB_Z8l3nwUxZhMJykiDUJy6bSHXXlwcYMg"
+ }
+ },
+
+ // Redirect to login automatically.
+ "redirectToLogin": false,
+
+ // Hide the news dialog.
+ "hideNews": false,
+
+ // Hide all onboarding tooltips and dialogs.
+ "hideOnboarding": false,
+
+ // Hide the today and now button.
+ "hideDateButtons": false,
+
+ // Hide the Local/UTC button
+ "hideDateTimeModeButton": false,
+
+ // Show the exposed values as information on the apps overview page.
+ "showInfo": false,
+
+ // The number of content items for dropdown selector.
+ "referencesDropdownItemCount": 100,
+
+ "google": {
+ // The Google analytics ID.
+ "analyticsId": "UA-99989790-2"
+ }
},
- "googleCloud": {
- /*
- * The name of the bucket in google cloud store.
- */
- "bucket": "squidex-assets"
+
+ "email": {
+ "smtp": {
+ // The host name to your email server.
+ "server": "",
+
+ // The sender email address.
+ "sender": "hello@squidex.io",
+
+ // The username to authenticate to your email server.
+ "username": "",
+
+ // The password to authenticate to your email server.
+ "password": "",
+
+ // Always use SSL if possible.
+ "enableSsl": true,
+
+ // The port to your email server.
+ "port": 587
+ },
+ "notifications": {
+ // The email subject when a new user is added as contributor.
+ "newUserSubject": "You have been invited to join Project $APP_NAME at Squidex CMS",
+
+ // The email body when a new user is added as contributor.
+ "newUserBody": "Welcome to Squidex\r\nDear User,\r\n\r\n$ASSIGNER_NAME ($ASSIGNER_EMAIL) has invited you to join Project (also called an App) $APP_NAME at Squidex Headless CMS. Login with your Github, Google or Microsoft credentials to create a new user account and start editing content now.\r\n\r\nThank you very much,\r\nThe Squidex Team\r\n\r\n<> [$UI_URL]",
+
+ // The email subject when an existing user is added as contributor.
+ "existingUserSubject": "[Squidex CMS] You have been invited to join App $APP_NAME",
+
+ // The email body when an existing user is added as contributor.
+ "existingUserBody": "Dear User,\r\n\r\n$ASSIGNER_NAME ($ASSIGNER_EMAIL) has invited you to join App $APP_NAME at Squidex Headless CMS.\r\n\r\nLogin or reload the Management UI to see the App.\r\n\r\nThank you very much,\r\nThe Squidex Team\r\n\r\n<> [$UI_URL]",
+
+ // The email subject when app usage reached
+ "usageSubject": "[Squidex CMS] You you are about to reach your usage limit for App $APP_NAME",
+
+ // The email body when app usage reached
+ "usageBody": "Dear User,\r\n\r\nYou you are about to reach your usage limit for App $APP_NAME at Squidex Headless CMS.\r\n\r\nYou have already used $API_CALLS of your monthy limit of $API_CALLS_LIMIT API calls.\r\n\r\nPlease check your clients or upgrade your plan!\r\n\r\n<> [$UI_URL]"
+ }
},
- "azureBlob": {
- /*
- * The name of the container in the Azure Blob Storage
- */
- "containerName": "squidex-assets",
-
- /*
- * The connection string to the azure storage service.
- */
- "connectionString": "UseDevelopmentStorage=true"
+
+ // Configure notifo if you want to have support for custom notifications.
+ "notifo": {
+ // The id of the app in notifo.
+ "appId": "",
+ // The API key for your app in notifo.
+ "apiKey": "",
+ // The API URL.
+ "apiUrl": "https://app.notifo.io"
},
- "AmazonS3": {
- /*
- * The url of the S3 API service. Leave it empty if using the one provided by Amazon
- */
- "serviceUrl": "",
-
- /*
- * The name of your bucket.
- */
- "bucket": "squidex-test",
-
- /*
- * The optional folder within the bucket.
- */
- "bucketFolder": "squidex-assets",
-
- /*
- * The region name of your bucket.
- */
- "regionName": "eu-central-1",
-
- /*
- * The access key for your user.
- *
- * Read More: https://supsystic.com/documentation/id-secret-access-key-amazon-s3/
- */
- "accessKey": "",
-
- /*
- * The secret key for your user.
- *
- * Read More: https://supsystic.com/documentation/id-secret-access-key-amazon-s3/
- */
- "secretKey": "",
-
- /*
- * Force path style property for AmazonS3Config
- */
- "forcePathStyle": false
+
+ "robots": {
+ // The text for the robots.txt file
+ "text": "User-agent: *\nAllow: /api/assets/*"
},
- "mongoDb": {
- /*
- * The connection string to your Mongo Server.
- *
- * Read More: https://docs.mongodb.com/manual/reference/connection-string/
- */
- "configuration": "mongodb://localhost",
-
- /*
- * The name of the event store database.
- */
- "database": "SquidexAssets",
-
- /*
- * The name of the Mongo Grid FS bucket.
- */
- "bucket": "fs"
+
+ "healthz": {
+ "gc": {
+ // The maximum number of megabyte that the process can consume until it is marked as not healthy.
+ "threshold": 4096
+ }
},
- "ftp": {
- /*
- *The host of the ftp service
- */
- "serverHost": "",
-
- /*
- *The host of the ftp service
- */
- "serverPort": "21",
-
- /*
- * Credentials.
- */
- "username": "",
- "password": "",
-
- /*
- * The relative or absolute path to the folder to store the assets.
- */
- "path": "Assets"
+
+ "contents": {
+ // The default page size if not specified by a query.
+ "defaultPageSize": 200,
+
+ // The maximum number of items to return for each query.
+ //
+ // Warning: Use pagination and not large number of items.
+ "maxResults": 200,
+
+ // The timeout when searching for single items in the database.
+ "timeoutFind": "00:00:01",
+
+ // The timeout when searching for multiple items in the database.
+ "timeoutQuery": "00:00:05"
},
- /*
- * Allow to expose the url in graph ql url.
- */
- "exposeSourceUrl": false
- },
-
- "orleans": {
- /*
- * Define the clustering type.
- *
- * Supported: MongoDB, Development
- */
- "clustering": "Development",
-
- /*
- * Tell Orleans it is running in kubernetes.
- *
- * Read more: https://dotnet.github.io/orleans/docs/deployment/kubernetes.html?q=kubernetes
- */
- "kubernetes": false,
-
- /*
- * The port is used to share messages between all cluster members. Must be accessible within your cluster or network.
- */
- "siloPort": "11111",
-
- /*
- * The ports used by Orleans to connect to external clients. Not used.
- */
- "gatewayPort": "40000",
-
- /*
- * The advertised IP address. Usually not needed.
- */
- "ipAddress": ""
- },
-
- "eventStore": {
- /*
- * Define the type of the event store.
- *
- * Supported: MongoDb
- */
- "type": "MongoDb",
- "mongoDb": {
- /*
- * The connection string to your Mongo Server.
- *
- * Read More: https://docs.mongodb.com/manual/reference/connection-string/
- */
- "configuration": "mongodb://localhost",
-
- /*
- * The name of the event store database.
- */
- "database": "Squidex"
- }
- },
-
- "eventPublishers": {
- /*
- * Additional event publishers (advanced usage only): (Name => Config)
- */
- "allToRabbitMq": {
- /*
- * Example:: Push all events to RabbitMq.
- */
- "type": "RabbitMq",
- "configuration": "amqp://guest:guest@localhost/",
- "exchange": "squidex",
- "enabled": false,
- "eventsFilter": ".*"
- }
- },
-
- "store": {
- /*
- * Define the type of the read store.
- *
- * Supported: MongoDb
- */
- "type": "MongoDb",
- "mongoDb": {
- /*
- * The connection string to your Mongo Server.
- *
- * Read More: https://docs.mongodb.com/manual/reference/connection-string/
- */
- "configuration": "mongodb://localhost",
-
- /*
- * The database for all your content collections (one collection per app).
- */
- "contentDatabase": "SquidexContent",
-
- /*
- * The database for all your other read collections.
- */
- "database": "Squidex"
- }
- },
-
- "identity": {
- /*
- * Set to true to show PII (Personally Identifiable Information) in the logs.
- */
- "showPII": true,
-
- /*
- * Enable password auth. Set this to false if you want to disable local login, leaving only 3rd party login options.
- */
- "allowPasswordAuth": true,
-
- /*
- * Initial admin user.
- */
- "adminEmail": "",
- "adminPassword": "",
-
- /*
- * Recreate the admin if it does not exist or the password does not match.
- */
- "adminRecreate": false,
-
- /*
- * Client with all admin permissions.
- */
- "adminClientId": "",
- "adminClientSecret": "",
-
- /*
- * The apps which should be visible on the dashboard for the admin.
- */
- "adminApps": [],
-
- /*
- * Settings for Google auth (keep empty to disable).
- */
- "googleClient": "1006817248705-t3lb3ge808m9am4t7upqth79hulk456l.apps.googleusercontent.com",
- "googleSecret": "QsEi-fHqkGw2_PjJmtNHf2wg",
-
- /*
- * Settings for Github auth (keep empty to disable).
- */
- "githubClient": "211ea00e726baf754c78",
- "githubSecret": "d0a0d0fe2c26469ae20987ac265b3a339fd73132",
-
- /*
- * Settings for Microsoft auth (keep empty to disable).
- * Tennant is optional for using a specific AzureAD tenant
- */
- "microsoftClient": "b55da740-6648-4502-8746-b9003f29d5f1",
- "microsoftSecret": "idWbANxNYEF4cB368WXJhjN",
- "microsoftTenant": null,
-
- /*
- * Settings for your custom oidc server.
- */
- "oidcName": "OIDC",
- "oidcAuthority": "",
- "oidcClient": "",
- "oidcSecret": "",
- "oidcMetadataAddress": "",
- "oidcScopes": [
- "email"
- ],
- "oidcResponseType": "id_token", // or "code"
- "oidcGetClaimsFromUserInfoEndpoint": false,
- "oidcOnSignoutRedirectUrl": "",
-
- /*
- * Lock new users automatically, the administrator must unlock them.
- */
- "lockAutomatically": false,
-
- /*
- * The url to you privacy statements, if you host squidex by yourself.
- */
- "privacyUrl": "https://squidex.io/privacy"
- },
-
- "news": {
- /*
- * The app name where the news are stored.
- */
- "appName": "squidex-website",
-
- /*
- * The credentials to the app (Readonly).
- */
- "clientId": "squidex-website:default",
- "clientSecret": "QGgqxd7bDHBTEkpC6fj8sbdPWgZrPrPfr3xzb3LKoec="
- },
-
- "translations": {
- "deepl": {
- /*
- * The deepl api key if you want to support automated translations.
- */
- "authKey": "",
- "mapping": {
- "zh-TW": "zh-TW",
- "zh-CN": "zh-CN"
- }
+
+ "assets": {
+ // The default page size if not specified by a query.
+ "defaultPageSize": 200,
+
+ // The maximum number of items to return for each query.
+ //
+ // Warning: Use pagination and not large number of items.
+ "maxResults": 200,
+
+ // The maximum file size in bytes. Default: 5MB
+ "maxSize": 5242880,
+
+ // True to delete assets recursively.
+ "deleteRecursive": true,
+
+ // True to delete assets files permanently.
+ "deletePermanent": false,
+
+ // The timeout when searching for single items in the database.
+ "timeoutFind": "00:00:01",
+
+ // The timeout when searching for multiple items in the database.
+ "timeoutQuery": "00:00:05",
+
+ // Create one folder per app.
+ //
+ // WARNING: If you change this parameter, previous assets are not available anymore.
+ "folderPerApp": false
+ },
+
+ "logging": {
+ // The log level.
+ //
+ // Trace, Debug, Information, Warning, Error, Fatal
+ "level": "Information",
+
+ // Setting the flag to true, enables well formatteds json logs.
+ "human": true,
+
+ // Set to true, to use colors.
+ "colors": true,
+
+ // Set to false to disable logging of http requests.
+ "logRequests": true,
+
+ // False to disable the log store.
+ "storeEnabled": true,
+
+ // The number of days request log items will be stored.
+ "storeRetentationInDays": 90,
+
+ "stackdriver": {
+ // True, to enable stackdriver integration.
+ "enabled": false
+ },
+
+ "otlp": {
+ // True, to enable OpenTelemetry Protocol integration.
+ "enabled": false,
+
+ // The endpoint to the agent.
+ "endpoint": ""
+ },
+
+ "applicationInsights": {
+ // True, to enable application insights integraon.
+ "enabled": false,
+
+ "connectionString": "InstrumentationKey=[key];IngestionEndpoint=https://[datacenter].in.applicationinsights.azure.com/"
+ }
+ },
+
+ "assetStore": {
+ // Define the type of the read store.
+ //
+ // SUPPORTED: Folder (local folder), MongoDb (GridFS), GoogleCloud (hosted in Google Cloud only), AzureBlob, AmazonS3, FTP (not recommended).
+ "type": "Folder",
+
+ "folder": {
+ // The relative or absolute path to the folder to store the assets.
+ "path": "Assets"
+ },
+ "googleCloud": {
+ // The name of the bucket in google cloud store.
+ "bucket": "squidex-assets"
+ },
+ "azureBlob": {
+ // The name of the container in the Azure Blob Storage
+ "containerName": "squidex-assets",
+
+ // The connection string to the azure storage service.
+ "connectionString": "UseDevelopmentStorage=true"
+ },
+ "amazonS3": {
+ // The url of the S3 API service. Leave it empty if using the one provided by Amazon
+ "serviceUrl": "",
+
+ // The name of your bucket.
+ "bucket": "squidex-test",
+
+ // The optional folder within the bucket.
+ "bucketFolder": "squidex-assets",
+
+ // The region name of your bucket.
+ "regionName": "eu-central-1",
+
+ // The access key for your user.
+ //
+ // Read More: https://supsystic.com/documentation/id-secret-access-key-amazon-s3/
+ "accessKey": "",
+
+ // The secret key for your user.
+ //
+ // Read More: https://supsystic.com/documentation/id-secret-access-key-amazon-s3/
+ "secretKey": "",
+
+ // Force path style property for AmazonS3Config
+ "forcePathStyle": false
+ },
+ "mongoDb": {
+ // The connection string to your Mongo Server.
+ //
+ // Read More: https://docs.mongodb.com/manual/reference/connection-string/
+ "configuration": "mongodb://localhost",
+
+ // The name of the event store database.
+ "database": "SquidexAssets",
+
+ // The name of the Mongo Grid FS bucket.
+ "bucket": "fs"
+ },
+ "ftp": {
+ //The host of the ftp service
+ "serverHost": "",
+
+ //The host of the ftp service
+ "serverPort": "21",
+
+ // Credentials.
+ "username": "",
+ "password": "",
+
+ // The relative or absolute path to the folder to store the assets.
+ "path": "Assets"
+ },
+ // Allow to expose the url in graph ql url.
+ "exposeSourceUrl": false
+ },
+
+ "orleans": {
+ // Define the clustering type.
+ //
+ // SUPPORTED: MongoDB, Development
+ "clustering": "Development",
+
+ // Tell Orleans it is running in kubernetes.
+ //
+ // Read more: https://dotnet.github.io/orleans/docs/deployment/kubernetes.html?q=kubernetes
+ "kubernetes": false,
+
+ // The port is used to share messages between all cluster members. Must be accessible within your cluster or network.
+ "siloPort": "11111",
+
+ // The ports used by Orleans to connect to external clients. Not used.
+ "gatewayPort": "40000",
+
+ // The advertised IP address. Usually not needed.
+ "ipAddress": ""
+ },
+
+ "eventStore": {
+ // Define the type of the event store.
+ //
+ // SUPPORTED: MongoDb
+ "type": "MongoDb",
+
+ "mongoDb": {
+ // The connection string to your Mongo Server.
+ //
+ // Read More: https://docs.mongodb.com/manual/reference/connection-string/
+ "configuration": "mongodb://localhost",
+
+ // The name of the event store database.
+ "database": "Squidex"
+ }
+ },
+
+ "eventPublishers": {
+ // Additional event publishers (advanced usage only): (Name => Config)
+ "allToRabbitMq": {
+ // Example:: Push all events to RabbitMq.
+ "type": "RabbitMq",
+ "configuration": "amqp://guest:guest@localhost/",
+ "exchange": "squidex",
+ "enabled": false,
+ "eventsFilter": ".*"
+ }
+ },
+
+ "store": {
+ // Define the type of the read store.
+ //
+ // SUPPORTED: MongoDb
+ "type": "MongoDb",
+
+ "mongoDb": {
+ // The connection string to your Mongo Server.
+ //
+ // Read More: https://docs.mongodb.com/manual/reference/connection-string/
+ "configuration": "mongodb://localhost",
+
+ // The database for all your content collections (one collection per app).
+ "contentDatabase": "SquidexContent",
+
+ // The database for all your other read collections.
+ "database": "Squidex"
+ }
+ },
+
+ "identity": {
+ // Set to true to show PII (Personally Identifiable Information) in the logs.
+ "showPII": true,
+
+ // Enable password auth. Set this to false if you want to disable local login, leaving only 3rd party login options.
+ "allowPasswordAuth": true,
+
+ // Initial admin user.
+ "adminEmail": "",
+ "adminPassword": "",
+
+ // Recreate the admin if it does not exist or the password does not match.
+ "adminRecreate": false,
+
+ // Client with all admin permissions.
+ "adminClientId": "",
+ "adminClientSecret": "",
+
+ // The apps which should be visible on the dashboard for the admin.
+ "adminApps": [],
+
+ // Settings for Google auth (keep empty to disable).
+ "googleClient": "1006817248705-t3lb3ge808m9am4t7upqth79hulk456l.apps.googleusercontent.com",
+ "googleSecret": "QsEi-fHqkGw2_PjJmtNHf2wg",
+
+ // Settings for Github auth (keep empty to disable).
+ "githubClient": "211ea00e726baf754c78",
+ "githubSecret": "d0a0d0fe2c26469ae20987ac265b3a339fd73132",
+
+ // Settings for Microsoft auth (keep empty to disable).3
+ //
+ // NOTE: Tennant is optional for using a specific AzureAD tenant
+ "microsoftClient": "b55da740-6648-4502-8746-b9003f29d5f1",
+ "microsoftSecret": "idWbANxNYEF4cB368WXJhjN",
+ "microsoftTenant": null,
+
+ // Settings for your custom oidc server.
+ "oidcName": "OIDC",
+ "oidcAuthority": "",
+ "oidcClient": "",
+ "oidcSecret": "",
+ "oidcMetadataAddress": "",
+ "oidcScopes": [
+ "email"
+ ],
+ "oidcResponseType": "id_token", // or "code"
+ "oidcGetClaimsFromUserInfoEndpoint": false,
+ "oidcOnSignoutRedirectUrl": "",
+
+ // Lock new users automatically, the administrator must unlock them.
+ "lockAutomatically": false,
+
+ // The url to you privacy statements, if you host squidex by yourself.
+ "privacyUrl": "https://squidex.io/privacy"
+ },
+
+ "news": {
+ // The app name where the news are stored.
+ "appName": "squidex-website",
+
+ // The credentials to the app (Readonly).
+ "clientId": "squidex-website:default",
+ "clientSecret": "QGgqxd7bDHBTEkpC6fj8sbdPWgZrPrPfr3xzb3LKoec="
+ },
+
+ "translations": {
+ "deepl": {
+ // The deepl api key if you want to support automated translations.
+ "authKey": "",
+ "mapping": {
+ "zh-TW": "zh-TW",
+ "zh-CN": "zh-CN"
+ }
+ },
+
+ "googleCloud": {
+ // The google cloud project id if you want to support automated translations.
+ "projectId": ""
+ }
+ },
+
+ "rebuild": {
+ // Set to true to rebuild apps.
+ "apps": false,
+
+ // Set to true to rebuild assets.
+ "assets": false,
+
+ // Set to true to create dummy asset files if they do not exist. Useful when a backup fail.
+ "assetFiles": false,
+
+ // Set to true to rebuild contents.
+ "contents": false,
+
+ // Set to true to rebuild rules.
+ "rules": false,
+
+ // Set to true to rebuild schemas.
+ "schemas": false,
+
+ // Set to true to rebuild indexes.
+ "indexes": false
+ },
+
+ // A list of configuration values that should be exposed from the info endpoint and in the UI.
+ "exposedConfiguration": {
+ "version": "squidex:version"
+ },
+
+ // Kafka Producer configuration
+ "kafka": {
+ "bootstrapServers": ""
},
- "googleCloud": {
- /*
- * The google cloud project id if you want to support automated translations.
- */
- "projectId": ""
+ // The client information for twitter.
+ "twitter": {
+ "clientId": "QZhb3HQcGCvE6G8yNNP9ksNet",
+ "clientSecret": "Pdu9wdN72T33KJRFdFy1w4urBKDRzIyuKpc0OItQC2E616DuZD"
}
- },
-
- "rebuild": {
- /*
- * Set to true to rebuild apps.
- */
- "apps": false,
-
- /*
- * Set to true to rebuild assets.
- */
- "assets": false,
-
- /*
- * Set to true to create dummy asset files if they do not exist. Useful when a backup fail.
- */
- "assetFiles": false,
-
- /*
- * Set to true to rebuild contents.
- */
- "contents": false,
-
- /*
- * Set to true to rebuild rules.
- */
- "rules": false,
-
- /*
- * Set to true to rebuild schemas.
- */
- "schemas": false,
-
- /*
- * Set to true to rebuild indexes.
- */
- "indexes": false
- },
-
- /*"
- * A list of configuration values that should be exposed from the info endpoint and in the UI.
- */
- "exposedConfiguration": {
- "version": "squidex:version"
- },
-
- /*
- * Kafka Producer configuration
- */
- "kafka": {
- "bootstrapServers": ""
- },
-
- /*
- * The client information for twitter.
- */
- "twitter": {
- "clientId": "QZhb3HQcGCvE6G8yNNP9ksNet",
- "clientSecret": "Pdu9wdN72T33KJRFdFy1w4urBKDRzIyuKpc0OItQC2E616DuZD"
- }
}