using System.Reflection; using Omika.Core.Observability; namespace Omika.Tests.Observability.External; /// /// Garde-fous d'architecture de la Phase 5 (§8/§9/§65/§66/§72) : les packages /// OpenTelemetry sont localisés UNIQUEMENT dans le projet infrastructure dédié /// (Omika.Observability.External), jamais dans Core ni dans le métier (App / /// App.Local / Data). Vérifications par réflexion sur les assemblies référencées. /// public class ExternalArchitectureTests { [Fact] public void Core_DoesNotReferenceOpenTelemetry() { Assembly core = typeof(OmikaEvent).Assembly; Assert.DoesNotContain(core.GetReferencedAssemblies(), a => a.Name!.Contains("OpenTelemetry")); Assert.DoesNotContain( core.GetTypes(), t => (t.FullName ?? "").Contains("OpenTelemetry", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("Otlp", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("SigNoz", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("ClickHouse", StringComparison.OrdinalIgnoreCase)); } [Theory] [InlineData("Omika.App")] [InlineData("Omika.App.Local")] [InlineData("Omika.Data")] public void BusinessAssemblies_DoNotReferenceExternalObservabilityInfrastructure(string assemblyName) { Assembly asm = Assembly.Load(assemblyName); Assert.DoesNotContain(asm.GetReferencedAssemblies(), a => a.Name!.Contains("OpenTelemetry") || a.Name!.Contains("SigNoz") || a.Name!.Contains("ClickHouse")); Assert.DoesNotContain( asm.GetTypes(), t => (t.FullName ?? "").Contains("OpenTelemetry", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("Otlp", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("SigNoz", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("ClickHouse", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("ActivitySource", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("TracerProvider", StringComparison.OrdinalIgnoreCase)); } [Fact] public void TrackAndLog_Path_ExposesOnlyVoidMethods_NoNetwork() { // Le chemin Track()/Log() du métier reste strictement void (never-throw, // non bloquant, sans réseau) : le réseau OTel est DERRIÈRE le TelemetryWorker. foreach (MethodInfo method in typeof(IOmikaTelemetry).GetMethods() .Concat(typeof(IEventTracker).GetMethods()) .Concat(typeof(IDiagnosticLogger).GetMethods())) { Assert.Equal(typeof(void), method.ReturnType); } } }