using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Wayne.Lib.IO;
namespace Wayne.Lib.Log
{
///
/// Logger is a static class used to create log objects.
///
public static class Logger
{
#region Fields
///
/// Default date and time format to use in log files.
///
public const string DefaultDateTimeFormat = "HH':'mm':'ss'.'fff'[#]'";
private const int DefaultDebugMarkerBroadcastPort = 11001;
private static readonly List OutstandingLogObjects = new List();
private static readonly object OutstandingLogObjectsLock = new object(); // Locking object to safely access the OutstandingLogObjects.
private static readonly Dictionary EventSubscriberDict = new Dictionary();
private static readonly object EventSubscriberDictSyncObj = new object();
private static readonly Dictionary ExternalLogWriterNameDict = new Dictionary();
private static readonly Dictionary ExternalLogWriterWrapperDict = new Dictionary();
private static readonly object ExternalLogWriterDictSyncObj = new object();
private static readonly byte[] DebugMarkerBroadcastReceiverBuffer = new byte[100];
private static readonly List DebugConfigFileNameList = new List();
private static readonly List EventConfigFileNameList = new List();
private static readonly List DebugConfigFilesList = new List();
private static readonly List EventConfigFilesList = new List();
private static readonly List DebugConfigBuilderList = new List();
private static readonly List EventConfigBuilderList = new List();
private static readonly List LeftoverLinesLogConfigOutputs = new List();
private static readonly List LeftoverEntitiesLogConfigOutputs = new List();
private static bool active;
private static LoggerThread loggerThread;
private static LoggerThread eventLoggerThread;
private static LogConfig debugConfig;
private static LogConfig eventConfig;
private static DotNetLog dotNetLog;
private static GlobalLogEntryCounter globalLogEntryCounter;
private static IPEndPoint debugMarkerBroadcastAddress;
private static System.Net.Sockets.Socket debugMarkerBroadcastReceiverSocket;
#endregion
#region Construction
static Logger()
{
Reset();
}
#endregion
#region Internal Properties
///
/// Tells whether someone has called the Close() method.
///
public static bool IsClosed
{
get { return !active; }
}
///
/// Internal access to the DebugConfig.
///
internal static LogConfig DebugConfig
{
get { return debugConfig; }
}
///
/// Internal access to the GlobalLogEntryCounter.
///
internal static GlobalLogEntryCounter GlobalLogEntryCounter
{
get { return globalLogEntryCounter; }
}
#endregion
#region Internal Methods
///
/// This method is used to fire an event instead of throwing an exception if something
/// "crashes" in a thread (in order to keep the thread alive but still "report" exceptions).
///
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
internal static void FireOnThreadException(LogException exception)
{
try
{
if (OnThreadException != null)
OnThreadException(null, new EventArgs(exception));
}
catch (Exception) { }
}
///
/// Internal method that is used by the EventLogSubscriptionLogWriter to publish an
/// event entry to a specific subscriber.
///
///
///
///
internal static void PublishEventLog(string eventSubscriberId, EventLogEntry eventLogEntry,
LogConfigEventLogStorageType storageType)
{
//eventLogStorage.Add(eventSubscriberId, eventLogEntry, storageType);
IEventSubscriber eventSubscriber;
lock (EventSubscriberDictSyncObj)
{
if (!EventSubscriberDict.TryGetValue(eventSubscriberId, out eventSubscriber))
eventSubscriber = null;
}
if (eventSubscriber != null)
eventSubscriber.HandleEvent(eventLogEntry);
}
#endregion
#region Internal Methods: Persistent log objects
internal static void RegisterPersistentLogObject(DebugLogger debugLogger)
{
lock (OutstandingLogObjectsLock)
{
if (!OutstandingLogObjects.Contains(debugLogger))
OutstandingLogObjects.Add(debugLogger);
}
}
internal static void UnregisterPersistentLogObject(DebugLogger debugLogger)
{
lock (OutstandingLogObjectsLock)
{
if (OutstandingLogObjects.Contains(debugLogger))
OutstandingLogObjects.Remove(debugLogger);
}
}
#endregion
#region Public Events
///
/// An event that is fired when the logging thread is catching an exception.
///
public static event EventHandler> OnThreadException;
#endregion
#region Public Properties
///
/// The current debug log configuration file.
///
[Obsolete("This property is no longer supported. Use the property DebugLoggingConfigured to check whether it's active or not.", true)]
public static string DebugConfigFileName
{
get { return string.Empty; }
}
///
/// The current event log configuration file.
///
[Obsolete("This property is no longer supported. Use the property EventLoggingConfigured to check whether it's active or not.", true)]
public static string EventConfigFileName
{
get { return string.Empty; }
}
///
/// Is any debug logging configured?
///
public static bool DebugLoggingConfigured
{
get { return debugConfig.IsConfigured; }
}
///
/// Is any event logging configured?
///
public static bool EventLoggingConfigured
{
get { return eventConfig.IsConfigured; }
}
///
/// Should the logger be synchronized or not?
/// Default is false (the log writing is performed in another thread).
///
public static bool Synchronized { get; set; }
#endregion
#region Public Methods: ConfigFile handling
///
/// Clear all loaded log configuration .
///
public static void ClearConfigFiles()
{
if (!active)
return;
DebugConfigFileNameList.Clear();
EventConfigFileNameList.Clear();
DebugConfigFilesList.Clear();
EventConfigFilesList.Clear();
DebugConfigBuilderList.Clear();
EventConfigBuilderList.Clear();
LeftoverLinesLogConfigOutputs.Clear();
LeftoverEntitiesLogConfigOutputs.Clear();
RefreshConfig();
}
///
/// Reloads the configuration from the specified configuration file.
///
/// Log configuration for the debug logging.
/// Log configuration for the event logging.
public static void SetConfigFile(string debugConfigFileName, string eventConfigFileName)
{
if (!active)
return;
ClearConfigFiles();
AddDebugConfigFile(debugConfigFileName);
AddEventConfigFile(eventConfigFileName);
}
///
/// Reloads the configuration from the specified configuration file for the debug logging. To activate the event logging
/// SetConfigFile(string,string) should be called.
///
/// Log configuration for the debug logging.
public static void SetConfigFile(string debugConfigFileName)
{
if (!active)
return;
ClearConfigFiles();
AddDebugConfigFile(debugConfigFileName);
}
///
/// Reloads the configuration, adding the given debug log config file.
///
/// Log configuration for the debug logging.
public static void AddDebugConfigFile(string debugConfigFileName)
{
if (!active)
return;
DebugConfigFileNameList.Add(debugConfigFileName);
RefreshConfig();
}
///
/// Reloads the configuration, adding the given debug log config file.
///
/// Log configurations for the debug logging.
public static void AddDebugConfigFile(params LogConfigBuilder[] logConfigBuilders)
{
if (!active)
return;
DebugConfigBuilderList.AddRange(logConfigBuilders);
RefreshConfig();
}
///
/// Reloads the configuration, adding the given debug log config file.
///
/// Log configuration for the debug logging.
public static void AddDebugConfigFile(Stream debugConfigFileStream)
{
AddDebugConfigFile(debugConfigFileStream, Encoding.UTF8);
}
///
/// Reloads the configuration, adding the given debug log config file.
///
/// Log configuration for the debug logging.
/// The encoding of the stream.
public static void AddDebugConfigFile(Stream debugConfigFileStream, Encoding encoding)
{
if (!active)
return;
DebugConfigFilesList.Add(GetFileLines(debugConfigFileStream, encoding));
RefreshConfig();
}
///
/// Reloads the configuration, adding the given event log config file.
///
/// Log configuration for the event logging.
public static void AddEventConfigFile(string eventConfigFileName)
{
if (!active)
return;
EventConfigFileNameList.Add(eventConfigFileName);
RefreshConfig();
}
///
/// Reloads the configuration, adding the given event log config file.
///
/// Log configurations for the event logging.
public static void AddEventConfigFile(params LogConfigBuilder[] logConfigBuilders)
{
if (!active)
return;
EventConfigBuilderList.AddRange(logConfigBuilders);
RefreshConfig();
}
///
/// Reloads the configuration, adding the given event log config file.
///
/// Log configuration for the event logging.
public static void AddEventConfigFile(Stream eventConfigFileStream)
{
AddDebugConfigFile(eventConfigFileStream, Encoding.UTF8);
}
///
/// Reloads the configuration, adding the given event log config file.
///
/// Log configuration for the event logging.
/// The encoding of the stream.
public static void AddEventConfigFile(Stream eventConfigFileStream, Encoding encoding)
{
if (!active)
return;
EventConfigFilesList.Add(GetFileLines(eventConfigFileStream, encoding));
RefreshConfig();
}
///
/// Reloads the configuration, adding the given leftover log line output.
///
/// An output to receive leftover log lines.
public static void AddLeftoverLinesOutput(LogConfigOutput output)
{
if (!active)
return;
LeftoverLinesLogConfigOutputs.Add((LogConfigOutput)output.Clone());
RefreshConfig();
}
///
/// Reloads the configuration, adding the given leftover log entity output.
///
/// An output to receive leftover log entities.
public static void AddLeftoverEntitiesOutput(LogConfigOutput output)
{
if (!active)
return;
LeftoverEntitiesLogConfigOutputs.Add((LogConfigOutput)output.Clone());
RefreshConfig();
}
private static string[] GetFileLines(Stream fileStream, Encoding encoding)
{
List lines = new List();
using (StreamReader reader = new StreamReader(fileStream, encoding))
{
while (!reader.EndOfStream)
lines.Add(reader.ReadLine());
}
return lines.ToArray();
}
#endregion
#region Public Methods: Refresh
///
/// Re-loads the configuration for the logging.
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
public static void RefreshConfig()
{
if (!active)
return;
InitDebugMarkerBroadcastListener();
// Refresh the DebugConfig.
List debugConfigFiles = new List(DebugConfigFilesList);
foreach (string fileName in DebugConfigFileNameList)
debugConfigFiles.Add(FileSupport.LoadToStringArray(fileName));
if (DebugConfigBuilderList.Count > 0)
debugConfigFiles.Add(LogConfigBuilder.GetLogConfigFileLines(DebugConfigBuilderList.ToArray()));
DebugConfig.Refresh(debugConfigFiles, LeftoverLinesLogConfigOutputs.ToArray(), LeftoverEntitiesLogConfigOutputs.ToArray());
// Refresh the EventConfig.
List eventConfigFiles = new List(EventConfigFilesList);
foreach (string fileName in EventConfigFileNameList)
eventConfigFiles.Add(FileSupport.LoadToStringArray(fileName));
if (EventConfigBuilderList.Count > 0)
eventConfigFiles.Add(LogConfigBuilder.GetLogConfigFileLines(EventConfigBuilderList.ToArray()));
eventConfig.Refresh(eventConfigFiles, new LogConfigOutput[0], new LogConfigOutput[0]);
// Start the thread if it's not yet started (first time it's null).
if ((loggerThread == null) && (debugConfigFiles.Count > 0))
loggerThread = new LoggerThread(LogType.Debug, debugConfig);
if ((eventLoggerThread == null) && (eventConfigFiles.Count > 0))
eventLoggerThread = new LoggerThread(LogType.Event, eventConfig);
// To prevent locking the list while iterating, take a copy and iterate through the copy.
// The danger of doing this is that an object could be removed after the copy and before its
// Invalidate-method is called. But nothing really bad can happen due to this...
List outstandingLogObjectsCopy;
lock (OutstandingLogObjectsLock)
{
outstandingLogObjectsCopy = new List(OutstandingLogObjects);
}
foreach (DebugLogger debugLogger in outstandingLogObjectsCopy)
{
try
{
debugLogger.Invalidate();
}
catch (Exception) { }
}
// Check if the dotNetLog should be active or not.
dotNetLog.CheckActive();
}
#endregion
#region Public Methods: Reset
///
/// Resets the logger completely.
///
public static void Reset()
{
Close();
active = true;
debugConfig = new LogConfig();
eventConfig = new LogConfig();
dotNetLog = new DotNetLog();
globalLogEntryCounter = new GlobalLogEntryCounter();
}
#endregion
#region Public Methods: Close
///
/// Closes the logger. This should be done as the last things before the application terminates.
///
public static void Close()
{
if (active)
{
// Shut down the config.
if (debugConfig != null)
{
debugConfig.Dispose();
debugConfig = null;
}
if (eventConfig != null)
{
eventConfig.Dispose();
eventConfig = null;
}
if (dotNetLog != null)
{
// Shut down the dotNetLog.
dotNetLog.Dispose();
dotNetLog = null;
}
ExternalLogWriterNameDict.Clear();
ExternalLogWriterWrapperDict.Clear();
// Now we're closed.
active = false;
// Shut down the loggerThread.
if (loggerThread != null)
{
loggerThread.Dispose();
loggerThread = null;
}
if (eventLoggerThread != null)
{
eventLoggerThread.Dispose();
eventLoggerThread = null;
}
if (debugMarkerBroadcastReceiverSocket != null)
{
try
{
if (debugMarkerBroadcastReceiverSocket.Connected)
{
debugMarkerBroadcastReceiverSocket.Shutdown(SocketShutdown.Both);
}
}
catch { }
try
{
debugMarkerBroadcastReceiverSocket.Close();
}
catch { }
debugMarkerBroadcastReceiverSocket = null;
}
if (globalLogEntryCounter != null)
{
globalLogEntryCounter.Dispose();
globalLogEntryCounter = null;
}
debugMarkerBroadcastAddress = null;
DebugConfigFileNameList.Clear();
DebugConfigFilesList.Clear();
EventConfigFileNameList.Clear();
EventConfigFilesList.Clear();
DebugConfigBuilderList.Clear();
EventConfigBuilderList.Clear();
OutstandingLogObjects.Clear();
EventSubscriberDict.Clear();
LeftoverLinesLogConfigOutputs.Clear();
LeftoverEntitiesLogConfigOutputs.Clear();
Synchronized = false;
}
}
#endregion
#region Public Methods: LogEntry
///
/// Logs the given LogEntry.
///
/// The LogEntry to log.
public static void AddEntry(LogEntry logEntry)
{
if (!active)
return;
if (loggerThread != null)
loggerThread.AddEntry(logEntry);
if ((eventLoggerThread != null) && (logEntry is EventLogEntry))
eventLoggerThread.AddEntry(logEntry); // eventThread has higher priority?
}
///
/// Logs the given ExceptionLogEntry.
///
/// The LogEntry to log.
public static void AddExceptionLogEntry(ExceptionLogEntry logEntry)
{
AddEntry(logEntry);
}
///
/// Logs the given ErrorLogEntry.
///
/// The LogEntry to log.
public static void AddErrorLogEntry(ErrorLogEntry logEntry)
{
AddEntry(logEntry);
}
///
/// Logs the given EventLogEntry.
///
/// The LogEntry to log.
public static void AddEventLogEntry(EventLogEntry logEntry)
{
AddEntry(logEntry);
}
#endregion
#region Public Methods: Unregister entity
///
/// Removes the specified entity from the internal filter buffers.
///
///
public static void UnregisterEntity(IIdentifiableEntity entity)
{
if (debugConfig != null)
debugConfig.UnregisterEntity(entity);
if (eventConfig != null)
eventConfig.UnregisterEntity(entity);
}
#endregion
#region Public Methods for Event Subscribers
///
/// Remove an event log from the storage. This method should be called from a registered IEventSubscriber when
/// it has handled an event.
///
///
///
public static void EventLogHandled(IEventSubscriber eventSubscriber, EventLogEntry eventLogEntry)
{
//eventLogStorage.Remove(eventSubscriber, eventLogEntry);
}
///
/// Register an IEventSubscriber, so it can start receiving events. The event subscriber will be sent the pending events that
/// has been stored since the subscriber was registered the last time.
///
///
public static void RegisterEventSubscriber(IEventSubscriber eventSubscriber)
{
if (eventSubscriber == null)
throw new ArgumentNullException("eventSubscriber");
lock (EventSubscriberDictSyncObj)
{
EventSubscriberDict[eventSubscriber.SubscriberId] = eventSubscriber;
}
//EventLogEntry[] entries = eventLogStorage.GetPendingEvents(eventSubscriber.SubscriberId);
//foreach (EventLogEntry entry in entries)
// eventSubscriber.HandleEvent(entry);
}
///
/// Unregister a registered IEventSubscriber.
///
///
public static void UnregisterEventSubscriber(IEventSubscriber eventSubscriber)
{
if (eventSubscriber == null)
throw new ArgumentNullException("eventSubscriber");
lock (EventSubscriberDictSyncObj)
{
EventSubscriberDict.Remove(eventSubscriber.SubscriberId);
}
}
#endregion
#region ExternalLogging
private static string GetExternalLogWriterKey(ExternalLogWriter externalLogWriter)
{
return string.Format("{0}#{1}", externalLogWriter.ExternalLogType, externalLogWriter.ExternalLogName);
}
private static string GetExternalLogWriterKey(ExternalLogWriterWrapper externalLogWriterWrapper)
{
return string.Format("{0}#{1}", externalLogWriterWrapper.ExternalLogType, externalLogWriterWrapper.ExternalLogName);
}
///
/// Register an ExternalLogWriter.
///
/// The external log writer to register.
public static void RegisterExternalLogger(ExternalLogWriter externalLogWriter)
{
if (ExternalLogWriterDictSyncObj != null)
lock (ExternalLogWriterDictSyncObj)
ExternalLogWriterNameDict[GetExternalLogWriterKey(externalLogWriter)] = externalLogWriter;
}
///
/// Unregister an ExternalLogWriter.
///
/// The external log writer to unregister.
public static void UnregisterExternalLogger(ExternalLogWriter externalLogWriter)
{
if (ExternalLogWriterDictSyncObj != null)
lock (ExternalLogWriterDictSyncObj)
{
ExternalLogWriterNameDict.Remove(GetExternalLogWriterKey(externalLogWriter));
bool found;
do
{
found = false;
foreach (KeyValuePair pair in ExternalLogWriterWrapperDict)
{
if (pair.Value == externalLogWriter)
{
ExternalLogWriterWrapperDict.Remove(pair.Key);
found = true;
break;
}
}
}
while (found);
}
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
internal static void PerformExternalLogEntry(ExternalLogWriterWrapper externalLogWriterWrapper, LogEntry logEntry)
{
if (ExternalLogWriterDictSyncObj != null)
{
lock (ExternalLogWriterDictSyncObj)
{
ExternalLogWriter externalLogWriter;
if (!ExternalLogWriterWrapperDict.TryGetValue(externalLogWriterWrapper, out externalLogWriter))
{
if (ExternalLogWriterNameDict.TryGetValue(GetExternalLogWriterKey(externalLogWriterWrapper), out externalLogWriter))
{
externalLogWriter.InitParametersInternal(externalLogWriterWrapper.Parameters);
ExternalLogWriterWrapperDict[externalLogWriterWrapper] = externalLogWriter;
}
}
if (externalLogWriter != null)
{
try
{
if (externalLogWriter.Active)
{
string text = LogTextWriting.GetLogEntryText(externalLogWriterWrapper, logEntry,
externalLogWriterWrapper.WritingParameters);
externalLogWriter.LogInternal(logEntry, text);
}
}
catch { }
}
}
}
}
///
/// Get the LogTextWritingParameters for the requested ExternalLogWriter.
///
/// The ExternalLogWriter to get the parameters of.
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")]
internal static LogTextWritingParameters GetExternalLoggerWritingParameters(ExternalLogWriter externalLogWriter)
{
if (ExternalLogWriterDictSyncObj != null)
{
lock (ExternalLogWriterDictSyncObj)
{
foreach (KeyValuePair pair in ExternalLogWriterWrapperDict)
{
if (pair.Value == externalLogWriter)
{
return pair.Key.WritingParameters;
}
}
}
}
return null;
}
#endregion
#region Debug Marker Broadcasting
///
/// Broadcasts a debug marker to be inserted into all active logfiles.
///
/// The text to insert into all the log files.
// public static void InjectDebugMarker(string debugMarker)
// {
// try
// {
// System.Net.Sockets.Socket transmitterSocket = null;
// try
// {
// try
// {
//transmitterSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.IP);
// transmitterSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
// var lingerOption = new LingerOption(true, 0);
// transmitterSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
// transmitterSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, 1);
// transmitterSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); // Bind the socket to the "any" end point.
// byte[] data = Encoding.UTF8.GetBytes(debugMarker);
// int offset = 0;
// int size = data.Length;
// if (size > DebugMarkerBroadcastReceiverBuffer.Length)
// size = DebugMarkerBroadcastReceiverBuffer.Length;
// int currentSentSize;
// do
// {
// currentSentSize = transmitterSocket.SendTo(data, offset, size, SocketFlags.None, GetDebugMarkerBroadcastIPEndPoint());
// offset += currentSentSize;
// size -= currentSentSize;
// }
// while ((size > 0) && (currentSentSize > 0));
// }
// catch (Exception) { }
// }
// finally
// {
// if (transmitterSocket != null)
// {
// try
// {
// transmitterSocket.Shutdown(SocketShutdown.Both);
// }
// finally
// {
// transmitterSocket.Close();
// }
// }
// }
// }
// catch (Exception) { }
// }
private static void InitDebugMarkerBroadcastListener()
{
if (debugMarkerBroadcastReceiverSocket == null)
{
try
{
debugMarkerBroadcastReceiverSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.IP);
debugMarkerBroadcastReceiverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
//debugMarkerBroadcastReceiverSocket.Bind(new IPEndPoint(IPAddress.Any, GetDebugMarkerBroadcastIPEndPoint().Port)); // Bind the socket to the "any" end point.
debugMarkerBroadcastReceiverSocket.BeginReceive(DebugMarkerBroadcastReceiverBuffer, 0, DebugMarkerBroadcastReceiverBuffer.Length, 0, ReceiveCallback, debugMarkerBroadcastReceiverSocket); // Start to listen.
}
catch
{
try
{
debugMarkerBroadcastReceiverSocket.Close();
}
catch (Exception)
{
}
debugMarkerBroadcastReceiverSocket = null;
}
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
if (debugMarkerBroadcastReceiverSocket != null)
{
try
{
try
{
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)ar.AsyncState;
int bytesReceived = 0;
try
{
try
{
bytesReceived = socket.EndReceive(ar);
}
catch { }
}
finally
{
if (bytesReceived > 0)
{
string debugMarker = Encoding.UTF8.GetString(DebugMarkerBroadcastReceiverBuffer, 0, bytesReceived);
AddEntry(new DebugMarkerLogEntry(debugMarker));
}
}
}
finally
{
if (active)
debugMarkerBroadcastReceiverSocket.BeginReceive(DebugMarkerBroadcastReceiverBuffer, 0, DebugMarkerBroadcastReceiverBuffer.Length, 0, ReceiveCallback, debugMarkerBroadcastReceiverSocket);
}
}
catch { }
}
}
//[System.Diagnostics.DebuggerStepThrough()]
//private static IPEndPoint GetDebugMarkerBroadcastIPEndPoint()
//{
// try
// {
// if (debugMarkerBroadcastAddress == null)
// {
// using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"Software\Dresser Wayne\ISM Nucleus\TCP IP\UDP Broadcast", false))
// {
// IPAddress broadcastAddress;
// int broadcastPort;
// if (key != null)
// {
// broadcastAddress = IPAddress.Parse((string)key.GetValue("BroadcastAddress", "255.255.255.255"));
// broadcastPort = (int)key.GetValue("LogMarkerInjectorPort", DefaultDebugMarkerBroadcastPort);
// }
// else
// {
// broadcastPort = DefaultDebugMarkerBroadcastPort;
// broadcastAddress = IPAddress.Broadcast;
// }
// if (broadcastAddress != null)
// debugMarkerBroadcastAddress = new IPEndPoint(broadcastAddress, broadcastPort);
// }
// }
// }
// catch
// {
// if (debugMarkerBroadcastAddress == null)
// debugMarkerBroadcastAddress = new IPEndPoint(IPAddress.Broadcast, DefaultDebugMarkerBroadcastPort);
// }
// return debugMarkerBroadcastAddress;
//}
#endregion
#region DateTimeToString
internal static string DateTimeToString(DateTime dateTime, string dateTimeFormat)
{
if (GlobalLogEntryCounter != null)
return DateTimeToString(dateTime, dateTimeFormat, GlobalLogEntryCounter.GetNextValue());
return DateTimeToString(dateTime, dateTimeFormat, 0);
}
internal static string DateTimeToString(DateTime dateTime, string dateTimeFormat, UInt64 logEntryIndex)
{
return FormatDateTime(dateTime) + "[" + logEntryIndex.ToString("00000") + "]";
}
private static string FormatDateTime(DateTime dt)
{
char[] chars = new char[12];
Write2Chars(chars, 0, dt.Hour);
chars[2] = ':';
Write2Chars(chars, 3, dt.Minute);
chars[5] = ':';
Write2Chars(chars, 6, dt.Second);
chars[8] = '.';
Write2Chars(chars, 9, dt.Millisecond / 10);
chars[11] = Digit(dt.Millisecond % 10);
return new string(chars);
}
private static void Write2Chars(char[] chars, int offset, int value)
{
chars[offset] = Digit(value / 10);
chars[offset + 1] = Digit(value % 10);
}
private static char Digit(int value)
{
return (char)(value + '0');
}
#endregion
}
}