How to Log Console Screen into a Text File? [duplicate] - c#

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Mirroring console output to a file
I've a console application in C# and I want to Log into a text file every text appears on the screen. How to do that ?
Unfortunately this thread is closed despite of my comment about the Mirroring console output to a file. The accepted post as answer by that thread IS NOT CORRECT. So why cannot ask the question again? I'm using console interactively and want a copy of all the text on console in a text file. SOS

C:\>yourconsoleapp.exe > yourtextfile.txt
edit: This assumes your console app requires no user input.

Replace all references to the Console class with the System.Diagnostics.Trace class. You can add a ConsoleTraceListener and a TextWriterTraceListener, and then everything you output to the console will end up in both places.

You could use Console.SetOut to redirect the output to a file, but then you wouldn't get output to the console as well unless you used a TextWriter that streamed to both.
You could try using System.Diagnostics.Trace and then adding listeners to both the console and a file.
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="configConsoleListener"
type="System.Diagnostics.ConsoleTraceListener" />
<add name="fileLogger"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="LogFile.log" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
</configuration>

This may be overly simplistic, but at a command prompt, if you do:
C:\>MyApplication >> output.txt
That will write all output from that given app to output.txt
If you don't actually need a programmatic solution, this might do the trick.

A simple Google search result : here
Sorry I am no longer programming with C# but I checked to code and it does make sense in this approach :)

Use log4j.
Go to log4j website and download dll.
Reference dll in your project.
Add this to top of your app.config
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] -%message%newline" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] -%message%newline" />
</layout>
</appender>
Put this as a member of any class you want to log to:
private static readonly ILog log = LogManager.GetLogger(typeof(Foo));
Put in a line like this to log:
log.Debug("Hello world!");

Related

Log4Net not working in Selenium Framework when Running SpecFlow Tests

