Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Omika.Core.Observability;
|
||||
using Omika.Core.Observability.External;
|
||||
using Omika.Core.Observability.Outbox;
|
||||
|
||||
namespace Omika.Tests.Observability.External;
|
||||
|
||||
/// <summary>Liste blanche et filtrage sécurité du mapping externe (§31/§79/§71).</summary>
|
||||
public class OmikaEventExternalMapperTests
|
||||
{
|
||||
[Fact]
|
||||
public void MapsWhitelistFields_AndExcludesIdentity()
|
||||
{
|
||||
var e = new TelemetryEvent
|
||||
{
|
||||
EventCode = TelemetryEventCodes.MobileAppStarted,
|
||||
Level = TelemetryLevel.Warning,
|
||||
Priority = TelemetryPriority.P2,
|
||||
Component = "SyncEngine",
|
||||
TraceId = Guid.NewGuid(),
|
||||
SessionId = Guid.NewGuid(),
|
||||
OperationId = Guid.NewGuid(),
|
||||
AppVersion = "1.2.3",
|
||||
Platform = "Android",
|
||||
ErrorCode = "ERR-1",
|
||||
DurationMs = 123,
|
||||
Success = true,
|
||||
DeviceId = "device-abc",
|
||||
ClientId = "client-1",
|
||||
UserId = "user-1",
|
||||
CollaborateurId = "col-1",
|
||||
EntityId = "entity-1"
|
||||
};
|
||||
|
||||
ExternalLogRecord? record = OmikaEventExternalMapper.ToLogRecord(e);
|
||||
|
||||
Assert.NotNull(record);
|
||||
Assert.Equal(LogLevel.Warning, record.Level);
|
||||
Assert.Equal(TelemetryEventCodes.MobileAppStarted.Value, record.EventCode);
|
||||
Assert.Equal(e.TraceId, record.TraceId);
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "omika.trace_id");
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "omika.session_id");
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "omika.operation_id");
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "component" && (string?)kv.Value == "SyncEngine");
|
||||
|
||||
// Identité métier : JAMAIS exportée (liste blanche externe).
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "omika.device_id");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "userid");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "clientid");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "collaborateurid");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "entityid");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropsForbiddenMetadataKeysAndValues()
|
||||
{
|
||||
var e = new TelemetryEvent
|
||||
{
|
||||
EventCode = TelemetryEventCodes.MobileAppStarted,
|
||||
Metadata = TelemetryMetadata.Create(
|
||||
("ok_key", "safe-value"),
|
||||
("password", "hunter2"),
|
||||
("Authorization", "Bearer secret"),
|
||||
("connectionString", "Server=..." ),
|
||||
("note", "contains token here"))
|
||||
};
|
||||
|
||||
ExternalLogRecord? record = OmikaEventExternalMapper.ToLogRecord(e);
|
||||
|
||||
Assert.NotNull(record);
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "ok_key");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "password");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "Authorization");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "connectionString");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "note");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReturnsNullForInvalidEvent()
|
||||
{
|
||||
Assert.Null(OmikaEventExternalMapper.ToLogRecord((OmikaEvent?)null));
|
||||
|
||||
// EventCode invalide (défaut) → événement non mappable.
|
||||
var e = new TelemetryEvent();
|
||||
Assert.Null(OmikaEventExternalMapper.ToLogRecord(e));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogLevelMapping_IsDeterministic()
|
||||
{
|
||||
Assert.Equal(LogLevel.Trace, OmikaEventExternalMapper.ToLogLevel(TelemetryLevel.Trace));
|
||||
Assert.Equal(LogLevel.Debug, OmikaEventExternalMapper.ToLogLevel(TelemetryLevel.Debug));
|
||||
Assert.Equal(LogLevel.Information, OmikaEventExternalMapper.ToLogLevel(TelemetryLevel.Info));
|
||||
Assert.Equal(LogLevel.Warning, OmikaEventExternalMapper.ToLogLevel(TelemetryLevel.Warning));
|
||||
Assert.Equal(LogLevel.Error, OmikaEventExternalMapper.ToLogLevel(TelemetryLevel.Error));
|
||||
Assert.Equal(LogLevel.Critical, OmikaEventExternalMapper.ToLogLevel(TelemetryLevel.Critical));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapsDto_WithWhitelist()
|
||||
{
|
||||
var dto = new DiagnosticEventDto
|
||||
{
|
||||
EventId = Guid.NewGuid(),
|
||||
EventCode = "OMK-MOB-SYNC-001",
|
||||
TimestampUtc = DateTimeOffset.UtcNow,
|
||||
Level = "Error",
|
||||
Priority = "P1",
|
||||
Component = "MobileSync",
|
||||
TraceId = Guid.NewGuid(),
|
||||
SessionId = Guid.NewGuid(),
|
||||
DeviceId = "device-abc",
|
||||
ClientId = "client-1",
|
||||
ErrorCode = "ERR-X",
|
||||
Metadata = new Dictionary<string, object?> { ["k"] = "v", ["password"] = "secret" }
|
||||
};
|
||||
|
||||
ExternalLogRecord? record = OmikaEventExternalMapper.ToLogRecord(dto);
|
||||
|
||||
Assert.NotNull(record);
|
||||
Assert.Equal(LogLevel.Error, record.Level);
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "omika.trace_id");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "deviceid");
|
||||
Assert.DoesNotContain(record.Attributes, kv => kv.Key == "password");
|
||||
Assert.Contains(record.Attributes, kv => kv.Key == "k");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user