diff --git a/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn.Test/SentryDsnAssemblyMetadataTests.cs b/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn.Test/SentryDsnAssemblyMetadataTests.cs
new file mode 100644
index 00000000..68b102f9
--- /dev/null
+++ b/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn.Test/SentryDsnAssemblyMetadataTests.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using NUnit.Framework;
+
+namespace ItemsPlanning.Pn.Test
+{
+ ///
+ /// The API host routes this plugin's Sentry events to the plugin's own project, which it finds through
+ /// [assembly: AssemblyMetadata("SentryDsn", ...)] on the plugin assembly (an
+ /// AssemblyMetadata item in the csproj). Only the shape is asserted; the value lives in the csproj.
+ ///
+ [TestFixture]
+ public class SentryDsnAssemblyMetadataTests
+ {
+ [Test]
+ public void PluginAssembly_DeclaresExactlyOneWellFormedSentryDsn()
+ {
+ var values = typeof(EformItemsPlanningPlugin).Assembly
+ .GetCustomAttributes()
+ .Where(x => x.Key == "SentryDsn")
+ .Select(x => x.Value)
+ .ToList();
+
+ Assert.That(values, Has.Count.EqualTo(1), "exactly one SentryDsn assembly metadata value");
+ Assert.That(Uri.TryCreate(values[0], UriKind.Absolute, out var dsn), Is.True, "absolute URI");
+ Assert.That(dsn!.Scheme, Is.EqualTo(Uri.UriSchemeHttps));
+ Assert.That(dsn.UserInfo, Is.Not.Empty, "public key in the user info");
+ Assert.That(dsn.AbsolutePath.Trim('/'), Does.Match(@"^\d+$"), "numeric project id as the path");
+ Assert.That(dsn.Host, Does.Match(@"^o\d+\.ingest(\.[a-z]+)?\.sentry\.io$"), "sentry.io ingest host");
+ }
+ }
+}
diff --git a/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/EformItemsPlanningPlugin.cs b/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/EformItemsPlanningPlugin.cs
index 0c0ac1e1..fed60a2e 100644
--- a/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/EformItemsPlanningPlugin.cs
+++ b/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/EformItemsPlanningPlugin.cs
@@ -121,28 +121,38 @@ public void ConfigureOptionsServices(
configuration.GetSection("ItemsPlanningBaseSettings"));
}
+ // Declared once, as in the csproj: the API host reads the
+ // same assembly metadata to route this plugin's events to its own Sentry project.
+ private static string SentryDsn =>
+ typeof(EformItemsPlanningPlugin).Assembly
+ .GetCustomAttributes()
+ .FirstOrDefault(x => x.Key == "SentryDsn")?.Value;
+
public void ConfigureDbContext(IServiceCollection services, string connectionString)
{
- SentrySdk.Init(options =>
+ if (!string.IsNullOrWhiteSpace(SentryDsn))
{
- // A Sentry Data Source Name (DSN) is required.
- // See https://docs.sentry.io/product/sentry-basics/dsn-explainer/
- // You can set it in the SENTRY_DSN environment variable, or you can set it in code here.
- options.Dsn = "https://d188dc3ab45515b062955aa299bec1dc@o4506241219428352.ingest.us.sentry.io/4508266878664704";
-
- // When debug is enabled, the Sentry client will emit detailed debugging information to the console.
- // This might be helpful, or might interfere with the normal operation of your application.
- // We enable it here for demonstration purposes when first trying Sentry.
- // You shouldn't do this in your applications unless you're troubleshooting issues with Sentry.
- options.Debug = false;
-
- // This option is recommended. It enables Sentry's "Release Health" feature.
- options.AutoSessionTracking = true;
-
- // This option is recommended for client applications only. It ensures all threads use the same global scope.
- // If you're writing a background service of any kind, you should remove this.
- options.IsGlobalModeEnabled = true;
- });
+ SentrySdk.Init(options =>
+ {
+ // A Sentry Data Source Name (DSN) is required.
+ // See https://docs.sentry.io/product/sentry-basics/dsn-explainer/
+ // You can set it in the SENTRY_DSN environment variable, or you can set it in code here.
+ options.Dsn = SentryDsn;
+
+ // When debug is enabled, the Sentry client will emit detailed debugging information to the console.
+ // This might be helpful, or might interfere with the normal operation of your application.
+ // We enable it here for demonstration purposes when first trying Sentry.
+ // You shouldn't do this in your applications unless you're troubleshooting issues with Sentry.
+ options.Debug = false;
+
+ // This option is recommended. It enables Sentry's "Release Health" feature.
+ options.AutoSessionTracking = true;
+
+ // This option is recommended for client applications only. It ensures all threads use the same global scope.
+ // If you're writing a background service of any kind, you should remove this.
+ options.IsGlobalModeEnabled = true;
+ });
+ }
string pattern = @"Database=(\d+)_eform-angular-items-planning-plugin;";
Match match = Regex.Match(connectionString!, pattern);
diff --git a/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/ItemsPlanning.Pn.csproj b/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/ItemsPlanning.Pn.csproj
index 8039fc77..7f2128b9 100644
--- a/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/ItemsPlanning.Pn.csproj
+++ b/eFormAPI/Plugins/ItemsPlanning.Pn/ItemsPlanning.Pn/ItemsPlanning.Pn.csproj
@@ -17,6 +17,10 @@
true
+
+
+
+