简体   繁体   English

归档日志文件

[英]Archiving Log Files

I have just rewritten a windows service process that outputs important info debug to a log file in the /programdata/myservice/ folder. 我刚刚重写了Windows服务进程,该进程将重要的信息调试输出到/ programdata / myservice /文件夹中的日志文件。

However at night at midnight I have a job that is supposed to take the current days log file and remove it's contents and then create an archived logfile with the date in the name for 3 days eg LogfileArchived15092014.log. 但是,在晚上的午夜,我有一份工作,该工作应该获取当前日期的日志文件并删除其内容,然后创建名称为3天的日期的归档日志文件,例如LogfileArchived15092014.log。

Some code then runs to delete log files older than this date so I only ever have todays current log file and 2 archived ones for debugging older issues etc. 然后一些代码运行以删除早于该日期的日志文件,因此我只有今天的当前日志文件和2个用于调试较旧问题的归档文件。

Now I have copied the code that does this from an old service that is working and it archives the log files and deletes old ones. 现在,我已经从正在运行的旧服务中复制了执行此操作的代码,并将该文件存档并删除了旧文件。 However for some reason when this new job runs I get I/O errors such as this (from the event viewer) 但是由于某种原因,当运行此新作业时,我收到了这样的I / O错误(从事件查看器中)

Error Running System Jobs: I/O Error archiving log file: C:\\ProgramData\\Brainiac\\LogfileArchived; 运行系统作业时出错:I / O归档日志文件时出错:C:\\ ProgramData \\ Brainiac \\ LogfileArchived; The process cannot access the file 'C:\\ProgramData\\Brainiac\\Logfile.log' because it is being used by another process. 该进程无法访问文件'C:\\ ProgramData \\ Brainiac \\ Logfile.log',因为该文件正在被另一个进程使用。

Now the reason the first path doesn't have an extension on it eg C:\\ProgramData\\Brainiac\\LogfileArchived is because it's obviously thrown an error before it's got to the part where the file date is created to be appended to the filename eg 现在,第一个路径没有扩展名的原因是例如C:\\ ProgramData \\ Brainiac \\ LogfileArchived,是因为在到达创建文件日期以附加到文件名的那一部分之前,它显然抛出了错误。

// set a lock up to prevent other processes locking
this.Locked = true;

