Пример #1
0
        protected virtual bool UpdateFilePath(LogFileInfo logFile, FileLogEntry entry, CancellationToken cancellationToken)
        {
            string filePath = FormatFilePath(logFile, entry);

            if (logFile.MaxSize > 0)
            {
                while (!CheckFileSize(filePath, logFile, entry))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    logFile.Counter++;
                    var newFilePath = FormatFilePath(logFile, entry);

                    if (filePath == newFilePath)
                    {
                        break;
                    }

                    filePath = newFilePath;
                }
            }


            if (logFile.CurrentPath == filePath)
            {
                return(false);
            }

            logFile.CurrentPath = filePath;
            return(true);
        }
Пример #2
0
        protected virtual bool CheckFileSize(string filePath, LogFileInfo logFile, FileLogEntry entry)
        {
            long currentFileSize;

            if (logFile.AppendStream == null || logFile.CurrentPath != filePath)
            {
                IFileInfo fileInfo = logFile.FileAppender.FileProvider.GetFileInfo(Path.Combine(logFile.BasePath, filePath));

                if (!fileInfo.Exists)
                {
                    return(true);
                }

                if (fileInfo.IsDirectory)
                {
                    return(false);
                }

                currentFileSize = fileInfo.Length;
            }
            else
            {
                currentFileSize = logFile.AppendStream.Length;
            }

            long expectedFileSize = currentFileSize > 0 ? currentFileSize : logFile.Encoding.GetPreamble().Length;

            expectedFileSize += logFile.Encoding.GetByteCount(entry.Text);

            return(expectedFileSize <= logFile.MaxSize);
        }
 internal LogEntryWriteFailed(object source, FileLoggerProcessor.LogFileInfo logFile, FileLogEntry logEntry, Exception exception)
 {
     Source    = source;
     _logFile  = logFile;
     _logEntry = logEntry;
     Exception = exception;
 }
Пример #4
0
        string GetPostfix(LogFileInfo logFile, Encoding fileEncoding, FileLogEntry entry)
        {
            if (HasPostfix(logFile, entry))
            {
                var sb = stringBuilder;
                stringBuilder = null;
                if (sb == null)
                {
                    sb = new StringBuilder();
                }

                while (true)
                {
                    BuildPostfix(sb, logFile, entry);
                    var postfix = sb.ToString();
                    sb.Clear();

                    if (CheckLogFile(logFile, postfix, fileEncoding, entry))
                    {
                        if (sb.Capacity > 64)
                        {
                            sb.Capacity = 64;
                        }

                        stringBuilder = sb;

                        return(postfix);
                    }
                }
            }
            else
            {
                return(null);
            }
        }
Пример #5
0
        protected virtual async Task WriteEntryCoreAsync(LogFileInfo logFile, FileLogEntry entry, CancellationToken cancellationToken)
        {
            if (logFile.AppendStream.Length == 0)
            {
                var preamble = logFile.Encoding.GetPreamble();
                await logFile.AppendStream.WriteAsync(preamble, 0, preamble.Length, cancellationToken).ConfigureAwait(false);
            }

            var data = logFile.Encoding.GetBytes(entry.Text);
            await logFile.AppendStream.WriteAsync(data, 0, data.Length, cancellationToken).ConfigureAwait(false);
        }
Пример #6
0
        protected virtual void BuildPostfix(StringBuilder sb, LogFileInfo logFile, FileLogEntry entry)
        {
            if (!string.IsNullOrEmpty(logFile.Settings.DateFormat))
            {
                sb.Append('-');
                sb.Append(entry.Timestamp.ToLocalTime().ToString(logFile.Settings.DateFormat, CultureInfo.InvariantCulture));
            }

            if (logFile.Settings.MaxFileSize > 0)
            {
                sb.Append('-');
                sb.Append(logFile.Counter.ToString(logFile.Settings.CounterFormat, CultureInfo.InvariantCulture));
            }
        }
