public void WhenConcurrentEventsRaised() { var logger = MockEventSourceOutProc.Logger; EventTextFormatter formatter = new EventTextFormatter(); EventSourceSettings settings = new EventSourceSettings("MockEventSourceOutProc", null, EventLevel.LogAlways); InMemorySink sink = new InMemorySink(formatter); SinkSettings sinkSettings = new SinkSettings("memorySink", sink, new List <EventSourceSettings>() { { settings } }); List <SinkSettings> sinks = new List <SinkSettings>() { { sinkSettings } }; TraceEventServiceConfiguration svcConfiguration = new TraceEventServiceConfiguration(sinks); TestScenario.WithConfiguration( svcConfiguration, () => { sink.WaitSignalCondition = () => sink.EventWrittenCount == 100; for (int n = 0; n < 100; n++) { logger.LogSomeMessage("some message" + n.ToString()); } sink.WaitOnAsyncEvents.WaitOne(TimeSpan.FromSeconds(10)); }); StringAssert.Contains(sink.ToString(), "some message99"); }
/// <summary> /// Initializes a new instance of the <see cref="TestApiServer"/> class. /// </summary> /// <param name="logSink">The Serilog destination logging sink.</param> /// <param name="configureServices">The action to populate the required services in the current hosted test server.</param> /// <param name="outputWriter">The logger instance to write log messages during the lifetime of the test server.</param> /// <exception cref="ArgumentNullException">When the <paramref name="logSink"/> is <c>null</c>.</exception> public TestApiServer(InMemorySink logSink, Action <IServiceCollection> configureServices, ITestOutputHelper outputWriter) { Guard.NotNull(logSink, nameof(logSink), "Requires a log sink to write the log messages to"); _configureServices = new Collection <Action <IServiceCollection> > { services => services.AddSingleton(logSink) }; _filterActions = new Collection <Action <FilterCollection> >(); _configures = new Collection <Action <IApplicationBuilder> >(); _configurationCollection = new Dictionary <string, string>(); if (configureServices != null) { _configureServices.Add(configureServices); } if (outputWriter is null) { _logger = NullLogger.Instance; } else { _logger = new XunitTestLogger(outputWriter); } LogSink = logSink; }
public async Task SharedAccessKeyAuthorizedRoute_DoesntEmitSecurityEventsByDefault_RunsAuthentication() { // Arrange var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => services.AddSecretStore(stores => stores.AddInMemory(SecretName, $"secret-{Guid.NewGuid()}"))) .ConfigureHost(host => host.UseSerilog((context, config) => config.WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { var request = HttpRequestBuilder.Get(SharedAccessKeyAuthenticationController.AuthorizedGetRoute); // Act using (HttpResponseMessage response = await server.SendAsync(request)) { // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); IEnumerable <LogEvent> logEvents = spySink.DequeueLogEvents(); Assert.DoesNotContain(logEvents, logEvent => { string message = logEvent.RenderMessage(); return(message.Contains("EventType") && message.Contains("Security")); }); } } }
public async Task SharedAccessKeyAuthorizedRoute_EmitsSecurityEventsWhenRequested_RunsAuthentication(bool emitsSecurityEvents) { // Arrange var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => { services.AddSecretStore(stores => stores.AddInMemory(SecretName, $"secret-{Guid.NewGuid()}")) .AddMvc(opt => opt.Filters.AddSharedAccessKeyAuthenticationOnHeader(HeaderName, SecretName, authOptions => { authOptions.EmitSecurityEvents = emitsSecurityEvents; })); }) .ConfigureHost(host => host.UseSerilog((context, config) => config.WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { var request = HttpRequestBuilder.Get(HealthController.GetRoute); // Act using (HttpResponseMessage response = await server.SendAsync(request)) { // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); IEnumerable <LogEvent> logEvents = spySink.DequeueLogEvents(); Assert.True(emitsSecurityEvents == logEvents.Any(logEvent => { string message = logEvent.RenderMessage(); return(message.Contains("EventType") && message.Contains("Security")); })); } } }
public void WhenNoLoggerIsSpecified_LoggingShouldGoToAutodiscoveredLogger() { var defaultLogger = Serilog.Log.Logger; try { var capturedLogs = new InMemorySink(); Serilog.Log.Logger = new Serilog.LoggerConfiguration() .WriteTo.Sink(capturedLogs) .CreateLogger(); var engine = DeployChanges.To .SQLiteDatabase("Data Source=:memory:") .WithScript(new SqlScript("1234", "SELECT 1")) .JournalTo(new NullJournal()) .Build(); var result = engine.PerformUpgrade(); result.Successful.ShouldBe(true); capturedLogs.Events.ShouldContain(e => e.MessageTemplate.Text == "Executing Database Server script '{0}'"); } finally { Serilog.Log.Logger = defaultLogger; } }
public async Task SendRequest_WithSerilogCorrelationEnrichment_ReturnsOkWithEnrichedCorrelationLogProperties() { // Arrange var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => services.AddHttpCorrelation()) .PreConfigure(app => app.UseHttpCorrelation()) .ConfigureHost(host => host.UseSerilog((context, serviceProvider, config) => config.Enrich.WithHttpCorrelationInfo(serviceProvider) .WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { var request = HttpRequestBuilder.Get(CorrelationController.GetRoute); // Act using (HttpResponseMessage response = await server.SendAsync(request)) { // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); CorrelationInfo correlationInfo = await AssertAppCorrelationInfoAsync(response); AssertLoggedCorrelationProperties(spySink, correlationInfo); } } }
public async Task JwtAuthorizedRoute_EmitSecurityEventsWhenRequested_RunsAuthorization(bool emitSecurityEvents) { // Arrange var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => { services.AddMvc(opt => opt.Filters.AddJwtTokenAuthorization(jwt => jwt.EmitSecurityEvents = emitSecurityEvents)); }) .ConfigureHost(host => host.UseSerilog((context, config) => config.WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { string accessToken = $"Bearer {_bogusGenerator.Random.AlphaNumeric(10)}.{_bogusGenerator.Random.AlphaNumeric(50)}"; var request = HttpRequestBuilder .Get(HealthController.GetRoute) .WithHeader(JwtTokenAuthorizationOptions.DefaultHeaderName, accessToken); // Act using (HttpResponseMessage response = await server.SendAsync(request)) { // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); IEnumerable <LogEvent> logEvents = spySink.DequeueLogEvents(); Assert.True(emitSecurityEvents == logEvents.Any(logEvent => { string message = logEvent.RenderMessage(); return(message.Contains("EventType") && message.Contains("Security")); })); } } }
public void WhenConcurrentEventsRaised() { var logger = MockEventSourceOutProc.Logger; EventTextFormatter formatter = new EventTextFormatter(); EventSourceSettings settings = new EventSourceSettings("MockEventSourceOutProc", null, EventLevel.LogAlways); InMemorySink sink = new InMemorySink(formatter); SinkSettings sinkSettings = new SinkSettings("memorySink", sink, new List<EventSourceSettings>() { { settings } }); List<SinkSettings> sinks = new List<SinkSettings>() { { sinkSettings } }; TraceEventServiceConfiguration svcConfiguration = new TraceEventServiceConfiguration(sinks); TestScenario.WithConfiguration( svcConfiguration, () => { sink.WaitSignalCondition = () => sink.EventWrittenCount == 100; for (int n = 0; n < 100; n++) { logger.LogSomeMessage("some message" + n.ToString()); } sink.WaitOnAsyncEvents.WaitOne(TimeSpan.FromSeconds(10)); }); StringAssert.Contains(sink.ToString(), "some message99"); }
internal void OnEtlFileReadStart(string fileName, bool isActiveEtl, string currentBookmark) { // Trace file subfolder to write bookmarks to this.traceFileSubFolder = this.GetTraceFileSubFolder(fileName); // Reset the last event index this.lastEventIndex.Set(DateTime.MinValue, -1); // Get the index up to which we have already processed. this.maxIndexAlreadyProcessed = this.GetMaxIndexAlreadyProcessed(this.traceFileSubFolder); // Create a new in-memory sink. this.inMemorySink = new InMemorySink( this.TraceSource, this.LogSourceId, this.traceFileSubFolder, this.inMemoryConsumer.ConsumerProcessTraceEventAction); // Signal start of processing to consumer this.inMemoryConsumer.OnProcessingPeriodStart(fileName, isActiveEtl, this.traceFileSubFolder); this.TraceSource.WriteInfo( this.LogSourceId, "Filtered traces from {0} will be written to an in-memory buffer.", fileName); }
public void WhenWriting_WriteToMemory() { var sink = new InMemorySink(new CompactKeyValueFormatter(), () => new DefaultDataRenderer()) { AppendNewLine = false }; sink.Write(GenericLogLevelName.Debug, GenericLogEntries); Assert.Equal(GenericLogText, sink.GetLogs().Substring(30)); }
/// <summary> /// Initializes a new instance of the <see cref="TestApiServer"/> class. /// </summary> /// <param name="logSink">The Serilog destination logging sink.</param> /// <param name="configureServices">The action to populate the required services in the current hosted test server.</param> /// <exception cref="ArgumentNullException">When the <paramref name="configureServices"/> is <c>null</c>.</exception> public TestApiServer(InMemorySink logSink, Action <IServiceCollection> configureServices) { Guard.NotNull(configureServices, "Configure services cannot be 'null'"); _configureServices = new Collection <Action <IServiceCollection> > { configureServices, services => services.AddSingleton(logSink) }; _filterActions = new Collection <Action <FilterCollection> >(); _configures = new Collection <Action <IApplicationBuilder> >(); _configurationCollection = new Dictionary <string, string>(); LogSink = logSink; }
public MainWindow() { InitializeComponent(); // Setup logging var sink = new InMemorySink(tbLog); Log.Logger = new LoggerConfiguration() .WriteTo.Sink(sink) .CreateLogger(); Log.Information("Cirilla v" + Assembly.GetExecutingAssembly().GetName().Version); Log.Information("Cirilla.Core v" + Assembly.GetAssembly(typeof(Core.Models.GMD)).GetName().Version); }
private static void AssertLoggedCorrelationProperties(InMemorySink testSink, CorrelationInfo correlationInfo) { KeyValuePair <string, LogEventPropertyValue>[] properties = testSink.DequeueLogEvents() .SelectMany(ev => ev.Properties) .ToArray(); Assert.Contains( properties.Where(prop => prop.Key == TransactionIdPropertyName), prop => correlationInfo.TransactionId == prop.Value.ToStringValue()); Assert.Contains( properties.Where(prop => prop.Key == OperationIdPropertyName), prop => correlationInfo.OperationId == prop.Value.ToStringValue()); }
public async Task SharedAccessKeyAuthorizedRoute_EmitsSecurityEventsWhenRequested_RunsAuthentication(bool emitsSecurityEvents) { // Arrange const string issuerKey = "issuer"; var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => { var certificateValidator = new CertificateAuthenticationValidator( new CertificateAuthenticationConfigBuilder() .WithIssuer(X509ValidationLocation.SecretProvider, issuerKey) .Build()); services.AddSecretStore(stores => stores.AddInMemory(issuerKey, "CN=issuer")) .AddSingleton(certificateValidator) .AddMvc(opt => opt.Filters.AddCertificateAuthentication(authOptions => { authOptions.EmitSecurityEvents = emitsSecurityEvents; })); }) .ConfigureHost(host => host.UseSerilog((context, config) => config.WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { var request = HttpRequestBuilder.Get(NoneAuthenticationController.GetRoute); // Act using (HttpResponseMessage response = await server.SendAsync(request)) { // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); IEnumerable <LogEvent> logEvents = spySink.DequeueLogEvents(); Assert.True(emitsSecurityEvents == logEvents.Any(logEvent => { string message = logEvent.RenderMessage(); return(message.Contains("EventType") && message.Contains("Security")); })); } } }
private void SetupSeriLog() { // Create Local Log Directory FileIO.CreateDirectory(GetLocalLogDir()); var testSink = new InMemorySink(); var logWindow = new LogWindowSink(richTextBoxLogWindow); string fileName = $@"{GetLocalLogDir()}\app-releaser" + "-{Date}.txt"; Log.Logger = new LoggerConfiguration() .WriteTo.Sink(testSink) .WriteTo.Sink(logWindow) .WriteTo.RollingFile(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}", pathFormat: fileName) .CreateLogger(); Log.Information("Application Starting Up."); Log.Information("SeriLog Setup."); }
public async Task CertificateAuthorizedRoute_EmitsSecurityEventsWhenRequested_RunsAuthentication() { // Arrange using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithSubject("unrecognized-subject-name")) { var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => { var certificateValidator = new CertificateAuthenticationValidator( new CertificateAuthenticationConfigBuilder() .WithSubject(X509ValidationLocation.SecretProvider, SubjectKey) .Build()); services.AddSecretStore(stores => stores.AddInMemory(SubjectKey, "CN=subject")) .AddClientCertificate(clientCertificate) .AddSingleton(certificateValidator); }) .ConfigureHost(host => host.UseSerilog((context, config) => config.WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { var request = HttpRequestBuilder.Get(CertificateAuthenticationOnMethodController.AuthorizedGetRouteEmitSecurityEvents); // Act using (HttpResponseMessage response = await server.SendAsync(request)) { // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); IEnumerable <LogEvent> logEvents = spySink.DequeueLogEvents(); Assert.Contains(logEvents, logEvent => { string message = logEvent.RenderMessage(); return(message.Contains("EventType") && message.Contains("Security")); }); } } } }
public LighthouseViewModel( Db db, ILogger logger, InMemorySink inMemmorySink, IWatchBuilds buildsWatcher, IControlBuildStatusLight buildStatusLightController, IControlSignalLight signalLightController) { _db = db; _logger = logger; _inMemorySink = inMemmorySink; _inMemorySink.Events.CollectionChanged += LogEventsCollectionChangedHandler; _buildsWatcher = buildsWatcher; _buildStatusLightController = buildStatusLightController; _signalLightController = signalLightController; IsRunning = false; ButtonText = "Start"; LighthouseSettings = GetSettings(); SetValidationRules(); StartStopLighthouse = ReactiveCommand.Create(OnStartStopClick, this.IsValid()); }
public async Task SendRequest_WithSerilogCorrelationenrichment_ReturnsOkWithDifferentOperationIdAndSameTransactionId() { // Arrange var spySink = new InMemorySink(); var options = new TestApiServerOptions() .ConfigureServices(services => services.AddHttpCorrelation()) .PreConfigure(app => app.UseHttpCorrelation()) .ConfigureHost(host => host.UseSerilog((context, serviceProvider, config) => config.Enrich.WithHttpCorrelationInfo(serviceProvider) .WriteTo.Sink(spySink))); await using (var server = await TestApiServer.StartNewAsync(options, _logger)) { var firstRequest = HttpRequestBuilder.Get(CorrelationController.GetRoute); using (HttpResponseMessage firstResponse = await server.SendAsync(firstRequest)) { // Assert Assert.Equal(HttpStatusCode.OK, firstResponse.StatusCode); CorrelationInfo firstCorrelationInfo = await AssertAppCorrelationInfoAsync(firstResponse); AssertLoggedCorrelationProperties(spySink, firstCorrelationInfo); var secondRequest = HttpRequestBuilder .Get(CorrelationController.GetRoute) .WithHeader("X-Transaction-ID", firstCorrelationInfo.TransactionId); using (HttpResponseMessage secondResponse = await server.SendAsync(secondRequest)) { Assert.Equal(HttpStatusCode.OK, secondResponse.StatusCode); CorrelationInfo secondCorrelationInfo = await AssertAppCorrelationInfoAsync(secondResponse); AssertLoggedCorrelationProperties(spySink, secondCorrelationInfo); Assert.NotEqual(firstCorrelationInfo.OperationId, secondCorrelationInfo.OperationId); Assert.Equal(firstCorrelationInfo.TransactionId, secondCorrelationInfo.TransactionId); } } } }
public void AssertionShouldNotFailWhenInstanceIsLoggedToAfterInvokingTheAssertion() { /* * This test is meant to verify the behaviour of the assertions * when a message is logged to the instance we're asserting on * after we invoked the assertion. * * The behaviour is that when calling Should(), the assertion * should (pun intended) capture a snapshot of the log events * at the point in time it was invoked. * * This prevents InvalidOperationExceptions because the internal * collection is modified. * * See https://github.com/sandermvanvliet/SerilogSinksInMemory/issues/16 */ var sink = new InMemorySink(); var logger = new LoggerConfiguration() .WriteTo.Sink(sink) .CreateLogger(); // Log 2 messages logger.Information("Message"); logger.Information("Message"); // Start assertion var assertion = sink.Should(); // Pretend another thread/task/fiber logs another message logger.Information("Message"); // Continue with the assertion assertion .HaveMessage("Message") .Appearing().Times(2); }
public static InMemorySinkAssertions Should(this InMemorySink instance) { return(new InMemorySinkAssertions(instance)); }