/// <summary> /// Initializes the log message. /// </summary> /// <param name="timestamp">Time the message was written to the log.</param> /// <param name="highPrecisionTimestamp"> /// Timestamp for relative time measurements with high precision /// (the actual precision depends on the <see cref="System.Diagnostics.Stopwatch"/> class). /// </param> /// <param name="lostMessageCount"> /// Gets or sets the number of preceding messages that have been lost before this message /// (useful when dealing with message streams). /// </param> /// <param name="logWriterName">Name of the log writer that was used to emit the message.</param> /// <param name="logLevelName">Name of the log level that is associated with the message.</param> /// <param name="tags">Tags that are associated with the message.</param> /// <param name="applicationName"> /// Name of the application emitting the log message /// (can differ from the process name, if the application is using an interpreter (the actual process)). /// </param> /// <param name="processName">Name of the process emitting the log message.</param> /// <param name="processId">Id of the process emitting the log message.</param> /// <param name="text">The actual text the log message is about.</param> /// <returns>The initialized log message.</returns> /// <exception cref="InvalidOperationException">The log message has not been prepared for asynchronous initialization.</exception> /// <exception cref="InvalidOperationException">The log message is already initialized.</exception> LogMessage ILogMessageInitializer.Initialize( DateTimeOffset timestamp, long highPrecisionTimestamp, int lostMessageCount, string logWriterName, string logLevelName, TagSet tags, string applicationName, string processName, int processId, string text) { lock (Sync) { if (!IsAsyncInitPending) { throw new InvalidOperationException("The log message is not prepared for asynchronous initialization."); } if (IsInitializedInternal) { throw new InvalidOperationException("The log message is already initialized."); } mTimestamp = timestamp; mHighPrecisionTimestamp = highPrecisionTimestamp; mLostMessageCount = lostMessageCount; mLogWriterName = logWriterName; mLogLevelName = logLevelName; mTags = tags; mApplicationName = applicationName; mProcessName = processName; mProcessId = processId; mText = text; IsAsyncInitPending = false; IsInitializedInternal = true; } OnPropertyChanged(null); return(this); }
/// <summary> /// Initializes the log message. /// </summary> /// <param name="id">Id uniquely identifying the message in the log file.</param> /// <param name="timestamp">Time the message was written to the log.</param> /// <param name="highPrecisionTimestamp"> /// Timestamp for relative time measurements with high precision /// (the actual precision depends on the <see cref="System.Diagnostics.Stopwatch"/> class). /// </param> /// <param name="lostMessageCount"> /// Gets or sets the number of preceding messages that have been lost before this message /// (useful when dealing with message streams). /// </param> /// <param name="logWriterName">Name of the log writer that was used to emit the message.</param> /// <param name="logLevelName">Name of the log level that is associated with the message.</param> /// <param name="tags">Tags that are associated with the message.</param> /// <param name="applicationName"> /// Name of the application emitting the log message /// (can differ from the process name, if the application is using an interpreter (the actual process)). /// </param> /// <param name="processName">Name of the process emitting the log message.</param> /// <param name="processId">Id of the process emitting the log message.</param> /// <param name="text">The actual text the log message is about.</param> /// <returns>The initialized log message.</returns> /// <exception cref="InvalidOperationException">The log message has not been prepared for asynchronous initialization.</exception> /// <exception cref="InvalidOperationException">The log message is already initialized.</exception> LogFileMessage IFileLogMessageInitializer.Initialize( long id, DateTimeOffset timestamp, long highPrecisionTimestamp, int lostMessageCount, string logWriterName, string logLevelName, TagSet tags, string applicationName, string processName, int processId, string text) { lock (Sync) { // disable raising the PropertyChanged event PropertyChangedSuspensionCounter++; // set specific message fields mId = id; // set command message fields ((ILogMessageInitializer)this).Initialize( timestamp, highPrecisionTimestamp, lostMessageCount, logWriterName, logLevelName, tags, applicationName, processName, processId, text); // enable raising the PropertyChanged event PropertyChangedSuspensionCounter--; } OnPropertyChanged(null); return(this); }
/// <summary> /// Initializes the log message atomically. /// The <see cref="PropertyChanged"/> event is only fired once. /// </summary> /// <param name="timestamp">Time the message was written to the log.</param> /// <param name="highPrecisionTimestamp"> /// Timestamp for relative time measurements with high precision /// (the actual precision depends on the <see cref="System.Diagnostics.Stopwatch"/> class). /// </param> /// <param name="lostMessageCount"> /// Gets or sets the number of preceding messages that have been lost before this message /// (useful when dealing with message streams). /// </param> /// <param name="logWriterName">Name of the log writer that was used to emit the message.</param> /// <param name="logLevelName">Name of the log level that is associated with the message.</param> /// <param name="tags">Tags that are associated with the message.</param> /// <param name="applicationName"> /// Name of the application emitting the log message /// (can differ from the process name, if the application is using an interpreter (the actual process)). /// </param> /// <param name="processName">Name of the process emitting the log message.</param> /// <param name="processId">Id of the process emitting the log message.</param> /// <param name="text">The actual text the log message is about.</param> /// <returns>The log message itself.</returns> /// <exception cref="NotSupportedException">The log message is read-only.</exception> /// <exception cref="InvalidOperationException">Initializing manually is not allowed as an asynchronous initialization is pending.</exception> public LogMessage InitWith( DateTimeOffset timestamp, long highPrecisionTimestamp, int lostMessageCount, string logWriterName, string logLevelName, TagSet tags, string applicationName, string processName, int processId, string text) { lock (Sync) { if (IsReadOnlyInternal) { throw new NotSupportedException("The log message is read-only."); } if (IsAsyncInitPending) { throw new InvalidOperationException("Initializing manually is not allowed as an asynchronous initialization is pending."); } mTimestamp = timestamp; mHighPrecisionTimestamp = highPrecisionTimestamp; mLostMessageCount = lostMessageCount; mLogWriterName = logWriterName; mLogLevelName = logLevelName; mTags = tags; mApplicationName = applicationName; mProcessName = processName; mProcessId = processId; mText = text; IsInitializedInternal = true; } OnPropertyChanged(null); return(this); }
/// <summary> /// Gets a deterministic set of random log messages. /// </summary> /// <param name="count">Number of log messages to generate.</param> /// <param name="randomNumberGeneratorSeed"> /// Seed for the random number generator /// (0 is usually used to generate default log message sets, use some other value to generate a different set). /// </param> /// <param name="maxDifferentWritersCount">Maximum number of different log writer names.</param> /// <param name="maxDifferentLevelsCount">Maximum number of different log level names.</param> /// <param name="maxDifferentApplicationsCount">Maximum number of different application names.</param> /// <param name="maxDifferentProcessIdsCount">Maximum number of different process ids.</param> /// <returns>The requested log message set.</returns> public static TMessage[] GetTestMessages <TMessage>( int count, int randomNumberGeneratorSeed = 0, int maxDifferentWritersCount = 50, int maxDifferentLevelsCount = 50, int maxDifferentApplicationsCount = 3, int maxDifferentProcessIdsCount = 10000) where TMessage : class, ILogMessage, new() { var messages = new List <TMessage>(); var random = new Random(randomNumberGeneratorSeed); var utcTimestamp = DateTime.Parse("2020-01-01T01:02:03"); long highPrecisionTimestamp = 0; // init list of tags to select from var allTags = new List <string>(); for (int i = 0; i < 50; i++) { allTags.Add($"Tag{i}"); } for (long i = 0; i < count; i++) { var timezoneOffset = TimeSpan.FromHours(random.Next(-14, 14)); int processId = random.Next(1, maxDifferentProcessIdsCount); // build tag set to associate with a message (up to 3 tags per message) // (the first and the last message must contain at least one tag for filter tests) int tagCount = random.Next(i == 0 || i == count - 1 ? 1 : 0, 3); var tags = new TagSet(); for (int j = 0; j < tagCount; j++) { tags += allTags[random.Next(0, allTags.Count - 1)]; } var message = new TMessage { Timestamp = new DateTimeOffset(utcTimestamp + timezoneOffset, timezoneOffset), HighPrecisionTimestamp = highPrecisionTimestamp, LostMessageCount = random.Next(0, 1), LogWriterName = $"Log Writer {random.Next(1, maxDifferentWritersCount)}", LogLevelName = $"Log Level {random.Next(1, maxDifferentLevelsCount)}", Tags = tags, ApplicationName = $"Application {random.Next(1, maxDifferentApplicationsCount)}", ProcessName = $"Process {processId}", ProcessId = processId, Text = $"[{i + 1:D6}/{count:D6}] Log message # Generated Text: {i / 10:D6}/{'a' + i % 10}" // lower-case letter in text only }; // move the timestamps up to 1 day into the future var timeSkip = TimeSpan.FromMilliseconds(random.Next(1, 24 * 60 * 60 * 1000)); utcTimestamp += timeSkip; highPrecisionTimestamp += timeSkip.Ticks * 10; // the high precision timestamp is in nanoseconds, ticks are in 100ps messages.Add(message); } // the first an the last message should have different field values to allow the tests to match properly if (count > 0) { var firstMessage = messages[0]; firstMessage.LogWriterName = "log writer of first message"; firstMessage.LogLevelName = "log level of first message"; firstMessage.ApplicationName = "application name of first message"; firstMessage.ProcessName = "process name of first message"; firstMessage.ProcessId = int.MinValue; firstMessage.Tags = new TagSet("tag-of-first-message"); // firstMessage.Text is just fine var lastMessage = messages[count - 1]; lastMessage.LogWriterName = "log writer of last message"; lastMessage.LogLevelName = "log level of last message"; lastMessage.ApplicationName = "application name of last message"; lastMessage.ProcessName = "process name of last message"; lastMessage.ProcessId = int.MaxValue; lastMessage.Tags = new TagSet("tag-of-last-message"); // lastMessage.Text is just fine } return(messages.ToArray()); }
public void OperatorInequality(bool expected, TagSet left, TagSet right) { bool isEqual = left != right; Assert.Equal(expected, isEqual); }