Пример #7
0
        async Task WriteEntryAsync(LogFileInfo logFile, FileLogEntry entry, CancellationToken disposeToken)
        {
            // discarding remaining entries if queue got disposed
            disposeToken.ThrowIfCancellationRequested();

            Encoding fileEncoding;
            string   filePath;
            bool     ensureBasePath;

            _settingsLock.EnterReadLock();
            try
            {
                fileEncoding = GetFileEncoding(logFile, entry);
                var postfix = GetPostfix(logFile, fileEncoding, entry);
                filePath       = logFile.GetFilePath(postfix);
                ensureBasePath = Settings.EnsureBasePath;
            }
            finally { _settingsLock.ExitReadLock(); }

            var fileInfo = Context.FileProvider.GetFileInfo(filePath);

            while (true)
            {
                try
                {
                    await Context.AppendAllTextAsync(fileInfo, entry.Text, fileEncoding).ConfigureAwait(false);

                    return;
                }
                catch
                {
                    if (ensureBasePath)
                    {
                        try
                        {
                            if (await Context.EnsureDirAsync(fileInfo).ConfigureAwait(false))
                            {
                                await Context.AppendAllTextAsync(fileInfo, entry.Text, fileEncoding).ConfigureAwait(false);

                                return;
                            }
                        }
                        catch { }
                    }
                }

                // discarding failed entry if queue got disposed
                await Task.Delay(1000, disposeToken).ConfigureAwait(false);
            }
        }
Пример #8
0
        async Task WriteEntryAsync(LogFileInfo logFile, FileLogEntry entry, CancellationToken shutdownToken)
        {
            // discarding remaining entries on shutdown
            shutdownToken.ThrowIfCancellationRequested();

            var fileAppender   = GetFileAppender(logFile);
            var fileEncoding   = GetFileEncoding(logFile, entry);
            var postfix        = GetPostfix(logFile, fileAppender, fileEncoding, entry);
            var filePath       = logFile.GetFilePath(postfix);
            var ensureBasePath = logFile.Settings.EnsureBasePath;

            var fileInfo = fileAppender.FileProvider.GetFileInfo(filePath);

            while (true)
            {
                try
                {
                    await fileAppender.AppendAllTextAsync(fileInfo, entry.Text, fileEncoding, shutdownToken).ConfigureAwait(false);

                    return;
                }
                catch
                {
                    if (ensureBasePath)
                    {
                        try
                        {
                            if (await fileAppender.EnsureDirAsync(fileInfo, shutdownToken).ConfigureAwait(false))
                            {
                                await fileAppender.AppendAllTextAsync(fileInfo, entry.Text, fileEncoding, shutdownToken).ConfigureAwait(false);

                                return;
                            }
                        }
                        catch { }
                    }
                }

                // discarding failed entry on shutdown
                if (Context.WriteRetryDelay > TimeSpan.Zero)
                {
                    await Task.Delay(Context.WriteRetryDelay, shutdownToken).ConfigureAwait(false);
                }
                else
                {
                    shutdownToken.ThrowIfCancellationRequested();
                }
            }
        }
Пример #9
0
        protected virtual string FormatFilePath(LogFileInfo logFile, FileLogEntry entry)
        {
            return(Regex.Replace(logFile.PathFormat, @"<(date|counter)(?::([^<>]+))?>", match =>
            {
                var inlineFormat = match.Groups[2].Value;

                switch (match.Groups[1].Value)
                {
                case "date": return GetDate(inlineFormat.Length > 0 ? inlineFormat : null, logFile, entry);

                case "counter": return GetCounter(inlineFormat.Length > 0 ? inlineFormat : null, logFile, entry);

                default: throw new InvalidOperationException();
                }
            }));
        }
