-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sure stdout-loglevel setting is honored through the whole actor system lifecycle #5251
Changes from all commits
0289b2b
3f962db
a2e2505
b36f917
38b93b2
a444df7
135ec8b
ba1d0d4
16db579
086a2bf
bdcb56d
bf5ea5a
926aab3
42d5d59
a09a755
c1a739a
fd223c3
52d5b3c
7babaf3
541d9dd
8e196c9
2108dfe
783d192
0d24266
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
// </copyright> | ||
//----------------------------------------------------------------------- | ||
|
||
using System; | ||
using Akka.Actor; | ||
using Akka.Event; | ||
using Xunit.Abstractions; | ||
|
@@ -16,20 +17,44 @@ namespace Akka.TestKit.Xunit.Internals | |
/// </summary> | ||
public class TestOutputLogger : ReceiveActor | ||
{ | ||
private readonly ITestOutputHelper _output; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="TestOutputLogger"/> class. | ||
/// </summary> | ||
/// <param name="output">The provider used to write test output.</param> | ||
public TestOutputLogger(ITestOutputHelper output) | ||
{ | ||
Receive<Debug>(e => output.WriteLine(e.ToString())); | ||
Receive<Info>(e => output.WriteLine(e.ToString())); | ||
Receive<Warning>(e => output.WriteLine(e.ToString())); | ||
Receive<Error>(e => output.WriteLine(e.ToString())); | ||
_output = output; | ||
|
||
Receive<Debug>(Write); | ||
Receive<Info>(Write); | ||
Receive<Warning>(Write); | ||
Receive<Error>(Write); | ||
Receive<InitializeLogger>(e => | ||
{ | ||
e.LoggingBus.Subscribe(Self, typeof (LogEvent)); | ||
}); | ||
} | ||
|
||
private void Write(LogEvent e) | ||
{ | ||
try | ||
{ | ||
_output.WriteLine(e.ToString()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add missing format exception catcher to Akka.TestKit.Xunit that was added to Akka.TestKit.Xunit2 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM |
||
} | ||
catch (FormatException ex) | ||
{ | ||
if (e.Message is LogMessage msg) | ||
{ | ||
var message = | ||
$"Received a malformed formatted message. Log level: [{e.LogLevel()}], Template: [{msg.Format}], args: [{string.Join(",", msg.Args)}]"; | ||
if(e.Cause != null) | ||
throw new AggregateException(message, ex, e.Cause); | ||
throw new FormatException(message, ex); | ||
} | ||
throw; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,57 +30,65 @@ public class TestEventListener : DefaultLogger | |
/// <returns>TBD</returns> | ||
protected override bool Receive(object message) | ||
{ | ||
if(message is InitializeLogger) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change if...then...else structure to switch |
||
switch (message) | ||
{ | ||
var initLogger = (InitializeLogger)message; | ||
var bus = initLogger.LoggingBus; | ||
var self = Context.Self; | ||
bus.Subscribe(self, typeof(Mute)); | ||
bus.Subscribe(self, typeof(Unmute)); | ||
bus.Subscribe(self, typeof(DeadLetter)); | ||
bus.Subscribe(self, typeof(UnhandledMessage)); | ||
Sender.Tell(new LoggerInitialized()); | ||
} | ||
else if(message is Mute) | ||
{ | ||
var mute = (Mute)message; | ||
foreach(var filter in mute.Filters) | ||
case InitializeLogger initLogger: | ||
{ | ||
AddFilter(filter); | ||
base.Receive(message); | ||
var bus = initLogger.LoggingBus; | ||
var self = Context.Self; | ||
bus.Subscribe(self, typeof(Mute)); | ||
bus.Subscribe(self, typeof(Unmute)); | ||
bus.Subscribe(self, typeof(DeadLetter)); | ||
bus.Subscribe(self, typeof(UnhandledMessage)); | ||
Sender.Tell(new LoggerInitialized()); | ||
break; | ||
} | ||
} | ||
else if(message is Unmute) | ||
{ | ||
var unmute = (Unmute)message; | ||
foreach(var filter in unmute.Filters) | ||
case Mute mute: | ||
{ | ||
RemoveFilter(filter); | ||
foreach(var filter in mute.Filters) | ||
{ | ||
AddFilter(filter); | ||
} | ||
|
||
break; | ||
} | ||
} | ||
else if(message is LogEvent) | ||
{ | ||
var logEvent = (LogEvent)message; | ||
if(!ShouldFilter(logEvent)) | ||
case Unmute unmute: | ||
{ | ||
Print(logEvent); | ||
foreach(var filter in unmute.Filters) | ||
{ | ||
RemoveFilter(filter); | ||
} | ||
|
||
break; | ||
} | ||
case LogEvent logEvent: | ||
{ | ||
if(!ShouldFilter(logEvent)) | ||
{ | ||
Print(logEvent); | ||
} | ||
|
||
break; | ||
} | ||
case DeadLetter letter: | ||
HandleDeadLetter(letter); | ||
break; | ||
|
||
case UnhandledMessage un: | ||
{ | ||
var rcp = un.Recipient; | ||
var warning = new Warning(rcp.Path.ToString(), rcp.GetType(), "Unhandled message from " + un.Sender + ": " + un.Message); | ||
if(!ShouldFilter(warning)) | ||
Print(warning); | ||
break; | ||
} | ||
|
||
default: | ||
Print(new Debug(Context.System.Name,GetType(),message)); | ||
break; | ||
} | ||
else if(message is DeadLetter) | ||
{ | ||
HandleDeadLetter((DeadLetter)message); | ||
} | ||
else if(message is UnhandledMessage) | ||
{ | ||
var un = (UnhandledMessage) message; | ||
var rcp = un.Recipient; | ||
var warning = new Warning(rcp.Path.ToString(), rcp.GetType(), "Unhandled message from " + un.Sender + ": " + un.Message); | ||
if(!ShouldFilter(warning)) | ||
Print(warning); | ||
} | ||
else | ||
{ | ||
Print(new Debug(Context.System.Name,GetType(),message)); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// //----------------------------------------------------------------------- | ||
// // <copyright file="ShutdownLoggerSpec.cs" company="Akka.NET Project"> | ||
// // Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com> | ||
// // Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net> | ||
// // </copyright> | ||
// //----------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Threading.Tasks; | ||
using Akka.Actor; | ||
using Akka.Configuration; | ||
using Akka.Event; | ||
using Akka.TestKit; | ||
using FluentAssertions; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
|
||
namespace Akka.Tests.Loggers | ||
{ | ||
public class ShutdownLoggerSpec: AkkaSpec | ||
{ | ||
private static readonly Config Config = ConfigurationFactory.ParseString(@" | ||
akka.loglevel = OFF | ||
akka.stdout-loglevel = OFF | ||
akka.stdout-logger-class = ""Akka.Tests.Loggers.ThrowingLogger, Akka.Tests"""); | ||
|
||
public ShutdownLoggerSpec(ITestOutputHelper output) : base(Config, output) | ||
{ | ||
} | ||
|
||
[Fact(DisplayName = "StandardOutLogger should not be called on shutdown when stdout-loglevel is set to OFF")] | ||
public async Task StandardOutLoggerShouldNotBeCalled() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM |
||
{ | ||
Sys.Settings.StdoutLogger.Should().BeOfType<ThrowingLogger>(); | ||
|
||
var probeRef = Sys.ActorOf(Props.Create(() => new LogProbe())); | ||
probeRef.Tell(new InitializeLogger(Sys.EventStream)); | ||
var probe = await probeRef.Ask<LogProbe>("hey"); | ||
|
||
await Sys.Terminate(); | ||
|
||
await Task.Delay(RemainingOrDefault); | ||
if (probe.Events.Any(o => o is Error err && err.Cause is ShutdownLogException)) | ||
throw new Exception("Test failed, log should not be called after shutdown."); | ||
} | ||
} | ||
|
||
internal class LogProbe : ReceiveActor | ||
{ | ||
public List<LogEvent> Events { get; } = new List<LogEvent>(); | ||
|
||
public LogProbe() | ||
{ | ||
Receive<string>(msg => Sender.Tell(this)); | ||
Receive<LogEvent>(Events.Add); | ||
Receive<InitializeLogger>(e => | ||
{ | ||
e.LoggingBus.Subscribe(Self, typeof (LogEvent)); | ||
Sender.Tell(new LoggerInitialized()); | ||
}); | ||
|
||
} | ||
} | ||
|
||
internal class ShutdownLogException : Exception | ||
{ | ||
public ShutdownLogException() | ||
{ } | ||
|
||
public ShutdownLogException(string msg) : base(msg) | ||
{ } | ||
} | ||
|
||
internal class ThrowingLogger : MinimalLogger | ||
{ | ||
protected override void Log(object message) | ||
{ | ||
throw new ShutdownLogException("This logger should never be called."); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably need to do more showing rather than telling here, but this is good for now