I am attempting to programmatically create a rolling file appender in C#. I'm using Visual Studios 2008. I am using log4net version 1.2.0.30714.
My main issue is that my rolling file appender is acting like a file appender. The log file will not roll based upon any size or date criteria I give it. Below is my configuration and I would appreciate any insight or suggestions. Below the code is some of the ideas I have tried.
string path = "Logs\";
string filename = "test.log";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
log4net.Layout.PatternLayout patternLayout = new log4net.Layout.PatternLayout("[%d] %l %n - %m %n%n");
patternLayout.ActivateOptions();
RollingFileAppender appender = new RollingFileAppender();
appender.Threshold = Level.ALL;
appender.StaticLogFileName = false;
appender.CountDirection = 0; // Makes the logs count 1, 2, 3
appender.RollingStyle = RollingFileAppender.RollingMode.Size;
appender.MaximumFileSize = "1KB";
appender.MaxFileSize = 1 * 1024; // 1 KB
appender.MaxSizeRollBackups = 5;
appender.DatePattern = "yy.MM.dd.hh.mm.ss";
appender.Layout = patternLayout;
appender.Name = "QTracImportHelper";
appender.ImmediateFlush = true;
appender.File = filename;
appender.Writer = new StreamWriter(path + filename, true);
appender.ActivateOptions();
Hierarchy hierarchy = (Hierarchy)LogManager.GetLoggerRepository();
hierarchy.Root.AddAppender(appender);
hierarchy.Configured = true;
I've noticed that removing the StreamWriter leads to no file being created at all but no exceptions. Removing the file name causes an exception from within log4net. I have tried using both MaxFileSize and MaximumFileSize to no avail as well as changing the rolling stile to Date and Composite. Additionally if the writer stream is malformed it will create the same exception as not including the File property ({"Value cannot be null.\r\nParameter name: fileName"}{System.ArgumentNullException}).
I think this may be due to you supplying the "Writer" parameter directly before the ActivateOptions() call. The writer should be opened by the RollingLogFileAppender not externally. It's only exposed because of the inheritance of the class from TextWriterAppender.
//Don't do this:
//appender.Writer = new StreamWriter(path + filename, true);
//Do fully-qualify the file name:
appender.File = Path.Combine(path, filename);
Related
I want to archive log files periodically(for every hour) from "Logs" folder to "Archive" folder and then delete those archived files from "logs" folder immediately. Can we achieve this using NLog?
Currently, I am using the below c# code for archiving, but I am not seeing the desired output. We are using Nlog version 4.7.11.
target.FileName = #"C:\Logs\Log-${date:format=yyyy-MM-dd-hh}.log";
target.ArchiveFileName = #"C:\Archives\Log-${date:format=yyyy-MM-dd-hh}.log";
target.ArchiveEvery = FileArchivePeriod.Hour;
target.ArchiveOldFileOnStartup = true;
target.DeleteOldFileOnStartup = true;
target.MaxArchiveDays = 10;
target.ArchiveNumbering = ArchiveNumberingMode.Date;
target.MaxArchiveFiles = 50;
target.ArchiveDateFormat = "yyyy-mmm-dd hh-mm";
target.EnableArchiveFileCompression = true;
NLog supports 2 file-archive-modes:
Static FileName Archive-mode, where ArchiveEvery controls when to roll.
Dynamic FileName Archive-mode, where FileName contains ${date} or ${shortdate} (Rolls automatically)
NLog does not support mixing these 2 file-archive-modes. If you want files to be moved into the Archive-folder, then you must use static FileName:
target.FileName = #"C:\Logs\App.log";
target.ArchiveFileName = #"C:\Archives\App-{#}.log.zip";
target.ArchiveEvery = FileArchivePeriod.Hour;
target.ArchiveOldFileOnStartup = true;
target.DeleteOldFileOnStartup = true;
target.MaxArchiveDays = 10;
target.ArchiveNumbering = ArchiveNumberingMode.DateAndSequence;
target.MaxArchiveFiles = 50;
target.ArchiveDateFormat = "yyyy-MM-dd-hh";
target.EnableArchiveFileCompression = true;
Alternative you can use dynamic-archive-mode and then use scheduled-task/cron-job to compress/move log-files to the wanted location:
target.FileName = #"C:\Logs\Log-${date:format=yyyy-MM-dd-hh}.log";
target.ArchiveOldFileOnStartup = true;
target.MaxArchiveDays = 10;
target.MaxArchiveFiles = 50;
See also Do not mix dynamic with static-archive-mode
You can extend your NLog method to run some method after logging. Please refer to the following: https://github.com/NLog/NLog/wiki/MethodCall-target.
MethodCall target: Calls the specified static method on each log message and passes contextual parameters to it.
You can create some code that uses System.IO to move and archive your code based on your needs.
var appender = (log4net.Appender.FileAppender)LogManager.GetRepository().GetAppenders()[0];
logger.Info(appender.File);
appender.File = string.Empty;
appender.File = newfileName;
appender.ActivateOptions();
I am changing this at runtime , it runs when a new month begins , it was working fine but for this month it did create a new file but still logging to September file
I have a problem here and i need some help.
I work on a C# software in WPF, i have finished it, the program compile but do not run.
I've tried to search the problem using step by step run and it end on this line
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = Application.StartupPath + #"\Logs\" + DateTime.Now.DayOfYear + ".txt" };
and
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
and i got this error : " Attempt to read or write protected memory. This often indicates that another memory is corrupted "
that happen randomly during execution but mostly while running theses lines of code.
If you got a solution i'll take it !
The WPF Application class does not have a StartupPath property.
You could add System.Windows.Forms as project reference and use System.Windows.Forms.Application.StartupPath
Alternative:
string appPath = System.Reflection.Assembly.GetExecutingAssembly()
.GetModules()[0].FullyQualifiedName;
string appDir = Path.GetDirectoryName(appPath);
To debug your code with finer granularity, you could rewrite it:
var fileName = Application.StartupPath;
fileName += #"\Logs\";
fileName += DateTime.Now.DayOfYear
fileName += ".txt";
var logfile = new NLog.Targets.FileTarget("logfile");
logFile.FileName = fileName;
I'm configuring NLog programmatically with this FileTarget:
var target = new FileTarget(TargetName)
{
FileName = Path.Combine(LogDir, "${level}.log"),
CreateDirs = true,
ArchiveFileName = Path.Combine(LogDir, "{#}.${level}.zip"),
ArchiveNumbering = ArchiveNumberingMode.Date,
ArchiveDateFormat = "yyyy-MM-dd",
ArchiveEvery = FileArchivePeriod.Day,
MaxArchiveFiles = MaxArchiveFiles,
OpenFileCacheSize = 5,
KeepFileOpen = true,
CleanupFileName = false,
Layout = NLogLayouts.BasicLayout(),
EnableArchiveFileCompression = true,
Encoding = Encoding.UTF8
};
Everythings works as it should be: I have separate log file for each log level.
When a new day starts (22.09.2020) AND some message is written to (e.g., INFO) log, archive is created. Its name is 2020-09-21.Info.zip
At the same moment, my program has no new messages to DEBUG level, and no archive is created before such a message is generated. The problem is that DEBUG level message can be written only in 2-3-or more days, but I want the Debug.log file to be archived at the moment day changed - not when a new message comes.
How can I configure NLog to achieve this?
My program saves user's input to a txt file on it's current location
TextWriter ts = new StreamWriter("url.txt");
ts.WriteLine(textBox2.Text.ToString());
ts.Close();
It reads that when application starts
if (File.Exists("url.txt")) {
TextReader tr = new StreamReader("url.txt");
readUrl = tr.ReadLine().ToString();
textBox2.Text = readUrl;
tr.Close();
}
I add this program to Windows startup with these code
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true)) {
key.SetValue("House Party Protocol", "\"" + Application.ExecutablePath + "\"");
}
I published it with ClickOnce and installed it to my computer. It starts at windows startup bu doesn't read txt file. When I open it manually it works. I think ClickOnce installation path and windows startup path are different. How should I change my startup code to avoid this
You could try to use a specific directory. For example, you could save the url.txt file to LocalApplicationData (the directory for application-specific data that is used by the current, non-roaming user).
static void Main(string[] args)
{
string inputText = string.Empty;
//string directory = Environment.CurrentDirectory;
string directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string path = Path.Combine(directory, "url.txt");
if (File.Exists(path))
{
TextReader tr = new StreamReader(path);
string readUrl = tr.ReadLine().ToString();
inputText = readUrl;
tr.Close();
}
string text = "abc";
TextWriter ts = new StreamWriter(path);
ts.WriteLine(text);
ts.Close();
}
If you really want to use the directory where the application is running then you could try to use Environment.CurrentDirectory (commented-out in the sample code above). This might give you the same error you had before (when using relative path) but it might help you troubleshoot the issue by showing what directory it's trying to use.
Here's a list of other special folders:
Environment.SpecialFolder