Пример #10
0
        public void Enqueue(string fileName, FileLogEntry entry)
        {
            LogFileInfo logFile;

            lock (_logFiles)
            {
                if (_isDisposed)
                {
                    throw new ObjectDisposedException(nameof(FileLoggerProcessor));
                }

                if (Context.CompleteToken.IsCancellationRequested)
                {
                    return;
                }

                if (!_logFiles.TryGetValue(fileName, out logFile))
                {
                    logFile = CreateLogFile();

                    logFile.BasePath  = Settings.BasePath;
                    logFile.FileName  = Path.ChangeExtension(fileName, null);
                    logFile.Extension = Path.GetExtension(fileName);

                    logFile.Queue = new ActionBlock <FileLogEntry>(
                        e => WriteEntryAsync(logFile, e, _disposeTokenSource.Token),
                        new ExecutionDataflowBlockOptions
                    {
                        MaxDegreeOfParallelism = 1,
                        BoundedCapacity        = Settings.MaxQueueSize,
                    });

                    _logFiles.Add(fileName, logFile);
                }
            }

            logFile.Queue.Post(entry);
        }
Пример #11
0
        public void Enqueue(FileLogEntry entry, ILogFileSettings fileSettings, IFileLoggerSettings settings)
        {
            LogFileInfo logFile;

            lock (_logFiles)
            {
                if (_status == Status.Completed)
                {
                    throw new ObjectDisposedException(nameof(FileLoggerProcessor));
                }

                if (_status != Status.Running)
                {
                    return;
                }

                if (!_logFiles.TryGetValue(fileSettings, out logFile))
                {
                    _logFiles.Add(fileSettings, logFile = CreateLogFile(fileSettings, settings));
                }
            }

            logFile.Queue.Post(entry);
        }
Пример #12
0
        public void Enqueue(string fileName, FileLogEntry entry)
        {
            LogFileInfo logFile;

            lock (_logFiles)
            {
                if (_isDisposed)
                {
                    throw new ObjectDisposedException(nameof(FileLoggerProcessor));
                }

                if (Context.CompleteToken.IsCancellationRequested)
                {
                    return;
                }

                if (!_logFiles.TryGetValue(fileName, out logFile))
                {
                    _logFiles.Add(fileName, logFile = CreateLogFile(fileName));
                }
            }

            logFile.Queue.Post(entry);
        }
 public LogFilePathFormatContext(FileLoggerProcessor processor, LogFileInfo logFile, FileLogEntry logEntry)
 {
     _processor = processor;
     _logFile   = logFile;
     _logEntry  = logEntry;
 }
Пример #14
0
 protected virtual string GetCounter(string inlineFormat, LogFileInfo logFile, FileLogEntry entry)
 {
     return(logFile.Counter.ToString(inlineFormat ?? logFile.CounterFormat, CultureInfo.InvariantCulture));
 }
 internal LogEntryDropped(object source, FileLoggerProcessor.LogFileInfo logFile, FileLogEntry logEntry)
 {
     Source    = source;
     _logFile  = logFile;
     _logEntry = logEntry;
 }
