private FileLogSink(LogGroupMutex logGroupMutex, string logFileDir, string logFileNameBase, int rotateLogFileWhenLargerBytes, FileStream logStream, int initialRotationIndex, DefaultFormat.Options formatOptions) { _logSessionId = Guid.NewGuid(); _logGroupMutex = logGroupMutex; _logFileDir = logFileDir; _logFileNameBase = logFileNameBase; _rotateLogFileWhenLargerBytes = (rotateLogFileWhenLargerBytes <= 0) ? -1 : rotateLogFileWhenLargerBytes; _logStream = logStream; _logWriter = new StreamWriter(logStream, LogTextEncoding); _rotationIndex = initialRotationIndex; _formatOptions = formatOptions ?? DefaultFormatOptions; }
/// <summary> /// Attention: All loggers from all processes that write to the same <c>logFileNameBase</c> MUST use the same value for <c>rotateLogFileWhenLargerBytes</c>! /// </summary> public static bool TryCreateNew( string logFileDir, string logFileNameBase, Guid logGroupId, int rotateLogFileWhenLargerBytes, DefaultFormat.Options formatOptions, out FileLogSink newSink) { // Bad usage - throw. if (logFileNameBase == null) { throw new ArgumentNullException(nameof(logFileNameBase)); } if (String.IsNullOrWhiteSpace(logFileNameBase)) { throw new ArgumentException($"{nameof(logFileNameBase)} may not be white-space only.", nameof(logFileNameBase)); } // Ok usage, but bad state - do not throw and return false. newSink = null; if (String.IsNullOrWhiteSpace(logFileDir)) { return(false); } // Normalize in respect to final dir separator: logFileDir = Path.GetDirectoryName(Path.Combine(logFileDir, ".")); // Ensure the directory exists: if (!EnsureDirectoryExists(logFileDir, out DirectoryInfo logFileDirInfo)) { return(false); } LogGroupMutex logGroupMutex = null; try { logGroupMutex = new LogGroupMutex(logGroupId); if (!logGroupMutex.TryAcquire(out LogGroupMutex.Handle logGroupMutexHandle)) { logGroupMutex.Dispose(); return(false); } using (logGroupMutexHandle) { DateTimeOffset now = DateTimeOffset.Now; int rotationIndex = FindLatestRotationIndex(logFileDirInfo, logFileNameBase, now); string logFileName = ConstructFilename(logFileNameBase, now, rotationIndex); string logFilePath = Path.Combine(logFileDir, logFileName); FileStream logStream = new FileStream(logFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); newSink = new FileLogSink(logGroupMutex, logFileDir, logFileNameBase, rotateLogFileWhenLargerBytes, logStream, rotationIndex, formatOptions); } if (newSink.TryLogInfo( SelfLogSourceInfo.WithCallInfo().WithAssemblyName(), "Logging session started", new object[] { "LogGroupId", newSink.LogGroupId, "LogSessionId", newSink.LogSessionId, "RotateLogFileWhenLargerBytes", newSink.RotateLogFileWhenLargerBytes })) { return(true); } } catch { } // If we did not succeed, the sink may be still constructed (e.g. TryLogInfo(..) returned false). // We need to dispose the sink before giving up, but be brepaed for it to sbe null. try { if (newSink != null) { newSink.Dispose(); // This will also dispose the logGroupMutex owned by the newSink. } else { logGroupMutex.Dispose(); } } catch { } newSink = null; return(false); }