I've got a simple C# program with the following log4net configuration:
<log4net>
<appender name="stdout" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%%-5level - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="stdout" />
</root>
</log4net>
And the following code (abbreviated for clarity):
public static void Main(String[] args)
{
var log = LogManager.GetLogger("Logger");
log.Info("Hello From Logger");
Console.WriteLine("Hello From Console");
}
I'm compiling and running this using .NET 4.5 mono on an Ubuntu 16.04 system. When I run the program using the console the output is as expected:
$ mono Program.exe
INFO - Hello From Logger
Hello From Console
However, when I run this same program in a Docker container in detached mode (i.e, "docker run -d") and then check the logs, I only get the log from the Console.WriteLine:
$ docker logs <container_id>
Hello From Console
While trying to track this down, I tried running the program using the daemonize tool (more info here) and it illustrated the same behavior, leading me to believe it was an issue with log4net instead of docker. I also wrote a custom appender for log4net that only does Console.Write (I believe that's the same functionality as ConsoleAppender, but I wanted to eliminate any other possible variables):
public class CustomAppender: AppenderSkeleton
{
protected override void Append(LoggingEvent loggingEvent)
{
Console.Write(RenderLoggingEvent(loggingEvent));
}
}
But no luck. Can anyone with a deep knowledge of log4net point me to where I could be doing something wrong, or explain what log4net could be doing to stdout such that other programs that should be capturing that stream don't?
UPDATE: The plot thickens! I wrote a quick and dirty executable that uses the Process class to execute my example program. It then grabs the stdout from the example program and writes it with Console.WriteLine, like so:
Process proc = new Process();
proc.StartInfo.FileName = "/path/to/example.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInto.RedirectStandardOutput = true;
proc.Start();
Thread.Sleep(1000);
Console.WriteLine(proc.StandardOutput.ReadToEnd());
This works fine when I run it directly from the console, but has the same problem when I run it from docker / daemonize. So now I'm really confused.
It's not much of an answer, but in case someone else runs into this problem, I was able to get logging to work by using the NLog library here.