Пример #16
0
        private async Task WriteEntryAsync(LogFileInfo logFile, FileLogEntry entry, CancellationToken cancellationToken)
        {
            // discarding remaining entries on forced complete
            cancellationToken.ThrowIfCancellationRequested();

            WriteEntryState state    = WriteEntryState.CheckFile;
            IFileInfo       fileInfo = null;

            for (; ;)
            {
                switch (state)
                {
                case WriteEntryState.CheckFile:
                    try
                    {
                        if (UpdateFilePath(logFile, entry, cancellationToken) && logFile.AppendStream != null)
                        {
                            logFile.CloseAppendStream();
                        }

                        state = logFile.AppendStream == null ? WriteEntryState.TryCreateStream : WriteEntryState.Write;
                    }
                    catch (Exception ex) when(!(ex is OperationCanceledException))
                    {
                        state = WriteEntryState.Idle;
                    }
                    break;

                case WriteEntryState.TryCreateStream:
                    try
                    {
                        fileInfo             = logFile.FileAppender.FileProvider.GetFileInfo(Path.Combine(logFile.BasePath, logFile.CurrentPath));
                        logFile.AppendStream = logFile.FileAppender.CreateAppendStream(fileInfo);

                        state = WriteEntryState.Write;
                    }
                    catch (Exception ex) when(!(ex is OperationCanceledException))
                    {
                        state = WriteEntryState.RetryCreateStream;
                    }
                    break;

                case WriteEntryState.RetryCreateStream:
                    try
                    {
                        if (await logFile.FileAppender.EnsureDirAsync(fileInfo, cancellationToken).ConfigureAwait(false))
                        {
                            logFile.AppendStream = logFile.FileAppender.CreateAppendStream(fileInfo);
                            state = WriteEntryState.Write;
                        }
                        else
                        {
                            state = WriteEntryState.Idle;
                        }
                    }
                    catch (Exception ex) when(!(ex is OperationCanceledException))
                    {
                        // discarding entry when file path is invalid
                        if (logFile.CurrentPath.IndexOfAny(s_invalidPathChars.Value) >= 0)
                        {
                            return;
                        }

                        state = WriteEntryState.Idle;
                    }
                    break;

                case WriteEntryState.Write:
                    try
                    {
                        try
                        {
                            await WriteEntryCoreAsync(logFile, entry, cancellationToken).ConfigureAwait(false);

                            if (logFile.AccessMode == LogFileAccessMode.KeepOpenAndAutoFlush)
                            {
                                // FlushAsync is extremely slow currently
                                // https://github.com/dotnet/corefx/issues/32837
                                logFile.AppendStream.Flush();
                            }
                        }
                        finally
                        {
                            if (logFile.AccessMode == LogFileAccessMode.OpenTemporarily)
                            {
                                logFile.CloseAppendStream();
                            }
                        }

                        return;
                    }
                    catch (Exception ex) when(!(ex is OperationCanceledException))
                    {
                        state = WriteEntryState.Idle;
                    }
                    break;

                case WriteEntryState.Idle:
                    // discarding failed entry on forced complete
                    if (Context.WriteRetryDelay > TimeSpan.Zero)
                    {
                        await Task.Delay(Context.WriteRetryDelay, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                    }

                    state = WriteEntryState.CheckFile;
                    break;
                }
            }
        }
Пример #17
0
        protected virtual bool CheckLogFile(LogFileInfo logFile, string postfix, IFileAppender fileAppender, Encoding fileEncoding, FileLogEntry entry)
        {
            if (logFile.Settings.MaxFileSize > 0)
            {
                var fileInfo = fileAppender.FileProvider.GetFileInfo(logFile.GetFilePath(postfix));
                if (fileInfo.Exists &&
                    (fileInfo.IsDirectory || fileInfo.Length + fileEncoding.GetByteCount(entry.Text) > logFile.Settings.MaxFileSize))
                {
                    logFile.Counter++;
                    return(false);
                }
            }

            return(true);
        }
Пример #18
0
 protected virtual Encoding GetFileEncoding(LogFileInfo logFile, FileLogEntry entry)
 {
     return(Settings.FileEncoding);
 }
Пример #19
0
 protected virtual bool HasPostfix(LogFileInfo logFile, FileLogEntry entry)
 {
     return(!string.IsNullOrEmpty(logFile.Settings.DateFormat) || logFile.Settings.MaxFileSize > 0);
 }
Пример #20
0
 protected virtual Encoding GetFileEncoding(LogFileInfo logFile, FileLogEntry entry)
 {
     return(logFile.Settings.FileEncoding ?? Encoding.UTF8);
 }
Пример #21
0
 protected virtual string GetDate(string inlineFormat, LogFileInfo logFile, FileLogEntry entry)
 {
     return(entry.Timestamp.ToLocalTime().ToString(inlineFormat ?? logFile.DateFormat, CultureInfo.InvariantCulture));
 }