// wrap in try as it keeps failing!!!!
try
{
    // take contents of current log file - the daily one I have been logging to all day      
    // I guess this is where the error is being raised due to the absence 
    // of a .log extension in the error message when mentioning the filename
    string content = this.ReadFileString(this.logFilePath);

    // for some reason todays log file was empty 
    // why would this be unless loggging was disabled?
    if (!String.IsNullOrEmpty(content))
    {
        // create a new log file with date stamp of yesterday added to the filename and guff removed to make it valid
        string file_date = DateTime.Now.Date.AddDays(-1).ToString().Replace("/", "").Replace("-", "");

        // remove time part - should be done at midnight but if not ensure colons and spaces are removed
        file_date = file_date.Replace("00:00:00", "").Replace(":", "").Replace(" ", "");

        // append .log to it
        this.logfilearchivepath += file_date + ".log";

        //Append all the contents of my daily log file to this new file 
        File.AppendAllText(this.logfilearchivepath, content, Encoding.UTF8);

So I suspect it is bombing out on this line 所以我怀疑它在这条线上轰炸

string content = this.ReadFileString(this.logFilePath);

Due to no extension being in the error message. 由于错误消息中没有扩展名。 So maybe I need a different way of accessing the contents? 所以也许我需要一种不同的方式来访问内容?

Now I don't know what other process has it locked (can I find out somehow?) but I have tried the following. 现在,我不知道它锁定了其他什么进程(我能以某种方式找到它吗?),但是我尝试了以下方法。

  1. Ensuring I don't have the file open on my own computer. 确保我没有在自己的计算机上打开文件。
  2. Adding a flag in which is supposed to prevent ANY logging to the log file. 添加一个应该阻止任何日志记录到日志文件的标志。 As you can see at the top I go 如您所见,我去了

    // set a lock up to prevent other processes locking this.Locked = true; //设置锁以防止其他进程对此进行锁定。

and in my method that does the logging I have a check for it to exit ASAP eg 在我做日志的方法中,我有一个检查要尽快退出,例如

// log to our application data folder - unless locked for some reason
public void LogMsg(string msg, string debugLevel = "HIGH")
{
   // we are prevented from logging at this point in time
   if (this.Locked) return;
  1. I also have wrapped the call to the ArchiveLogFile() method in 3 try/catch statements, each with a Thread.Sleep in between of longer and longer gaps in case something was still logging. 我还用3个try / catch语句包装了对ArchiveLogFile()方法的调用,每条语句之间都有一个Thread.Sleep,间隔越来越长,以防万一仍在记录日志。

  2. I have also tried using DB locks. 我也尝试过使用数据库锁。

So I have a table called LOCKS and methods to insert/remove a lock record and also a method to check one doesn't exist. 因此,我有一个名为LOCKS的表,以及用于插入/删除锁记录的方法,以及用于检查一个不存在的方法。

So if multiple processes tried running the same code at the same time from different apps then it shouldn't be able to as a lock record would exist in the database which gets inserted before the job starts running and is removed after the job has completed (a RUNNING lock) 因此,如果多个进程尝试从不同的应用程序同时运行相同的代码,则该锁不应存在,因为数据库中将存在锁定记录,该锁定记录在作业开始运行之前就已插入,而在作业完成之后会被删除( RUNNING锁)

Also once completed a LOGFILE_ARCHIVED lock record is inserted so that the same OR a different job knows the log file has been archived and doesn't try to archive it again. 同样,一旦完成,将插入LOGFILE_ARCHIVED锁定记录,以便相同或不同的作业知道日志文件已被归档,并且不再尝试再次对其进行归档。

I use the computers name in the lock files as the process could run on multiple servers/computers at any one time. 我在锁定文件中使用了计算机名称,因为该过程可以同时在多台服务器/计算机上运行。

So what other solutions could I do to get round this problem? 那么,我可以采取其他什么解决方案来解决这个问题呢?

Should I use a different method for obtaining the log file contents that wouldn't be blocked by something locking the file (I don't know what is doing the locking but the this.Locked = True should prevent anything being logged to the file during the archive job) but obviously the "lock" on the file is higher up than my code. 我是否应该使用其他方法来获取不会因锁定文件而被阻止的日志文件内容(我不知道该进行什么锁定,但是this.Locked = True应该防止在此期间将任何内容记录到该文件中存档作业),但显然文件上的“锁”高于我的代码。

This is a windows service written in C# .NET 4.5 on a Win 7 machine. 这是在Win 7计算机上用C#.NET 4.5编写的Windows服务。

Thanks for your help. 谢谢你的帮助。

I got it working. 我知道了 I just had an issue with the this.Locked being in the Helper class and other concurrent instances of the DLL being called ignoring it (multi threaded issue) so I just placed my DB Lock check into the Init of the Helper Class so it was 我只是有一个问题this.Locked在Helper类中,而DLL的其他并发实例被称为忽略它(多线程问题),所以我只是将DB Lock检查放入了Helper类的Init中,

this.Locked = this.GetCurrentLockedStatus();

And then any process would have got the same value. 然后,任何过程都将具有相同的价值。 This meant no logging was going on during the file transfer as I was adding the LOCK record in before attempting to do it and exiting any LogMsg method if 这意味着在文件传输期间没有日志记录正在进行,因为我在尝试执行LOCK记录之前添加了LOCK记录,并且在出现以下情况时退出了任何LogMsg方法

this.Locked = true;

Now it works like a charm. 现在,它就像一种魅力。 Don't really know why the old service was working though. 虽然真的不知道为什么旧的服务仍然有效。 I can see lots of I/O errors in the event log for it but eventually it just manages to do it for some reason. 我可以在事件日志中看到很多I / O错误,但由于某种原因,最终它还是设法做到了。 This method of using the DB to maintain locks seems to be much better and faster. 使用数据库维护锁的这种方法似乎更好,更快。

Thanks for your help. 谢谢你的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM