/// <summary> /// Callback used to accept a connection on the server socket /// </summary> /// <param name="asyncResult">The result of the asynchronous operation</param> /// <remarks> /// <para> /// On connection adds to the list of connections /// if there are two many open connections you will be disconnected /// </para> /// </remarks> private void OnConnect(IAsyncResult asyncResult) { Socket socket = m_serverSocket.EndAccept(asyncResult); SocketClient client = new SocketClient(socket); try { LogLog.Trace("TelnetAppender: Accepting connection from [" + socket.RemoteEndPoint.ToString() + "]"); int currentActiveConnectionsCount = m_clients.Count; if (currentActiveConnectionsCount < MAX_CONNECTIONS) { client.Send("TelnetAppender v1.0 (" + (currentActiveConnectionsCount + 1) + " active connections)\r\n\r\n"); AddClient(client); } else { client.Send("Sorry - Too many connections.\r\n"); client.Dispose(); } } catch (Exception) { LogLog.Warn("Add connection to list: exception while trying to add connection"); } finally { if (m_serverSocket != null) { m_serverSocket.BeginAccept(new AsyncCallback(OnConnect), null); } } }
/// <summary> /// Parses an object renderer. /// </summary> /// <param name="element">The renderer element.</param> /// <remarks> /// <para> /// Parse an XML element that represents a renderer. /// </para> /// </remarks> protected void ParseRenderer(XmlElement element) { string renderingClassName = element.GetAttribute(RENDERING_TYPE_ATTR); string renderedClassName = element.GetAttribute(RENDERED_TYPE_ATTR); LogLog.Trace("XmlHierarchyConfigurator: Rendering class [" + renderingClassName + "], Rendered class [" + renderedClassName + "]."); IObjectRenderer renderer = (IObjectRenderer)OptionConverter.InstantiateByClassName(renderingClassName, typeof(IObjectRenderer), null); if (renderer == null) { LogLog.Error("XmlHierarchyConfigurator: Could not instantiate renderer [" + renderingClassName + "]."); return; } else { try { m_hierarchy.RendererMap.Put(SystemInfo.GetTypeFromString(renderedClassName, true, true), renderer); } catch (Exception e) { LogLog.Error("XmlHierarchyConfigurator: Could not find class [" + renderedClassName + "].", e); } } }
/// <summary> /// Write an environment variable to the output /// </summary> /// <param name="writer">the writer to write to</param> /// <param name="state">null, state is not set</param> /// <remarks> /// <para> /// Writes the environment variable to the output <paramref name="writer"/>. /// The name of the environment variable to output must be set /// using the <see cref="Library.Logging.Util.PatternConverter.Option"/> /// property. /// </para> /// </remarks> override protected void Convert(TextWriter writer, object state) { try { if (this.Option != null && this.Option.Length > 0) { // Lookup the environment variable string envValue = Environment.GetEnvironmentVariable(this.Option); if (envValue != null && envValue.Length > 0) { writer.Write(envValue); } } } catch (System.Security.SecurityException secEx) { // This security exception will occur if the caller does not have // unrestricted environment permission. If this occurs the expansion // will be skipped with the following warning message. LogLog.Trace("EnvironmentPatternConverter: Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx); } catch (Exception ex) { LogLog.Error("EnvironmentPatternConverter: Error occurred while converting environment variable.", ex); } }
/// <summary> /// Shutting down a hierarchy will <i>safely</i> close and remove /// all appenders in all loggers including the root logger. /// </summary> /// <remarks> /// <para> /// Shutting down a hierarchy will <i>safely</i> close and remove /// all appenders in all loggers including the root logger. /// </para> /// <para> /// Some appenders need to be closed before the /// application exists. Otherwise, pending logging events might be /// lost. /// </para> /// <para> /// The <c>Shutdown</c> method is careful to close nested /// appenders before closing regular appenders. This is allows /// configurations where a regular appender is attached to a logger /// and again to a nested appender. /// </para> /// </remarks> override public void Shutdown() { LogLog.Trace("Hierarchy: Shutdown called on Hierarchy [" + this.Name + "]"); // begin by closing nested appenders Root.CloseNestedAppenders(); lock (m_ht) { ILogger[] currentLoggers = this.GetCurrentLoggers(); foreach (Logger logger in currentLoggers) { logger.CloseNestedAppenders(); } // then, remove all appenders Root.RemoveAllAppenders(); foreach (Logger logger in currentLoggers) { logger.RemoveAllAppenders(); } } base.Shutdown(); }
/// <summary> /// Configures the specified repository using a <c> Logging</c> element. /// </summary> /// <param name="repository">The hierarchy to configure.</param> /// <param name="element">The element to parse.</param> /// <remarks> /// <para> /// Loads the Logging configuration from the XML element /// supplied as <paramref name="element"/>. /// </para> /// <para> /// This method is ultimately called by one of the Configure methods /// to load the configuration from an <see cref="XmlElement"/>. /// </para> /// </remarks> static private void ConfigureFromXml(ILoggerRepository repository, XmlElement element) { if (element == null) { LogLog.Error("XmlConfigurator: ConfigureFromXml called with null 'element' parameter"); } else if (repository == null) { LogLog.Error("XmlConfigurator: ConfigureFromXml called with null 'repository' parameter"); } else { LogLog.Trace("XmlConfigurator: Configuring Repository [" + repository.Name + "]"); IXmlRepositoryConfigurator configurableRepository = repository as IXmlRepositoryConfigurator; if (configurableRepository == null) { LogLog.Warn("XmlConfigurator: Repository [" + repository + "] does not support the XmlConfigurator"); } else { // Copy the xml data into the root of a new document // this isolates the xml config data from the rest of // the document XmlDocument newDoc = new XmlDocument(); XmlElement newElement = (XmlElement)newDoc.AppendChild(newDoc.ImportNode(element, true)); // Pass the configurator the config element configurableRepository.Configure(newElement); } } }
/// <summary> /// Write the current thread identity to the output /// </summary> /// <param name="writer">the writer to write to</param> /// <param name="state">null, state is not set</param> /// <remarks> /// <para> /// Writes the current thread identity to the output <paramref name="writer"/>. /// </para> /// </remarks> override protected void Convert(TextWriter writer, object state) { #if (NETCF || SSCLI) // On compact framework there's no notion of current thread principals writer.Write(SystemInfo.NotAvailableText); #else try { if (System.Threading.Thread.CurrentPrincipal != null && System.Threading.Thread.CurrentPrincipal.Identity != null && System.Threading.Thread.CurrentPrincipal.Identity.Name != null) { writer.Write(System.Threading.Thread.CurrentPrincipal.Identity.Name); } } catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Trace("IdentityPatternConverter: Security exception while trying to get current thread principal. Error Ignored."); writer.Write(SystemInfo.NotAvailableText); } #endif }
/// <summary> /// Configures the <see cref="ILoggerRepository"/> using the file specified, /// monitors the file for changes and reloads the configuration if a change /// is detected. /// </summary> /// <param name="repository">The repository to configure.</param> /// <param name="configFile">The XML file to load the configuration from.</param> /// <remarks> /// <para> /// The configuration file must be valid XML. It must contain /// at least one element called <c> Logging</c> that holds /// the configuration data. /// </para> /// <para> /// The configuration file will be monitored using a <see cref="FileSystemWatcher"/> /// and depends on the behavior of that class. /// </para> /// <para> /// For more information on how to configure Logging using /// a separate configuration file, see <see cref="Configure(FileInfo)"/>. /// </para> /// </remarks> /// <seealso cref="Configure(FileInfo)"/> static public void ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile) { LogLog.Trace("XmlConfigurator: configuring repository [" + repository.Name + "] using file [" + configFile + "] watching for file updates"); if (configFile == null) { LogLog.Error("XmlConfigurator: ConfigureAndWatch called with null 'configFile' parameter"); } else { // Configure Logging now Configure(repository, configFile); try { // Create a watch handler that will reload the // configuration whenever the config file is modified. ConfigureAndWatchHandler.StartWatching(repository, configFile); } catch (Exception ex) { LogLog.Error("XmlConfigurator: Failed to initialize configuration file watcher for file [" + configFile.FullName + "]", ex); } } }
/// <summary> /// Write the current threads username to the output /// </summary> /// <param name="writer">the writer to write to</param> /// <param name="state">null, state is not set</param> /// <remarks> /// <para> /// Write the current threads username to the output <paramref name="writer"/>. /// </para> /// </remarks> override protected void Convert(TextWriter writer, object state) { #if (NETCF || SSCLI) // On compact framework there's no notion of current Windows user writer.Write(SystemInfo.NotAvailableText); #else try { System.Security.Principal.WindowsIdentity windowsIdentity = null; windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent(); if (windowsIdentity != null && windowsIdentity.Name != null) { writer.Write(windowsIdentity.Name); } } catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Trace("UserNamePatternConverter: Security exception while trying to get current windows identity. Error Ignored."); writer.Write(SystemInfo.NotAvailableText); } #endif }
/// <summary> /// Event handler used by <see cref="ConfigureAndWatchHandler"/>. /// </summary> /// <param name="source">The <see cref="FileSystemWatcher"/> firing the event.</param> /// <param name="e">The argument indicates the file that caused the event to be fired.</param> /// <remarks> /// <para> /// This handler reloads the configuration from the file when the event is fired. /// </para> /// </remarks> private void ConfigureAndWatchHandler_OnRenamed(object source, RenamedEventArgs e) { LogLog.Trace("ConfigureAndWatchHandler: " + e.ChangeType + " [" + m_configFile.FullName + "]"); // Deliver the event in TimeoutMillis time // timer will fire only once m_timer.Change(TimeoutMillis, Timeout.Infinite); }
/// <summary> /// Gets the repository name and repository type for the specified assembly. /// </summary> /// <param name="assembly">The assembly that has a <see cref="Library.Logging.Config.RepositoryAttribute"/>.</param> /// <param name="repositoryName">in/out param to hold the repository name to use for the assembly, caller should set this to the default value before calling.</param> /// <param name="repositoryType">in/out param to hold the type of the repository to create for the assembly, caller should set this to the default value before calling.</param> /// <exception cref="ArgumentNullException"><paramref name="assembly" /> is <see langword="null" />.</exception> private void GetInfoForAssembly(Assembly assembly, ref string repositoryName, ref Type repositoryType) { if (assembly == null) { throw new ArgumentNullException("assembly"); } try { // Look for the RepositoryAttribute on the assembly object[] repositoryAttributes = Attribute.GetCustomAttributes(assembly, typeof(Library.Logging.Config.RepositoryAttribute), false); if (repositoryAttributes == null || repositoryAttributes.Length == 0) { // This is not a problem, but its nice to know what is going on. LogLog.Trace("DefaultRepositorySelector: Assembly [" + assembly + "] does not have a RepositoryAttribute specified."); } else { if (repositoryAttributes.Length > 1) { LogLog.Error("DefaultRepositorySelector: Assembly [" + assembly + "] has multiple Library.Logging.Config.RepositoryAttribute assembly attributes. Only using first occurrence."); } Library.Logging.Config.RepositoryAttribute domAttr = repositoryAttributes[0] as Library.Logging.Config.RepositoryAttribute; if (domAttr == null) { LogLog.Error("DefaultRepositorySelector: Assembly [" + assembly + "] has a RepositoryAttribute but it does not!."); } else { // If the Name property is set then override the default if (domAttr.Name != null) { repositoryName = domAttr.Name; } // If the RepositoryType property is set then override the default if (domAttr.RepositoryType != null) { // Check that the type is a repository if (typeof(ILoggerRepository).IsAssignableFrom(domAttr.RepositoryType)) { repositoryType = domAttr.RepositoryType; } else { LogLog.Error("DefaultRepositorySelector: Repository Type [" + domAttr.RepositoryType + "] must implement the ILoggerRepository interface."); } } } } } catch (Exception ex) { LogLog.Error("DefaultRepositorySelector: Unhandled exception in GetInfoForAssembly", ex); } }
/// <summary> /// Configures the <see cref="ILoggerRepository"/> using the specified configuration /// file. /// </summary> /// <param name="repository">The repository to configure.</param> /// <param name="configFile">The XML file to load the configuration from.</param> /// <remarks> /// <para> /// The configuration file must be valid XML. It must contain /// at least one element called <c> Logging</c> that holds /// the configuration data. /// </para> /// <para> /// The Logging configuration file can possible be specified in the application's /// configuration file (either <c>MyAppName.exe.config</c> for a /// normal application on <c>Web.config</c> for an ASP.NET application). /// </para> /// <para> /// The first element matching <c><configuration></c> will be read as the /// configuration. If this file is also a .NET .config file then you must specify /// a configuration section for the <c> Logging</c> element otherwise .NET will /// complain. Set the type for the section handler to <see cref="System.Configuration.IgnoreSectionHandler"/>, for example: /// <code lang="XML" escaped="true"> /// <configSections> /// <section name="Logging" type="System.Configuration.IgnoreSectionHandler" /> /// </configSections> /// </code> /// </para> /// <example> /// The following example configures Logging using a configuration file, of which the /// location is stored in the application's configuration file : /// </example> /// <code lang="C#"> /// using Library.Logging.Config; /// using System.IO; /// using System.Configuration; /// /// ... /// /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings[" Logging-config-file"])); /// </code> /// <para> /// In the <c>.config</c> file, the path to the Logging can be specified like this : /// </para> /// <code lang="XML" escaped="true"> /// <configuration> /// <appSettings> /// <add key=" Logging-config-file" value="log.config"/> /// </appSettings> /// </configuration> /// </code> /// </remarks> #else /// <summary> /// Configures the <see cref="ILoggerRepository"/> using the specified configuration /// file. /// </summary> /// <param name="repository">The repository to configure.</param> /// <param name="configFile">The XML file to load the configuration from.</param> /// <remarks> /// <para> /// The configuration file must be valid XML. It must contain /// at least one element called <c> Logging</c> that holds /// the configuration data. /// </para> /// <example> /// The following example configures Logging using a configuration file, of which the /// location is stored in the application's configuration file : /// </example> /// <code lang="C#"> /// using Library.Logging.Config; /// using System.IO; /// using System.Configuration; /// /// ... /// /// XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings[" Logging-config-file"])); /// </code> /// <para> /// In the <c>.config</c> file, the path to the Logging can be specified like this : /// </para> /// <code lang="XML" escaped="true"> /// <configuration> /// <appSettings> /// <add key=" Logging-config-file" value="log.config"/> /// </appSettings> /// </configuration> /// </code> /// </remarks> #endif static public void Configure(ILoggerRepository repository, FileInfo configFile) { LogLog.Trace("XmlConfigurator: configuring repository [" + repository.Name + "] using file [" + configFile + "]"); if (configFile == null) { LogLog.Error("XmlConfigurator: Configure called with null 'configFile' parameter"); } else { // Have to use File.Exists() rather than configFile.Exists() // because configFile.Exists() caches the value, not what we want. if (File.Exists(configFile.FullName)) { // Open the file for reading FileStream fs = null; // Try hard to open the file for (int retry = 5; --retry >= 0;) { try { fs = configFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read); break; } catch (IOException ex) { if (retry == 0) { LogLog.Error("XmlConfigurator: Failed to open XML config file [" + configFile.Name + "]", ex); // The stream cannot be valid fs = null; } System.Threading.Thread.Sleep(250); } } if (fs != null) { try { // Load the configuration from the stream Configure(repository, fs); } finally { // Force the file closed whatever happens fs.Close(); } } } else { LogLog.Trace("XmlConfigurator: config file [" + configFile.FullName + "] not found. Configuration unchanged."); } } }
/// <summary> /// Initialize the appender based on the options set /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="IOptionHandler"/> delayed object /// activation scheme. The <see cref="ActivateOptions"/> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="ActivateOptions"/> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="ActivateOptions"/> must be called again. /// </para> /// </remarks> override public void ActivateOptions() { base.ActivateOptions(); if (m_securityContext == null) { m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); } bool sourceAlreadyExists = false; string currentLogName = null; using (SecurityContext.Impersonate(this)) { sourceAlreadyExists = EventLog.SourceExists(m_applicationName); if (sourceAlreadyExists) { currentLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); } } if (sourceAlreadyExists && currentLogName != m_logName) { LogLog.Trace("EventLogAppender: Changing event source [" + m_applicationName + "] from log [" + currentLogName + "] to log [" + m_logName + "]"); } else if (!sourceAlreadyExists) { LogLog.Trace("EventLogAppender: Creating event source Source [" + m_applicationName + "] in log " + m_logName + "]"); } string registeredLogName = null; using (SecurityContext.Impersonate(this)) { if (sourceAlreadyExists && currentLogName != m_logName) { // // Re-register this to the current application if the user has changed // the application / logfile association // EventLog.DeleteEventSource(m_applicationName, m_machineName); CreateEventSource(m_applicationName, m_logName, m_machineName); registeredLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); } else if (!sourceAlreadyExists) { CreateEventSource(m_applicationName, m_logName, m_machineName); registeredLogName = EventLog.LogNameFromSourceName(m_applicationName, m_machineName); } } m_levelMapping.ActivateOptions(); LogLog.Trace("EventLogAppender: Source [" + m_applicationName + "] is registered to log [" + registeredLogName + "]"); }
/// <summary> /// Inserts the events into the database. /// </summary> /// <param name="events">The events to insert into the database.</param> /// <remarks> /// <para> /// Insert all the events specified in the <paramref name="events"/> /// array into the database. /// </para> /// </remarks> override protected void SendBuffer(LoggingEvent[] events) { if (m_reconnectOnError && (m_dbConnection == null || m_dbConnection.State != ConnectionState.Open)) { LogLog.Trace("AdoNetAppender: Attempting to reconnect to database. Current Connection State: " + ((m_dbConnection == null)?"<null>":m_dbConnection.State.ToString())); InitializeDatabaseConnection(); InitializeDatabaseCommand(); } // Check that the connection exists and is open if (m_dbConnection != null && m_dbConnection.State == ConnectionState.Open) { if (m_useTransactions) { // Create transaction // NJC - Do this on 2 lines because it can confuse the debugger IDbTransaction dbTran = null; try { dbTran = m_dbConnection.BeginTransaction(); SendBuffer(dbTran, events); // commit transaction dbTran.Commit(); } catch (Exception ex) { // rollback the transaction if (dbTran != null) { try { dbTran.Rollback(); } catch (Exception) { // Ignore exception Log.Information("Error while trying to do Rollback."); } } // Can't insert into the database. That's a bad thing ErrorHandler.Error("Exception while writing to database", ex); } } else { // Send without transaction SendBuffer(null, events); } } }
/// <summary> /// Configures the <see cref="ILoggerRepository"/> using the specified configuration /// file. /// </summary> /// <param name="repository">The repository to configure.</param> /// <param name="configStream">The stream to load the XML configuration from.</param> /// <remarks> /// <para> /// The configuration data must be valid XML. It must contain /// at least one element called <c> Logging</c> that holds /// the configuration data. /// </para> /// <para> /// Note that this method will NOT close the stream parameter. /// </para> /// </remarks> static public void Configure(ILoggerRepository repository, Stream configStream) { LogLog.Trace("XmlConfigurator: configuring repository [" + repository.Name + "] using stream"); if (configStream == null) { LogLog.Error("XmlConfigurator: Configure called with null 'configStream' parameter"); } else { // Load the config file into a document XmlDocument doc = new XmlDocument(); try { // Allow the DTD to specify entity includes XmlReaderSettings settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Parse; // Create a reader over the input stream XmlReader xmlReader = XmlReader.Create(configStream, settings); // load the data into the document doc.Load(xmlReader); } catch (Exception ex) { LogLog.Error("XmlConfigurator: Error while loading XML configuration", ex); // The document is invalid doc = null; } if (doc != null) { LogLog.Trace("XmlConfigurator: loading XML configuration"); // Configure using the ' Logging' element XmlNodeList configNodeList = doc.GetElementsByTagName("Logging"); if (configNodeList.Count == 0) { LogLog.Trace("XmlConfigurator: XML configuration does not contain a < Logging> element. Configuration Aborted."); } else if (configNodeList.Count > 1) { LogLog.Error("XmlConfigurator: XML configuration contains [" + configNodeList.Count + "] < Logging> elements. Only one is allowed. Configuration Aborted."); } else { ConfigureFromXml(repository, configNodeList[0] as XmlElement); } } } }
/// <summary> /// Writes the events to the database using the transaction specified. /// </summary> /// <param name="dbTran">The transaction that the events will be executed under.</param> /// <param name="events">The array of events to insert into the database.</param> /// <remarks> /// <para> /// The transaction argument can be <c>null</c> if the appender has been /// configured not to use transactions. See <see cref="UseTransactions"/> /// property for more information. /// </para> /// </remarks> virtual protected void SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) { if (m_usePreparedCommand) { // Send buffer using the prepared command object if (m_dbCommand != null) { if (dbTran != null) { m_dbCommand.Transaction = dbTran; } // run for all events foreach (LoggingEvent e in events) { // Set the parameter values foreach (AdoNetAppenderParameter param in m_parameters) { param.FormatValue(m_dbCommand, e); } // Execute the query m_dbCommand.ExecuteNonQuery(); } } } else { // create a new command using (IDbCommand dbCmd = m_dbConnection.CreateCommand()) { if (dbTran != null) { dbCmd.Transaction = dbTran; } // run for all events foreach (LoggingEvent e in events) { // Get the command text from the Layout string logStatement = GetLogStatement(e); LogLog.Trace("AdoNetAppender: LogStatement [" + logStatement + "]"); dbCmd.CommandText = logStatement; dbCmd.ExecuteNonQuery(); } } } }
private void GrowConditionally() //under lock { if (myChunkToFill.Next.CheckEmpty(this)) { return; } LogLog.Trace(LogCategory, "Grow: {0} bytes", ChunkSize); myChunkToFill.Next = new Chunk(ChunkSize) { Next = myChunkToFill.Next }; myLastShrinkOrGrowTimeMs = Environment.TickCount; }
/// <summary> /// Initialize the appender based on the options set. /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="IOptionHandler"/> delayed object /// activation scheme. The <see cref="ActivateOptions"/> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="ActivateOptions"/> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="ActivateOptions"/> must be called again. /// </para> /// <para> /// Create the socket handler and wait for connections /// </para> /// </remarks> public override void ActivateOptions() { base.ActivateOptions(); try { LogLog.Trace("TelnetAppender: Creating SocketHandler to listen on port [" + m_listeningPort + "]"); m_handler = new SocketHandler(m_listeningPort); } catch (Exception ex) { LogLog.Error("TelnetAppender: Failed to create SocketHandler", ex); throw; } }
public void Acknowledge(long seqNumber) { lock (myLock) { if (seqNumber > AcknowledgedSeqN) { LogLog.Trace(LogCategory, "New acknowledged seqN: {0}", seqNumber); AcknowledgedSeqN = seqNumber; } else { throw new InvalidOperationException($"Acknowledge({seqNumber}) called, while next {nameof(seqNumber)} MUST BE greater than `{AcknowledgedSeqN}`"); } } }
public void Acknowledge(long seqNumber) { lock (myLock) { LogLog.Trace(LogCategory, "New acknowledged seqN: {0}", seqNumber); if (seqNumber > AcknowledgedSeqN) { AcknowledgedSeqN = seqNumber; } else { //it's ok ack came 2 times for same package, because if connection lost/resume client resend package with lower number and could receive packages with lower numbers //throw new InvalidOperationException($"Acknowledge({seqNumber}) called, while next {nameof(seqNumber)} MUST BE greater than `{AcknowledgedSeqN}`"); } } }
/// <summary> /// Sets and <i>opens</i> the file where the log output will go. The specified file must be writable. /// </summary> /// <param name="fileName">The path to the log file. Must be a fully qualified path.</param> /// <param name="append">If true will append to fileName. Otherwise will truncate fileName</param> /// <remarks> /// <para> /// If there was already an opened file, then the previous file /// is closed first. /// </para> /// <para> /// This method will ensure that the directory structure /// for the <paramref name="fileName"/> specified exists. /// </para> /// </remarks> virtual protected void OpenFile(string fileName, bool append) { if (LogLog.IsErrorEnabled) { // Internal check that the fileName passed in is a rooted path bool isPathRooted = false; using (SecurityContext.Impersonate(this)) { isPathRooted = Path.IsPathRooted(fileName); } if (!isPathRooted) { LogLog.Error("FileAppender: INTERNAL ERROR. OpenFile(" + fileName + "): File name is not fully qualified."); } } lock (this) { Reset(); LogLog.Trace("FileAppender: Opening file for writing [" + fileName + "] append [" + append + "]"); // Save these for later, allowing retries if file open fails m_fileName = fileName; m_appendToFile = append; LockingModel.CurrentAppender = this; LockingModel.OpenFile(fileName, append, m_encoding); m_stream = new LockingStream(LockingModel); if (m_stream != null) { m_stream.AcquireLock(); try { SetQWForFiles(new StreamWriter(m_stream, m_encoding)); } finally { m_stream.ReleaseLock(); } } WriteHeader(); } }
/// <summary> /// Creates a new repository selector. /// </summary> /// <param name="defaultRepositoryType">The type of the repositories to create, must implement <see cref="ILoggerRepository"/></param> /// <remarks> /// <para> /// Create an new repository selector. /// The default type for repositories must be specified, /// an appropriate value would be <see cref="Library.Logging.Repository.Hierarchy.Hierarchy"/>. /// </para> /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="defaultRepositoryType"/> is <see langword="null" />.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="defaultRepositoryType"/> does not implement <see cref="ILoggerRepository"/>.</exception> public DefaultRepositorySelector(Type defaultRepositoryType) { if (defaultRepositoryType == null) { throw new ArgumentNullException("defaultRepositoryType"); } // Check that the type is a repository if (!(typeof(ILoggerRepository).IsAssignableFrom(defaultRepositoryType))) { throw Library.Logging.Util.SystemInfo.CreateArgumentOutOfRangeException("defaultRepositoryType", defaultRepositoryType, "Parameter: defaultRepositoryType, Value: [" + defaultRepositoryType + "] out of range. Argument must implement the ILoggerRepository interface"); } m_defaultRepositoryType = defaultRepositoryType; LogLog.Trace("DefaultRepositorySelector: defaultRepositoryType [" + m_defaultRepositoryType + "]"); }
/// <summary> /// Automatically configures the <see cref="ILoggerRepository"/> using settings /// stored in the application's configuration file. /// </summary> /// <remarks> /// <para> /// Each application has a configuration file. This has the /// same name as the application with '.config' appended. /// This file is XML and calling this function prompts the /// configurator to look in that file for a section called /// <c> Logging</c> that contains the configuration data. /// </para> /// <para> /// To use this method to configure Logging you must specify /// the <see cref=" LoggingConfigurationSectionHandler"/> section /// handler for the <c> Logging</c> configuration section. See the /// <see cref=" LoggingConfigurationSectionHandler"/> for an example. /// </para> /// </remarks> /// <param name="repository">The repository to configure.</param> static public void Configure(ILoggerRepository repository) { LogLog.Trace("XmlConfigurator: configuring repository [" + repository.Name + "] using .config file section"); try { LogLog.Trace("XmlConfigurator: Application config file is [" + SystemInfo.ConfigurationFileLocation + "]"); } catch { // ignore error LogLog.Trace("XmlConfigurator: Application config file location unknown"); } try { XmlElement configElement = null; // hard coded section configElement = ConfigurationManager.GetSection("ApplicationConfig/Logging") as XmlElement; if (configElement == null) { // Failed to load the xml config using configuration settings handler LogLog.Error("XmlConfigurator: Failed to find configuration section ' Logging' in the application's .config file. Check your .config file for the < Logging> and <configSections> elements. The configuration section should look like: <section name=\" Logging\" type=\"Library.Logging.Config. LoggingConfigurationSectionHandler, Logging\" />"); } else { // Configure using the xml loaded from the config file ConfigureFromXml(repository, configElement); } } catch (System.Configuration.ConfigurationException confEx) { if (confEx.BareMessage.IndexOf("Unrecognized element") >= 0) { // Looks like the XML file is not valid LogLog.Error("XmlConfigurator: Failed to parse config file. Check your .config file is well formed XML.", confEx); } else { // This exception is typically due to the assembly name not being correctly specified in the section type. string configSectionStr = "<section name=\"Library.Logging\" type=\"Library.Logging.Config. LoggingConfigurationSectionHandler," + Assembly.GetExecutingAssembly().FullName + "\" />"; LogLog.Error("XmlConfigurator: Failed to parse config file. Is the <configSections> specified as: " + configSectionStr, confEx); } } }
/// <summary> /// Parses the children of a logger element. /// </summary> /// <param name="catElement">The category element.</param> /// <param name="log">The logger instance.</param> /// <param name="isRoot">Flag to indicate if the logger is the root logger.</param> /// <remarks> /// <para> /// Parse the child elements of a <logger> element. /// </para> /// </remarks> protected void ParseChildrenOfLoggerElement(XmlElement catElement, Logger log, bool isRoot) { // Remove all existing appenders from log. They will be // reconstructed if need be. log.RemoveAllAppenders(); foreach (XmlNode currentNode in catElement.ChildNodes) { if (currentNode.NodeType == XmlNodeType.Element) { XmlElement currentElement = (XmlElement)currentNode; if (currentElement.LocalName == APPENDER_REF_TAG) { IAppender appender = FindAppenderByReference(currentElement); string refName = currentElement.GetAttribute(REF_ATTR); if (appender != null) { LogLog.Trace("XmlHierarchyConfigurator: Adding appender named [" + refName + "] to logger [" + log.Name + "]."); log.AddAppender(appender); } else { LogLog.Error("XmlHierarchyConfigurator: Appender named [" + refName + "] not found."); } } else if (currentElement.LocalName == LEVEL_TAG || currentElement.LocalName == PRIORITY_TAG) { ParseLevel(currentElement, log, isRoot); } else { SetParameter(currentElement, log); } } } IOptionHandler optionHandler = log as IOptionHandler; if (optionHandler != null) { optionHandler.ActivateOptions(); } }
/// <summary> /// Create a new repository for the repository specified /// </summary> /// <param name="repositoryName">the repository to associate with the <see cref="ILoggerRepository"/></param> /// <param name="repositoryType">the type of repository to create, must implement <see cref="ILoggerRepository"/>. /// If this param is null then the default repository type is used.</param> /// <returns>the repository created</returns> /// <remarks> /// <para> /// The <see cref="ILoggerRepository"/> created will be associated with the repository /// specified such that a call to <see cref="GetRepository(string)"/> with the /// same repository specified will return the same repository instance. /// </para> /// <para> /// If the named repository already exists an exception will be thrown. /// </para> /// <para> /// If <paramref name="repositoryType"/> is <c>null</c> then the default /// repository type specified to the constructor is used. /// </para> /// </remarks> /// <exception cref="ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception> /// <exception cref="LogException">throw if the <paramref name="repositoryName"/> already exists</exception> public ILoggerRepository CreateRepository(string repositoryName, Type repositoryType) { if (repositoryName == null) { throw new ArgumentNullException("repositoryName"); } // If the type is not set then use the default type if (repositoryType == null) { repositoryType = m_defaultRepositoryType; } lock (this) { ILoggerRepository rep = null; // First check that the repository does not exist rep = m_name2repositoryMap[repositoryName] as ILoggerRepository; if (rep != null) { throw new LogException("Repository [" + repositoryName + "] is already defined. Repositories cannot be redefined."); } else { LogLog.Trace("DefaultRepositorySelector: Creating repository [" + repositoryName + "] using type [" + repositoryType + "]"); // Call the no arg constructor for the repositoryType rep = (ILoggerRepository)Activator.CreateInstance(repositoryType); // Set the name of the repository rep.Name = repositoryName; // Store in map m_name2repositoryMap[repositoryName] = rep; // Notify listeners that the repository has been created OnLoggerRepositoryCreatedEvent(rep); } return(rep); } }
/// <summary> /// Parses a logger element. /// </summary> /// <param name="loggerElement">The logger element.</param> /// <remarks> /// <para> /// Parse an XML element that represents a logger. /// </para> /// </remarks> protected void ParseLogger(XmlElement loggerElement) { // Create a new Library.Logging.Logger object from the <logger> element. string loggerName = loggerElement.GetAttribute(NAME_ATTR); LogLog.Trace("XmlHierarchyConfigurator: Retrieving an instance of Library.Logging.Repository.Logger for logger [" + loggerName + "]."); Logger log = m_hierarchy.GetLogger(loggerName) as Logger; // Setting up a logger needs to be an atomic operation, in order // to protect potential log operations while logger // configuration is in progress. lock (log) { bool additivity = OptionConverter.ToBoolean(loggerElement.GetAttribute(ADDITIVITY_ATTR), true); LogLog.Trace("XmlHierarchyConfigurator: Setting [" + log.Name + "] additivity to [" + additivity + "]."); log.Additivity = additivity; ParseChildrenOfLoggerElement(loggerElement, log, false); } }
/// <summary> /// Write the current process ID to the output /// </summary> /// <param name="writer">the writer to write to</param> /// <param name="state">null, state is not set</param> /// <remarks> /// <para> /// Write the current process ID to the output <paramref name="writer"/>. /// </para> /// </remarks> override protected void Convert(TextWriter writer, object state) { #if (NETCF || SSCLI) // On compact framework there is no System.Diagnostics.Process class writer.Write(SystemInfo.NotAvailableText); #else try { writer.Write(System.Diagnostics.Process.GetCurrentProcess().Id); } catch (System.Security.SecurityException) { // This security exception will occur if the caller does not have // some undefined set of SecurityPermission flags. LogLog.Trace("ProcessIdPatternConverter: Security exception while trying to get current process id. Error Ignored."); writer.Write(SystemInfo.NotAvailableText); } #endif }
/// <summary> /// Configures the SecurityContextProvider /// </summary> /// <param name="sourceAssembly">The assembly that this attribute was defined on.</param> /// <param name="targetRepository">The repository to configure.</param> /// <remarks> /// <para> /// Creates a provider instance from the <see cref="ProviderType"/> specified. /// Sets this as the default security context provider <see cref="SecurityContextProvider.DefaultProvider"/>. /// </para> /// </remarks> override public void Configure(Assembly sourceAssembly, ILoggerRepository targetRepository) { if (m_providerType == null) { LogLog.Error("SecurityContextProviderAttribute: Attribute specified on assembly [" + sourceAssembly.FullName + "] with null ProviderType."); } else { LogLog.Trace("SecurityContextProviderAttribute: Creating provider of type [" + m_providerType.FullName + "]"); SecurityContextProvider provider = Activator.CreateInstance(m_providerType) as SecurityContextProvider; if (provider == null) { LogLog.Error("SecurityContextProviderAttribute: Failed to create SecurityContextProvider instance of type [" + m_providerType.Name + "]."); } else { SecurityContextProvider.DefaultProvider = provider; } } }
/// <summary> /// Parses a level element. /// </summary> /// <param name="element">The level element.</param> /// <param name="log">The logger object to set the level on.</param> /// <param name="isRoot">Flag to indicate if the logger is the root logger.</param> /// <remarks> /// <para> /// Parse an XML element that represents a level. /// </para> /// </remarks> protected void ParseLevel(XmlElement element, Logger log, bool isRoot) { string loggerName = log.Name; if (isRoot) { loggerName = "root"; } string levelStr = element.GetAttribute(VALUE_ATTR); LogLog.Trace("XmlHierarchyConfigurator: Logger [" + loggerName + "] Level string is [" + levelStr + "]."); if (INHERITED == levelStr) { if (isRoot) { LogLog.Error("XmlHierarchyConfigurator: Root level cannot be inherited. Ignoring directive."); } else { LogLog.Trace("XmlHierarchyConfigurator: Logger [" + loggerName + "] level set to inherit from parent."); log.Level = null; } } else { log.Level = log.Hierarchy.LevelMap[levelStr]; if (log.Level == null) { LogLog.Error("XmlHierarchyConfigurator: Undefined level [" + levelStr + "] on Logger [" + loggerName + "]."); } else { LogLog.Trace("XmlHierarchyConfigurator: Logger [" + loggerName + "] level set to [name=\"" + log.Level.Name + "\",value=" + log.Level.Value + "]."); } } }
private void ShrinkConditionally(Chunk upTo) //under lock { Assertion.Assert(myChunkToFill != upTo, "myFreeChunk != upTo"); var now = Environment.TickCount; if (now - myLastShrinkOrGrowTimeMs <= ShrinkIntervalMs && /*overflow*/ now - myLastShrinkOrGrowTimeMs >= 0) { return; } myLastShrinkOrGrowTimeMs = now; while (true) { var toRemove = myChunkToFill.Next; if (toRemove == upTo || !toRemove.CheckEmpty(this)) { break; } LogLog.Trace(LogCategory, "Shrink: {0} bytes, seqN: {1}", ChunkSize, toRemove); myChunkToFill.Next = toRemove.Next; } }
/// <summary> /// Deliver the <see cref="LoggingEvent"/> to the attached appenders. /// </summary> /// <param name="loggingEvent">The event to log.</param> /// <remarks> /// <para> /// Call the appenders in the hierarchy starting at /// <c>this</c>. If no appenders could be found, emit a /// warning. /// </para> /// <para> /// This method calls all the appenders inherited from the /// hierarchy circumventing any evaluation of whether to log or not /// to log the particular log request. /// </para> /// </remarks> virtual protected void CallAppenders(LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } int writes = 0; for (Logger c = this; c != null; c = c.m_parent) { if (c.m_appenderAttachedImpl != null) { // Protected against simultaneous call to addAppender, removeAppender,... c.m_appenderLock.AcquireReaderLock(); try { if (c.m_appenderAttachedImpl != null) { writes += c.m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent); } } finally { c.m_appenderLock.ReleaseReaderLock(); } } if (!c.m_additive) { break; } } // No appenders in hierarchy, warn user only once. // // Note that by including the AppDomain values for the currently running // thread, it becomes much easier to see which application the warning // is from, which is especially helpful in a multi-AppDomain environment // (like IIS with multiple VDIRS). Without this, it can be difficult // or impossible to determine which .config file is missing appender // definitions. // if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0) { LogLog.Trace("Logger: No appenders could be found for logger [" + Name + "] repository [" + Repository.Name + "]"); LogLog.Trace("Logger: Please initialize the Logging system properly."); try { LogLog.Trace("Logger: Current AppDomain context information: "); LogLog.Trace("Logger: BaseDirectory : " + SystemInfo.ApplicationBaseDirectory); #if !NETCF LogLog.Trace("Logger: FriendlyName : " + AppDomain.CurrentDomain.FriendlyName); LogLog.Trace("Logger: DynamicDirectory: " + AppDomain.CurrentDomain.DynamicDirectory); #endif } catch (SecurityException secEx) { // Insufficient permissions to display info from the AppDomain LogLog.Warn("Insufficient permissions to display info from the AppDomain: " + secEx.Message); } m_hierarchy.EmittedNoAppenderWarning = true; } }