예제 #1
0
        /// <summary>
        /// Create a log file scanner
        /// </summary>
        /// <param name="pathAndMask">File path and mask with glob syntax (i.e. /var/log/auth*.log)</param>
        /// <param name="maxFileSizeBytes">Max size of file (in bytes) before it is deleted or 0 for unlimited</param>
        /// <param name="fileProcessingIntervalMilliseconds">How often to process files, in milliseconds, less than 1 for manual processing, in which case <see cref="ProcessFiles"/> must be called as needed.</param>
        /// <param name="encoding">Encoding or null for utf-8. The encoding must either be single or variable byte, like ASCII, Ansi, utf-8, etc. UTF-16 and the like are not supported.</param>
        /// <param name="maxLineLength">Maximum line length before considering the file a binary file and failing</param>
        public LogFileScanner(string pathAndMask, long maxFileSizeBytes = 0, int fileProcessingIntervalMilliseconds = 0, Encoding encoding = null, int maxLineLength = 8192)
        {
            // glob syntax, replace all backslash to forward slash
            PathAndMask = pathAndMask;
            PathAndMask.ThrowIfNullOrEmpty(nameof(pathAndMask), "Must pass a non-empty path and mask to log file scanner");

            // set properties
            this.maxFileSize   = maxFileSizeBytes;
            this.encoding      = encoding ?? Encoding.UTF8;
            this.maxLineLength = maxLineLength;

            try
            {
                // add initial files
                foreach (WatchedFile file in LogFileScanner.GetFiles(PathAndMask))
                {
                    watchedFiles.Add(file);
                }
            }
            catch
            {
                // generally catching all exceptions and not reporting is bad, but in this case we don't care,
                // we will try to get files on every ProcessFiles call and can throw the exception then
            }

            // setup timer to process files
            if (fileProcessingIntervalMilliseconds > 0)
            {
                fileProcessingTimer          = new System.Timers.Timer(fileProcessingIntervalMilliseconds);
                fileProcessingTimer.Elapsed += (sender, args) => ProcessFiles();
                fileProcessingTimer.Start();
            }
        }
예제 #2
0
        private HashSet <WatchedFile> GetCurrentWatchedFiles()
        {
            // read in existing files that match the mask in the directory being watched
            HashSet <WatchedFile> watchedFilesCopy = new HashSet <WatchedFile>();

            foreach (WatchedFile file in LogFileScanner.GetFiles(PathAndMask))
            {
                watchedFilesCopy.Add(file);
            }

            lock (watchedFiles)
            {
                // remove files that no longer exist
                foreach (WatchedFile existing in watchedFiles.ToArray())
                {
                    if (!watchedFilesCopy.Contains(existing))
                    {
                        Logger.Debug("Removing parsed log file {0}", existing.FileName);
                        watchedFiles.Remove(existing);
                    }
                }

                // add new files
                foreach (WatchedFile newFile in watchedFilesCopy)
                {
                    // add the file, will fail if it already exists
                    if (watchedFiles.Add(newFile))
                    {
                        Logger.Debug("Adding parsed log file {0}", newFile.FileName);
                    }
                }

                // make a copy of everything so we can enumerate outside a lock
                watchedFilesCopy.Clear();
                foreach (WatchedFile file in watchedFiles)
                {
                    watchedFilesCopy.Add(file);
                }
            }

            return(watchedFilesCopy);
        }