I'm struggling with Log4Net for a good while now. I have followed this post
as an example. The difference is, in my case, I have two separate projects, one with all objects that interacts with WebDriver and web elements (FrameworkProject), second is actual test project(TestProject). I have read a lot and I'm almost sure I have set it correctly...
FrameworkProject assembly file includes [assembly: log4net.Config.XmlConfigurator(Watch = true)]
My Log4Net.config file is as follow:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="MyAppender" />
<appender-ref ref="MyFileAppender" />
</root>
<appender name="MyAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="MyFileAppender" type="log4net.Appender.FileAppender">
<file value="application.log" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
When I debug my SpecFlow tests and I reach the line XmlConfigurator.Configure(); (look example above) I'm still getting
log4net:ERROR Failed to find configuration section 'log4net' in the application's.
This drops me mad now and I have no clue of what might be wrong. Could this be the cause of running test?? Note: I have log4net set up ONLY in FrameworkProject
I have log4net set up ONLY in FrameworkProject
That's the problem. Roughly speaking, your "entry point" during test execution is your Test Project, hence it's looking for log4net configuration section inside of "entry point's" application configuration file (Test Project's app.config). Thus you should move your log4net configuration to Test Project's application configuration file.
On a second notice, it looks like you don't need to call XmlConfigurator.Configure if you use assembly level attribute: 1, 2.

log4net info hangs console application if called from a worker thread

I have a problem where log4net hangs on a info statement. I have a C# multithreaded console application. The main thread creates several working threads that log using log4net, writing to a file and to the console. The logger is a static variable in some base class. At some random point into executing the application the logger will hang on a info statement, but only on some machines. I came across some post about rare cases where on specific system setups the log write buffer will fill and log4net will wait for it to empty, what never happens. Thus the application hangs. In my case the logger writes into the file, but then stops and the message does not reach the console. Pressing ctrl-c on the console actually causes the application to continue normally.
I tried to make the logger a member of my class instead of having it static as suggested here: http://apache-logging.6191.n7.nabble.com/Multi-threaded-ASP-NET-application-not-working-td21782.html
But that just caused my application to hang at the first log statement there was.
This is the call where it hangs:
_logger.Info($"Generation: {_ea.CurrentGeneration}/{_maxGenerations}, " +
$"Time/gen: {timePerGen} ms, Est. time remaining: {Utilities.TimeToString(timeRemainingEst)} " +
$"Fitness - Max: {_ea.Statistics._maxFitness:F4} Mean: {_ea.Statistics._meanFitness:F4}, " +
$"Complexity - Max: {_ea.Statistics._maxComplexity:F0} Mean: {_ea.Statistics._meanComplexity:F2} " +
$"Champ: {_ea.CurrentChampGenome.Complexity:F0} Strategy: {_ea.ComplexityRegulationMode}, " +
$"Specie size - Max: {_ea.Statistics._maxSpecieSize:D} Min: {_ea.Statistics._minSpecieSize:D}, " +
$"Generations since last improvement: {_ea.CurrentGeneration - _lastMaxFitnessImprovementGen}"
);
Has anyone encountered similar issues and know how to fix it or a workaround?
Here is the requested log4net config
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" value="ENTM/%property{name}/%property{id}/%property{count}/log.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%utcdate{yyyy-MM-dd HH:mm:ss} [%thread] %-5level: %message%newline" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<target value="Console.Error" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%utcdate{yyyy-MM-dd HH:mm:ss} [%thread] %-5level: %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="FileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>

how to create dynamic log using log4net

My Project is in C# (Windows Form) .net3.5
In my code there are multiple events and in each event multiple searches are running.
I have to create log file for each event and multiple searches can access & write this single log file.
The problem is that I don't know how to use log4net for creating multiple logs with dynamic(set at run time) names.
How to set there location(Path)
I explorer internet regarding my problem but haven't found any help which address this type of issues.
any idea pls
log4net is generally used to have mutiple sources and appenders.
To generate a defined source, ask LogManager to have a named log, generally we use a type to identify a log, but feel free to use a string if you want:
var myLog = LogManager.GetLogger("NAME");
....
var myLog = LogManager.GetLogger(GetType());
In the first case logger is identified by "NAME", in the second by the type name with namespaces.
Then you can configure the appenders, for all logs, for a subset of them, with filters and so on.
Let's see an example:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="MYFILE" type="log4net.Appender.RollingFileAppender">
<file value=".\logs\myname.log"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level (%thread) %logger - %message%newline"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<!-- all logger append to these appenders />
<appender-ref ref="xxxxxx"/>
</root>
<logger name="NAME">
<level value="INFO"/>
<appender-ref ref="MYFILE"/>
</logger>
<!-- add other appender here -->
Don't forget to call at your application start XmlConfigurator.Configure();

log4net EventLog custom logname created, but not used

In a project, i'm using log4net to write down in the event log. I need to create a custom log so all will go there. I have tried to add the event to different logs, and it worked, but for some reasons, now it is impossible to change the logname from the config file. Even if I change it, it will keep the previous one and log into it. Here is a sample of my app.config:
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy-MMMM-dd HH:mm:ss, fff} [%thread] %level %message %exception%newline"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
<ApplicationName>TestLoggerFichierConfig</ApplicationName>
<LogName>AgentLogger</LogName>
</appender>
I read that the event log must be restarted when adding a new log so the recent events will be displayed in it. I did this, and it allowed me to see the new log that has been created, but nothing will go there. Is it possible to force Log4Net to stop using the previous log to rather use the one I defined in the app.config?
Thanks for the help.
Update:
It seems that le EventLogs recognizes the source application and decide in wich log to put the new events since he remembers where it previously went. When I first set the logName, it works fine. If I stop the app, change the logname and restart it, the event will still go to the previous log. If the logName does not exists in the event log, it will be created, but not used! There might be something to do, but it is not in the side of log4net, and it may be dangerous to change the windows settings at this level. I created two eventLogAppender on the same app.config file, both pointing at different logs. the events got to the same log though. It is being obvious that the problem doesn't come from log4net, and the solution to my problem will not be solved by code. Thanks for the great advices though.
Something is probably wrong with your configuration and it is simply not telling you about it because log4net itself is designed to never, ever throw errors.
You can turn on internal debugging for log4net, but don't deploy to production with log4net debugging turned on. Weirdness will eventually happen if deploy your product with the log4net debugging switch on.
http://haacked.com/archive/2006/09/27/Log4Net_Troubleshooting.aspx
http://logging.apache.org/log4net/release/faq.html (see the troubleshooting section)
I ran into this and it wasn't down to log4net but the re-mapping of the source to a new custom log. I took log4net out of the equation and finding that the problem occurred usint the EventLog class directly, I eventually found EventLog.CreateEventSource is not creating a custom log
I think it's also the reason behind this Windows service always writes to custom log and application log
First and foremost, I'd encourage you to turn on internal debugging, as found in the link ntcolonel posted. Add this to your config file:
<add key="log4net.Internal.Debug" value="true"/>
Perhaps I am not understanding your question entirely, but I'd like to ensure you have both created the appender and properly tell log4net that you want to actually use that appender:
<log4net debug="true">
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\SomeApplication.xml"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<countDirection value="1"/>
<maxSizeRollBackups value="30"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<layout type="log4net.Layout.XmlLayoutSchemaLog4j">
<locationInfo value="true"/>
</layout>
</appender>
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="SomeDistributionList#somehost.com"/>
<from value="SomeApplication#somehost.com"/>
<subject type="log4net.Util.PatternString" value="Some Application Error - %property{log4net:HostName}"/>
<smtpHost value="smtp.somehost.com"/>
<bufferSize value="1"/>
<threshold value="ERROR"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %property{log4net:HostName} %logger %level %newline%newline%property{ExceptionThrottleInformation}%newline%newline%message%newline"/>
</layout>
<filter type="SomeNamespace.SomeSubNamespace.Log4Net.ExceptionThrottleFilter, SomeSubNamespace">
<threshold value="10"/>
<thresholdTimeoutSeconds value="60"/>
<timeoutSecondsBetweenMessages value="600000"/>
<exceptionText value="Timeout expired"/>
</filter>
</appender>
<appender name="DatabaseAppender" type="SomeNamespace.SomeSubNamespace.DatabaseTraceAppender, SomeSubNamespace">
<hoursToKeepInformationalTraces value="48"/>
<hoursToKeepErrorTraces value="96"/>
<threshold value="INFO"/>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="SmtpAppender"/>
<appender-ref ref="DatabaseAppender"/>
</root>
Note that while I have multiple appenders, I reference which to call within the root tag. Since you didn't post your whole config file, it's tough to tell if everything is matching as it should.

Where will log4net create this log file?

When I set the file value to logs\log-file.txt, where exactly will it create this folder? In the /bin directory?
My web.config looks like this:
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="logs\log-file.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
</log4net>
Is this the correct way to log:
ILog logger = LogManager.GetLogger(typeof(CCController));
logger.Error("Some Page", ex); // where ex is the exception instance
If you want your log file to be place at a specified location which will be decided at run time may be your project output directory then you can configure your .config file entry in that way
<file type="log4net.Util.PatternString" value="%property{LogFileName}.txt" />
and then in the code before calling log4net configure, set the new path like below
log4net.GlobalContext.Properties["LogFileName"] = #"E:\\file1"; //log file path
log4net.Config.XmlConfigurator.Configure();
How simple is it? :)
it will create the file in the root directory of your project/solution.
You can specify a location of choice in the web.config of your app as follows:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:/ServiceLogs/Olympus.Core.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value=".yyyyMMdd.log" />
<maximumFileSize value="5MB" />
<staticLogFileName value="true" />
<lockingModel type="log4net.Appender.RollingFileAppender+MinimalLock" />
<maxSizeRollBackups value="-1" />
<countDirection value="1" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level [%thread] %logger - %message%newline%exception" />
</layout>
</appender>
the file tag specifies the location.
The file value can either be an absolute path like "c:\logs\log.txt" or a relative path which I believe is relative to the bin directory.
As far as implementing it, I usually place the following at the top of any class I plan to log in:
private static readonly ILog Log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
Finally, you can use it like so:
Log.Debug("This is a DEBUG level message.");
Log4net is saving into your project folder. Something like: \SolutionFolder\ProjectFolder\bin\SolutionConfiguration\logs\log-file.txt.
Where:
SolutionFolder is where you save your solution
ProjectFolder is the folder where your project lives into the solution and
SolutionConfiguration is the folder that contais all the binaries of your project (the default is Debug or Release)
Hope this helps!
FileAppender appender = repository.GetAppenders().OfType<FileAppender>().FirstOrDefault();
if (appender != null)
logger.DebugFormat("log file located at : {0}", appender.File);
else
logger.Error("Could not locate fileAppender");
For the log folder and file stuff, go with #Bens answer.
I will comment on the creating log part, though. Imo there is no correct way. When coding loggers manually I do it the way you're doing it:
ILog logger = LogManager.GetLogger(typeof(CCController));
because it is short and concise.
That said, I do not create the logger instances inside the classes these days, I let my IoC container inject it for me.
I was developing for .NET core 2.1 using log4net 2.0.8 and found NealWalters code moans about 0 arguments for XmlConfigurator.Configure(). I found a solution by Matt Watson here
log4net.GlobalContext.Properties["LogFileName"] = #"E:\\file1"; //log file path
var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
I think your sample is saving to your project folders and unless the default iis, or .NET , user has create permission then it won't be able to create the logs folder.
I'd create the logs folder first and allow the iis user full permission and see if the log file is being created.
if you want to choose dynamically the path to the log file use the method written in this link: method to dynamic choose the log file path.
if you want you can set the path to where your app EXE file exists like this -
var logFileLocation = System.IO.Path.GetDirectoryName
(System.Reflection.Assembly.GetEntryAssembly().Location);
and then send this 'logFileLocation' to the method written in the link above like this:
Initialize(logFileLocation);
and you are ready to go! :)
In your case, the log file will be in bin\Debug\netcoreapp3.1\ folder
and this may depends on your framework too.
I used Asp.Net core 3.1 so the folder path is bin\Debug\netcoreapp3.1\

Categories