- Most of the guidelines for the log4net-user list also apply to the dev list.
- Please have a quick read through the guidelines, thanks.
-
-
- To prevent spam, we require you to be subscribed to the list before posting to it.
-
-
- This is the log4net developer list, it holds discussions relating to the
- development of log4net not the use of log4net. If you have a question that begins
- with the word "How" or you are unsure as the the appropriate list to post to then
- you probably want to start with the log4net-user list.
-
- Anyone can checkout source code from our anonymous SVN
- server. To do so, simply use the following command (if you are
- using a GUI SVN client, configure it appropriately).
-
- If you are not familiar with SVN, the Apache
- Source Code Repositories
- page has links to more information on SVN.
-
-
-
-
Issue Tracking
-
-
- Many bugs reported end up not being a bug in the log4net code,
- but are due to incorrect configuration, problems caused by installed applications,
- the operating system, etc.
-
-
- Before reporting a bug please make every effort to investigate and resolve the problem yourself.
- Just reporting a bug will not fix it. A good bug report includes a detailed
- description of the problem and a succinct test case which can reproduce the problem.
-
-
- Before reporting an issue please investigate the following information sources for
- a potential resolution.
-
- Before reporting a bug, you are advised to discuss it on the relevant mailing list first.
-
-
- Search the bug database to see if the bug
- you are seeing has already been reported. If it has been reported then you can vote for the issue.
-
-
Reporting an Issue
-
-
- If after you have exhausted all other resources to resolve a problem you may want to file a bug report.
- Please make sure the problem is a bug in Logging and not a bug in your application.
-
-
- Please make sure you provide as much information as possible. Its very hard to fix a bug if the person
- looking into the problem can't reproduce it. Here is a listing of information which should be included:
-
-
-
Version - log4net version, or if from a nightly build, version and date of build.
-
Application Type - Assembly type, i.e. exe or dll, and how your code is launched, e.g. console application, windows application, ASP.NET project, COM+ hosted object, etc...
-
Framework - The .NET framework running the application, name (e.g. MS .NET, Mono, SSCLI) and version.
-
Platform - Computer operating system, version, and hardware platform in use.
-
Configuration - Attach configuration files if they would help track down the bug.
-
Log Files - Review your logs files, produced with internal log4net debug enabled. Submit any relevant sections of the log which help document the bug.
-
Stack Traces - Any stack traces generated by the bug, if any.
-
Example - Example configuration files or web applications which demonstrate the bug. When submitting an example which reproduces the bug, please try to make it as simple as possible.
-
Bug Fix Patch - A patch created using diff -u which fixes the bug. (If you have found a bug fix which can be applied to the code).
-
Description of the Bug - A description of the bug, include observed as well as expected behavior.
-
Miscellaneous - Any other information you feel will help track down the problem.
-
-
- Just reporting a bug will not fix it. A good bug report includes a detailed description of the
- problem and a succinct test case which can reproduce the problem. The very best sort of report
- includes an NUnit testcase which reproduces the issue, this means that we can fix it and that we can
- be sure that it stays fixed in future!
-
- Before starting to work on a patch it is probably a good idea to join the log4net-dev
- mailing list to check that equivalent or complementary work is not already underway.
-
-
- Currently the only supported way of submitting patches to log4net
- is via the JIRA issue tracking system.
-
-
- The preferred method of generating a patch is a unified context diff against
- the latest development version in SVN. To do this you should do the following:
-
-
-
-
- Get the latest version of the code from SVN, see the section above on
- Anonymous SVN Access for details on how to obtain the SVN version.
-
-
-
-
- Make your code changes to the log4net source. Please follow existing
- code styles where possible. If adding new API methods or classes then
- these should be appropriately documented with code comments.
- Contributions intended for inclusion in ASF products must be licensed
- to ASF under the terms of the
- Apache Software License.
-
-
-
-
- Generate a unified context diff for the files you have changed. Run the
- svn diff > patch-file command from the root of the log4net
- codebase to generate a diff file.
-
-
-
-
- If you have added new files these will not be included in the diff. You
- will need to attach these files separately.
-
-
-
-
- If you are not using SVN then you can still generate a unified context diff
- using the diff GNU tool with the -u command line options.
- The GNU tools are available for Windows as part
- of the Cygwin package.
-
-
- If you are unable to generate a diff please submit each file separately and place
- block comments around each code change to highlight the differences.
-
-
- In order to submit your patch please follow the following steps:
-
-
-
-
- Create a new issue for your patch. On the
- log4net issues home page
- select the Create New Issue from the menu bar. You will need to be logged
- into JIRA in order to create an issue.
-
-
-
-
- Select the issue type as appropriate.
-
-
-
-
- Prefix the summary with [PATCH]. Enter a description of the changes made,
- new features, or bug fixes in your patch.
-
-
-
-
- Once the issue has been created you can attach your patch file to the issue
- by selecting the Attach file to this issue operation from the left hand
- menu. When attaching your patch you must select the Grant license to ASF for
- inclusion in ASF works option. When attaching a patch please include in the
- description the baseline version of log4net you used to build your patch, if against
- an SVN version please include the version number and if from a tag or branch include
- the repository path.
-
-
-
-
- If you have other files to attach, e.g. you have added new files to log4net, then
- attach each file separately. Please include in the description the name of the file
- attached and the path it should live in the project.
-
-
-
-
- A notification will be sent to the log4net-dev list once you have created your issue,
- however it may also be worth mailing the log4net-dev list to encourage the project
- committers to apply your patch, or at least find out when they may do so.
-
- log4net has graduated from the Incubator project, however at the time
- the following releases were made, log4net was still undergoing incubation,
- therefore these releases are not officially endorsed by the ASF.
-
-
- Future releases of log4net will be officially endorsed by the ASF.
-
- The log4net project was started by Neoworks Limited
- in June 2001. It was created as an internal project within Neoworks to port the Apache
- log4j code base to the Microsoft .NET Framework. The code base was initially branched
- from a pre-alpha log4j 1.2.
-
-
- In July 2001 a Sourceforge project was started
- and log4net was published under the Apache Software License. The first public release of
- log4net was made in September 2001. A further 10 releases were made on the sourceforge
- site.
-
-
- In December 2003 the Apache Logging Services project was created.
- In February 2004 log4net was donated by Neoworks to the Apache Software Foundation
- to become a member of the Logging Services project.
-
-
- In February 2007 log4net graduated from the Apache Incubator project to become a
- fully fledged Apache project. Apache log4net is a subproject of the Logging Services project.
-
- log4net is a tool to help the programmer output log statements to a variety
- of output targets. log4net is a port of the excellent log4j framework to the
- .NET runtime. We have kept the framework similar in spirit to the original log4j
- while taking advantage of new features in the .NET runtime.
- For more information on log4net see the features document.
-
-
- log4net is part of the Apache Logging Services
- project. The Logging Services project is intended to provide cross-language logging
- services for purposes of application debugging and auditing.
-
- The Apache Software License Version 2.0 applies to all releases of
- log4net starting with log4net 1.2.1.
-
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
- The License is accompanied by this NOTICE:
-
-
-
- **
- ** NOTICE file corresponding to the section 4 (d) of the Apache License,
- ** Version 2.0, in this case for the Apache log4net distribution.
- **
-
- Please read the LICENSE files present in the root directory of this
- distribution.
-
- Apache log4net
- Copyright 2001-2007 The Apache Software Foundation
-
- This product includes software developed at
- The Apache Software Foundation (http://www.apache.org/).
-
-
- The log4net release builds are built using NAnt. Log4net can also be built
- using Visual Studio .NET 2002, 2003, or 2005.
-
-
- To build a release build of log4net you will need to create a strong
- name key file. See the Strong Name section below.
-
-
Visual Studio
-
-
- Visual Studio .NET 2002, 2003 and 2005 are supported build platforms for log4net.
-
-
Visual Studio .NET 2002
-
-
- The log4net distribution includes a solution and project file
- for Visual Studio .NET 2002. Open the log4net.sln
- from the src directory in the distribution.
-
-
- The log4net project requires only the following references:
-
-
-
System
-
System.Data
-
System.Web
-
System.XML
-
-
-
Visual Studio .NET 2003
-
-
- Open the Visual Studio .NET 2002 solution file as above.
- Visual Studio will convert the solution and project files
- to Visual Studio .NET 2003 format.
-
-
- After converting the log4net project you must change the
- Conditional Compilation Constants specified for the
- log4net project. Open the project properties dialog and
- select the Configuration Properties/Build sheet.
- Replace the NET_1_0 constant with NET_1_1.
- Remember to do this for both Debug and Release configurations.
-
-
- The log4net project file is not suitable for building log4net
- for the .NET Compact Framework. To build for the Compact Framework
- you must create a new C# project for Smart Devices. Configure the
- project as a library project. Add all the C# files from the
- src directory in the distribution.
-
-
-
Visual Studio 2005
-
-
- Open the Visual Studio .NET 2002 solution file as above.
- Visual Studio will convert the solution and project files
- to Visual Studio .NET 2003 format.
-
-
- After converting the log4net project you must change the
- Conditional compilation symbols specified for the
- log4net project. Open the project properties page and
- select the Build sheet.
- Replace the NET_1_0 symbol with NET_2_0.
- Remember to do this for both Debug and Release configurations.
-
-
- In addition the log4net project requires the following new references:
-
-
-
System.Configuration
-
-
- The log4net project file is not suitable for building log4net
- for the .NET Compact Framework. To build for the Compact Framework
- you must create a new C# project for Smart Devices. Configure the
- project as a library project. Add all the C# files from the
- src directory in the distribution.
-
-
-
-
NAnt
-
-
- The log4net distribution is built using the NAnt tool.
- A recent NAnt version 0.85 nightly build is required to build log4net, this is
- available from nant.sourceforge.net.
-
-
- To support building log4net for the SSCLI framework the NAnt configuration
- files need to be updated to specify the SSCLI framework directory.
-
-
- To build log4net from the command line, change directory to the root of the
- log4net distribution, ensure that the nant executable is in the
- PATH, and then run the following command:
-
-
-nant -buildfile:log4net.build compile-all
-
- This command will build log4net for all the supported frameworks
- that are available on the current machine. To list all the build
- targets that are available run the following command:
-
-
-nant -buildfile:log4net.build -projecthelp
-
- Under windows the build.cmd can be used
- to script the nant build. This can be called from a different
- directory and will locate the correct log4net.build file to use.
- For example:
-
-
-build.cmd compile-all
-
-
Strong Name
-
-
- In order to build the Release builds of log4net a Strong
- Name key is required.
-
-
- Use the sn.exe tool in the
- .NET Framework SDK to generate a strong name key pair.
-
-
-sn -k log4net.snk
-
- The log4net.snk file should be placed in the root of the
- log4net distribution, in the same folder as the log4net.build
- file.
-
-
-
SDK Reference
-
-
- NDoc 1.3 is used to build the log4net SDK documentation.
- NDoc is available from ndoc.sourceforge.net.
-
-
-
HTML Documentation
-
-
- The log4net HTML documentation is built using Velocity.
- The source are XML files in the xdocs/src directory.
- Building the documentation requires Java, Ant, and Velocity.
- Run ant from within the xdocs directory.
-
- This document presents example configurations for the built-in appenders.
- These configurations are designed to work with the
- log4net.Config.DOMConfigurator and the
- log4net.Repository.Hierarchy.Hierarchy.
-
-
- These examples are by no means exhaustive configurations for the appenders.
- For a full list of the parameters that can be specified to each appender and
- more details on each options see the SDK documentation for the appender.
-
- The configuration of the AdoNetAppender depends on the
- provider selected for the target database. Here are some examples.
-
-
MS SQL Server
-
-
- The following example shows how to configure the AdoNetAppender
- to log messages to a SQL Server database. The events are written in batches of 100
- (BufferSize). The ConnectionType specifies the fully qualified type name
- for the System.Data.IDbConnection to use to connect to the
- database. The ConnectionString is database provider specific.
- The CommandText is either a prepared statement or a stored procedure, in this
- case it is a prepared statement. Each parameter to the prepared statement or stored procedure
- is specified with its name, database type and a layout that renders the value for the
- parameter.
-
-
- The database table definition is:
-
-
-
-CREATE TABLE [dbo].[Log] (
- [Id] [int] IDENTITY (1, 1) NOT NULL,
- [Date] [datetime] NOT NULL,
- [Thread] [varchar] (255) NOT NULL,
- [Level] [varchar] (50) NOT NULL,
- [Logger] [varchar] (255) NOT NULL,
- [Message] [varchar] (4000) NOT NULL,
- [Exception] [varchar] (2000) NULL
-)
-
- This example shows how to write events to a SQLite Database.
- This was tested against v0.21 of the
- SQLite .NET provider.
-
-
- SQLite doesn't have strongly-typed columns or field lengths but its
- recommended you still include this information for readability.
- The database table definition is:
-
-
-
-CREATE TABLE Log (
- LogId INTEGER PRIMARY KEY,
- Date DATETIME NOT NULL,
- Level VARCHAR(50) NOT NULL,
- Logger VARCHAR(255) NOT NULL,
- Message TEXT DEFAULT NULL
-);
-
- The following example shows how to configure the AspNetTraceAppender
- to log messages to the ASP.NET TraceContext. The messages are written to the
- System.Web.TraceContext.Write method if they are below
- level WARN. If they are WARN or above they are written to the
- System.Web.TraceContext.Warn method.
-
- The following example shows how to configure the BufferingForwardingAppender
- to buffer 100 messages before delivering them to the ConsoleAppender.
-
- This example shows how to deliver only significant events. A LevelEvaluator
- is specified with a threshold of WARN. This means that the events will only
- be delivered when a message with level of WARN or higher level is logged.
- Up to 512 (BufferSize) previous messages of any level will also be delivered to provide context
- information. Messages not sent will be discarded.
-
- The following example shows how to configure the ColoredConsoleAppender
- to log messages to the console. By default the messages are sent to the console
- standard output stream. This example shows how to highlight error messages.
-
- The following example shows how to configure the ConsoleAppender
- to log messages to the console. By default the messages are sent to the console
- standard output stream.
-
- The following example shows how to configure the EventLogAppender to log
- to the Application event log on the local machine using the
- event Source of the AppDomain.FriendlyName.
-
- For more information on how to setup the event log to allow the
- EventLogAppender to write to it, see the
- FAQ: Why doesn't the EventLogAppender work?.
-
- The following example shows how to configure the FileAppender
- to write messages to a file. The file specified is log-file.txt. The file will
- be appended to rather than overwritten each time the logging process starts.
-
- This example shows how to configure the file name to write to using
- an environment variable TMP. The encoding to use to write
- to the file is also specified.
-
- The following example shows how to configure the ForwardingAppender.
- The forwarding appender allows a set of constraints to be used to decorate an appender.
- In this example the ConsoleAppender is decorated with a Threshold of
- level WARN. This means that an event directed to the ConsoleAppender
- directly will be logged regardless of its level, but an event directed to the ForwardingAppender
- will only be passed on to the ConsoleAppender if its level is WARN
- or higher. This appender is used only in special circumstances.
-
- The following example shows how to configure the NetSendAppender
- to deliver messages to a specific user's screen. As this appender is typically only
- used for important notifications a Threshold of level Error
- is specified. This example delivers the messages to the user nicko on the
- machine SQUARE. However things are not always straight forward using the Windows
- Messenger Service, one possible outcome using this configuration is that the Server
- will broadcast looking for a WINS server which it will then ask to deliver the message
- to the Recipient, the WINS server will deliver it to the first terminal that the
- user logged in from.
-
- The following example shows how to configure the RemotingAppender
- to deliver logging events to a specified Sink (in this example
- the sink is tcp://localhost:8085/LoggingSink).
- In this example the events are delivered in blocks of 95 events because
- of the BufferSize. No events are discarded. The OnlyFixPartialEventData
- option allows the appender to ignore certain logging event properties that
- can be very slow to generate (e.g. the calling location information).
-
- This example configures the RemotingAppender to
- deliver the events only when an event with level ERROR
- or above is logged. When the events are delivered, up to 200 (BufferSize)
- previous events (regardless of level) will be delivered to provide context.
- Events not delivered will be discarded.
-
- The RollingFileAppender builds on the
- FileAppender and has the same options
- as that appender.
-
-
- The following example shows how to configure the RollingFileAppender
- to write to the file log.txt. The file written to will always be called log.txt
- because the StaticLogFileName param is specified. The file will be rolled based on
- a size constraint (RollingStyle). Up to 10 (MaxSizeRollBackups)
- old files of 100 KB each (MaximumFileSize) will be kept. These rolled files will be
- named: log.txt.1, log.txt.2, log.txt.3, etc...
-
- This example show how to configure the RollingFileAppender
- to roll log files on a date period. This example will roll the log file every minute!
- To change the rolling period adjust the DatePattern value.
- For example, a date pattern of "yyyyMMdd" will roll every day.
- See System.Globalization.DateTimeFormatInfo for a list of available patterns.
-
- This example show how to configure the RollingFileAppender
- to roll log files on a date period and within a date period on file size. For each day
- only the last 10 files of 1MB will be kept.
-
- This example show how to configure the RollingFileAppender
- to roll log files once per program execution. The appendToFile
- property is set to false to prevent the appender from overwriting
- the existing files. The maxSizeRollBackups is set to negative
- 1 to allow an infinite number of backup files. The file size does have to be limited but
- here it is set to 50 Gigabytes which, if a log file exceeds this size limit during a single
- run then it will also be rolled.
-
- The following example shows how to configure the SmtpAppender
- to deliver log events via SMTP email. The To, From, Subject and
- SmtpHost are required parameters.
- This example shows how to deliver only significant events. A LevelEvaluator
- is specified with a threshold of WARN. This means that an email
- will be sent for each WARN or higher level message that is logged.
- Each email will also contain up to 512 (BufferSize) previous messages of any level to
- provide context. Messages not sent will be discarded.
-
- The SmtpPickupDirAppender is configured similarly
- to the SmtpAppender. The only difference is that rather
- than specify a SmtpHost parameter a PickupDir must be specified.
-
-
- The PickupDir parameter is a path that must exist and the code executing the
- appender must have permission to create new files and write to them in this directory.
- The path is relative to the application's base directory (AppDomain.BaseDirectory).
-
-
- The following example shows how to configure the SmtpPickupDirAppender
- to deliver log events via SMTP email. The To, From, Subject and
- PickupDir are required parameters.
- This example shows how to deliver only significant events. A LevelEvaluator
- is specified with a threshold of WARN. This means that an email
- will be sent for each WARN or higher level message that is logged.
- Each email will also contain up to 512 (BufferSize) previous messages of any level to
- provide context. Messages not sent will be discarded.
-
- The following example shows how to configure the TraceAppender
- to log messages to the System.Diagnostics.Trace system.
- This is the tracing system supplied with the .net base class libraries.
- See the MSDN documentation for the System.Diagnostics.Trace
- class for more details on how to configure the trace system.
-
- The following examples are only available in the log4net release download, not
- on-line. To obtain the examples download one of the log4net releases.
-
-
-
-
Building Examples
-
-
Building An Example
-
-
- A single example can be build by running nant from
- the example directory.
-
-
- For example running nant in the
- examples\net\1.0\Tutorials\ConsoleApp\cs directory
- will build the C# version of the .NET 1.0 ConsoleApp example.
-
-
- nant can be run in any directory containing a
- nant.build file. The typical behavior of the build file
- is to build all projects under the current directory.
-
-
- For example running nant in the
- examples\net\1.1 directory
- will build all the examples for the .NET 1.1 platform.
-
-
-
Building All Examples
-
-
- To build all the examples either run nant in the
- examples directory or you can specify the
- compile-examples target to the main log4net nant build.
-
-
-
Visual Studio .NET
-
-
- There are Visual Studio .NET 2002 project files for the .NET 1.0 framework.
- The solution files for C# and VB are in the examples\net\1.0
- folder.
-
-
- For the Managed C++ project there is a Visual Studio .NET 2003 project file
- in the examples\net\1.1 folder.
-
-
-
-
Examples
-
-
Tutorial - ConsoleApp
-
-
- ConsoleApp shows how to write a simple console application that initializes
- logging and logs various events.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute ConsoleApp.exe from the build output directory.
-
-
-
Tutorial - WebApp
-
-
- ConsoleApp shows how to write a simple ASP.NET web application that initializes
- logging and logs various events.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example you need to have an ASP.NET container application to
- host the web application, for example IIS. In IIS create a new virtual
- directory pointing to the WebApp src directory. Configure IIS to recognize
- this virtual directory as an application. Open up a web browser, navigate to
- the virtual directory and to the WebForm1.aspx page within it.
-
-
-
Remoting - RemotingClient
-
-
- The RemotingClient application is a simple console application that configures
- log4net with the RemotingAppender. This appender will attempt to deliver the
- logging events to a remoting listener. This example should be run in conjunction
- with the RemotingServer.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute RemotingClient.exe from the build output directory.
-
-
-
Remoting - RemotingServer
-
-
- The RemotingServer application is a simple console application that listens for
- logging events from a remote RemotingAppender and then logs them through the
- local log4net instance. This example should be run in conjunction
- with the RemotingClient.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute RemotingServer.exe from the build output directory.
- While this process is running execute the RemotingClient.exe program on
- the same machine. The logging events from the client are transferred to the server.
-
-
-
Repository - SimpleModule
-
-
- The SimpleModule is a class library that is intended to be used as part of
- the SimpleApp example,
- This class library uses the log4net.Config.Repository
- attribute to create a separate configuration space from other assemblies.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- This library is intended to be used as part of the SimpleApp example.
-
-
-
Repository - SharedModule
-
-
- The SharedModule is a class library that is intended to be used as part of
- the SimpleApp example,
- This class library uses log4net but does not attempt to configure logging.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- This library is intended to be used as part of the SimpleApp example.
-
-
-
Repository - SimpleApp
-
-
- The SimpleApp example uses the SimpleModule and SharedModule to demonstrate
- the ways in which multiple assemblies within the same process may be
- separately configured.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute SimpleApp.exe from the build output directory.
-
-
-
Extensibility - EventIDLogApp
-
-
- The EventIDLogApp example demonstrates using the log4net.Ext.EventID extension.
- The extension needs to be built separately from the
- extensions\net\1.0\log4net.Ext.EventID directory.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute EventIDLogApp.exe from the build output directory.
-
-
-
Extensibility - TraceLogApp
-
-
- The TraceLogApp example demonstrates using the log4net.Ext.Trace extension.
- The extension needs to be built separately from the
- extensions\net\1.0\log4net.Ext.Trace directory.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute TraceLogApp.exe from the build output directory.
-
-
-
SampleAppenders
-
-
- This project includes the following example appenders.
-
-
-
- AsyncAppender
-
-
- FastDbAppender
-
-
- FireEventAppender
-
-
- MessageBoxAppender
-
-
- MessageObjectExpanderAppender
-
-
- MsmqAppender
-
-
- PatternFileAppender
-
-
- SimpleSmtpAppender
-
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute SampleAppendersApp.exe from the build output directory.
-
-
-
SampleLayouts
-
-
- This project includes the following example layouts.
-
-
-
- ForwardingLayout
-
-
- LineWrappingLayout
-
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute SampleLayoutsApp.exe from the build output directory.
-
-
-
Performance - NotLogging
-
-
- The NotLogging example benchmarks the performance of log4net logging statements in
- user code in various scenarios including when logging is disabled.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- The WmiAppender sample shows an example appender that fires events through
- Windows Management Instrumentation.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- log4net is a tool to help the programmer output log statements to a variety of
- output targets.
-
-
- In case of problems with an application, it is helpful to enable logging so
- that the problem can be located. With log4net it is possible to enable logging at
- runtime without modifying the application binary. The log4net package is designed
- so that log statements can remain in production code without incurring a
- high performance cost. It follows that the speed of logging (or rather not
- logging) is crucial.
-
-
- At the same time, log output can be so voluminous that it quickly becomes
- overwhelming. One of the distinctive features of log4net (and common to all of
- the log4x libraries) is the notion of hierarchical
- loggers. Using these loggers it is possible to selectively control
- which log statements are output at arbitrary granularity.
-
-
- log4net is designed with two distinct goals in mind: speed and flexibility. There
- is a tight balance between these two requirements.
-
- No. log4net is not reliable. It is a best-effort and fail-stop logging system.
-
-
- By fail-stop, we mean that log4net will not throw unexpected exceptions at
- run-time potentially causing your application to crash. If for any reason, log4net
- throws an uncaught exception (except for ArgumentException and
- ArgumentNullException which may be thrown), please send an email
- to the
- log4net-user@logging.apache.org mailing list. Uncaught exceptions
- are handled as serious bugs requiring immediate attention.
-
-
- Moreover, log4net will not revert to System.Console.Out
- or System.Console.Error when its designated
- output stream is not opened, is not writable or becomes full. This avoids
- corrupting an otherwise working program by flooding the user's terminal because
- logging fails. However, log4net will output a single message to
- System.Console.Error and System.Diagnostics.Trace
- indicating that logging can not be performed.
-
- log4net runs on many different frameworks and each framework has its own requirements.
- As a rule of thumb you will need an ECMA-335 compliant CLI runtime, for example,
- the Microsoft .NET runtime 1.0 (1.0.3705) or 1.1 (1.1.4322).
-
-
- Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support
- document for more information.
-
- The log output can be customized in many ways. Moreover, one can completely
- override the output format by implementing one's own ILayout
-
-
- Here is an example output using PatternLayout with the conversion
- pattern %timestamp [%thread] %-5level %logger{2} %ndc - %message%newline
-
-
-
-176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
-225 [main] INFO examples.SortAlgo - Entered the sort method.
-262 [main] DEBUG SortAlgo.OUTER i=1 - Outer loop.
-276 [main] DEBUG SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0
-290 [main] DEBUG SortAlgo.OUTER i=0 - Outer loop.
-304 [main] INFO SortAlgo.DUMP - Dump of integer array:
-317 [main] INFO SortAlgo.DUMP - Element [0] = 0
-331 [main] INFO SortAlgo.DUMP - Element [1] = 1
-343 [main] INFO examples.Sort - The next log statement should be an error message.
-346 [main] ERROR SortAlgo.DUMP - Tried to dump an uninitialized array.
-467 [main] INFO examples.Sort - Exiting main method.
-
-
- The first field is the number of milliseconds elapsed since the start of the
- program. The second field is the thread outputting the log statement. The third
- field is the level of the log statement. The fourth field is the rightmost
- two components of the name of the logger making the log request. The fifth field (just
- before the '-') is the nested diagnostic context (NDC). Note the
- nested diagnostic context may be empty as in the first two statements. The text
- after the '-' is the message of the statement.
-
- The logger concept lies at the heart of log4net's configuration. Loggers are organized into a
- hierarchy and give the programmer run-time control on which logging statements
- are printed or not.
-
-
- Loggers are assigned levels through the configuration of log4net. A log statement is
- routed through to the appender depending on its level and its logger.
-
Why should I donate my extensions to log4net back to the project?
-
-
- Contrary to the GNU Public License (GPL) the Apache Software License does not
- make any claims over your extensions. By extensions, we mean totally new code
- that invokes existing log4net code. You are free to do whatever you wish with
- your proprietary log4net extensions. In particular, you may choose to
- never release your extensions to the wider public. For details see the
- Apache License, Version 2.0.
-
-
- We are very careful not to unnecessarily change the log4net client API so that newer log4net
- releases are backward compatible with previous versions. We are a lot less
- scrupulous with the internal log4net API. Thus, if your extension is designed to
- work with the internals of a specific log4net version, then when the next release
- of log4net comes out, you will probably need to adapt your proprietary extensions to the
- new release. Thus, you will be forced to spend precious resources in order to
- keep up with log4net changes. This is commonly referred to as the "stupid-tax".
- By donating the code and making it part of the standard distribution, you save
- yourself the unnecessary maintenance work.
-
-
- If your extensions are useful then someone will eventually write an extension
- providing the same or very similar functionality. Your development effort will
- be wasted.
-
-
- Unless the proprietary log4net extension is business critical, there is little
- reason for not donating your extensions back to the project.
-
- log4net is a port of the popular log4j logging library.
- The initial port was done in June 2001, since then we have tried to remain in the
- spirit of the original log4j. See the log4net history page for more details.
-
- Logging behavior can be set using configuration files which are parsed at runtime.
- Using configuration files the programmer can define loggers and set their
- levels.
-
-
- Configuration files are specified in XML. See log4net.Config.XmlConfigurator
- for more details.
-
-
- See the various log4net.Layout and log4net.Appender
- components for specific configuration options.
-
How do I completely disable all logging at runtime?
-
-
- Setting the Threshold on the Hierarchy to Level OFF will disable all
- logging from that Hierarchy. This can be done in the log4net configuration file
- by setting the "threshold" attribute on the log4net configuration element to "OFF".
- For example:
-
What are the configurable options for an appender?
-
-
- log4net uses public properties to configure components such as
- Appenders, Layouts, Loggers etc.
-
-
- Thus, any writable public property in on the appender corresponds to a
- configurable option. For example, in RollingFileAppender the
- public int MaxSizeRollBackups { set; } property corresponds to
- the MaxSizeRollBackups option.
-
-
- Layouts options are also defined by their writable properties. Same goes for most
- other log4net components.
-
Is it possible to direct log output to different appenders by level?
-
-
- Yes it is. Setting the Threshold option of any appender extending
- AppenderSkeleton, (most log4net appenders extend
- AppenderSkeleton) will filter out all log events
- with a lower level than the value of the threshold option.
-
-
- For example, setting the threshold of an appender to DEBUG will also allow INFO,
- WARN, ERROR and FATAL messages to log along with DEBUG messages. (DEBUG is the
- lowest level). This is usually acceptable as there is little use for DEBUG
- messages without the surrounding INFO, WARN, ERROR and FATAL messages.
- Similarly, setting the threshold of an appender to ERROR will filter out DEBUG,
- INFO and WARN messages but not ERROR or FATAL messages.
-
-
- This policy usually best encapsulates what the user actually wants to do, as
- opposed to her mind-projected solution.
-
-
- If you must filter events by exact level match, then you can attach a
- LevelMatchFilter to any appender to filter out logging
- events by exact level match.
-
- The .NET runtime will try to locate the assembly called MyAssembly.
- How .NET locates assemblies is beyond the scope of this FAQ.
-
-
- When loading an assembly from the GAC the fully qualified assembly name,
- including the version, culture and public key must be specified. This is
- in the standard syntax supported by System.Type.GetType.
- See the next FAQ on how to get the version and public key for an assembly.
-
- The fully qualified name for an assembly includes the version, culture and
- public key. The public key is derived from the strong name used to identify
- the publisher. When referencing an assembly from the GAC the fully qualified
- name must be used. To get the version, culture and public key you can use a
- tool like the excellent .NET Reflector from Lutz Roeder available from
- http://www.aisto.com/roeder/dotnet.
-
- Newlines in the config file need to be escaped using an XML numeric character reference.
- The sequence that represents a CR LF is . The following example adds
- a header and footer to the output each followed by a newline.
-
How do I use a pattern to set the value of a string property?
-
-
- Log4net supports a pattern syntax for setting string properties similar to the
- PatternLayout used to format the output messages.
- This pattern syntax can be used by specifying type="log4net.Util.PatternString"
- on the string property in the config file. This tells the config parser to pass the
- value to the PatternString type before converting the result
- to a string. For details on the patterns supported see the
- PatternString SDK Reference.
-
-
- The following example sets the file name for a FileAppender to include the
- current process id by specifying the %processid pattern in the
- File property.
-
- You can name logging loggers by locality. It turns out that
- instantiating a logger in each class, with the logger name equal to the
- fully-qualified name of the class, is a useful and straightforward approach of
- defining loggers. This approach has many benefits:
-
-
-
- It is very simple to implement.
-
- It is very simple to explain to new developers.
-
- It automatically mirrors your application's own modular design.
-
- It can be further refined at will.
-
- Printing the logger automatically gives information on the locality of the
- log statement.
-
-
- However, this is not the only way for naming loggers. A common alternative
- is to name loggers by functional areas. For example, the
- "database" logger, "remoting" logger, "security" logger, or the "XML"
- logger.
-
-
- You may choose to name loggers by functionality and subcategorize by
- locality, as in "DATABASE.MyApp.MyClass" or
- "DATABASE.MyApp.MyModule.MyOtherClass".
-
-
- You are totally free in choosing the names of your loggers. The
- log4net package merely allows you to manage your names in a hierarchy. However,
- it is your responsibility to define this hierarchy.
-
-
- Note: by naming loggers by locality one tends to name things by
- functionality, since in most cases the locality relates closely to
- functionality.
-
How do I get the fully-qualified name of a class in a static block?
-
-
- You can easily retrieve the fully-qualified name of a class in a static block
- for class X, with the statement typeof(X).Name.
- Note that X is the class name and span an instance.
- However because the LogManager.GetLogger method is overloaded
- to take an instance of Type as well as string
- usually only the type of the class is required.
-
-
- Here is the suggested usage template:
-
-
-
-public class Foo
-{
- private static readonly ILog log = LogManager.GetLogger(typeof(Foo));
- ... other code
-}
-
-
- An equivalent and more portable solution, though slightly longer, is to use the declaring type
- of the static constructor.
-
-
-
-public class Foo
-{
- private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- ... other code
-}
-
-
- Note: the .NET Compact Framework 1.0 does not support System.Reflection.MethodBase.GetCurrentMethod().
-
-log.Debug("Entry number: " + i + " is " + entry[i]);
-
-
- incurs the cost of constructing the message parameter, that is converting both
- integer i and entry[i] to
- a string, and concatenating intermediate strings. This, regardless of whether
- the message will be logged or not.
-
-
- If you are worried about speed, then write
-
-
-
-if(log.IsDebugEnabled)
-{
- log.Debug("Entry number: " + i + " is " + entry[i]);
-}
-
-
- This way you will not incur the cost of parameter construction if debugging is
- disabled for logger log. On the other hand, if the logger is
- debug enabled, you will incur the cost of evaluating whether the logger is
- enabled or not, twice: once in IsDebugEnabled and once in Debug.
- This is an insignificant overhead since evaluating a logger takes less than
- 1% of the time it takes to actually log a statement.
-
- So you don't think that the previous FAQ is really the fastest way
- of not logging? Well there is a faster way but it does have some
- drawbacks. Starting from:
-
-
-
-if(log.IsDebugEnabled)
-{
- log.Debug("Entry number: " + i + " is " + entry[i]);
-}
-
-
- It is possible to further eliminate the calls to IsDebugEnabled
- so that the call is only made once per logger. If you are using one logger
- for each class then you can store the enabled state for the logger in a static
- variable in the class and then test against this variable:
-
- So why exactly is this faster? Well to start with the IsDebugEnabled
- is not called for each log statement, it is called once per logger. Furthermore as the
- isDebugEnabled variable is private static readonly
- the JIT compiler can at run-time optimize out the if test altogether.
- This means that at runtime the JIT compiler won't even compile the logging statements into native code, i.e.
- all the logging just disappears.
-
-
- So what is the downside to using this? Well one of the clever features of log4net is that
- you can change the logging configuration while your program is running. If you need to
- investigate an issue in your application, you don't have to stop the application, setup the
- logging and restart the application, you can change the logging configuration and the
- log4net will reload it (see XmlConfigurator.ConfigureAndWatch APIs for more
- information). However if the JIT has compiled out all of the logging statements
- then they are gone and you can't get them back by reloading the configuration file. Effectively
- this means that the logging configuration can only be set when the application loads and
- it cannot be changed at runtime. It is up to you to decide if you need ultimate speed or need
- to be able to reload the logging configuration while the application is running.
-
Can the outputs of multiple client request go to different log files?
-
-
- Many developers are confronted with the problem of distinguishing the log
- output originating from the same class but different client requests. They come
- up with ingenious mechanisms to fan out the log output to different files. In
- most cases, this is not the right approach.
-
-
- It is simpler to use a context property or stack (ThreadContext).
- Typically, one would ThreadContext.Properties["ID"] = "XXX"
- client specific information, such as the client's hostname, ID or any other
- distinguishing information when starting to handle the client's request.
- Thereafter, log output will automatically include the context data
- so that you can distinguish logs from different client requests even if they
- are output to the same file.
-
-
- See the ThreadContext and the PatternLayout classes for more
- information.
-
How do I get multiple process to log to the same file?
-
-
- By default the FileAppender holds an exclusive write
- lock on the log file while it is logging. This prevents other processes from
- writing to the file. The FileAppender can be configured
- to use a different locking model, MinimalLock, that
- only acquires the write lock while a log is being written. This allows multiple
- processes to interleave writes to the same file, albeit with a loss in performance.
- See the FileAppender config examples
- for an example MinimalLock configuration.
-
-
- While the MinimalLock model may be used to interleave
- writes to a single file it may not be the optimal solution, especially when
- logging from multiple machines. Alternatively you may have one or more processes
- log to RemotingAppenders.
- Using the RemoteLoggingServerPlugin (or
- IRemoteLoggingSink) a process can receive all the events and
- log them to a single log file.
-
If I have many processes across multiple hosts (possibly across multiple time zones) logging to the same file using the RemotingAppender, what happens to timestamps?
-
-
- The timestamp is created when the logging event is created. That is so say,
- when the Debug, Info,
- Warn, Error
- or Fatal method is invoked. This is unaffected by the time at
- which they may arrive at a remote server. Since the timestamps are
- transmitted in UTC format by the RemotingAppender,
- they all appear in the same time zone as
- the host creating the logfile. Since the clocks of various machines may not be
- synchronized, this may account for time interval inconsistencies between events
- generated on different hosts.
-
- The simple answer is as soon as possible. The long answer is more complex.
-
-
- If you are configuring log4net programmatically, i.e. by calling the
- XmlConfigurator.Configure method then you should do so
- before you begin logging and it is reasonable to do this very soon after application
- start.
-
-
- If you are configuring log4net by specifying assembly level attributes on
- your assembly then the configuration will be loaded once the first call to
- the LogManager.GetLogger is made. It is necessary
- that the first call to LogManager.GetLogger made
- during the process (or AppDomain) is made from the assembly that has the
- configuration attributes. Log4net will look only once and only on the first
- calling assembly for the configuration attributes.
-
- Yes. You can implement the log4net.Layout.ILayout
- interface to create you own customized log format, or you can extend the
- LayoutSkeleton class which provides a default
- implementation of the ILayout interface.
- Appenders can be parameterized to use the layout of your choice.
-
- Yes. You can implement the log4net.Appender.IAppender
- interface to create you own customized appender. We recommend that you extend the
- log4net.Appender.AppenderSkeleton class rather than
- starting from scratch. You should implement your custom code in a assembly
- separate from the log4net assembly. To get started it is worth looking at the
- source of the log4net.Appender.TraceAppender as an
- example of the minimum amount of code required to get an appender working.
-
-
- To configure log4net to use your custom appender you need to specify the
- assembly qualified name of the appender type in the config file. For
- example:
-
- There are 2 different ways to enable internal debugging in log4net.
- These are listed below. The preferred method is to specify
- the log4net.Internal.Debug option in the application's
- config file.
-
-
-
-
- Internal debugging can also be enabled by setting a value in the application's
- configuration file (not the log4net configuration file, unless the log4net config
- data is embedded in the application's config file). The log4net.Internal.Debug
- application setting must be set to the value true.
- For example:
-
- This setting is read immediately on startup an will cause all internal
- debugging messages to be emitted.
-
-
-
-
- To enable log4net's internal debug programmatically you need
- to set the log4net.Util.LogLog.InternalDebugging
- property to true. Obviously the sooner this
- is set the more debug will be produced.
-
-
-
-
- Internal debugging messages are written to the console and to the
- System.Diagnostics.Trace
- system. If the application does not have a console the messages logged
- there will be lost. Note that an application can redirect the console
- stream by setting the System.Console.Out. The
- Trace system will by default send the message to an attached debugger
- (where the messages will appear in the output window). If the process
- does not have a debugger attached then the messages are sent to the
- system debugger. A utility like DebugView from
- http://www.sysinternals.com
- may be used to capture these messages.
-
-
- As log4net internal debug messages are written to the System.Diagnostics.Trace
- system it is possible to redirect those messages to a local file. You can define
- a trace listener by adding the following to your application's .config file:
-
- If you are not getting events delivered to the event log this usually indicates
- a permissions problem. Basically if the event log does not exist the EventLogAppender
- tries to create it, but you need local administrator permissions to create event logs
- (just to write into the right bit of the registry). You don't need administrator
- permissions to log to an existing event log, but it must exist. If you are using the
- event log from a web application or service using the event log can be a little tricky.
-
-
- A web application will run as the user account ASPNET. This account deliberately has
- few permissions to reduce the chances of someone hacking into the web server. While the
- account has permission to write to the event log it does not have permission to create
- event sources (registry create and write access), which are needed to write to the event log.
-
-
- There are a couple of solutions:
-
-
-
-
- Make the ASPNET user a member of the Administrators group. This will work because the
- user will then have the required permissions. This is not recommended
- for production use.
-
-
-
-
- As the event source only needs to be created once for the machine, create an installer
- and configure it to create the event source.
- The installer will need to be run as Administrator (don't they all). See
- System.Diagnostics.EventLogInstaller in the Microsoft .NET
- Framework SDK for an example of how to create a simple event log installer.
-
Why can't I log to a FileAppender from a web application?
-
-
- The web application runs as a special user account on the web server
- called ASPNET. This account has restricted permissions to protect the
- web server from attacks. By default this account may not have permission
- to write to the file system. Make sure that the ASPNET account has
- permission to create and write to files in the directory chosen for
- logging.
-
- A windows service runs as a user account specified in the services
- control panel. This account may have restricted permissions, make
- sure that the account has permission to create and write to files
- in the directory chosen for logging.
-
-
- A windows service is launched by windows. The current directory in
- a service is set to the windows system directory (e.g.
- C:\Windows\System32). If you are loading
- the configuration file from the current directory then be aware
- that this path will not be the location of your assemblies.
- The best way to get the path to your assemblies is to use
- AppDomain.BaseDirectory.
- Note that the log4net internals never use the current directory.
-
- If you need to use ODBC to connect to your database then please note that the
- ADO.NET ODBC drivers are not included in the standard .NET framework redistributable.
- You can download the drivers from microsoft download at:
- ODBC .NET Data Provider.
-
- log4net is a tool to help the programmer output log statements to a
- variety of output targets. In case of problems with an application,
- it is helpful to enable logging so that the problem can be located.
- With log4net it is possible to enable logging at runtime without
- modifying the application binary. The log4net package is designed so
- that log statements can remain in shipped code without incurring a
- high performance cost. It follows that the speed of logging (or
- rather not logging) is crucial.
-
-
- At the same time, log output can be so voluminous that it quickly becomes
- overwhelming. One of the distinctive features of log4net is the notion of
- hierarchical loggers. Using these loggers it is possible to selectively
- control which log statements are output at arbitrary granularity.
-
-
- log4net is designed with two distinct goals in mind: speed and flexibility
-
-
-
Features
-
-
-
Support for multiple frameworks
-
Output to multiple logging targets
-
Hierarchical logging architecture
-
XML Configuration
-
Dynamic Configuration
-
Logging Context
-
Proven architecture
-
Modular and extensible design
-
High performance with flexibility
-
-
-
Support for multiple frameworks
-
-
- log4net runs on all ECMA CLI 1.0 compatible runtimes.
- log4net has specific builds for the following frameworks:
-
-
-
Microsoft .NET Framework 1.0 (1.0.3705)
-
Microsoft .NET Framework 1.1 (1.1.4322)
-
Microsoft .NET Framework 2.0 (2.0.50727)
-
Microsoft .NET Compact Framework 1.0
-
-
Mono 1.0
-
Mono 2.0
-
Microsoft Shared Source CLI 1.0
-
CLI 1.0 Compatible
-
-
- Note: Due to the .NET frameworks support for backward compatibility
- log4net will run on future versions of the runtimes listed above.
-
-
-
Output to multiple logging targets
-
-
- log4net ships with the following appenders (not on all frameworks):
-
-
-
-
-
- Type
-
- Description
-
-
-
log4net.Appender.AdoNetAppender
-
- Writes logging events to a database using either prepared statements or stored
- procedures.
-
-
-
-
log4net.Appender.AnsiColorTerminalAppender
-
- Writes color highlighted logging events to a an ANSI terminal window.
-
-
-
-
log4net.Appender.AspNetTraceAppender
-
- Writes logging events to the ASP trace context. These can then be rendered at
- the end of the ASP page or on the ASP trace page.
-
-
-
-
log4net.Appender.ColoredConsoleAppender
-
- Writes color highlighted logging events to the application's Windows Console.
-
-
-
-
log4net.Appender.ConsoleAppender
-
- Writes logging events to the application's Console. The events may go to either
- the standard our stream or the standard error stream.
-
-
-
-
log4net.Appender.EventLogAppender
-
- Writes logging events to the Windows Event Log.
-
-
-
-
log4net.Appender.FileAppender
-
- Writes logging events to a file in the file system.
-
-
-
-
log4net.Appender.LocalSyslogAppender
-
- Writes logging events to the local syslog service (UNIX only).
-
-
-
-
log4net.Appender.MemoryAppender
-
- Stores logging events in an in memory buffer.
-
-
-
-
log4net.Appender.NetSendAppender
-
- Writes logging events to the Windows Messenger service. These messages are
- displayed in a dialog on a users terminal.
-
-
-
-
log4net.Appender.OutputDebugStringAppender
-
- Writes logging events to the debugger. If the application has no
- debugger, the system debugger displays the string. If the application has no
- debugger and the system debugger is not active, the message is ignored.
-
-
-
-
log4net.Appender.RemoteSyslogAppender
-
- Writes logging events to a remote syslog service using UDP networking.
-
-
-
-
log4net.Appender.RemotingAppender
-
- Writes logging events to a remoting sink using .NET remoting.
-
-
-
-
log4net.Appender.RollingFileAppender
-
- Writes logging events to a file in the file system. The RollingFileAppender can
- be configured to log to multiple files based upon date or file size
- constraints.
-
-
-
-
log4net.Appender.SmtpAppender
-
- Sends logging events to an email address.
-
-
-
-
log4net.Appender.TelnetAppender
-
- Clients connect via Telnet to receive logging events.
-
-
-
-
log4net.Appender.TraceAppender
-
- Writes logging events to the .NET trace system.
-
-
-
-
log4net.Appender.UdpAppender
-
- Sends logging events as connectionless UDP datagrams to a remote host or a
- multicast group using a UdpClient.
-
-
-
-
-
-
-
Hierarchical logging architecture
-
-
- Hierarchical logging is an ideal fit with component based development.
- Each component has its own of logger. When individually tested, the
- properties of these loggers may be set as the developer requires.
- When combined with other components, the loggers inherit the properties
- determined by the integrator of the components. One can selectively elevate
- logging priorities on one component without affecting the other components.
- This is useful when you need a detailed trace from just a single component
- without crowding the trace file with messages from other components. All
- this can be done through configuration files; no code changes are required.
-
-
-
XML Configuration
-
-
- log4net is configured using an XML configuration file. The configuration
- information can be embedded within other XML configuration files
- (such as the application's .config file) or in a separate file. The
- configuration is easily readable and updateable while retaining the
- flexibility to express all configurations.
-
-
- Alternatively log4net can be configured programmatically.
-
-
-
Dynamic Configuration
-
-
- log4net can monitor its configuration file for changes and dynamically
- apply changes made by the configurator. The logging levels, appenders,
- layouts, and just about everything else can be adjusted at runtime.
- In many cases it is possible to diagnose application issues without
- terminating the process in question. This can a very valuable tool in
- investigating issues with deployed applications.
-
-
-
Logging Context
-
-
- log4net can be used to collect logging context data in a way that is transparent
- to the developer at the point of logging. The GlobalContext and the
- ThreadContext allow the application to store contextual data that is
- attached to logging messages. For instance, in a web service,
- once the caller is authenticated the username of the caller could be
- stored in a ThreadContext property. This property would then be automatically
- logged as part of each subsequent logging message made from the same thread.
-
-
-
Proven architecture
-
-
- log4net is based on the highly successful log4j logging library,
- in development since 1996. This popular and proven architecture has
- so far been ported to 12 languages.
-
- log4net is built on a number of different frameworks. Each new version of the frameworks add
- new features. To take advantage of these new features we must build log4net using the
- appropriate framework. We also maintain builds compatible with older versions of the frameworks.
-
-
- It is important to remember that the .NET frameworks support backward compatibility, that is
- a new version of the framework will run binary assemblies that were targeted to previous versions
- of the framework.
-
-
- While the number of different builds available may seem confusing, you only need to select the
- nearest build for your platform that is equal to or earlier than your chosen deployment framework.
- If you intend to deploy your application on the Microsoft .NET Framework 1.0 don't pick the
- log4net build that is built against the Microsoft .NET Framework 1.1 because the .NET framework
- does not guarantee forward compatibility only backward compatibility.
-
-
- The lowest common denominator build is the CLI 1.0 Compatible build. This build is compatible with
- the ECMA/ISO CLI 1.0 standard APIs and will run on all frameworks that support the standard. (Note
- that the Microsoft .NET Compact Framework does not support this standard). Use this build if you
- intend to deploy you application on both the Microsoft .NET Frameworks and the Mono frameworks.
-
- For each of these frameworks a log4net assembly targeting the framework is supplied. Although it's
- perfectly possible to use the .NET Framework 1.0 version of log4net on the .NET Framework 1.1, having
- an assembly that really targets a specific framework allows us to use features in that framework that
- are not available in other frameworks or remove features from log4net that are not supported in a
- specific framework.
-
-
-
Appenders
-
-
- The appenders available to each framework depend on the functionality of the
- framework and the platform it runs on:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Appender
-
.NET Framework 1.0
-
.NET Framework 1.1
-
.NET Framework 2.0
-
.NET CF 1.0
-
Mono 1.2
-
Shared Source CLI 1.0
-
CLI 1.0 Compatible
-
-
-
AdoNetAppender
-
x
-
x
-
x
-
x
-
x
-
-
x
-
-
-
AnsiColorTerminalAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
AspNetTraceAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
BufferingForwardingAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
ColoredConsoleAppender
-
x
-
x
-
x
-
-
-
-
-
-
-
ConsoleAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
DebugAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
EventLogAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
FileAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
ForwardingAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
LocalSyslogAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
MemoryAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
NetSendAppender
-
x
-
x
-
x
-
-
-
-
-
-
-
OutputDebugStringAppender
-
x
-
x
-
x
-
x
-
-
-
-
-
-
RemoteSyslogAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
RemotingAppender
-
x
-
x
-
x
-
-
x
-
x
-
x
-
-
-
RollingFileAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
SmtpAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
SmtpPickupDirAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
TelnetAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
TraceAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
UdpAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
-
-
Framework Specific Notes
-
-
Microsoft .NET Framework 1.0 (1.0.3705)
-
-
- none
-
-
-
Microsoft .NET Framework 1.1 (1.1.4322)
-
-
- none
-
-
-
Microsoft .NET Framework 2.0 (2.0.50727)
-
-
- none
-
-
-
Microsoft .NET Compact Framework 1.0
-
-
-
-
Assembly attributes
-
- The .NET Compact Framework 1.0 does not support retrieving assembly level
- attributes, therefore all log4net configuration attributes were removed from
- the .NET Compact Framework 1.0 version of log4net.
-
-
- For Smart-device applications, the log4net system can be configured by passing
- the location of the log4net configuration file to the
- log4net.Config.XmlConfigurator.Configure(FileInfo)
- method in the entry point of the application.
-
-
For example:
-
-
-namespace TestApp
-{
- using System.IO;
-
- public class EntryPoint
- {
- /// <summary>
- /// Application entry point.
- /// </summary>
- public static void Main()
- {
- // Uncomment the next line to enable log4net internal debugging
- // log4net.Util.LogLog.InternalDebugging = true;
-
- // This will instruct log4net to look for a configuration file
- // called config.log4net in the root directory of the device
- log4net.Config.XmlConfigurator.Configure(new FileInfo(@"\config.log4net"));
-
- ...
-
- // This will shutdown the log4net system
- log4net.LogManager.Shutdown();
- }
- }
-}
-
-
-
-
Notification events
-
- The .NET Compact Framework 1.0 does not support notification events during the
- application shutdown, therefore log4net cannot automatically hook the
- application shutdown notification.
-
-
- Applications will need to programmatically shutdown the log4net system during
- the application's shutdown using the
- log4net.LogManager.Shutdown()
- method in order to prevent losing logging events.
- See the code above for an example.
-
-
-
-
FileSystemWatcher
-
- The .NET Compact Framework 1.0 does not support the
- System.IO.FileSystemWatcher
- class. As a result, the
- XmlConfiguratorAttribute.Watch
- property and the
- XmlConfigurator.ConfigureAndWatch
- methods are not available. Watching changes to the log4net configuration
- file is not supported on the .NET Compact Framework 1.0.
-
-
-
-
UserName
-
- The .NET Compact Framework 1.0 does not support the
- System.Security.Principal.WindowsIdentity class.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.UserName property will return the value
- "NOT AVAILABLE".
-
-
-
-
Identity
-
- The .NET Compact Framework 1.0 does not support the
- System.Security.Principal.IPrincipal interface.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.Identity property will return the value
- "NOT AVAILABLE".
-
-
-
-
Environment variables
-
- The .NET Compact Framework 1.0 does not support retrieving environment
- variables, therefore it's not possible to substitute environment variables in
- parameter values when using the .NET Compact Framework 1.0 version of log4net.
-
-
-
-
Serialization
-
- The .NET Compact Framework 1.0 does not support serialization, therefore none of
- the log4net classes in the .NET Compact Framework 1.0 version are serializable.
-
-
-
-
LoggingEvent.Domain
-
- The .NET Compact Framework 1.0 does not support AppDomain functionality. The
- friendly name for the current AppDomain is stored in the LoggingEvent.Domain
- property and is accessed using the %a pattern of the
- PatternLayout. On the .NET Compact Framework 1.0 this
- value is generated by taking the file name for the application's primary module.
-
-
-
-
-
Mono
-
-
- There are 2 separate builds of log4net for mono; Mono 1.0, built using the C# compiler in a mode
- which is compatible with the CLI 1.0 language specification, and; Mono 2.0, built using the .NET
- 2.0 extensions to the C# language.
-
-
Mono 1.0
-
-
- none
-
-
-
Mono 2.0
-
-
- none
-
-
-
-
Microsoft Shared Source CLI 1.0
-
-
-
-
FileSystemWatcher
-
- SSCLI 1.0 does not support the
- System.IO.FileSystemWatcher
- class. As a result, the
- XmlConfiguratorAttribute.Watch
- property and the
- XmlConfigurator.ConfigureAndWatch
- methods are not available. Watching changes to the log4net configuration
- file is not supported on SSCLI 1.0.
-
-
-
-
UserName
-
- SSCLI 1.0 does not support the
- System.Security.Principal.WindowsIdentity class.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.UserName property will return the value
- "NOT AVAILABLE".
-
-
-
-
Identity
-
- SSCLI 1.0 does not support the
- System.Security.Principal.IPrincipal interface.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.Identity property will return the value
- "NOT AVAILABLE".
-
-
-
-
-
CLI 1.0 Compatible
-
-
- This build of log4net is designed to run on any ECMA CLI 1.0 compatible runtime.
- The assembly does not support any platform specific features. The build includes
- the common subset of functionality found in the .NET 1.0 and Mono 1.0 builds.
- The output assembly is built using the Microsoft .NET 1.0 compiler and library.
-
-
- The log4net CLI 1.0 assembly is runtime compatible with the following frameworks:
-
-
-
Microsoft .NET Framework 1.0 (and higher)
-
Mono 1.0 (and higher)
-
-
- Only a Release build is generated for this configuration because the assembly
- debugging information has not been standardized.
-
- Apache log4j includes Chainsaw
- a graphical log viewer.
-
-
- Chainsaw can either receive and display log events in realtime over
- the network, or it can load a previously created log file.
-
-
- Before Chainsaw can display data, one or more receivers must be setup.
- This is usually done by specifying an xml config file when the program
- first starts up.
- Save one or more of the sample xml config files to your local system and
- load them when Chainsaw starts.
-
-
Logging via UDP
-
-
- log4net can be configured to log messages via UDP in such a way that Chainsaw
- can receive and display them.
-
-
log4net UDP Configuration
-
-
- Configure log4net to use a UdpAppender with the following config snippet:
-
- Chainsaw can also load an XML log file if it is formatted according
- to the log4j schema. Use the following log4net config to output
- to file using the log4j schema:
-
- Inserting log requests into the application code requires a fair amount of
- planning and effort. Observation shows that approximately 4 percent of code is
- dedicated to logging. Consequently, even moderately sized applications will
- have thousands of logging statements embedded within their code. Given their
- number, it becomes imperative to manage these log statements without the need
- to modify them manually.
-
-
- The log4net environment is fully configurable programmatically. However, it is
- far more flexible to configure log4net using configuration files. Currently,
- configuration files are written in XML.
-
-
- Let us give a taste of how this is done with the help of an imaginary
- application
- MyApp
- that uses log4net.
-
-
-using Com.Foo;
-
-// Import log4net classes.
-using log4net;
-using log4net.Config;
-
-public class MyApp
-{
- // Define a static logger variable so that it references the
- // Logger instance named "MyApp".
- private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
-
- static void Main(string[] args)
- {
- // Set up a simple configuration that logs on the console.
- BasicConfigurator.Configure();
-
- log.Info("Entering application.");
- Bar bar = new Bar();
- bar.DoIt();
- log.Info("Exiting application.");
- }
-}
-
- MyApp
- begins by importing log4net related classes. It then defines a static logger
- variable with the name
- MyApp
- which happens to be the fully qualified name of the class.
-
-
- MyApp
- uses the following
- Bar
- class:
-
-
-// Import log4net classes.
-using log4net;
-
-namespace Com.Foo
-{
- public class Bar
- {
- private static readonly ILog log = LogManager.GetLogger(typeof(Bar));
-
- public void DoIt()
- {
- log.Debug("Did it again!");
- }
- }
-}
-
- The invocation of the
- BasicConfigurator.Configure()
- method creates a rather simple log4net setup. This method is hardwired to add
- to the root logger a
- ConsoleAppender. The output will be formatted using a
- PatternLayout
- set to the pattern
- "%-4timestamp [%thread] %-5level %logger %ndc - %message%newline".
-
-
- Note that by default, the root logger is assigned to
- Level.DEBUG.
-
-
- The output of MyApp is:
-
-
-
-0 [main] INFO MyApp - Entering application.
-36 [main] DEBUG Com.Foo.Bar - Did it again!
-51 [main] INFO MyApp - Exiting application.
-
-
- As a side note, let me mention that in log4net child loggers link only to their
- existing ancestors. In particular, the logger named
- Com.Foo.Bar
- is linked directly to the
- root
- logger, thereby circumventing the unused
- Com
- or
- Com.Foo
- loggers. This significantly increases performance and reduces log4net's memory
- footprint.
-
-
- The
- MyApp
- class configures log4net by invoking
- BasicConfigurator.Configure()
- method. Other classes only need to import the
- log4net
- namespace, retrieve the loggers they wish to use, and log away.
-
-
- The previous example always outputs the same log information. Fortunately, it
- is easy to modify
- MyApp
- so that the log output can be controlled at run-time. Here is a slightly
- modified version.
-
- This version of
- MyApp
- instructs the
- XmlConfigurator
- to parse a configuration file and set up logging accordingly. The path to the
- configuration file is specified on the command line.
-
-
- Here is a sample configuration file that results in exactly same output as the
- previous
- BasicConfigurator
- based example.
-
-
-
-<log4net>
- <!-- A1 is set to be a ConsoleAppender -->
- <appender name="A1" type="log4net.Appender.ConsoleAppender">
-
- <!-- A1 uses PatternLayout -->
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
- </layout>
- </appender>
-
- <!-- Set root logger level to DEBUG and its only appender to A1 -->
- <root>
- <level value="DEBUG" />
- <appender-ref ref="A1" />
- </root>
-</log4net>
-
-
- Suppose we are no longer interested in seeing the output of any component
- belonging to the
- Com.Foo
- package. The following configuration file shows one possible way of achieving
- this.
-
-
-
-<log4net>
- <!-- A1 is set to be a ConsoleAppender -->
- <appender name="A1" type="log4net.Appender.ConsoleAppender">
-
- <!-- A1 uses PatternLayout -->
- <layout type="log4net.Layout.PatternLayout">
- <!-- Print the date in ISO 8601 format -->
- <conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" />
- </layout>
- </appender>
-
- <!-- Set root logger level to DEBUG and its only appender to A1 -->
- <root>
- <level value="DEBUG" />
- <appender-ref ref="A1" />
- </root>
-
- <!-- Print only messages of level WARN or above in the package Com.Foo -->
- <logger name="Com.Foo">
- <level value="WARN" />
- </logger>
-</log4net>
-
-
- The output of
- MyApp
- configured with this file is shown below.
-
-
-
-2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application.
-2000-09-07 14:07:41,529 [main] INFO MyApp - Exiting application.
-
-
- As the logger
- Com.Foo.Bar
- does not have an assigned level, it inherits its level from
- Com.Foo, which was set to WARN in the configuration
- file. The log statement from the
- Bar.DoIt
- method has the level DEBUG, lower than the logger level WARN. Consequently,
- DoIt()
- method's log request is suppressed.
-
-
- Here is another configuration file that uses multiple appenders.
-
- Calling the enhanced MyApp with the this configuration file will output the
- following on the console.
-
-
-
- INFO [main] (MyApp.cs:16) - Entering application.
-DEBUG [main] (Bar.cs:12) - Doing it again!
- INFO [main] (MyApp.cs:19) - Exiting application.
-
-
- In addition, as the root logger has been allocated a second appender, output
- will also be directed to the
- example.log
- file. This file will be rolled over when it reaches 100KB. When roll-over
- occurs, the old version of
- example.log
- is automatically moved to
- example.log.1.
-
-
- Note that to obtain these different logging behaviors we did not need to
- recompile code. We could just as easily have logged to an email address,
- redirected all
- Com.Foo
- output to an NT Event logger, or forwarded logging events to a remote log4net
- server, which would log according to local server policy.
-
-
- For more examples of configuring appenders using the XmlConfigurator
- see the Example Appender Configuration
- document.
-
-
Configuration Attributes
-
-
- The log4net configuration can be configured using assembly-level attributes rather than
- specified programmatically.
-
-
-
- XmlConfiguratorAttribute
-
- The log4net.Config.XmlConfiguratorAttribute Allows the
- XmlConfigurator to be configured using the following properties:
-
-
-
- ConfigFile
-
- If specified, this is the filename of the configuration file to use with the
- XmlConfigurator. This file path is relative to the
- application base directory (AppDomain.CurrentDomain.BaseDirectory).
-
-
- This property cannot be used in conjunction with the
- ConfigFileExtension property.
-
-
-
- ConfigFileExtension
-
- If specified, this is the extension for the configuration file. The assembly
- file name is used as the base name with the this extension appended. For example
- if the assembly is loaded from the a file TestApp.exe
- and the ConfigFileExtension property is set to
- log4net then the configuration file name is
- TestApp.exe.log4net. This is equivalent to setting the
- ConfigFile property to TestApp.exe.log4net.
-
-
- The path to the configuration file is build by using the application base
- directory (AppDomain.CurrentDomain.BaseDirectory),
- the assembly file name and the configuration file extension.
-
-
- This property cannot be used in conjunction with the
- ConfigFile property.
-
-
-
- Watch
-
- If this flag is specified and set to true
- then the framework will watch the configuration file and will reload the config
- each time the file is modified.
-
-
-
-
- If neither of the ConfigFile or ConfigFileExtension
- properties are specified, the application configuration file (e.g. TestApp.exe.config)
- will be used as the log4net configuration file.
-
-
- Example usage:
-
-
-// Configure log4net using the .config file
-[assembly: log4net.Config.XmlConfigurator(Watch=true)]
-// This will cause log4net to look for a configuration file
-// called TestApp.exe.config in the application base
-// directory (i.e. the directory containing TestApp.exe)
-// The config file will be watched for changes.
-
-
-// Configure log4net using the .log4net file
-[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
-// This will cause log4net to look for a configuration file
-// called TestApp.exe.log4net in the application base
-// directory (i.e. the directory containing TestApp.exe)
-// The config file will be watched for changes.
-
-
- This attribute may only be used once per assembly.
-
-
-
-
- Using attributes can be a clearer method for defining where the application's
- configuration will be loaded from. However it is worth noting that attributes
- are purely passive. They are information only. Therefore if you use configuration
- attributes you must invoke log4net to allow it to read the attributes. A simple
- call to LogManager.GetLogger will cause the attributes
- on the calling assembly to be read and processed. Therefore it is imperative
- to make a logging call as early as possible during the application start-up, and
- certainly before any external assemblies have been loaded and invoked.
-
-
-
Configuration Files
-
-
- Typically the log4net configuration is specified using a file. This file can
- be read in one of two ways:
-
-
-
Using the .NET System.Configuration API
-
Reading the file contents directly
-
-
.config Files
-
-
- The System.Configuration API is only available if the
- configuration data is in the application's config file; the file named
- MyApp.exe.config or Web.config. Because the System.Configuration
- API does not support reloading of the config file the configuration settings
- cannot be watched using the log4net.Config.XmlConfigurator.ConfigureAndWatch
- methods. The main advantage of using the System.Configuration
- APIs to read the configuration data is that it requires less permissions than accessing
- the configuration file directly.
-
-
- The only way to configure an application using the System.Configuration
- APIs is to call the log4net.Config.XmlConfigurator.Configure() method or
- the log4net.Config.XmlConfigurator.Configure(ILoggerRepository) method.
-
-
- In order to embed the configuration data in the .config file the section name must be
- identified to the .NET config file parser using a configSections element.
- The section must specify the log4net.Config.Log4NetConfigurationSectionHandler
- that will be used to parse the config section. This type must be fully assembly qualified
- because it is being loaded by the .NET config file parser not by log4net. The correct
- assembly name for the log4net assembly must be specified.
- The following is a simple example configuration file that specifies the correct
- section handler to use for the log4net section.
-
- In the above example the log4net assembly is specified.
- This assembly must be located where the .NET runtime can find it. For example it could
- be located in the same directory as the application. If the log4net assembly is stored in
- the GAC then the fully qualified assembly name must be specified including the culture,
- version and public key.
-
-
- When using the .config file to specify the configuration the section name and
- XML element name must be log4net.
-
-
-
Reading Files Directly
-
-
- The XmlConfigurator can directly read any XML file and use it to configure log4net.
- This includes the application's .config file; the file named MyApp.exe.config
- or Web.config. The only reason not to read the configuration file directly is if the
- application does not have sufficient permissions to read the file, then the configuration
- must be loaded using the .NET configuration APIs (see above).
-
-
- The file to read the configuration from can be specified using any of
- the log4net.Config.XmlConfigurator methods that
- accept a System.IO.FileInfo object. Because the
- file system can be monitored for file change notifications the
- ConfigureAndWatch methods can be used to monitor
- the configuration file for modifications and automatically reconfigure log4net.
-
-
- Additionally the log4net.Config.XmlConfiguratorAttribute
- can be used to specify the file to read the configuration from.
-
-
- The configuration is read from the log4net element
- in the file. Only one log4net element can be specified
- in the file but it may be located anywhere in the XML hierarchy. For example it
- may be the root element:
-
- The above example shows how the configuration data can be embedded
- inside a .config file even though the file is being read directly
- by log4net. An important note is that the .NET config file parser
- will throw an exception if it finds an element that has not been
- registered using the configSections element.
- Therefore in the above example the log4net
- section name is registered, but the type specified to handle the
- section is System.Configuration.IgnoreSectionHandler.
- This is a built-in class that indicates that another method for reading
- the config section will be employed.
-
-
-
-
Configuration Syntax
-
-
- log4net includes a configuration reader that parses an XML DOM, the
- log4net.Config.XmlConfigurator. This section defines the
- syntax accepted by the configurator.
-
-
- This is an example of a valid XML configuration. The root element
- must be <log4net>. Note that this does not mean
- that this element cannot be embedded in another XML document. See the section above
- on Configuration Files for more information
- on how to embed the XmlConfigurator XML in a configuration file.
-
- The <log4net> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
debug
-
- Optional attribute. Value must be either true or false.
- The default value is false. Set this attribute to true
- to enable internal log4net debugging for this configuration.
-
-
-
-
update
-
- Optional attribute. Value must be either Merge or Overwrite.
- The default value is Merge. Set this attribute to Overwrite
- to reset the configuration of the repository being configured before applying this configuration.
-
-
-
-
threshold
-
- Optional attribute. Value must be the name of a level registered on the repository.
- The default value is ALL. Set this attribute to limit the messages
- that are logged across the whole repository, regardless of the logger that the message is logged to.
-
-
-
-
-
- The <log4net> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender
-
- Zero or more elements allowed. Defines an appender.
-
-
-
-
logger
-
- Zero or more elements allowed. Defines the configuration of a logger.
-
-
-
-
renderer
-
- Zero or more elements allowed. Defines an object renderer.
-
-
-
-
root
-
- Optional element, maximum of one allowed. Defines the configuration of the root logger.
-
-
-
-
param
-
- Zero or more elements allowed. Repository specific parameters
-
-
-
-
-
Appenders
-
-
- Appenders may only be defined as child elements of the <log4net>
- element. Each appender must be uniquely named. The implementing type for the appender must be specified.
-
-
- This example shows an appender of type log4net.Appender.ConsoleAppender being
- defined. The appender will be known as ConsoleAppender.
-
- The <appender> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
name
-
- Required attribute. Value must be a string name for this appender. The name must be unique
- among all the appenders defined in this configuration file. This name is used by the
- <appender-ref> element of a Logger to reference an appender.
-
-
-
-
type
-
- Required attribute. Value must be the type name for this appender. If the appender is
- not defined in the log4net assembly this type name must be fully assembly qualified.
-
-
-
-
-
- The <appender> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender-ref
-
- Zero or more elements allowed. Allows the appender to reference other appenders.
- Not supported by all appenders.
-
-
-
-
filter
-
- Zero or more elements allowed. Defines the filters used by this appender.
-
-
-
-
layout
-
- Optional element, maximum of one allowed. Defines the layout used by this appender.
-
-
-
-
param
-
- Zero or more elements allowed. Appender specific parameters.
-
- Filters elements may only be defined as children of <appender> elements.
-
-
- The <filter> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
type
-
- Required attribute. Value must be the type name for this filter. If the filter is
- not defined in the log4net assembly this type name must be fully assembly qualified.
-
-
-
-
-
- The <filter> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
param
-
- Zero or more elements allowed. Filter specific parameters.
-
-
-
-
-
- Filters form a chain that the event has to pass through. Any filter along the way can accept the event
- and stop processing, deny the event and stop processing, or allow the event on to the next filter.
- If the event gets to the end of the filter chain without being denied it is implicitly accepted and will be logged.
-
- The first filter will look for the substring 'database' in the message text of the event.
- If the text is found the filter will accept the message and filter processing will stop,
- the message will be logged. If the substring is not found the event will be passed to
- the next filter to process. If there is no next filter the event would be implicitly
- accepted and would be logged. But because we don't want the non matching events to be
- logged we need to use a log4net.Filter.DenyAllFilter
- that will just deny all events that reach it. This filter is only useful at the end of the filter chain.
-
-
- If we want to allow events that have either 'database' or 'ldap' in the message text we can use the following filters:
-
- Layout elements may only be defined as children of <appender> elements.
-
-
- The <layout> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
type
-
- Required attribute. Value must be the type name for this layout. If the layout is
- not defined in the log4net assembly this type name must be fully assembly qualified.
-
-
-
-
-
- The <layout> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
param
-
- Zero or more elements allowed. Layout specific parameters.
-
-
-
-
-
- This example shows how to configure a layout that uses the log4net.Layout.PatternLayout.
-
- Only one root logger element may only be defined and it must be a child of <log4net> element.
- The root logger is the root of the logger hierarchy. All loggers ultimately inherit from this logger.
-
- The <root> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender-ref
-
- Zero or more elements allowed. Allows the logger to reference appenders by name.
-
-
-
-
level
-
- Optional element, maximum of one allowed. Defines the logging level for this logger.
- This logger will only accept event that are at this level or above.
-
-
-
-
param
-
- Zero or more elements allowed. Logger specific parameters.
-
-
-
-
-
-
Loggers
-
-
- Logger elements may only be defined as children of the <log4net> element.
-
- The <logger> element supports the following attributes.
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
name
-
- Required attribute. Value must be the name of the logger.
-
-
-
-
additivity
-
- Optional attribute. Value may be either true or false.
- The default value is true. Set this attribute to false
- to prevent this logger from inheriting the appenders defined on parent loggers.
-
-
-
-
-
- The <logger> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender-ref
-
- Zero or more elements allowed. Allows the logger to reference appenders by name.
-
-
-
-
level
-
- Optional element, maximum of one allowed. Defines the logging level for this logger.
- This logger will only accept event that are at this level or above.
-
-
-
-
param
-
- Zero or more elements allowed. Logger specific parameters.
-
-
-
-
-
-
Renderers
-
-
- Renderer elements may only be defined as children of the <log4net> element.
-
- The <renderer> element supports the following attributes.
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
renderingClass
-
- Required attribute. Value must be the type name for this renderer. If the type is
- not defined in the log4net assembly this type name must be fully assembly qualified.
- This is the type of the object that will take responsibility for rendering the
- renderedClass.
-
-
-
-
renderedClass
-
- Required attribute. Value must be the type name for the target type for this renderer. If the type is
- not defined in the log4net assembly this type name must be fully assembly qualified.
- This is the name of the type that this renderer will render.
-
-
-
-
-
- The <renderer> element supports no child elements.
-
-
-
Parameters
-
-
- Parameter elements may be children of many elements. See the specific elements above for details.
-
- The <param> element supports the following attributes.
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
name
-
- Required attribute. Value must be the name of the parameter to set on the parent object.
-
-
-
-
value
-
- Optional attribute. One of value or type attributes must be specified.
- The value of this attribute is a string that can be converted to the value of the
- parameter.
-
-
-
-
type
-
- Optional attribute. One of value or type attributes must be specified.
- The value of this attribute is a type name to create and set as the value of the
- parameter. If the type is not defined in the log4net assembly this type name must
- be fully assembly qualified.
-
-
-
-
-
- The <param> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
param
-
- Zero or more elements allowed. Parameter specific parameters.
-
-
-
-
-
- An example param that uses nested param elements:
-
- Configuration parameters map directly to writable properties on an object.
- The properties available depend on the actual type of the object being
- configured. The log4net SDK documentation contains the API reference for
- all the components included in the log4net assembly.
-
-
- For 3rd party components please see their relevant API reference for
- details of the properties available.
-
-
-
Compact Parameter Syntax
-
-
- All parameters may alternately be specified using the parameter name as the element name
- rather than using the param element and name attribute.
-
- Most real-world systems have to deal with multiple clients simultaneously. In a
- typical multithreaded implementation of such a system, different threads will
- handle different clients. Logging is especially well suited to trace and debug
- complex distributed applications. An approach to differentiate the
- logging output of one client from another is to instantiate a new separate
- logger for each client. However this promotes the proliferation of loggers and
- increases the management overhead of logging.
-
-
- A lighter technique is to uniquely stamp each log request initiated from the
- same client interaction.
-
-
- Log4net supports different types of contextual logging and contexts with different scopes.
-
-
Scopes
-
-
- Contextual data can be set in different scopes. These contexts have progressively narrower visibility.
- In the logging event itself the values from all of the contexts are combined together such that
- values specified in a lower scoped context hide values from a higher context.
-
-
-
-
-
Scope
-
Type
-
Description
-
-
-
Global
-
log4net.GlobalContext
-
- The global context is shared by all threads in the current AppDomain.
- This context is thread safe for use by multiple threads concurrently.
-
-
-
-
Thread
-
log4net.ThreadContext
-
- The thread context is visible only to the current managed thread.
-
-
-
-
Logical Thread
-
log4net.ThreadLogicalContext
-
- The logical thread context is visible to a logical thread. Logical
- threads can jump from one managed thread to another. For more details
- see the .NET API System.Runtime.Remoting.Messaging.CallContext.
-
-
-
-
Event
-
log4net.Core.LoggingEvent
-
- Each event captures the current contextual state at the time the event
- is generated. Contextual data can be set on the event itself. This context
- is only visible to the code generating the event itself.
-
-
-
-
-
-
Context Properties
-
-
- The log4net contexts store properties, i.e. name value pairs. The name is a string
- the value is any object. A property can be set as follows:
-
- If properties with the same name are set in more than one context scope then
- the value in the narrowest scope (lower down in the list above) will hide the
- other values.
-
-
- The property values are stored as objects within the LoggingEvent.
- The PatternLayout supports rendering the value of a named
- property using the %property{name} syntax. The value is
- converted to a string by passing it to the log4net.ObjectRenderer.RendererMap
- which will locate any custom renderer for the value type. The default behavior for
- custom types is to call the object's ToString() method.
-
-
Active Property Values
-
-
- An active property value is one who's value changes over time.
-
-
- For example, imagine a custom type that implemented the
- ToString() method to return the
- number of bytes allocated by the runtime garbage collector.
-
-
-
-public class GCAllocatedBytesHelper
-{
- public override string ToString()
- {
- return GC.GetTotalMemory(true).ToString();
- }
-}
-
-
- An instance of this type can be added to the log4net.GlobalContext
- during application startup:
-
-
-
-log4net.GlobalContext.Properties["GCAllocatedBytes"] = new GCAllocatedBytesHelper();
-
-
-
- Once this property is set in the context all subsequent logging events will have a property
- called GCAllocatedBytes. The value of the property will be an instance of the
- GCAllocatedBytesHelper type. When this value is rendered to a
- string by calling the ToString method the current number of bytes
- allocated by the garbage collector will be returned and included in the output.
-
-
-
-
Context Stacks
-
-
- Sometimes simple key value pairs are not the most convenient way of capturing contextual
- information. A stack of information is a very convenient way of storing data especially
- as our applications tend to be stack based.
-
-
- The ThreadContext and LogicalThreadContext
- also support storing contextual data in a stack. The stack is stored in context property,
- therefore stacks have names and more than one stack can exist in the same context. A property
- value set in a narrower context would override a stack with the same property name set in a
- wider scoped context.
-
-
- The stack supports Push and Pop methods.
- As more contextual data is pushed onto the stack the stack grows. When the stack is rendered
- all the data pushed onto the stack is output with the most recent data to the right hand
- end of the string.
-
-
- As the stack is just an object stored in the context properties it is also rendered
- using the same PatternLayout syntax: %property{name}.
- Where name is the name of the stack.
-
-
- Calls the the stack's Push and Pop
- methods must be matched up so that each push has a corresponding pop. The
- Push method also returns an IDisposable
- object that will perform the required pop operation when it is disposed. This allows
- the C# using syntax to be used to automate the stack management.
-
- The INFO level log has a stack stored in its NDC property. The top item in the
- stack is the string context.
- The using syntax ensures that the value context is popped off the stack
- at the end of the block.
-
-
- The using
- syntax is recommended because it removes some work load from the developer and
- reduces errors in matching up the Push and Pop calls, especially when exceptions
- can occur.
-
-
-
Nested Diagnostic Contexts
-
-
- The NDC (Nested Diagnostic Context) exists for compatibility
- with older versions of log4net. This helper class implements a stack which is stored
- in the thread context property named NDC.
-
-
-
Mapped Diagnostic Contexts
-
-
- The MDC (MappedDiagnostic Context) exists for compatibility
- with older versions of log4net. This helper class implements a properties map which is
- mapped directly through to the thread context properties.
-
-
-
- To illustrate this point, let us take the example of a web service delivering
- content to numerous clients. The web service can build the NDC at the very
- beginning of the request before executing other code. The contextual
- information can be the client's host name and other information inherent to the
- request, typically information contained in cookies. Hence, even if the web
- service is serving multiple clients simultaneously, the logs initiated by the
- same code, i.e. belonging to the same logger, can still be distinguished
- because each client request will have a different NDC stack. Contrast this with
- the complexity of passing a freshly instantiated logger to all code exercised
- during the client's request.
-
-
- Nevertheless, some sophisticated applications, such as virtual hosting web
- servers, must log differently depending on the virtual host context and also
- depending on the software component issuing the request. Log4net supports
- multiple logger repositories. This would allow each virtual host to possess its own copy
- of the logger hierarchy. Configuring multiple logger hierarchies is beyond the
- scope of this document.
-
- One of the often-cited arguments against logging is its computational cost.
- This is a legitimate concern as even moderately sized applications can generate
- thousands of log requests. Much effort was spent measuring and tweaking logging
- performance. Log4net claims to be fast and flexible: speed first, flexibility
- second.
-
-
- The user should be aware of the following performance issues.
-
-
-
- Logging performance when logging is turned off.
-
- When logging is turned off entirely or just for a set of levels, the cost of a
- log request consists of a method invocation plus an integer comparison.
-
-
- However, The method invocation involves the "hidden" cost of parameter
- construction.
-
-
- For example, for some logger
- log, writing,
-
-
-log.Debug("Entry number: " + i + " is " + entry[i].ToString());
-
- incurs the cost of constructing the message parameter, i.e. converting both
- integer
- i
- and
- entry[i]
- to strings, and concatenating intermediate strings, regardless of whether the
- message will be logged or not. This cost of parameter construction can be quite
- high and it depends on the number and type of the parameters involved.
-
-
- To avoid the parameter construction cost write:
-
-
-if(log.IsDebugEnabled)
-{
- log.Debug("Entry number: " + i + " is " + entry[i].ToString());
-}
-
- This will not incur the cost of parameter construction if debugging is
- disabled. On the other hand, if the logger is debug-enabled, it will incur
- twice the cost of evaluating whether the logger is enabled or not: once in
- IsDebugEnabled
- and once in
- Debug. This is an insignificant overhead because
- evaluating a logger takes about 1% of the time it takes to actually log.
-
-
- Certain users resort to pre-processing or compile-time techniques to compile
- out all log statements. This leads to perfect performance efficiency with
- respect to logging. However, since the resulting application binary does not
- contain any log statements, logging cannot be turned on for that binary. In
- many people's opinion this is a disproportionate price to pay in exchange for a
- small performance gain.
-
-
-
- The performance of deciding whether to log or not to log when logging is
- turned on.
-
- This is essentially the performance of walking the logger hierarchy. When
- logging is turned on, log4net still needs to compare the level of the log
- request with the level of the request logger. However, loggers may not have an
- assigned level; they can inherit them from the logger hierarchy. Thus, before
- inheriting a level, the logger may need to search its ancestors.
-
-
- There has been a serious effort to make this hierarchy walk to be as fast as
- possible. For example, child loggers link only to their existing ancestors. In
- the
- BasicConfigurator
- example shown earlier, the logger named
- Com.Foo.Bar
- is linked directly to the root logger, thereby circumventing the nonexistent
- Com
- or
- Com.Foo
- loggers. This significantly improves the speed of the walk, especially in
- "sparse" hierarchies.
-
-
- The typical cost of walking the hierarchy is typically 3 times slower than when
- logging is turned off entirely.
-
-
-
- Actually outputting log messages
-
- This is the cost of formatting the log output and sending it to its target
- destination. Here again, a serious effort was made to make layouts (formatters)
- perform as quickly as possible. The same is true for appenders.
-
-
-
-
- Although log4net has many features, its first design goal was speed. Some
- log4net components have been rewritten many times to improve performance.
- Nevertheless, contributors frequently come up with new optimizations. You
- should be pleased to know that when configured with the
- SimpleLayout
- performance tests have shown log4net to log within an order of magnitude of
- System.Console.WriteLine.
-
-
-
Logging Event Flow
-
-
- The following is the series of steps and checks that a messages goes through while being logged.
- For the purposes of this example we will document an INFO level
- message being logged on logger ConsoleApp.LoggingExample. This logger is configured
- to use the log4net.Appender.ConsoleAppender. The repository used
- in this example is a log4net.Repository.Hierarchy object.
-
-
-
-
- The user logs a message using the ILog.Info method on the logger
- obtained using a call to log4net.LogManager.GetLogger("ConsoleApp.LoggingExample").
- For example: log4net.LogManager.GetLogger("ConsoleApp.LoggingExample").Info("Application Start");
- The ILog interface is actually an extension to log4net that provides level
- specific logging methods (i.e. Debug, Info, Warn, Error, and Fatal).
-
-
-
-
- The message is then logged through to the ILogger.Log method on the
- appropriate log4net.Repository.Hierarchy.Logger object. The
- ILogger.Log method takes the Level to
- log at as a parameter and therefore works for all levels.
-
-
-
-
- The repository threshold level is compared to the message level to determine if the message
- can be logged. If the message level is below the threshold level the message is not logged.
- In this case the repository is a log4net.Repository.Hierarchy object.
-
-
-
-
- The Logger level is compared to the message level to determine if the
- message can be logged. Note that the Logger level is inherited from a
- parent Logger if not specified explicitly for this Logger.
- If the message level is below the Logger level the message is not logged.
-
-
-
-
- A LoggingEvent instance is created to encapsulate the message being logged.
-
-
-
-
- The list of appenders for the Logger is built. This includes appenders
- attached to parent Loggers except where excluded by the
- Logger.Additivity property.
-
-
-
-
- The LoggingEvent object is passed to the
- IAppender.DoAppend method for each appender.
-
-
-
-
- For Each Appender that the LoggingEvent is delivered to the following
- actions take place:
-
-
-
-
- The appender threshold level is compared to the message level to determine if the message
- can be logged. If the message level is below the threshold level the message is not logged.
-
-
-
-
- If the appender has a filter chain the LoggingEvent is passed down the
- filter chain which can decide if the message can be logged or not.
-
-
-
-
- Next an appender specific check is performed. Usually this check will verify that all the
- required properties are set for the appender (e.g. a Layout is set if required).
-
-
-
-
- The LoggingEvent is passed to the appender specific
- Append method. What happens now is specific to the appender.
-
-
-
-
- The following actions take place in the ConsoleAppender.Append method:
-
-
-
-
- The ConsoleAppender uses a Layout to
- format the message as a string for display.
-
-
-
-
- The Layout uses the LoggingEvent.RenderedMessage
- property to get the string for the message object. This uses the registered
- IObjectRenderer for the type of the message object.
-
-
-
-
- The message text is displayed on the console using the Console.WriteLine method.
-
- This document is based on Short introduction to log4j by Ceki Glc.
-
-
- The log4net framework is based on log4j, see
- http://logging.apache.org/log4j for more information on log4j.
- The log4net framework, source code, binaries, documentation, examples and related
- materials are published under the terms of the
- Apache License, Version 2.0,
- a copy of which has been included with this distribution in the LICENSE.txt file.
-
-
- This document is an introduction to the log4net API, its unique features and
- design rationale. Log4net is an open source project based on the work of many
- authors. It allows the developer to control which log statements are output
- with arbitrary granularity. It is fully configurable at runtime using external
- configuration files.
-
-
- Almost every large application includes its own logging or tracing API.
- Inserting log statements into code is a low-tech method for debugging it. It
- may also be the only way because debuggers are not always available or
- applicable. This is usually the case for multithreaded applications and
- distributed applications at large.
-
-
- Once an application has been deployed it may not be possible to utilize
- development and debugging tools. An administrator can use effective logging
- systems to diagnose and fix many configuration issues.
-
-
- Experience indicates that logging is an important component of the development
- cycle. It offers several advantages. It provides precise context about the
- execution of the application. Once inserted into the code, the generation of
- logging output requires no human intervention. Moreover, log output can be
- saved in persistent medium to be studied at a later time. In addition to its
- use in the development cycle, a sufficiently rich logging package can also be
- viewed as an auditing tool.
-
-
- Logging does have its drawbacks. It can slow down an application. If too
- verbose, it can cause scrolling blindness. To alleviate these concerns, log4net
- is designed to be reliable, fast and extensible. Since logging is rarely the
- main focus of an application, the log4net API strives to be simple to
- understand and to use.
-
-
-
Frameworks
-
-
- Log4net is available for several frameworks. For each supported framework an
- assembly targeting that framework is built:
-
-
-
Microsoft .NET Framework 1.0 (1.0.3705)
-
Microsoft .NET Framework 1.1 (1.1.4322)
-
Microsoft .NET Compact Framework 1.0
-
Microsoft .NET Compact Framework 2.0
-
Mono 1.0
-
Mono 2.0
-
Microsoft Shared Source CLI 1.0
-
CLI 1.0 Compatible
-
-
- Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support
- document for more information.
-
-
-
Loggers and Appenders
-
-
- Log4net has three main components: loggers, appenders and layouts.
- These three types of components work together to enable developers to log
- messages according to message type and level, and to control at runtime how
- these messages are formatted and where they are reported. These components are
- helped by filters that control the actions of the appender and
- object renderers that turn objects into strings.
-
-
Logger hierarchy
-
-
- The first and foremost advantage of any logging API over plain
- System.Console.WriteLine
- resides in its ability to disable certain log statements while allowing others
- to print unhindered. This capability assumes that the logging space, that is,
- the space of all possible logging statements, is categorized according to some
- developer-chosen criteria.
-
-
- Loggers are named entities. Logger names are case-sensitive and they follow the
- following hierarchical naming rule:
-
-
-
Named Hierarchy
-
-
- A logger is said to be an ancestor of another logger if its name
- followed by a dot is a prefix of the descendant logger name. A logger is
- said to be a parent of a child logger if there are no ancestors
- between itself and the descendant logger.
-
-
- The hierarchy works very much in the same way as the namespace and class
- hierarchy in .NET. This is very convenient as we shall soon see.
-
-
-
-
- For example, the logger named
- "Foo.Bar"
- is a parent of the logger named
- "Foo.Bar.Baz". Similarly,
- "System"
- is a parent of
- "System.Text"
- and an ancestor of
- "System.Text.StringBuilder". This naming scheme
- should be familiar to most developers.
-
-
- The root logger resides at the top of the logger hierarchy. It is exceptional
- in three ways:
-
-
-
- It always exists
-
- It cannot be retrieved by name
-
- It always has an assigned level
-
-
- Loggers are retrieved using the static method from the
- log4net.LogManager
- class. The
- GetLogger
- methods take the name of the desired logger as a parameter. They are listed
- below:
-
-
-
-namespace log4net
-{
- public class LogManager
- {
- public static ILog GetLogger(string name);
- public static ILog GetLogger(Type type);
- }
-}
-
-
- The
- GetLogger
- methods that takes a
- Type
- parameter uses the fully qualified type name as the name of the logger to
- retrieve.
-
-
- These
- GetLogger
- methods return an
- ILog
- interface. That is the representation of the Logger passed back to the
- developer. The
- ILog
- interface is defined below:
-
-
-
-namespace log4net
-{
- public interface ILog
- {
- /* Test if a level is enabled for logging */
- bool IsDebugEnabled { get; }
- bool IsInfoEnabled { get; }
- bool IsWarnEnabled { get; }
- bool IsErrorEnabled { get; }
- bool IsFatalEnabled { get; }
-
- /* Log a message object */
- void Debug(object message);
- void Info(object message);
- void Warn(object message);
- void Error(object message);
- void Fatal(object message);
-
- /* Log a message object and exception */
- void Debug(object message, Exception t);
- void Info(object message, Exception t);
- void Warn(object message, Exception t);
- void Error(object message, Exception t);
- void Fatal(object message, Exception t);
-
- /* Log a message string using the System.String.Format syntax */
- void DebugFormat(string format, params object[] args);
- void InfoFormat(string format, params object[] args);
- void WarnFormat(string format, params object[] args);
- void ErrorFormat(string format, params object[] args);
- void FatalFormat(string format, params object[] args);
-
- /* Log a message string using the System.String.Format syntax */
- void DebugFormat(IFormatProvider provider, string format, params object[] args);
- void InfoFormat(IFormatProvider provider, string format, params object[] args);
- void WarnFormat(IFormatProvider provider, string format, params object[] args);
- void ErrorFormat(IFormatProvider provider, string format, params object[] args);
- void FatalFormat(IFormatProvider provider, string format, params object[] args);
- }
-}
-
-
- Loggers may be assigned levels. Levels are instances of the
- log4net.Core.Level
- class. The following levels are defined in order of increasing priority:
-
-
-
- ALL
-
-
- DEBUG
-
-
- INFO
-
-
- WARN
-
-
- ERROR
-
-
- FATAL
-
-
- OFF
-
-
-
- If a given logger is not assigned a level, then it inherits one from its
- closest ancestor with an assigned level. More formally:
-
-
-
Level Inheritance
-
-
- The inherited level for a given logger X, is equal to the first
- non-null level in the logger hierarchy, starting at X and proceeding
- upwards in the hierarchy towards the root logger.
-
-
-
-
- To ensure that all loggers can eventually inherit a level, the root logger
- always has an assigned level. The default value for the root logger is
- DEBUG.
-
-
- Below are four tables with various assigned level values and the resulting
- inherited levels according to the above rule.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
none
-
Proot
-
-
-
X.Y
-
none
-
Proot
-
-
-
X.Y.Z
-
none
-
Proot
-
-
-
-
- In Example 1 above, only the root logger is assigned a level. This level
- value,
- Proot, is inherited by the other loggers
- X,
- X.Y
- and
- X.Y.Z.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
Px
-
Px
-
-
-
X.Y
-
Pxy
-
Pxy
-
-
-
X.Y.Z
-
Pxyz
-
Pxyz
-
-
-
-
- In Example 2 above, all loggers have an assigned level value. There is
- no need for level inheritance.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
Px
-
Px
-
-
-
X.Y
-
none
-
Px
-
-
-
X.Y.Z
-
Pxyz
-
Pxyz
-
-
-
-
- In Example 3 above, the loggers
- root,
- X
- and
- X.Y.Z
- are assigned the levels
- Proot,
- Px
- and
- Pxyz
- respectively. The logger
- X.Y
- inherits its level value from its parent
- X.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
Px
-
Px
-
-
-
X.Y
-
none
-
Px
-
-
-
X.Y.Z
-
none
-
Px
-
-
-
-
- In Example 4 above, the loggers root and
- X
- and are assigned the levels
- Proot
- and
- Px
- respectively. The loggers
- X.Y
- and
- X.Y.Z
- inherits their level value from their nearest parent
- X
- having an assigned level.
-
-
- Logging requests are made by invoking one of the printing methods of a logger
- instance (through the log4net.ILog). These printing methods are
- Debug,
- Info,
- Warn,
- Error, and
- Fatal.
-
-
- By definition, the printing method determines the level of a logging request.
- For example, if
- log
- is a logger instance, then the statement
- log.Info("..")
- is a logging request of level INFO.
-
-
- A logging request is said to be enabled if its level is higher than or
- equal to the level of its logger. Otherwise, the request is said to be disabled.
- A logger without an assigned level will inherit one from the hierarchy. This
- rule is summarized below.
-
-
-
Basic Selection Rule
-
-
- A log request of level L in a logger with (either assigned or inherited,
- whichever is appropriate) level K, is enabled if L >= K.
-
-
-
-
- This rule is at the heart of log4net. It assumes that levels are ordered. For
- the standard levels, we have
- DEBUG < INFO < WARN < ERROR < FATAL.
-
-
- Calling the
- log4net.LogManager.GetLogger
- method with the same name will always return a reference to the exact same
- logger object.
-
-
- For example, in:
-
-
-
-ILog x = LogManager.GetLogger("wombat");
-ILog y = LogManager.GetLogger("wombat");
-
-
- x
- and
- y
- refer to exactly the same logger object.
-
-
- Thus, it is possible to configure a logger and then to retrieve the same
- instance somewhere else in the code without passing around references. In
- fundamental contradiction to biological parenthood, where parents always
- precede their children, log4net loggers can be created and configured in any
- order. In particular, a "parent" logger will find and link to its descendants
- even if it is instantiated after them.
-
-
- Configuration of the log4net environment is typically done at application
- initialization. The preferred way is by reading a configuration file. This
- approach will be discussed shortly.
-
-
- Log4net makes it easy to name loggers by software component. This can be
- accomplished by statically instantiating a logger in each class, with the
- logger name equal to the fully qualified name of the class. This is a useful
- and straightforward method of defining loggers. As the log output bears the
- name of the generating logger, this naming strategy makes it easy to identify
- the origin of a log message. However, this is only one possible, albeit common,
- strategy for naming loggers. Log4net does not restrict the possible set of
- loggers. The developer is free to name the loggers as desired.
-
-
- Nevertheless, naming loggers after the class where they are located seems to be
- the best strategy known so far. It is simple an obvious to the developers where
- each log message came from. Most importantly it leverages the design of the
- application to produce the design of the logger hierarchy. Hopefully some
- thought has gone into the design of the application.
-
-
-
Appenders
-
-
- The ability to selectively enable or disable logging requests based on their
- logger is only part of the picture. Log4net allows logging requests to print to
- multiple destinations. In log4net speak, an output destination is called an appender.
- Appenders must implement the log4net.Appenders.IAppender
- interface.
-
-
- The following appenders are defined in the log4net package:
-
- Writes logging events to the application's Console. The events may go to either
- the standard our stream or the standard error stream. The events may have configurable
- text and background colors defined for each level.
-
- Writes logging events to the debugger. If the application has no
- debugger, the system debugger displays the string. If the application has no
- debugger and the system debugger is not active, the message is ignored.
-
- Writes logging events to a file in the file system. The RollingFileAppender can
- be configured to log to multiple files based upon date or file size
- constraints.
-
- Sends logging events as connectionless UDP datagrams to a remote host or a
- multicast group using a UdpClient.
-
-
-
-
-
- More than one appender can be attached to a logger.
-
-
-
- Each enabled logging request for a given logger will be forwarded to all
- the appenders in that logger as well as the appenders higher in the hierarchy.
-
- In other words, appenders are inherited additively from the logger hierarchy.
- For example, if a console appender is added to the root logger, then all
- enabled logging requests will at least print on the console. If in addition a
- file appender is added to a logger, say X, then enabled logging requests
- for X and X's children will print on a file and on the
- console. It is possible to override this default behavior so that appender
- accumulation is no longer additive by setting the additivity flag on the logger
- to
- false.
-
-
- The rules governing appender additivity are summarized below.
-
-
-
Appender Additivity
-
-
- The output of a log statement of logger X will go to all the appenders
- in X and its ancestors. This is the meaning of the term "appender
- additivity".
-
-
- However, if an ancestor of logger X, say Y, has the additivity
- flag set to
- false, then X's output will be directed to all
- the appenders in X and it's ancestors up to and including Y but
- not the appenders in any of the ancestors of Y.
-
-
- Loggers have their additivity flag set to
- true
- by default.
-
-
-
-
- The table below shows an example:
-
-
-
-
-
- Logger Name
-
- Added Appenders
-
- Additivity Flag
-
- Output Targets
-
- Comment
-
-
-
root
-
A1
-
not applicable
-
A1
-
There is no default appender attached to root.
-
-
-
x
-
A-x1, A-x2
-
true
-
A1, A-x1, A-x2
-
Appenders of "x" and root.
-
-
-
x.y
-
none
-
true
-
A1, A-x1, A-x2
-
Appenders of "x" and root.
-
-
-
x.y.z
-
A-xyz1
-
true
-
A1, A-x1, A-x2, A-xyz1
-
Appenders in "x.y.z", "x" and root.
-
-
-
security
-
A-sec
-
false
-
A-sec
-
No appender accumulation since the additivity flag is set to
- false.
-
-
-
security.access
-
none
-
true
-
A-sec
-
Only appenders of "security" because the additivity flag in "security" is set
- to
- false.
-
-
-
-
-
Filters
-
-
- Appenders can filter the events that are delivered to them. The filters can be
- specified in the configuration to allow fine control of the events that are
- logged through different appenders.
-
-
- The simplest form of control is to specify a
- Threshold
- on the appender. This works by logging only the events that have a level that
- is greater than or equal to the threshold.
-
-
- More complex and custom event filtering can be done using the filter chain
- defined on each appender. Filters must implement the
- log4net.Filter.IFilter interface.
-
-
- The following filters are defined in the log4net package:
-
- The filters can be configured to either accept or reject the event based upon
- the match.
-
-
-
Layouts
-
-
- More often than not, users wish to customize not only the output destination
- but also the output format. This is accomplished by associating a layout
- with an appender. The layout is responsible for formatting the logging request
- according to the user's wishes, whereas an appender takes care of sending the
- formatted output to its destination. The
- PatternLayout, part of the standard log4net
- distribution, lets the user specify the output format according to conversion
- patterns similar to the C language
- printf
- function.
-
-
- For example, the PatternLayout with the conversion pattern
- "%timestamp [%thread] %-5level %logger - %message%newline"
- will output something akin to:
-
-
-
-176 [main] INFO Com.Foo.Bar - Located nearest gas station.
-
-
- The first field is the number of milliseconds elapsed since the start of the
- program. The second field is the thread making the log request. The third field
- is the level of the log statement. The fourth field is the name of the logger
- associated with the log request. The text after the '-' is the message of the
- statement.
-
-
- The following layouts are included in the log4net package:
-
- Formats the logging event as an XML element that
- complies with the log4j event dtd.
-
-
-
-
-
-
Object Renderers
-
-
- Just as importantly, log4net will render the content of the log message
- according to user specified criteria. For example, if you frequently need to
- log
- Oranges, an object type used in your current project,
- then you can register an
- OrangeRenderer
- that will be invoked whenever an orange needs to be logged.
-
-
- Object rendering follows the class hierarchy. For example, assuming oranges are
- fruits, if you register an
- FruitRenderer, all fruits including oranges will be
- rendered by the
- FruitRenderer, unless of course you registered an
- orange specific
- OrangeRenderer.
-
-
- Object renderers have to implement the
- log4net.ObjectRenderer.IObjectRenderer
- interface.
-
- Plugins are additional modular components that are attached to a logger repository.
-
-
- Plugins are stored in the PluginMap of an
- ILoggerRepository.
- Plugins are attached to the repository by using the PluginMap.Add
- method.
-
-
- The following plugins are included in the log4net package:
-
-
-
-
-
- Type
-
- Description
-
-
-
log4net.Plugin.RemoteLoggingServerPlugin
-
- Creates a remote logging sink that can receive logging events from a
- RemotingAppender.
-
-
-
-
-
-
-
RemoteLoggingServerPlugin
-
- Creates a remote logging sink that can receive logging events from a
- RemotingAppender.
-
-
- Creates a remoting logging sink. A single
- parameter must be passed to the constructor that specifies the sink URI. This is a
- name used to identify the logging sink object published via remoting and must be
- agreed with the client before communication can take place.
-
-
- Example usage:
-
-
-
-
-
Plugin Attributes
-
-
- Plugins can be configured using the following assembly-level attributes:
-
-
-
-
PluginAttribute
-
- Specifies a plugin type to create and attach to the default repository. This attribute
- does not allow plugins to be parameterized. The plugin class must have a public default constructor.
-
-
- This attribute may be used as many times as necessary to attach plugins to the repository.
-
- Logging repositories are considered advanced functionality. The default behavior
- should be sufficient for most users.
-
-
- Log4net supports logging repositories. A repository is uniquely named.
- Each repository is a (ILoggerRepository).
- Multiple assemblies can link to the same repository.
-
-
- By default there is a single logging repository per process (more precisely per AppDomain). This extends
- across all assemblies loaded into the process and allows them to all share a
- single configuration. The configuration of the repository only needs to be done once,
- typically in the entry point to the application, either programmatically or using
- a configuration attribute.
-
-
- Named logging repositories can be created using the LogManager.CreateRepository
- method. The repository for can be retrieved using the
- LogManager.GetRepository method.
- A repository created in this way will need to be configured programmatically.
-
-
Attributes
-
-
- An assembly may choose to utilize a named logging repository rather than the default repository.
- This completely separates the logging for the assembly from the rest of the application.
- This can be very useful to component developers that wish to use log4net for their
- components but do not want to require that all the applications that use their
- component are aware of log4net. It also means that their debugging configuration is
- separated from the applications configuration. The assembly should specify the
- RepositoryAttribute to set its logging repository.
-
-
- The log4net logging repositories can be configured using the following assembly-level
- attributes:
-
-
-
- AliasRepositoryAttribute
-
- Specifies a named repository to use as this assembly's repository.
-
-
- An assembly's logger repository is defined by its
- RepositoryAttribute, however this can be overridden by an
- assembly loaded before the target assembly.
-
-
- An assembly can alias another assembly's repository by specifying
- this attribute with the name of the target repository.
-
-
- This attribute may be used as many times as necessary to alias all the required
- repositories.
-
-
-
- RepositoryAttribute
-
- Specifies the logging repository for the assembly.
-
-
- Assemblies are mapped to logging repositories. This attribute controls the configuration of the repository. The
- Name property specifies the name of the repository
- for this assembly. The RepositoryType
- property specifies the type of the repository object to create for the assembly.
- If this attribute is not specified and a Name
- is not specified then the assembly will be part of the default shared logging
- repository.
-
-
- This attribute may only be used once per assembly.
-
[LOG4NET-72] - Performance of ILog.xxxFormat methods
-
[LOG4NET-74] - Change MemoryAppender member variables to protected
-
-
-
-
1.2.9 Beta
-
-
Breaking Changes
-
-
-
-
Renamed namespaces
-
- Renamed namespace log4net.spi to log4net.Core.
- Renamed namespace log4net.helpers to log4net.Util.
-
-
-
-
Renamed config classes and attributes
-
- In the log4net.Config namespace the DOMConfigurator,
- DOMConfiguratorAttribute, DomainAttribute,
- and AliasDomainAttribute have been marked as obsolete. These types are
- still available and functional in this release.
-
-
- The XmlConfigurator and XmlConfiguratorAttribute
- types replace DOMConfigurator and
- DOMConfiguratorAttribute. The RepositoryAttribute
- and AliasRepositoryAttribute types replace
- DomainAttribute and AliasDomainAttribute.
-
-
-
-
Fixed pascal casing of type names
-
- Renamed AdoNetAppender, AspNetTraceAppender,
- SmtpAppender, Iso8601DateFormatter,
- MdcFilter, and NdcFilter.
- Note that the config file type resolver is case insensitive so this is only a breaking change
- for code that programmatically creates a type that has been renamed.
-
-
-
-
Layouts changed to stream their output to a TextWriter
-
- Layouts have been changed to format their output to a TextWriter
- rather than return a string. This increases performance and reduces temporary object creation.
-
-
-
-
C style string escapes no longer supported by config parser
-
- The XML config parser no longer supports decoding C style escape sequences in strings.
- Previously sequences like \n and \\
- where decoded. Instead use the appropriate XML encodings as required.
-
-
-
-
-
New Features
-
-
-
-
New CLI build
-
- A new log4net assembly is built that targets all CLI 1.0 compatible runtimes.
- This build is essentially a common subset of the Mono 1.0 and .NET 1.0 builds.
- It is built using the MS .NET 1.0 compiler and libraries but does not use any
- platform specific APIs.
-
-
- This build is only available in release configuration and can be found at
- bin\cli\1.0\release.
-
-
-
-
Logging contexts
-
- Logging contexts can be used to record contextual data that is relevant to the current
- process. Logging contexts are both an extension of the concepts embodied in the
- MDC and NDC and a replacement for
- them. The MDC and NDC have been
- reimplemented to use the ThreadContext as storage.
-
-
- The logging contexts provide a single unified view that cuts across different
- scopes within an application.
- The contexts are layered in the following order of narrowing scope:
- GlobalContext, ThreadContext,
- LogicalThreadContext, and LoggingEvent.
- Context values specified in a narrower scope hide the matching value in a wider scope.
-
-
-
-
PatternLayout customization and long pattern names
-
- The PatternLayout now supports long pattern names.
- These pattern names are significantly more readable than the single character patterns.
-
-
- The PatternLayout now supports custom patterns. New patterns
- can be defined in the config file:
-
- The above config defines a custom pattern called myConverter
- which is bound to the TestApp.MyPatternConverter, TestApp
- type. This type must extend the log4net.Util.PatternConverter
- base class. The custom pattern can then be used in the pattern string.
-
- A new pattern based type, PatternString, can be used in
- the config file to set string properties using a pattern syntax. For example the
- File property of the FileAppender could be set as follows:
-
- The XmlConfigurator methods now support loading the
- configuration data from a URI. Config can be loaded from any URI supported by the
- System.Net.WebRequest class.
-
-
-
-
Support for No-Touch deployment
-
- Log4net supports configuring No-Touch deployment applications using the
- XmlConfiguratorAttribute. If a relative config file
- or extension is specified then this is resolved relative to the deployment
- URI.
-
-
-
-
Config file parser enhancements
-
- The config file parser has been enhanced to support specifying the property subtype, or intermediate type,
- directly on the property element, for example:
-
- Implicit conversion will be attempted between the value string and the type specified,
- and then again between the type and the target property type.
-
-
-
-
.NET string formatting syntax
-
- Added .NET String.Format style formatting syntax methods to
- the ILog interface. The new methods are:
- DebugFormat, InfoFormat,
- WarnFormat, ErrorFormat
- and FatalFormat.
-
-
-
-
Customizable levels
-
- Levels are defined by the repository LevelMap. The defined
- levels, the relative ordering of levels and level display names can be configured on
- a per-repository basis.
-
-
-
-
Per-appender security contexts
-
- Appenders that interact with controlled platform resources, e.g. files, can be
- configured to use a separate security context when accessing these resources.
- The calling thread may not have appropriate privileges to access the resource a
- custom SecurityContext can be used to elevate the
- privileges of the appender. The WindowsSecurityContext
- is used to specify alternative credentials on the Windows platform.
-
-
-
-
Added new appenders
-
-
AnsiColorTerminalAppender
-
-
- The AnsiColorTerminalAppender writes events to
- the application's ANSI terminal window. It can be configured to specify
- the text and background colors for different level events. Note that Console
- applications running on Windows do not have an ANSI terminal window and
- should use the ColoredConsoleAppender instead.
-
-
-
LocalSyslogAppender
-
-
- Logs events to a local syslog service. This appender uses the POSIX libc syslog
- library functions. If these functions are not available on the local system then
- this appender will not work!
-
-
-
RemoteSyslogAppender
-
-
- The RemoteSyslogAppender uses the BSD syslog protocol to
- log to a syslog daemon. The syslogd listens for for messages on UDP port 514.
-
-
-
TelnetAppender
-
-
- The TelnetAppender accepts socket connections and streams
- logging messages back to the client. The output is provided in a telnet-friendly way
- so that a log can be monitored over a TCP/IP socket.
- This allows simple remote monitoring of application logging.
-
-
-
-
-
-
Added new LoggerMatchFilter filter
-
- Added LoggerMatchFilter which matches a string against
- the event's logger name.
-
-
-
-
Pluggable file locking models for the FileAppender
-
- The FileAppender (and by extension the
- RollingFileAppender) now support pluggable file
- locking models. The default model, ExclusiveLock,
- maintains the current exclusive file locking behavior. An alternative
- model, MinimalLock, can be used to support writing to
- a single output file from multiple processes.
-
- The RollingFileAppender now supports a new
- rolling style, Once. In this mode the appender
- will roll the file once per run.
-
-
-
-
SmtpAppender authentication
-
- On the .NET 1.1 platform only, the SmtpAppender supports authenticating
- against the mail server using either username and password or integrated NTLM authentication.
-
-
-
-
AdoNetAppender ReconnectOnError
-
- Added new configuration property to AdoNetAppender.
- Setting ReconnectOnError to true
- will force the appender to attempt to reconnect to the database if the connection
- is lost.
-
-
-
-
UdpAppender hostname support
-
- The UdpAppender config property RemoteAddress
- can now be specified as a DNS hostname string. The hostname is resolved to an IP address.
-
-
-
-
-
Other Changes
-
-
-
-
FxCop compliance
-
- Updates to bring the internal code in line with the current FxCop rules.
-
-
-
-
Separate NUnit tests
-
- Moved the NUnit tests into a separate project, log4net.Tests.
-
-
-
-
Bug Fixes
-
-
RemotingAppender
-
-
- Sends events from a ThreadPool thread
- rather than the calling thread to prevent transfer,
- and potential loss, of the CallContext.
-
-
-
RollingFileAppender
-
-
- Fixed date rolling period detection for non UTC timezones.
-
-
-
ColoredConsoleAppender
-
-
- Updated to support writing more than 30,000 chars in a single message.
- Fixed background color overspill if the console window needs to
- scroll the contents.
-
-
-
-
-
-
-
-
1.2.0 Beta 8
-
-
-
-
Changed assembly name to log4net
-
- The build output is now log4net.dll
- for all frameworks. This is a breaking change.
-
-
- To resolve cross platform and cross version issues we have
- changed the log4net assembly to use a common name for all
- frameworks. The assembly friendly name is now log4net.
- The builds for each framework can now be differentiated
- by the assembly title. This includes the name of the framework
- that the assembly was built on.
-
-
-
-
Combined Release and ReleaseStrong builds
-
- The Release and ReleaseStrong builds have been consolidated into
- a single build called Release. This Release build is strongly named.
-
-
-
-
New Appender: ColoredConsoleAppender
-
- The ColoredConsoleAppender writes events to the
- application's console. It can be configured to specify the text and background
- colors for different level events.
-
-
-
-
New Appender: SmtpPickupDirAppender
-
- The SmtpPickupDirAppender generates SMTP compliant
- messages and writes them to a local directory. These files can then be read
- by an SMTP agent (e.g. the IIS SMTP Agent) and delivered.
-
-
-
-
New Layout: XmlLayoutSchemaLog4j
-
- This new layout formats the logging events as XML which complies with
- the log4j event dtd. This can be used to transfer log event from log4net
- to log4j. Currently the only appender that can communicate directly with
- log4j is the UdpAppender.
-
-
-
-
New PatternLayout conversion characters
-
- Added support for capturing the current thread principal name and the
- app domain friendly name for each logging event.
-
-
-
%a
-
- Used to output the friendly name of the AppDomain where the
- logging event was generated.
-
-
%u
-
- Used to output the user name for the currently active user
- (Principal.Identity.Name).
-
-
-
-
-
Types specified in the config file are now loaded ignoring case
-
- All types specified in the configuration files are now loaded
- using a case insensitive method.
-
-
-
-
Fine grained fixing for buffered events
-
- The LoggingEvent now supports fine grained
- fixing of data that needs to be accessed outside the append context,
- e.g. when an event is buffered. The new Fix
- property takes a combination of the FixFlags
- enumeration values.
-
-
-
-
Code updated inline with FxCop 1.21
-
- In line with the FxCop 1.21 guidelines:
- Sealed utility classes. Added serialization security demand to GetObjectData.
- Renamed parameters.
-
-
-
-
EventLogAppender 32K Limit
-
- There is a limit of 32K characters in an EventLog message. Added a
- check that only logs the first 32000 characters from the rendered
- message.
-
-
-
-
-
1.2.0 Beta 7
-
-
-
-
Updated to support the Microsoft .NET Framework 1.1 Final
-
- Updated to support the Microsoft .NET Framework 1.1 Final Beta (1.1.4322).
-
-
-
-
Features document
-
- Added a new document that covers the main features of log4net.
- See the features
- document for more information.
-
-
-
-
Hierarchy disabled until it is configured
-
- The Hierarchy is now disabled until it has been configured.
- All messages logged to the Hierarchy before it has been
- configured will be ignored without an error message being
- written to the console.
-
-
- If you are configuring log4net programmatically (i.e. not using
- one of the built-in configurators) you must set the
- ILoggerRepository.Configured property
- to true once you have configured
- the repository.
-
-
- The no appenders defined for a logger message will no longer be
- displayed on the console by default. This message will only be
- displayed if internal debugging is enabled.
-
-
-
-
New examples in VisualBasic.NET, JScript and Managed C++
-
- New examples in VisualBasic.NET, JScript and Managed C++.
- TODO Link to document about examples.
-
-
-
-
Code and Documentation Updates
-
- Code fixes. Documentation and manual updates.
- See the ChangeLog for more information.
-
-
-
-
Added document with example appender configurations
- Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support document for more information.
-
-
-
-
New build system using NAnt
-
- The new build system allows log4net to be built for all supported frameworks and
- in all build configurations in one go.
-
-
-
-
New source code & distribution layout
-
- The source code & distribution layout has been updated to support the new
- build environment and multiple target frameworks.
-
-
-
-
Removed DomainAttribute.UseDefaultDomain property
-
- Updated default behavior of DefaultRepositorySelector. Assemblies
- are now by default placed into the default domain. To specify another domain,
- the DomainAttribute must be used. This is the opposite behavior
- to what was previously available. If you were previously specifying the DomainAttribute.UseDefaultDomain
- property then you should remove it, and if the default behavior is now
- sufficient, you do not need to specify the DomainAttribute at all.
-
-
-
-
Updated configuration file parser
-
- Updated config file parser to use the element name as the property to set. Also
- removed <object> tag, the type attribute can now be
- specified on the property element directly.
-
- The EventLogAppender now supports setting the event ID in the
- event log, this is taken from the EventID property from the per
- event Properties map on the LoggingEvent.
-
-
-
-
Updated ADONetAppender
-
-
-
- Added support for prepared statements and stored procedures
-
- Added RawTimeStampLayoutto correctly convert the timestamps into
- database date time format
-
- Added ExceptionLayout to render the exception data
-
-
-
-
-
Support for front-end extension
-
- This allows the logging API to be wrapped or adapted for specific purposes. Two
- extension samples are included in the distribution:
-
-
-
-
-
-
-
-
-
- Extension
-
- Description
-
-
-
log4net.Ext.Trace
-
Adds trace logging methods
-
-
-
log4net.Ext.EventID
-
Adds additional eventId parameter to all methods
-
-
-
-
-
-
-
Added ForwardingAppender
-
Forwards events to multiple sub appenders after applying filter rules.
-
-
-
Added BufferingForwardingAppender
-
Forward events to sub appenders after buffering them.
-
-
-
Added ASPNetTraceAppender
-
Logs events to the ASP.NET trace system.
-
-
-
Added NetSendAppender
-
Delivers logging events using the Windows Messenger service.
-
-
-
Added UdpAppender
-
Sends logging events as connectionless UDP datagrams to a remote host or a
- multicast group.
-
-
-
Removed obsolete methods
-
-
-
Lots of updates to improve our compliance with FxCop
-
-
-
Improved SDK documentation
-
-
-
-
1.2.0 Beta 5
-
-
-
-
Fixed Exception thrown when DOM Configurator called with a null XML
- Element.
-
This occurred if the configuration file did not have a log4net section defined.
-
-
-
Made level lookup case insensitive
-
-
-
Prevented the Hierarchy's Threshold level from being set to a null reference
-
-
-
-
1.2.0 Beta 4
-
-
-
-
Added event specific properties to the logging event object
-
- Appenders can add additional information to the events they are logging. The RemotingAppender
- and the SMTPAppender both add a 'hostname' property to the events.
- These properties can be accessed using the PatternLayout with the
- %P{name} syntax.
-
-
-
-
Added a plugin framework
-
An IPlugin interface can be attached to any repository.
-
-
-
A new RemoteLoggingServerPlugin plugin acts as the server for the
- RemotingAppender
-
-
-
Updated the core log4net framework to work in an environment with no
- permissions
-
Specific appenders still require additional permissions to log correctly
-
-
-
Added support for domain aliasing using the AliasDomainAttribute
-
This allows a parent assembly to take control of the logging domain for child
- assemblies.
-
-
-
Added events for repository creation, configuration change, configuration reset
- and repository shutdown
-
-
-
Added LevelMap to the ILoggerRepository interface
-
The mapping from level name to level object is now repository specific,
- therefore each repository can have independent mappings.
-
-
-
Moved hierarchy specific config file parser to new DOMHierarchyConfigurator class
-
This is controlled by the Hierarchy object and allows for better
- encapsulation.
-
-
-
Added OnlyFixPartialEventData property to the buffered appenders
-
This setting causes slow settings to be ignored. This significantly improves the
- performance of the buffered appenders.
-
-
-
XML entity references are supported in the XML config file.
-
-
-
Added support for expanding environment variables in <param> values
-
- The environment variables must be specified as ${FOO} where FOO
- is the name of the variable to expand.
-
-
-
-
Upgraded to use NUnit 2.0
-
-
-
File appenders can specify the encoding to use for the file
-
-
-
Added strong named configuration
-
-
-
-
1.2.0 Beta 3
-
-
-
-
Added log4net.Ext.Trace extension
-
This is a separate assembly that adds a trace level to log4net.
-
-
-
The default log file output directory is now the application base directory not
- the current directory
-
-
-
Added MemoryAppender
-
Stores all the logging events in an in-memory buffer.
-
-
-
Moved the Hierarchy implementation into a separate namespace
-
- The log4net.Repository.Hierarchy namespace now contains all the
- code that is specific to the Hierarchy implementation.
-
-
-
-
Refactored the DOMConfigurator and BasicConfigurator
-
- The Hierarchy specific data schema and implementation could be has
- now been moved to the log4net.Repository.Hierarchy namespace. The
- bootstrap code for these configurators remains in the log4net.Config
- namespace.
-
-
-
-
Replaced the DOMConfiguratorAttribute UseExecutableDomain
- property with UseDefaultDomain
-
- This change to the implementation of the DOMConfiguratorAttribute should
- allow the configuration of multiple assemblies to be accomplished more easily,
- especially when developing web applications (ASP.NET).
-
-
-
-
A few good bug fixes!
-
-
-
-
1.2.0 Beta 2
-
-
-
-
Added ADONetAppender
-
Thanks to TechnologyOneCorp.com.
-
-
-
Added TraceLogAssembly extensibility example
-
-
-
Lots of bug fixes
-
-
-
-
1.2.0 Beta 1
-
-
-
-
Added 6 new examples
-
-
-
Split Category class into Logger and LogManager classes
-
- The instance methods from Category have moved to the Logger
- class. The static methods from Category have moved to the LogManager
- class. The Category class still exists but for backward
- compatibility only. Changed interface ICategoryFactory to ILoggerFactory
- and the implementation class DefaultCategoryFactory to DefaultLoggerFactory.
-
-
-
-
Replaced Priority class with Level class
-
- The Priority class has been replaced by the Level class.
- The Priority class still exists for backward compatibility only.
- The Level class implements a static pool of Level objects.
- The Level class is sealed and serializable.
-
-
-
-
Added ILoggerRepository interface implemented by Hierarchy
-
- The Hierarchy class implements the ILoggerRepository interface.
- This interface is used by the LogManager class and therefore
- allows different implementations of ILoggerRepository to be used.
-
-
-
-
Enhanced NUnit tests
-
- All the NUnit tests can be run using a single TestSuite: NUnitGUI
- log4net.LogManager+AllTests,log4net.dll.
-
-
-
-
Added support for serializing LoggingEvents
-
- The LoggingEvent class is serializable. All local state is
- captured before serialization occurs. This now allows LoggingEvent
- objects to be serialized between applications or machines.
-
-
-
-
Added RemotingAppender
-
- Delivers LoggingEvents to a remote interface. This can be used to
- collect distributed logging into a single log file. There is an example
- remoting sink that receives the logging events, see examples\net\remoting\RemotingServer
- for details.
-
-
-
-
Added support for rendering composite objects
-
- The IObjectRenderer interface method DoRender now
- takes a RendererMap argument. This allows the renderer to use the
- appropriate renderer from the RendererMap to render any nested
- objects.
-
-
-
-
Added support for rendering exceptions
-
- The DefaultRenderer now has support for rendering exceptions to a
- string. This includes nested exceptions. The RendererMap is now
- used to render exceptions in the LoggingEvent. This allows the
- rendering of specific exceptions to be enhanced by specific renderers.
-
-
-
-
Added ITriggeringEventEvaluator interface
-
- This interface is used by SMTPAppender and RemotingAppender
- to determine if a LoggingEvent meets a set of user defined
- criteria. These appenders use the interface to determine whether or not to
- deliver the current buffer of events to their listener. The interface is
- implemented by the LevelEvaluator class, which triggers above a
- set level.
-
-
-
-
Added regex matching to the MDCFilter, NDCFilter and StringMatchFilter
-
- The MDCFilter, NDCFilter and StringMatchFilter
- can now be configured to use regex matches in addition to substring matches.
- Set the RegexToMatch property to use this feature.
-
-
-
-
Added XMLLayout
-
- emits an XML element for each LoggingEvent. This allows logging
- events to be stored and manipulated as XML. The DTD for the XML emitted is in
- the log4net-events.dtd
-
-
-
-
Added support for <logger> and <level> elements in the
- DOMConfigurator
-
- As the Category and Priority classes have been
- replaced by the Logger and Level classes. The DOMConfigurator
- has been updated to allow the <logger> and <level>
- elements to be used in place of the <category> and <priority>
- elements. The old elements are still accepted for backward compatibility.
-
-
-
-
Added Threshold property to Hierarchy
-
- Changed DisableXXX() methods on Hierarchy to a Threshold
- property.
-
-
-
-
Added support for logging domains
-
- The LogManager supports multiple logging domains. The LogManager
- uses an instance of the IRepositorySelector class to map from
- domains to ILoggerRepository instances. The default implementation
- is to have a separate ILoggerRepository for each domain. When a
- call is made to the static methods on LogManager the domain can be
- specified (as a string) or the domain can be inferred automatically from the
- calling assembly. The default behavior is for each assembly loaded into the
- process to have its own domain and ILoggerRepository. These can
- each be configured separately. This allows standalone assemblies to use log4net
- without conflicting with other modules in the process. The domain for the
- assembly is configured using metadata attributes defined on the assembly.
-
-
-
-
DOMConfigurator can set params to arbitrary objects
-
- Using a new <object> element, params can now be set to any
- creatable object.
-
- log4net user support is provided via a mailing list. Discussion on log4net is held on the
- log4net-user mailing list. Please search the archives before posting because it
- is likely that your question has been answered before.
-
-
Mailing List Archives
-
-
- You can browse the mailing list archives at the following locations:
-
- Before posting please read the following guidelines:
-
-
-
-
- Ask smart questions
- Every volunteer project obtains its strength from the people involved
- in it. You are welcome to join any of our mailing lists. You can
- choose to lurk, or actively participate; it's up to you. The level of
- community responsiveness to specific questions is generally directly
- proportional to the amount of effort you spend formulating your
- question. Eric Raymond and Rick Moen have even written an essay entitled
- "Asking Smart Questions"
- precisely on this topic.
-
-
-
-
-
- Keep your email short and to the point
- If your email is more than about a page of text, chances are that it
- won't get read by very many people. It is much better to try to pack a
- lot of informative information (see above about asking smart questions)
- into as small of an email as possible. If you are replying to a previous
- email, it is a good idea to only quote the parts that you are replying
- to and to remove the unnecessary bits. This makes it easier for people
- to follow a thread as well as making the email archives easier to search
- and read.
-
-
-
-
-
- Do your best to ensure that you are not sending HTML or "Stylelized" email to the list
- If you are using Outlook or Outlook Express or Eudora, chances are that
- you are sending HTML email by default. There is usually a setting that
- will allow you to send "Plain Text" email. If you are using Microsoft
- products to send email, there are several bugs in the software that
- prevent you from turning off the sending of HTML email. Please read this
- page as well.
-
-
-
-
-
- Watch where you are sending email
- Our mailing lists have set the Reply-To to go back to the
- list. That means that when you Reply to a message, it will go to the list
- and not to the original author directly. The reason is because it helps
- facilitate discussion on the list for everyone to benefit from. Be careful
- of this as sometimes you may intend to reply to a message directly to someone
- instead of the entire list.
-
-
- The appropriate contents of the Reply-To header is an age-old debate that
- should not be brought up on the mailing lists. You can examine opposing points of view
- condemning
- our convention and condoning
- it. Bringing this topic up for debate again on a mailing list will add nothing new
- and is considered off-topic.
-
-
-
-
-
- Do not cross post messages
- In other words, pick a mailing list and send your messages to that mailing
- list only. Do not send your messages to multiple mailing lists. The reason is
- that people may be subscribed to one list and not to the other. Therefore,
- some people will only see part of the conversation.
-
-
-
-
- Where relevant please try to include the following information in your postings.
-
-
-
-
- Specify the version of log4net you are using.
-
-
-
-
-
- Specify what your assembly type is, i.e. exe or dll, and how your code is launched,
- e.g. console application, windows application, ASP.NET project, COM+ hosted object, etc...
-
-
-
-
-
- Specify which runtime platform (e.g. MS .NET, Mono, SSCLI) you are using and which version.
-
-
-
-
-
- If you are having configuration issues then include logging configuration files if any, plus source code.
-
-
-
-
-
- If possible please reproduce your issue with the
- internal log4net debugging
- enabled. Include this debug output in your post, it is usually the first thing we ask for in diagnosing issues.
-
-
-
-
-
- If you think you have found a bug then a short example reproducing the problem is very much appreciated.
-
-
-
-
- To prevent spam, we require you to be subscribed to the list before posting to it.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/mono/1.0/Performance/NotLogging/cs/nant.build b/examples/mono/1.0/Performance/NotLogging/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/NotLogging/cs/nant.config b/examples/mono/1.0/Performance/NotLogging/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/NotLogging/cs/src/AssemblyInfo.cs b/examples/mono/1.0/Performance/NotLogging/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/NotLogging/cs/src/NotLogging.cs b/examples/mono/1.0/Performance/NotLogging/cs/src/NotLogging.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/NotLogging/nant.build b/examples/mono/1.0/Performance/NotLogging/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/NotLogging/nant.config b/examples/mono/1.0/Performance/NotLogging/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/nant.build b/examples/mono/1.0/Performance/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Performance/nant.config b/examples/mono/1.0/Performance/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SharedModule/cs/nant.build b/examples/mono/1.0/Repository/SharedModule/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SharedModule/cs/nant.config b/examples/mono/1.0/Repository/SharedModule/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SharedModule/cs/src/AssemblyInfo.cs b/examples/mono/1.0/Repository/SharedModule/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SharedModule/cs/src/Math.cs b/examples/mono/1.0/Repository/SharedModule/cs/src/Math.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SharedModule/nant.build b/examples/mono/1.0/Repository/SharedModule/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SharedModule/nant.config b/examples/mono/1.0/Repository/SharedModule/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/cs/nant.build b/examples/mono/1.0/Repository/SimpleApp/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/cs/nant.config b/examples/mono/1.0/Repository/SimpleApp/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/cs/src/App.config b/examples/mono/1.0/Repository/SimpleApp/cs/src/App.config
old mode 100755
new mode 100644
index d87f2d9f..10a5b298
--- a/examples/mono/1.0/Repository/SimpleApp/cs/src/App.config
+++ b/examples/mono/1.0/Repository/SimpleApp/cs/src/App.config
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/mono/1.0/Repository/SimpleApp/cs/src/AssemblyInfo.cs b/examples/mono/1.0/Repository/SimpleApp/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/cs/src/EntryPoint.cs b/examples/mono/1.0/Repository/SimpleApp/cs/src/EntryPoint.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/cs/src/SimpleApp.exe.log4net b/examples/mono/1.0/Repository/SimpleApp/cs/src/SimpleApp.exe.log4net
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/nant.build b/examples/mono/1.0/Repository/SimpleApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleApp/nant.config b/examples/mono/1.0/Repository/SimpleApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/cs/nant.build b/examples/mono/1.0/Repository/SimpleModule/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/cs/nant.config b/examples/mono/1.0/Repository/SimpleModule/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/cs/src/AssemblyInfo.cs b/examples/mono/1.0/Repository/SimpleModule/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/cs/src/Math.cs b/examples/mono/1.0/Repository/SimpleModule/cs/src/Math.cs
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/cs/src/SimpleModule.dll.log4net b/examples/mono/1.0/Repository/SimpleModule/cs/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/nant.build b/examples/mono/1.0/Repository/SimpleModule/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/SimpleModule/nant.config b/examples/mono/1.0/Repository/SimpleModule/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/nant.build b/examples/mono/1.0/Repository/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Repository/nant.config b/examples/mono/1.0/Repository/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Tutorials/ConsoleApp/cs/nant.build b/examples/mono/1.0/Tutorials/ConsoleApp/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Tutorials/ConsoleApp/cs/nant.config b/examples/mono/1.0/Tutorials/ConsoleApp/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/mono/1.0/Tutorials/ConsoleApp/cs/src/App.config b/examples/mono/1.0/Tutorials/ConsoleApp/cs/src/App.config
old mode 100755
new mode 100644
index 4680e125..f312d5f2
--- a/examples/mono/1.0/Tutorials/ConsoleApp/cs/src/App.config
+++ b/examples/mono/1.0/Tutorials/ConsoleApp/cs/src/App.config
@@ -1,4 +1,25 @@
+
+
+
-
\ No newline at end of file
+
diff --git a/examples/net/1.1/Repository/SimpleApp/js/src/AssemblyInfo.js b/examples/net/1.1/Repository/SimpleApp/js/src/AssemblyInfo.js
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleApp/js/src/EntryPoint.js b/examples/net/1.1/Repository/SimpleApp/js/src/EntryPoint.js
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleApp/js/src/SimpleApp.exe.log4net b/examples/net/1.1/Repository/SimpleApp/js/src/SimpleApp.exe.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleApp/nant.build b/examples/net/1.1/Repository/SimpleApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleApp/nant.config b/examples/net/1.1/Repository/SimpleApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/js/nant.build b/examples/net/1.1/Repository/SimpleModule/js/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/js/nant.config b/examples/net/1.1/Repository/SimpleModule/js/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/js/src/AssemblyInfo.js b/examples/net/1.1/Repository/SimpleModule/js/src/AssemblyInfo.js
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/js/src/Math.js b/examples/net/1.1/Repository/SimpleModule/js/src/Math.js
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/js/src/SimpleModule.dll.log4net b/examples/net/1.1/Repository/SimpleModule/js/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/nant.build b/examples/net/1.1/Repository/SimpleModule/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/SimpleModule/nant.config b/examples/net/1.1/Repository/SimpleModule/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/nant.build b/examples/net/1.1/Repository/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Repository/nant.config b/examples/net/1.1/Repository/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Tutorials/ConsoleApp/cpp/nant.build b/examples/net/1.1/Tutorials/ConsoleApp/cpp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Tutorials/ConsoleApp/cpp/nant.config b/examples/net/1.1/Tutorials/ConsoleApp/cpp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/1.1/Tutorials/ConsoleApp/cpp/src/App.config b/examples/net/1.1/Tutorials/ConsoleApp/cpp/src/App.config
old mode 100755
new mode 100644
index c46c37b4..de78cf09
--- a/examples/net/1.1/Tutorials/ConsoleApp/cpp/src/App.config
+++ b/examples/net/1.1/Tutorials/ConsoleApp/cpp/src/App.config
@@ -1,4 +1,25 @@
+
+
+
+
+
+
+
+Local8.0.50727
@@ -140,4 +162,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Appenders/SampleAppendersApp/nant.build b/examples/net/2.0/Appenders/SampleAppendersApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Appenders/SampleAppendersApp/nant.config b/examples/net/2.0/Appenders/SampleAppendersApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/nant.config b/examples/net/2.0/Appenders/WmiAppender/cs/nant.config
index b0553a7f..52613e83 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/nant.config
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/nant.config
@@ -1,23 +1,23 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/AssemblyInfo.cs b/examples/net/2.0/Appenders/WmiAppender/cs/src/AssemblyInfo.cs
index 9105dfe5..16c39de3 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/AssemblyInfo.cs
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/AssemblyInfo.cs
@@ -1,67 +1,67 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-//
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-//
-[assembly: AssemblyTitle("log4net.Appender.WmiAppender")]
-[assembly: AssemblyDescription("The Apache Software Foundation log4net Logging Framework - WmiAppender")]
-
-#if DEBUG
-[assembly: AssemblyConfiguration("Debug")]
-#else
-[assembly: AssemblyConfiguration("Retail")]
-#endif
-
-[assembly: AssemblyProduct("log4net")]
-[assembly: AssemblyCulture("")]
-
-//
-// In order to sign your assembly you must specify a key to use. Refer to the
-// Microsoft .NET Framework documentation for more information on assembly signing.
-//
-// Use the attributes below to control which key is used for signing.
-//
-// Notes:
-// (*) If no key is specified, the assembly is not signed.
-// (*) KeyName refers to a key that has been installed in the Crypto Service
-// Provider (CSP) on your machine. KeyFile refers to a file which contains
-// a key.
-// (*) If the KeyFile and the KeyName values are both specified, the
-// following processing occurs:
-// (1) If the KeyName can be found in the CSP, that key is used.
-// (2) If the KeyName does not exist and the KeyFile does exist, the key
-// in the KeyFile is installed into the CSP and used.
-// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
-// When specifying the KeyFile, the location of the KeyFile should be
-// relative to the project output directory which is
-// %Project Directory%\obj\. For example, if your KeyFile is
-// located in the project directory, you would specify the AssemblyKeyFile
-// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
-// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
-// documentation for more information on this.
-//
-[assembly: AssemblyDelaySign(false)]
-[assembly: AssemblyKeyFile("")]
-[assembly: AssemblyKeyName("")]
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("log4net.Appender.WmiAppender")]
+[assembly: AssemblyDescription("The Apache Software Foundation log4net Logging Framework - WmiAppender")]
+
+#if DEBUG
+[assembly: AssemblyConfiguration("Debug")]
+#else
+[assembly: AssemblyConfiguration("Retail")]
+#endif
+
+[assembly: AssemblyProduct("log4net")]
+[assembly: AssemblyCulture("")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/IWmiBoundEvent.cs b/examples/net/2.0/Appenders/WmiAppender/cs/src/IWmiBoundEvent.cs
index 90445119..0ccd376e 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/IWmiBoundEvent.cs
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/IWmiBoundEvent.cs
@@ -1,53 +1,53 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using log4net.Core;
-using System.Management.Instrumentation;
-
-namespace log4net.Appender
-{
- ///
- /// Subclass of for events that need to bind to a
- ///
- ///
- ///
- /// If the . is
- /// a then the default behavior of the
- /// is to call the method passing the .
- /// This allows the event object to capture additional data from the
- /// before it is fired.
- ///
- ///
- public interface IWmiBoundEvent : IEvent
- {
- ///
- /// This method is called before this instance is fired
- ///
- /// the containing the data
- ///
- ///
- /// The calls this method passing the
- /// object. Implementors should capture any required data from the
- /// and store it in their instance prior to firing to WMI.
- ///
- ///
- void Bind(LoggingEvent loggingEvent);
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using log4net.Core;
+using System.Management.Instrumentation;
+
+namespace log4net.Appender
+{
+ ///
+ /// Subclass of for events that need to bind to a
+ ///
+ ///
+ ///
+ /// If the . is
+ /// a then the default behavior of the
+ /// is to call the method passing the .
+ /// This allows the event object to capture additional data from the
+ /// before it is fired.
+ ///
+ ///
+ public interface IWmiBoundEvent : IEvent
+ {
+ ///
+ /// This method is called before this instance is fired
+ ///
+ /// the containing the data
+ ///
+ ///
+ /// The calls this method passing the
+ /// object. Implementors should capture any required data from the
+ /// and store it in their instance prior to firing to WMI.
+ ///
+ ///
+ void Bind(LoggingEvent loggingEvent);
+ }
+}
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.cs b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.cs
index 5e563b38..a2398838 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.cs
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.cs
@@ -1,255 +1,255 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.Threading;
-using log4net.Appender;
-using log4net.Core;
-using System.Management.Instrumentation;
-
-// This is the WMI namespace for event objects in this assembly
-[assembly: Instrumented("root/log4net")]
-
-namespace log4net.Appender
-{
- ///
- /// fires instrumented events for each
- ///
- ///
- ///
- /// This appender fires Windows Management Instrumentation (WMI) events for
- /// each .
- ///
- ///
- /// By default this appender fires objects, however
- /// this can be overridden by specifying a custom or by setting
- /// the . to an
- /// instance.
- ///
- ///
- /// This assembly must be registered with WMI. Use the InstallUtil tool
- /// shipped with the .NET framework to install this assembly. This will register
- /// the root/log4net WMI namespace.
- ///
- ///
- public sealed class WmiAppender : IAppender, IOptionHandler
- {
- #region Private Instance Fields
-
- ///
- /// The layout of this appender.
- ///
- ///
- /// See for more information.
- ///
- private WmiLayout m_layout;
-
- ///
- /// The name of this appender.
- ///
- ///
- /// See for more information.
- ///
- private string m_name;
-
- ///
- /// The level threshold of this appender.
- ///
- ///
- ///
- /// There is no level threshold filtering by default.
- ///
- ///
- /// See for more information.
- ///
- ///
- private Level m_threshold;
-
- ///
- /// It is assumed and enforced that errorHandler is never null.
- ///
- ///
- ///
- /// It is assumed and enforced that errorHandler is never null.
- ///
- ///
- /// See for more information.
- ///
- ///
- private IErrorHandler m_errorHandler = new log4net.Util.OnlyOnceErrorHandler("WmiAppender");
-
- #endregion
-
- #region Public Instance Properties
-
- ///
- /// Gets or sets the name of this appender.
- ///
- /// The name of the appender.
- ///
- ///
- /// The name uniquely identifies the appender.
- ///
- ///
- public string Name
- {
- get { return m_name; }
- set { m_name = value; }
- }
-
- ///
- /// Gets or sets the threshold of this appender.
- ///
- ///
- /// The threshold of the appender.
- ///
- ///
- ///
- /// All log events with lower level than the threshold level are ignored
- /// by the appender.
- ///
- ///
- /// In configuration files this option is specified by setting the
- /// value of the option to a level
- /// string, such as "DEBUG", "INFO" and so on.
- ///
- ///
- public Level Threshold
- {
- get { return m_threshold; }
- set { m_threshold = value; }
- }
-
- ///
- /// Gets or sets the for this appender.
- ///
- /// The layout of the appender.
- ///
- ///
- /// The to use to format the
- /// as an .
- ///
- ///
- public WmiLayout Layout
- {
- get { return m_layout; }
- set { m_layout = value; }
- }
-
- ///
- /// Gets or sets the for this appender.
- ///
- /// The of the appender
- ///
- ///
- /// The default value is a .
- ///
- ///
- public IErrorHandler ErrorHandler
- {
- get { return m_errorHandler; }
- set
- {
- if (value == null)
- {
- // We do not throw exception here since the cause is probably a
- // bad config file.
- log4net.Util.LogLog.Warn(GetType(), "WmiAppender: You have tried to set a null error-handler.");
- }
- else
- {
- m_errorHandler = value;
- }
- }
- }
-
- #endregion Public Instance Properties
-
- ///
- /// Activate this appender
- ///
- ///
- ///
- /// If a has not been specified then this
- /// method will create a default instance.
- ///
- ///
- public void ActivateOptions()
- {
- if (m_layout == null)
- {
- m_layout = new WmiLayout();
- }
- }
-
- ///
- /// Close this appender
- ///
- public void Close()
- {
- }
-
- ///
- /// Process a
- ///
- /// the containing the data
- ///
- ///
- /// Uses the to format the
- /// as an . This is then fired.
- ///
- ///
- public void DoAppend(LoggingEvent loggingEvent)
- {
- if (loggingEvent == null)
- {
- throw new ArgumentNullException("loggingEvent");
- }
-
- try
- {
- if (IsAsSevereAsThreshold(loggingEvent.Level))
- {
- IEvent instrumentationEvent = m_layout.Format(loggingEvent);
- if (instrumentationEvent != null)
- {
- instrumentationEvent.Fire();
- }
- }
- }
- catch(Exception ex)
- {
- ErrorHandler.Error("Failed in DoAppend", ex);
- }
- catch
- {
- // Catch handler for non System.Exception types
- ErrorHandler.Error("Failed in DoAppend (unknown exception)");
- }
- }
-
- ///
- /// Checks if the message level is below this appender's threshold.
- ///
- private bool IsAsSevereAsThreshold(Level level)
- {
- return ((m_threshold == null) || level >= m_threshold);
- }
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using System.Threading;
+using log4net.Appender;
+using log4net.Core;
+using System.Management.Instrumentation;
+
+// This is the WMI namespace for event objects in this assembly
+[assembly: Instrumented("root/log4net")]
+
+namespace log4net.Appender
+{
+ ///
+ /// fires instrumented events for each
+ ///
+ ///
+ ///
+ /// This appender fires Windows Management Instrumentation (WMI) events for
+ /// each .
+ ///
+ ///
+ /// By default this appender fires objects, however
+ /// this can be overridden by specifying a custom or by setting
+ /// the . to an
+ /// instance.
+ ///
+ ///
+ /// This assembly must be registered with WMI. Use the InstallUtil tool
+ /// shipped with the .NET framework to install this assembly. This will register
+ /// the root/log4net WMI namespace.
+ ///
+ ///
+ public sealed class WmiAppender : IAppender, IOptionHandler
+ {
+ #region Private Instance Fields
+
+ ///
+ /// The layout of this appender.
+ ///
+ ///
+ /// See for more information.
+ ///
+ private WmiLayout m_layout;
+
+ ///
+ /// The name of this appender.
+ ///
+ ///
+ /// See for more information.
+ ///
+ private string m_name;
+
+ ///
+ /// The level threshold of this appender.
+ ///
+ ///
+ ///
+ /// There is no level threshold filtering by default.
+ ///
+ ///
+ /// See for more information.
+ ///
+ ///
+ private Level m_threshold;
+
+ ///
+ /// It is assumed and enforced that errorHandler is never null.
+ ///
+ ///
+ ///
+ /// It is assumed and enforced that errorHandler is never null.
+ ///
+ ///
+ /// See for more information.
+ ///
+ ///
+ private IErrorHandler m_errorHandler = new log4net.Util.OnlyOnceErrorHandler("WmiAppender");
+
+ #endregion
+
+ #region Public Instance Properties
+
+ ///
+ /// Gets or sets the name of this appender.
+ ///
+ /// The name of the appender.
+ ///
+ ///
+ /// The name uniquely identifies the appender.
+ ///
+ ///
+ public string Name
+ {
+ get { return m_name; }
+ set { m_name = value; }
+ }
+
+ ///
+ /// Gets or sets the threshold of this appender.
+ ///
+ ///
+ /// The threshold of the appender.
+ ///
+ ///
+ ///
+ /// All log events with lower level than the threshold level are ignored
+ /// by the appender.
+ ///
+ ///
+ /// In configuration files this option is specified by setting the
+ /// value of the option to a level
+ /// string, such as "DEBUG", "INFO" and so on.
+ ///
+ ///
+ public Level Threshold
+ {
+ get { return m_threshold; }
+ set { m_threshold = value; }
+ }
+
+ ///
+ /// Gets or sets the for this appender.
+ ///
+ /// The layout of the appender.
+ ///
+ ///
+ /// The to use to format the
+ /// as an .
+ ///
+ ///
+ public WmiLayout Layout
+ {
+ get { return m_layout; }
+ set { m_layout = value; }
+ }
+
+ ///
+ /// Gets or sets the for this appender.
+ ///
+ /// The of the appender
+ ///
+ ///
+ /// The default value is a .
+ ///
+ ///
+ public IErrorHandler ErrorHandler
+ {
+ get { return m_errorHandler; }
+ set
+ {
+ if (value == null)
+ {
+ // We do not throw exception here since the cause is probably a
+ // bad config file.
+ log4net.Util.LogLog.Warn(GetType(), "WmiAppender: You have tried to set a null error-handler.");
+ }
+ else
+ {
+ m_errorHandler = value;
+ }
+ }
+ }
+
+ #endregion Public Instance Properties
+
+ ///
+ /// Activate this appender
+ ///
+ ///
+ ///
+ /// If a has not been specified then this
+ /// method will create a default instance.
+ ///
+ ///
+ public void ActivateOptions()
+ {
+ if (m_layout == null)
+ {
+ m_layout = new WmiLayout();
+ }
+ }
+
+ ///
+ /// Close this appender
+ ///
+ public void Close()
+ {
+ }
+
+ ///
+ /// Process a
+ ///
+ /// the containing the data
+ ///
+ ///
+ /// Uses the to format the
+ /// as an . This is then fired.
+ ///
+ ///
+ public void DoAppend(LoggingEvent loggingEvent)
+ {
+ if (loggingEvent == null)
+ {
+ throw new ArgumentNullException("loggingEvent");
+ }
+
+ try
+ {
+ if (IsAsSevereAsThreshold(loggingEvent.Level))
+ {
+ IEvent instrumentationEvent = m_layout.Format(loggingEvent);
+ if (instrumentationEvent != null)
+ {
+ instrumentationEvent.Fire();
+ }
+ }
+ }
+ catch(Exception ex)
+ {
+ ErrorHandler.Error("Failed in DoAppend", ex);
+ }
+ catch
+ {
+ // Catch handler for non System.Exception types
+ ErrorHandler.Error("Failed in DoAppend (unknown exception)");
+ }
+ }
+
+ ///
+ /// Checks if the message level is below this appender's threshold.
+ ///
+ private bool IsAsSevereAsThreshold(Level level)
+ {
+ return ((m_threshold == null) || level >= m_threshold);
+ }
+ }
+}
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.csproj b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.csproj
index 036cd2b1..04b4480f 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.csproj
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiAppender.csproj
@@ -1,112 +1,134 @@
-
-
- Local
- 8.0.50727
- 2.0
- {BE56F892-37BA-489C-A91D-F2761FDB96EF}
- Debug
- AnyCPU
-
-
-
-
- log4net.Appender.WmiAppender
-
-
- JScript
- Grid
- IE50
- false
- Library
- log4net.Appender.WmiAppender
-
-
-
-
-
-
-
-
- ..\bin\Debug\
- false
- 285212672
- false
-
-
- DEBUG;TRACE
-
-
- true
- 4096
- false
- false
- false
- false
- 4
- full
- prompt
-
-
- ..\bin\Release\
- false
- 285212672
- false
-
-
- TRACE
-
-
- false
- 4096
- true
- false
- false
- false
- 4
- none
- prompt
-
-
-
- False
- ..\..\..\..\..\..\..\bin\net\2.0\debug\log4net.dll
-
-
- System
-
-
- System.Configuration.Install
-
-
- System.Management
-
-
-
-
- AssemblyVersionInfo.cs
-
-
-
- Code
-
-
- Code
-
-
- Component
-
-
- Code
-
-
- Code
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+ Local
+ 8.0.50727
+ 2.0
+ {BE56F892-37BA-489C-A91D-F2761FDB96EF}
+ Debug
+ AnyCPU
+
+
+
+
+ log4net.Appender.WmiAppender
+
+
+ JScript
+ Grid
+ IE50
+ false
+ Library
+ log4net.Appender.WmiAppender
+
+
+
+
+
+
+
+
+ ..\bin\Debug\
+ false
+ 285212672
+ false
+
+
+ DEBUG;TRACE
+
+
+ true
+ 4096
+ false
+ false
+ false
+ false
+ 4
+ full
+ prompt
+
+
+ ..\bin\Release\
+ false
+ 285212672
+ false
+
+
+ TRACE
+
+
+ false
+ 4096
+ true
+ false
+ false
+ false
+ 4
+ none
+ prompt
+
+
+
+ False
+ ..\..\..\..\..\..\..\bin\net\2.0\debug\log4net.dll
+
+
+ System
+
+
+ System.Configuration.Install
+
+
+ System.Management
+
+
+
+
+ AssemblyVersionInfo.cs
+
+
+
+ Code
+
+
+ Code
+
+
+ Component
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiInstaller.cs b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiInstaller.cs
index 347ec16b..03bb8653 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiInstaller.cs
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiInstaller.cs
@@ -1,32 +1,32 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.Management.Instrumentation;
-
-namespace log4net.Appender
-{
- ///
- /// Register this assembly with WMI
- ///
- [System.ComponentModel.RunInstaller(true)]
- public class WmiInstaller : DefaultManagementProjectInstaller
- {
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using System.Management.Instrumentation;
+
+namespace log4net.Appender
+{
+ ///
+ /// Register this assembly with WMI
+ ///
+ [System.ComponentModel.RunInstaller(true)]
+ public class WmiInstaller : DefaultManagementProjectInstaller
+ {
+ }
+}
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLayout.cs b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLayout.cs
index 68e0bee5..eaf51d8c 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLayout.cs
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLayout.cs
@@ -1,100 +1,100 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using log4net.Core;
-using System.Management.Instrumentation;
-
-namespace log4net.Appender
-{
- public class WmiLayout
- {
- ///
- /// Formats a for instrumentation
- ///
- /// the containing the data
- /// an instrumentation event that can be fired
- ///
- ///
- /// If the of the
- /// is an then
- /// that instance is returned. If the instance also implements the
- /// interface then the
- /// method will be called on the instance with the
- /// parameter.
- ///
- ///
- /// If the of the
- /// is not an
- /// then the method will be called
- /// to create an appropriate instrumentation event object.
- ///
- ///
- public virtual IEvent Format(LoggingEvent loggingEvent)
- {
- // See if the caller gave us an Instrumentation Event
- IEvent instrumentationEvent = loggingEvent.MessageObject as IEvent;
- if (instrumentationEvent != null)
- {
- // See if the caller gave us a Bound Instrumentation Event
- IWmiBoundEvent boundEvent = instrumentationEvent as IWmiBoundEvent;
- if (boundEvent != null)
- {
- // Attach the logging event to the bound instrumentation event
- boundEvent.Bind(loggingEvent);
- }
-
- return instrumentationEvent;
- }
-
- // We must create our own IEvent
- return CreateEvent(loggingEvent);
- }
-
- ///
- /// Create the instance that should be fired
- ///
- /// the containing the data
- /// an instrumentation event that can be fired
- ///
- ///
- /// The default implementation of this method creates a
- /// instance using the data from the .
- ///
- ///
- /// Subclasses should override this method to return their own custom
- /// instrumentation event object.
- ///
- ///
- protected virtual IEvent CreateEvent(LoggingEvent loggingEvent)
- {
- WmiLoggingEvent wmiEvent = new WmiLoggingEvent();
-
- wmiEvent.TimeStamp = loggingEvent.TimeStamp;
- wmiEvent.LoggerName = loggingEvent.LoggerName;
- wmiEvent.Level = loggingEvent.Level.DisplayName;
- wmiEvent.Message = loggingEvent.RenderedMessage;
- wmiEvent.ThreadName = loggingEvent.ThreadName;
- wmiEvent.ExceptionString = loggingEvent.GetExceptionString();
- wmiEvent.Domain = loggingEvent.Domain;
-
- return wmiEvent;
- }
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using log4net.Core;
+using System.Management.Instrumentation;
+
+namespace log4net.Appender
+{
+ public class WmiLayout
+ {
+ ///
+ /// Formats a for instrumentation
+ ///
+ /// the containing the data
+ /// an instrumentation event that can be fired
+ ///
+ ///
+ /// If the of the
+ /// is an then
+ /// that instance is returned. If the instance also implements the
+ /// interface then the
+ /// method will be called on the instance with the
+ /// parameter.
+ ///
+ ///
+ /// If the of the
+ /// is not an
+ /// then the method will be called
+ /// to create an appropriate instrumentation event object.
+ ///
+ ///
+ public virtual IEvent Format(LoggingEvent loggingEvent)
+ {
+ // See if the caller gave us an Instrumentation Event
+ IEvent instrumentationEvent = loggingEvent.MessageObject as IEvent;
+ if (instrumentationEvent != null)
+ {
+ // See if the caller gave us a Bound Instrumentation Event
+ IWmiBoundEvent boundEvent = instrumentationEvent as IWmiBoundEvent;
+ if (boundEvent != null)
+ {
+ // Attach the logging event to the bound instrumentation event
+ boundEvent.Bind(loggingEvent);
+ }
+
+ return instrumentationEvent;
+ }
+
+ // We must create our own IEvent
+ return CreateEvent(loggingEvent);
+ }
+
+ ///
+ /// Create the instance that should be fired
+ ///
+ /// the containing the data
+ /// an instrumentation event that can be fired
+ ///
+ ///
+ /// The default implementation of this method creates a
+ /// instance using the data from the .
+ ///
+ ///
+ /// Subclasses should override this method to return their own custom
+ /// instrumentation event object.
+ ///
+ ///
+ protected virtual IEvent CreateEvent(LoggingEvent loggingEvent)
+ {
+ WmiLoggingEvent wmiEvent = new WmiLoggingEvent();
+
+ wmiEvent.TimeStamp = loggingEvent.TimeStamp;
+ wmiEvent.LoggerName = loggingEvent.LoggerName;
+ wmiEvent.Level = loggingEvent.Level.DisplayName;
+ wmiEvent.Message = loggingEvent.RenderedMessage;
+ wmiEvent.ThreadName = loggingEvent.ThreadName;
+ wmiEvent.ExceptionString = loggingEvent.GetExceptionString();
+ wmiEvent.Domain = loggingEvent.Domain;
+
+ return wmiEvent;
+ }
+ }
+}
diff --git a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLoggingEvent.cs b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLoggingEvent.cs
index 0d4e69ae..72efdc80 100644
--- a/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLoggingEvent.cs
+++ b/examples/net/2.0/Appenders/WmiAppender/cs/src/WmiLoggingEvent.cs
@@ -1,47 +1,47 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using log4net.Core;
-using System.Management.Instrumentation;
-
-namespace log4net.Appender
-{
- ///
- /// The default instrumented event raised by the
- ///
- ///
- ///
- /// This is the default event fired by the .
- /// To fire a custom event set the to a
- /// subclass of that overrides the
- /// method.
- ///
- ///
- public class WmiLoggingEvent : BaseEvent
- {
- public DateTime TimeStamp;
- public string LoggerName;
- public string Level;
- public string Message;
- public string ThreadName;
- public string ExceptionString;
- public string Domain;
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using log4net.Core;
+using System.Management.Instrumentation;
+
+namespace log4net.Appender
+{
+ ///
+ /// The default instrumented event raised by the
+ ///
+ ///
+ ///
+ /// This is the default event fired by the .
+ /// To fire a custom event set the to a
+ /// subclass of that overrides the
+ /// method.
+ ///
+ ///
+ public class WmiLoggingEvent : BaseEvent
+ {
+ public DateTime TimeStamp;
+ public string LoggerName;
+ public string Level;
+ public string Message;
+ public string ThreadName;
+ public string ExceptionString;
+ public string Domain;
+ }
+}
diff --git a/examples/net/2.0/Appenders/WmiAppender/nant.config b/examples/net/2.0/Appenders/WmiAppender/nant.config
index d7014bbc..ba0a7243 100644
--- a/examples/net/2.0/Appenders/WmiAppender/nant.config
+++ b/examples/net/2.0/Appenders/WmiAppender/nant.config
@@ -1,21 +1,21 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/examples/net/2.0/Appenders/nant.build b/examples/net/2.0/Appenders/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Appenders/nant.config b/examples/net/2.0/Appenders/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/EventIDLogApp/cs/nant.build b/examples/net/2.0/Extensibility/EventIDLogApp/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/EventIDLogApp/cs/nant.config b/examples/net/2.0/Extensibility/EventIDLogApp/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/EventIDLogApp/cs/src/App.config b/examples/net/2.0/Extensibility/EventIDLogApp/cs/src/App.config
old mode 100755
new mode 100644
index d95aae73..24d69787
--- a/examples/net/2.0/Extensibility/EventIDLogApp/cs/src/App.config
+++ b/examples/net/2.0/Extensibility/EventIDLogApp/cs/src/App.config
@@ -1,4 +1,25 @@
+
+
+
+Local8.0.50727
@@ -113,4 +135,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Extensibility/EventIDLogApp/nant.build b/examples/net/2.0/Extensibility/EventIDLogApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/EventIDLogApp/nant.config b/examples/net/2.0/Extensibility/EventIDLogApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/cs/nant.build b/examples/net/2.0/Extensibility/TraceLogApp/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/cs/nant.config b/examples/net/2.0/Extensibility/TraceLogApp/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/cs/src/AssemblyInfo.cs b/examples/net/2.0/Extensibility/TraceLogApp/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.cs b/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.csproj b/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.csproj
old mode 100755
new mode 100644
index 5ef677e0..4648085c
--- a/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.csproj
+++ b/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.csproj
@@ -1,4 +1,26 @@
-
+
+
+
+Local8.0.50727
@@ -111,4 +133,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.exe.log4net b/examples/net/2.0/Extensibility/TraceLogApp/cs/src/TraceLogApp.exe.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/nant.build b/examples/net/2.0/Extensibility/TraceLogApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/TraceLogApp/nant.config b/examples/net/2.0/Extensibility/TraceLogApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/nant.build b/examples/net/2.0/Extensibility/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Extensibility/nant.config b/examples/net/2.0/Extensibility/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Layouts/SampleLayoutsApp/cs/nant.build b/examples/net/2.0/Layouts/SampleLayoutsApp/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Layouts/SampleLayoutsApp/cs/nant.config b/examples/net/2.0/Layouts/SampleLayoutsApp/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Layouts/SampleLayoutsApp/cs/src/App.config b/examples/net/2.0/Layouts/SampleLayoutsApp/cs/src/App.config
old mode 100755
new mode 100644
index 89ff23f3..d5b85621
--- a/examples/net/2.0/Layouts/SampleLayoutsApp/cs/src/App.config
+++ b/examples/net/2.0/Layouts/SampleLayoutsApp/cs/src/App.config
@@ -1,4 +1,25 @@
+
+
+
+Local8.0.50727
@@ -117,4 +139,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Layouts/SampleLayoutsApp/nant.build b/examples/net/2.0/Layouts/SampleLayoutsApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Layouts/SampleLayoutsApp/nant.config b/examples/net/2.0/Layouts/SampleLayoutsApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Layouts/nant.build b/examples/net/2.0/Layouts/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Layouts/nant.config b/examples/net/2.0/Layouts/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/cs/nant.build b/examples/net/2.0/Performance/NotLogging/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/cs/nant.config b/examples/net/2.0/Performance/NotLogging/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/cs/src/AssemblyInfo.cs b/examples/net/2.0/Performance/NotLogging/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/cs/src/NotLogging.cs b/examples/net/2.0/Performance/NotLogging/cs/src/NotLogging.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/cs/src/NotLogging.csproj b/examples/net/2.0/Performance/NotLogging/cs/src/NotLogging.csproj
old mode 100755
new mode 100644
index a80b7d47..f13c2bf3
--- a/examples/net/2.0/Performance/NotLogging/cs/src/NotLogging.csproj
+++ b/examples/net/2.0/Performance/NotLogging/cs/src/NotLogging.csproj
@@ -1,4 +1,26 @@
-
+
+
+
+Local8.0.50727
@@ -106,4 +128,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Performance/NotLogging/nant.build b/examples/net/2.0/Performance/NotLogging/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/nant.config b/examples/net/2.0/Performance/NotLogging/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/vb/nant.build b/examples/net/2.0/Performance/NotLogging/vb/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/vb/nant.config b/examples/net/2.0/Performance/NotLogging/vb/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/vb/src/AssemblyInfo.vb b/examples/net/2.0/Performance/NotLogging/vb/src/AssemblyInfo.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/vb/src/NotLogging.vb b/examples/net/2.0/Performance/NotLogging/vb/src/NotLogging.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Performance/NotLogging/vb/src/NotLogging.vbproj b/examples/net/2.0/Performance/NotLogging/vb/src/NotLogging.vbproj
old mode 100755
new mode 100644
index 6dd27030..8124f718
--- a/examples/net/2.0/Performance/NotLogging/vb/src/NotLogging.vbproj
+++ b/examples/net/2.0/Performance/NotLogging/vb/src/NotLogging.vbproj
@@ -1,3 +1,25 @@
+
+
+
+
+
+
+Local8.0.50727
@@ -101,4 +123,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Remoting/RemotingClient/nant.build b/examples/net/2.0/Remoting/RemotingClient/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingClient/nant.config b/examples/net/2.0/Remoting/RemotingClient/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingServer/cs/nant.build b/examples/net/2.0/Remoting/RemotingServer/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingServer/cs/nant.config b/examples/net/2.0/Remoting/RemotingServer/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingServer/cs/src/App.config b/examples/net/2.0/Remoting/RemotingServer/cs/src/App.config
old mode 100755
new mode 100644
index b49a40c4..52b699d9
--- a/examples/net/2.0/Remoting/RemotingServer/cs/src/App.config
+++ b/examples/net/2.0/Remoting/RemotingServer/cs/src/App.config
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Remoting/RemotingServer/cs/src/AssemblyInfo.cs b/examples/net/2.0/Remoting/RemotingServer/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingServer/cs/src/RemotingServer.cs b/examples/net/2.0/Remoting/RemotingServer/cs/src/RemotingServer.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingServer/cs/src/RemotingServer.csproj b/examples/net/2.0/Remoting/RemotingServer/cs/src/RemotingServer.csproj
old mode 100755
new mode 100644
index 8179eb53..6a172cce
--- a/examples/net/2.0/Remoting/RemotingServer/cs/src/RemotingServer.csproj
+++ b/examples/net/2.0/Remoting/RemotingServer/cs/src/RemotingServer.csproj
@@ -1,4 +1,26 @@
-
+
+
+
+Local8.0.50727
@@ -100,4 +122,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Remoting/RemotingServer/nant.build b/examples/net/2.0/Remoting/RemotingServer/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/RemotingServer/nant.config b/examples/net/2.0/Remoting/RemotingServer/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/nant.build b/examples/net/2.0/Remoting/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Remoting/nant.config b/examples/net/2.0/Remoting/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/cs/nant.build b/examples/net/2.0/Repository/SharedModule/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/cs/nant.config b/examples/net/2.0/Repository/SharedModule/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/cs/src/AssemblyInfo.cs b/examples/net/2.0/Repository/SharedModule/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/cs/src/Math.cs b/examples/net/2.0/Repository/SharedModule/cs/src/Math.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/cs/src/SharedModule.csproj b/examples/net/2.0/Repository/SharedModule/cs/src/SharedModule.csproj
old mode 100755
new mode 100644
index 4c03b0cc..1dfb7c9c
--- a/examples/net/2.0/Repository/SharedModule/cs/src/SharedModule.csproj
+++ b/examples/net/2.0/Repository/SharedModule/cs/src/SharedModule.csproj
@@ -1,4 +1,26 @@
-
+
+
+
+Local8.0.50727
@@ -107,4 +129,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Repository/SharedModule/nant.build b/examples/net/2.0/Repository/SharedModule/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/nant.config b/examples/net/2.0/Repository/SharedModule/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/vb/nant.build b/examples/net/2.0/Repository/SharedModule/vb/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/vb/nant.config b/examples/net/2.0/Repository/SharedModule/vb/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/vb/src/AssemblyInfo.vb b/examples/net/2.0/Repository/SharedModule/vb/src/AssemblyInfo.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/vb/src/Math.vb b/examples/net/2.0/Repository/SharedModule/vb/src/Math.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SharedModule/vb/src/SharedModule.vbproj b/examples/net/2.0/Repository/SharedModule/vb/src/SharedModule.vbproj
old mode 100755
new mode 100644
index e1f00294..6079c28f
--- a/examples/net/2.0/Repository/SharedModule/vb/src/SharedModule.vbproj
+++ b/examples/net/2.0/Repository/SharedModule/vb/src/SharedModule.vbproj
@@ -1,3 +1,25 @@
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Repository/SimpleApp/cs/src/AssemblyInfo.cs b/examples/net/2.0/Repository/SimpleApp/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/cs/src/EntryPoint.cs b/examples/net/2.0/Repository/SimpleApp/cs/src/EntryPoint.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/cs/src/SimpleApp.csproj b/examples/net/2.0/Repository/SimpleApp/cs/src/SimpleApp.csproj
old mode 100755
new mode 100644
index edefbb4b..fa3a91b3
--- a/examples/net/2.0/Repository/SimpleApp/cs/src/SimpleApp.csproj
+++ b/examples/net/2.0/Repository/SimpleApp/cs/src/SimpleApp.csproj
@@ -1,4 +1,26 @@
-
+
+
+
+Local8.0.50727
@@ -118,4 +140,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Repository/SimpleApp/cs/src/SimpleApp.exe.log4net b/examples/net/2.0/Repository/SimpleApp/cs/src/SimpleApp.exe.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/nant.build b/examples/net/2.0/Repository/SimpleApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/nant.config b/examples/net/2.0/Repository/SimpleApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/nant.build b/examples/net/2.0/Repository/SimpleApp/vb/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/nant.config b/examples/net/2.0/Repository/SimpleApp/vb/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/src/App.config b/examples/net/2.0/Repository/SimpleApp/vb/src/App.config
old mode 100755
new mode 100644
index 4fcc7688..c37efd08
--- a/examples/net/2.0/Repository/SimpleApp/vb/src/App.config
+++ b/examples/net/2.0/Repository/SimpleApp/vb/src/App.config
@@ -1,8 +1,29 @@
+
+
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/src/AssemblyInfo.vb b/examples/net/2.0/Repository/SimpleApp/vb/src/AssemblyInfo.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/src/EntryPoint.vb b/examples/net/2.0/Repository/SimpleApp/vb/src/EntryPoint.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/src/SimpleApp.exe.log4net b/examples/net/2.0/Repository/SimpleApp/vb/src/SimpleApp.exe.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleApp/vb/src/SimpleApp.vbproj b/examples/net/2.0/Repository/SimpleApp/vb/src/SimpleApp.vbproj
old mode 100755
new mode 100644
index 65f3888a..f1bedee3
--- a/examples/net/2.0/Repository/SimpleApp/vb/src/SimpleApp.vbproj
+++ b/examples/net/2.0/Repository/SimpleApp/vb/src/SimpleApp.vbproj
@@ -1,3 +1,25 @@
+
+
+
+
+
+
+Local8.0.50727
@@ -108,4 +130,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Repository/SimpleModule/cs/src/SimpleModule.dll.log4net b/examples/net/2.0/Repository/SimpleModule/cs/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/nant.build b/examples/net/2.0/Repository/SimpleModule/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/nant.config b/examples/net/2.0/Repository/SimpleModule/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/vb/nant.build b/examples/net/2.0/Repository/SimpleModule/vb/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/vb/nant.config b/examples/net/2.0/Repository/SimpleModule/vb/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/vb/src/AssemblyInfo.vb b/examples/net/2.0/Repository/SimpleModule/vb/src/AssemblyInfo.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/vb/src/Math.vb b/examples/net/2.0/Repository/SimpleModule/vb/src/Math.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/vb/src/SimpleModule.dll.log4net b/examples/net/2.0/Repository/SimpleModule/vb/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Repository/SimpleModule/vb/src/SimpleModule.vbproj b/examples/net/2.0/Repository/SimpleModule/vb/src/SimpleModule.vbproj
old mode 100755
new mode 100644
index 9a99c44b..25b33136
--- a/examples/net/2.0/Repository/SimpleModule/vb/src/SimpleModule.vbproj
+++ b/examples/net/2.0/Repository/SimpleModule/vb/src/SimpleModule.vbproj
@@ -1,3 +1,25 @@
+
+
+
+
+
+
+Local8.0.50727
@@ -107,4 +129,4 @@
-
\ No newline at end of file
+
diff --git a/examples/net/2.0/Tutorials/ConsoleApp/cs/src/LoggingExample.cs b/examples/net/2.0/Tutorials/ConsoleApp/cs/src/LoggingExample.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/ConsoleApp/nant.build b/examples/net/2.0/Tutorials/ConsoleApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/ConsoleApp/nant.config b/examples/net/2.0/Tutorials/ConsoleApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/ConsoleApp/vb/nant.build b/examples/net/2.0/Tutorials/ConsoleApp/vb/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/ConsoleApp/vb/nant.config b/examples/net/2.0/Tutorials/ConsoleApp/vb/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/ConsoleApp/vb/src/App.config b/examples/net/2.0/Tutorials/ConsoleApp/vb/src/App.config
old mode 100755
new mode 100644
index 682eb7b9..f3d71025
--- a/examples/net/2.0/Tutorials/ConsoleApp/vb/src/App.config
+++ b/examples/net/2.0/Tutorials/ConsoleApp/vb/src/App.config
@@ -1,4 +1,25 @@
+
+
+
+
<%@ Application Codebehind="Global.asax.cs" Inherits="WebApp.Global" %>
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/Global.asax.cs b/examples/net/2.0/Tutorials/WebApp/cs/src/Global.asax.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/Global.asax.resx b/examples/net/2.0/Tutorials/WebApp/cs/src/Global.asax.resx
old mode 100755
new mode 100644
index 7e323966..c8e3ce72
--- a/examples/net/2.0/Tutorials/WebApp/cs/src/Global.asax.resx
+++ b/examples/net/2.0/Tutorials/WebApp/cs/src/Global.asax.resx
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/SimpleModule.dll.log4net b/examples/net/2.0/Tutorials/WebApp/cs/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/Web.config b/examples/net/2.0/Tutorials/WebApp/cs/src/Web.config
old mode 100755
new mode 100644
index 84f7881b..8389366f
--- a/examples/net/2.0/Tutorials/WebApp/cs/src/Web.config
+++ b/examples/net/2.0/Tutorials/WebApp/cs/src/Web.config
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.csproj b/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.csproj
old mode 100755
new mode 100644
index 47c5a7c2..105bfdba
--- a/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.csproj
+++ b/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.csproj
@@ -1,3 +1,25 @@
+
+
+
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.dll.log4net b/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.vsdisco b/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.vsdisco
old mode 100755
new mode 100644
index 10b0ed10..639642ee
--- a/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.vsdisco
+++ b/examples/net/2.0/Tutorials/WebApp/cs/src/WebApp.vsdisco
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx b/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx
old mode 100755
new mode 100644
index 3219c8c3..7de98908
--- a/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx
+++ b/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx
@@ -1,3 +1,24 @@
+
+
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApp.WebForm1" %>
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx.cs b/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx.cs
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx.resx b/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx.resx
old mode 100755
new mode 100644
index 7e323966..c8e3ce72
--- a/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx.resx
+++ b/examples/net/2.0/Tutorials/WebApp/cs/src/WebForm1.aspx.resx
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/nant.build b/examples/net/2.0/Tutorials/WebApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/nant.config b/examples/net/2.0/Tutorials/WebApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/readme.txt b/examples/net/2.0/Tutorials/WebApp/readme.txt
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/nant.build b/examples/net/2.0/Tutorials/WebApp/vb/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/nant.config b/examples/net/2.0/Tutorials/WebApp/vb/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/AssemblyInfo.vb b/examples/net/2.0/Tutorials/WebApp/vb/src/AssemblyInfo.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/AssemblyVersionInfo.vb b/examples/net/2.0/Tutorials/WebApp/vb/src/AssemblyVersionInfo.vb
old mode 100755
new mode 100644
index 16a5ff8e..124d1a6a
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/AssemblyVersionInfo.vb
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/AssemblyVersionInfo.vb
@@ -32,5 +32,5 @@
-
-
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax b/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax
old mode 100755
new mode 100644
index ef097998..93c16a4e
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax
@@ -1 +1,22 @@
+
+
<%@ Application Codebehind="Global.asax.vb" Inherits="WebApp.Global" %>
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax.resx b/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax.resx
old mode 100755
new mode 100644
index 7e323966..c8e3ce72
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax.resx
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax.resx
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax.vb b/examples/net/2.0/Tutorials/WebApp/vb/src/Global.asax.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/SimpleModule.dll.log4net b/examples/net/2.0/Tutorials/WebApp/vb/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/Web.config b/examples/net/2.0/Tutorials/WebApp/vb/src/Web.config
old mode 100755
new mode 100644
index 972e1f49..fe903043
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/Web.config
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/Web.config
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.dll.log4net b/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vbproj b/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vbproj
old mode 100755
new mode 100644
index 5574753d..42d33e5c
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vbproj
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vbproj
@@ -1,3 +1,25 @@
+
+
+
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vsdisco b/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vsdisco
old mode 100755
new mode 100644
index 10b0ed10..639642ee
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vsdisco
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/WebApp.vsdisco
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx b/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx
old mode 100755
new mode 100644
index 34e607de..5b8c8496
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx
@@ -1,3 +1,24 @@
+
+
<%@ Page language="vb" Codebehind="WebForm1.aspx.vb" AutoEventWireup="false" Inherits="WebApp.WebForm1" %>
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx.resx b/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx.resx
old mode 100755
new mode 100644
index 7e323966..c8e3ce72
--- a/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx.resx
+++ b/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx.resx
@@ -1,4 +1,25 @@
+
+
diff --git a/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx.vb b/examples/net/2.0/Tutorials/WebApp/vb/src/WebForm1.aspx.vb
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/nant.build b/examples/net/2.0/Tutorials/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/Tutorials/nant.config b/examples/net/2.0/Tutorials/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/cs-examples.sln b/examples/net/2.0/cs-examples.sln
old mode 100755
new mode 100644
index 56a2a761..7b5e2b26
--- a/examples/net/2.0/cs-examples.sln
+++ b/examples/net/2.0/cs-examples.sln
@@ -1,5 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "Tutorials\ConsoleApp\cs\src\ConsoleApp.csproj", "{933969DF-2BC5-44E6-8B1A-400FC276A23F}"
ProjectSection(WebsiteProperties) = preProject
Debug.AspNetCompiler.Debug = "True"
diff --git a/examples/net/2.0/nant.build b/examples/net/2.0/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/nant.config b/examples/net/2.0/nant.config
old mode 100755
new mode 100644
diff --git a/examples/net/2.0/vb-examples.sln b/examples/net/2.0/vb-examples.sln
old mode 100755
new mode 100644
index e7fde504..c5afc467
--- a/examples/net/2.0/vb-examples.sln
+++ b/examples/net/2.0/vb-examples.sln
@@ -1,4 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 7.00
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ConsoleApp", "Tutorials\ConsoleApp\vb\src\ConsoleApp.vbproj", "{41B855A4-F3BF-43F8-BE6F-2ABD5E5C8D42}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "WebApp", "http://localhost/WebAppVB/WebApp.vbproj", "{4CEA8E96-BF74-488D-9967-EAB779EF430A}"
diff --git a/examples/net/nant.build b/examples/net/nant.build
old mode 100755
new mode 100644
diff --git a/examples/net/nant.config b/examples/net/nant.config
old mode 100755
new mode 100644
diff --git a/examples/netcf/1.0/Tutorials/ConsoleApp/cs/nant.build b/examples/netcf/1.0/Tutorials/ConsoleApp/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/netcf/1.0/Tutorials/ConsoleApp/cs/nant.config b/examples/netcf/1.0/Tutorials/ConsoleApp/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/netcf/1.0/Tutorials/ConsoleApp/cs/src/AssemblyInfo.cs b/examples/netcf/1.0/Tutorials/ConsoleApp/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/netcf/1.0/Tutorials/ConsoleApp/cs/src/ConsoleApp.csdproj b/examples/netcf/1.0/Tutorials/ConsoleApp/cs/src/ConsoleApp.csdproj
old mode 100755
new mode 100644
index aab0f599..49693d23
--- a/examples/netcf/1.0/Tutorials/ConsoleApp/cs/src/ConsoleApp.csdproj
+++ b/examples/netcf/1.0/Tutorials/ConsoleApp/cs/src/ConsoleApp.csdproj
@@ -1,3 +1,25 @@
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/examples/sscli/1.0/Repository/SimpleApp/cs/src/AssemblyInfo.cs b/examples/sscli/1.0/Repository/SimpleApp/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleApp/cs/src/EntryPoint.cs b/examples/sscli/1.0/Repository/SimpleApp/cs/src/EntryPoint.cs
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleApp/cs/src/SimpleApp.exe.log4net b/examples/sscli/1.0/Repository/SimpleApp/cs/src/SimpleApp.exe.log4net
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleApp/nant.build b/examples/sscli/1.0/Repository/SimpleApp/nant.build
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleApp/nant.config b/examples/sscli/1.0/Repository/SimpleApp/nant.config
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/cs/nant.build b/examples/sscli/1.0/Repository/SimpleModule/cs/nant.build
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/cs/nant.config b/examples/sscli/1.0/Repository/SimpleModule/cs/nant.config
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/cs/src/AssemblyInfo.cs b/examples/sscli/1.0/Repository/SimpleModule/cs/src/AssemblyInfo.cs
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/cs/src/Math.cs b/examples/sscli/1.0/Repository/SimpleModule/cs/src/Math.cs
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/cs/src/SimpleModule.dll.log4net b/examples/sscli/1.0/Repository/SimpleModule/cs/src/SimpleModule.dll.log4net
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/nant.build b/examples/sscli/1.0/Repository/SimpleModule/nant.build
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/SimpleModule/nant.config b/examples/sscli/1.0/Repository/SimpleModule/nant.config
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/nant.build b/examples/sscli/1.0/Repository/nant.build
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Repository/nant.config b/examples/sscli/1.0/Repository/nant.config
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Tutorials/ConsoleApp/js/nant.build b/examples/sscli/1.0/Tutorials/ConsoleApp/js/nant.build
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Tutorials/ConsoleApp/js/nant.config b/examples/sscli/1.0/Tutorials/ConsoleApp/js/nant.config
old mode 100755
new mode 100644
diff --git a/examples/sscli/1.0/Tutorials/ConsoleApp/js/src/App.config b/examples/sscli/1.0/Tutorials/ConsoleApp/js/src/App.config
old mode 100755
new mode 100644
index 2d644aeb..12c4fef7
--- a/examples/sscli/1.0/Tutorials/ConsoleApp/js/src/App.config
+++ b/examples/sscli/1.0/Tutorials/ConsoleApp/js/src/App.config
@@ -1,4 +1,25 @@
+
+
+
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
@@ -218,7 +218,7 @@ public static ILog GetLogger(Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
@@ -233,7 +233,7 @@ public static ILog GetLogger(string domain, Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
diff --git a/extensions/net/1.0/log4net.Ext.MarshalByRef/cs/src/log4net.Ext.MarshalByRef.csproj b/extensions/net/1.0/log4net.Ext.MarshalByRef/cs/src/log4net.Ext.MarshalByRef.csproj
old mode 100755
new mode 100644
index 7c2ebeb4..c8b8b69a
--- a/extensions/net/1.0/log4net.Ext.MarshalByRef/cs/src/log4net.Ext.MarshalByRef.csproj
+++ b/extensions/net/1.0/log4net.Ext.MarshalByRef/cs/src/log4net.Ext.MarshalByRef.csproj
@@ -1,3 +1,25 @@
+
+
+
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
@@ -215,7 +215,7 @@ public static ITraceLog GetLogger(Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
@@ -230,7 +230,7 @@ public static ITraceLog GetLogger(string domain, Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
diff --git a/extensions/net/1.0/log4net.Ext.Trace/cs/src/log4net.Ext.Trace.csproj b/extensions/net/1.0/log4net.Ext.Trace/cs/src/log4net.Ext.Trace.csproj
old mode 100755
new mode 100644
index 7b9ef1e6..c3679ecf
--- a/extensions/net/1.0/log4net.Ext.Trace/cs/src/log4net.Ext.Trace.csproj
+++ b/extensions/net/1.0/log4net.Ext.Trace/cs/src/log4net.Ext.Trace.csproj
@@ -1,3 +1,25 @@
+
+
+
-
-
-
-
- Primary types used by calling applications to generate log messages.
- Output appenders.
- Configuration types and attributes.
- Core framework types.
- Date formatting types.
- Output event filters.
- Output message layouts.
- Pattern handlers for the PatternLayout.
- Message object to string renderer framework.
- Plugin module base types.
- Logger repository base types and interfaces.
- Standard hierarchy repository implementation.
- Utility types.
- Pattern handlers for the PatternString.
- Type conversion framework.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/log4net.build b/log4net.build
old mode 100755
new mode 100644
index 9461a11a..7469f44c
--- a/log4net.build
+++ b/log4net.build
@@ -16,605 +16,1244 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
-
-
+
+
+
+
+
-
+
-
-
+
+
@@ -624,20 +1263,85 @@ limitations under the License.
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -647,19 +1351,62 @@ limitations under the License.
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -675,13 +1422,13 @@ limitations under the License.
+
+
+
+
-
-
-
-
-
+
@@ -692,19 +1439,58 @@ limitations under the License.
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -718,567 +1504,257 @@ limitations under the License.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/log4net.include b/log4net.include
old mode 100755
new mode 100644
index 56fa5ab3..4384c592
--- a/log4net.include
+++ b/log4net.include
@@ -139,6 +139,7 @@ limitations under the License.
+
@@ -169,7 +170,7 @@ limitations under the License.
-
+
@@ -226,32 +227,71 @@ limitations under the License.
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -300,6 +340,30 @@ limitations under the License.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/log4net.shfbproj b/log4net.shfbproj
new file mode 100644
index 00000000..612c3a41
--- /dev/null
+++ b/log4net.shfbproj
@@ -0,0 +1,88 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ {18040100-bf45-4b3e-9265-9dc4b14c17ec}
+ 1.9.5.0
+
+ Documentation
+ Documentation
+ Documentation
+
+ .NET Framework 2.0
+ doc\sdk\net\4.0\
+ log4net-sdk-1.2.15
+ en-US
+ Standard
+ Blank
+ False
+ VS2010
+ False
+ MemberName
+ Apache log4net™ SDK Documentation
+ Copyright 2004-2015 The Apache Software Foundation
+ http://logging.apache.org/log4net/
+ AboveNamespaces
+
+
+
+
+ OnlyWarningsAndErrors
+ HtmlHelp1, Website
+ False
+ True
+ False
+ False
+ True
+ Apache log4net, Apache and log4net are trademarks of The Apache Software Foundation.
+ Summary, Parameter, Returns, AutoDocumentCtors, TypeParameter, AutoDocumentDispose
+ http://logging.apache.org/log4net/mail-lists.html
+ Msdn
+ Msdn
+ False
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/log4net.snk b/log4net.snk
new file mode 100644
index 00000000..bad5f7db
Binary files /dev/null and b/log4net.snk differ
diff --git a/log4net.snk.gpg b/log4net.snk.gpg
deleted file mode 100644
index 626e4e1a..00000000
Binary files a/log4net.snk.gpg and /dev/null differ
diff --git a/log4net.snk.readme b/log4net.snk.readme
old mode 100755
new mode 100644
index 18956b01..47642869
--- a/log4net.snk.readme
+++ b/log4net.snk.readme
@@ -2,19 +2,27 @@ Apache log4net Strong Name Key Readme
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The log4net release builds are strongly named using the log4net.snk key
-file. This file is not distributed as part of the log4net source or
-binary downloads. See the log4net documentation for more details.
-
-Before you can build your own release builds you will need to generate
-a strong name key that identifies your assemblies.
-
-Generating your own strong name key.
-
-Run the SN utility from the .NET Framework SDK as follows:
-
- sn -k log4net.snk
-
-A new strong name key pair will be created and written to the log4net.snk
-file.
-
-
+file. This key is different from the key used to sign log4net 1.2.10
+and earlier releases.
+
+Starting with log4net 1.2.11 we've decided to use a key that we don't
+keep secret so you can build a drop-in replacement for an official
+release yourself. This means that the strong name of a log4net
+assembly no longer provides any means of checking its authenticity.
+The only way to ensure you are using an official release by the Apache
+Software Foundation is by downloading the distribution from the Apache
+log4net download page and verifying the PGP signature of the ZIP
+archive.
+
+The key used to sign those older releases is not and has never been
+distributed as part of the log4net source or binary downloads.
+
+In order to make it easier to migrate from log4net 1.2.10 to newer
+releases log4net 1.2.11 we also provide builds using the key used to
+sign 1.2.10. We may stop distributing these alternative builds in the
+future.
+
+You should use the binary builds signed with log4net.snk for new
+projects and only use the ones signed with "the old key" if switching
+to the newer builds is not possible because other parts of your
+project depend on the old strong name.
diff --git a/old-log4net.snk.gpg b/old-log4net.snk.gpg
new file mode 100644
index 00000000..57126212
Binary files /dev/null and b/old-log4net.snk.gpg differ
diff --git a/pom.xml b/pom.xml
index 9922a8d4..6cfbdb81 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,223 +20,246 @@
log4netapache-log4netpom
- 1.2.11-SNAPSHOT
+ 1.2.15Apache log4netLogging framework for Microsoft .NET Framework.
- http://logging.apache.org:80/log4net
+ http://logging.apache.org/log4net/
+ 2004JIRA
- http://issues.apache.org/jira/
+ https://issues.apache.org/jira/browse/LOG4NET
- Gump
- http://vmgump.apache.org/gump/public/logging-log4net/logging-log4net/index.html
+ Jenkins
+ https://builds.apache.org/job/log4net-trunk-build/
-
- log4net-user : log4net usage
- log4net-user-subscribe@logging.apache.org
- log4net-user-unsubscribe@logging.apache.org
- log4net-user@logging.apache.org
- http://mail-archives.apache.org/mod_mbox/logging-log4net-user/
-
- http://marc.info/?l=log4net-user
- http://dir.gmane.org/gmane.comp.log.log4net.user
-
-
-
- log4net-dev : log4net development
- log4net-dev-subscribe@logging.apache.org
- log4net-dev-unsubscribe@logging.apache.org
- log4net-dev@logging.apache.org
- http://mail-archives.apache.org/mod_mbox/logging-log4net-dev/
-
- http://marc.info/?l=log4net-dev
- http://dir.gmane.org/gmane.comp.apache.logging.log4net.devel
-
-
-
-
-
- Apache License, Version 2.0
- http://www.apache.org/licenses/LICENSE-2.0.txt
- repo
-
-
-
- scm:svn:http://svn.apache.org/repos/asf/logging/log4net/trunk
- scm:svn:https://svn.apache.org/repos/asf/logging/log4net/trunk
- http://svn.apache.org/viewcvs.cgi/logging/log4net/trunk
-
-
+
+ log4net-user : log4net usage
+ log4net-user-subscribe@logging.apache.org
+ log4net-user-unsubscribe@logging.apache.org
+ log4net-user@logging.apache.org
+ http://mail-archives.apache.org/mod_mbox/logging-log4net-user/
+
+ http://marc.info/?l=log4net-user
+ http://dir.gmane.org/gmane.comp.log.log4net.user
+
+
+
+ log4net-dev : log4net development
+ log4net-dev-subscribe@logging.apache.org
+ log4net-dev-unsubscribe@logging.apache.org
+ log4net-dev@logging.apache.org
+ http://mail-archives.apache.org/mod_mbox/logging-log4net-dev/
+
+ http://marc.info/?l=log4net-dev
+ http://dir.gmane.org/gmane.comp.apache.logging.log4net.devel
+
+
+
+ logging commits : all svn commits of the logging projects including log4net
+ commits-subscribe@logging.apache.org
+ commits-unsubscribe@logging.apache.org
+ Read-Only List
+ http://mail-archives.apache.org/mod_mbox/logging-commits/
+
+
+
+
+ Apache License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+ scm:svn:http://svn.apache.org/repos/asf/logging/log4net/trunk
+ scm:svn:https://svn.apache.org/repos/asf/logging/log4net/trunk
+ http://svn.apache.org/viewvc/logging/log4net/trunk
+
+ Apache Software Foundationhttp://www.apache.org
-
-
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ 0.11
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+ 3.4
+
+ ${basedir}/src/site/site.vm
+
+ maven-antrun-plugin
+ 1.8
- compile
- compile
-
-
-
-
-
+ installrun
-
-
- test-compile
- test-compile
-
-
-
-
-
-
-
-
- run
-
-
-
- test
- test
-
-
-
-
-
-
- run
-
-
-
- site
- site
-
-
-
-
-
-
-
+
+
-
- run
-
-
- post-site
- post-site
-
-
-
-
-
-
-
-
- run
-
-
-
- site-deploy
- site-deploy
-
-
-
-
-
-
-
-
- run
-
-
-
-
-
- ant
- ant-nodeps
- 1.6.5
-
-
-
-
- maven-assembly-plugin
-
-
- src/assembly/bin.xml
-
- false
-
-
-
-
- assembly
-
-
-
+
+
+ org.apache.ant
+ ant
+ 1.9.4
+
+
+
-
-
-
+
+
- true
+ org.apache.maven.plugins
+ maven-site-plugin
+ 3.4
+
+ ${basedir}/src/site/site.vm
+
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ 0.11
+
+
+
+ **/*.suo
+ **/*.user
+ **/obj/**
+ bin/**
+ build/**
+ doc/sdk/**
+ src/log4net.xml
+ src/GeneratedAssemblyInfo.cs
+ tests/bin/**
+
+
+ *.snk*
+ tests/lib/prerequisites.txt
+
+
+
+
+ org.apache.maven.pluginsmaven-project-info-reports-plugin
+ ${commons.project-info.version}
+
+ cimscm
- cimdependencies
+ license
+ project-teamissue-trackingmailing-list
- license
-
- maven-release-plugin
-
- site-deploy
-
-
-
- maven-changes-plugin
-
-
-
- changes-report
-
-
-
-
- %URL%/browse/%ISSUE%
-
-
-
+
+
+
+ Curt Arnold
+ carnold
+
+
+ Stefan Bodewig
+ bodewig
+
+
+ Nicko Cadell
+ nicko
+
+
+ Niall Daley
+ niall
+
+
+ Gert Driesen
+ drieseng
+
+
+ Ron Grabowski
+ rgrabowski
+
+
+ Dominik Psenner
+ dpsenner
+
+
+
+
+
+ Julian Biddle
+
+
+ Daniel Cazzulino
+
+
+ Aspi Havewala
+
+
+ Rick Hobbs
+
+
+ Lance Nehring
+
+
+ Angelika Schnagl
+
+
+ Edward Smit
+
+
+ Douglas de la Torre
+
+
+ Pavlos Touboulidis
+
+
+ Thomas Voss
+
+
+ Jarrod Alexander
+
+
+
+
+
+
+ logging.site
- file:///tmp/log4net-deploy
+ file:///${user.dir}/target/site-deploy
diff --git a/src/Appender/AdoNetAppender.cs b/src/Appender/AdoNetAppender.cs
old mode 100755
new mode 100644
index f4c6f688..061aece9
--- a/src/Appender/AdoNetAppender.cs
+++ b/src/Appender/AdoNetAppender.cs
@@ -134,11 +134,11 @@ public class AdoNetAppender : BufferingAppenderSkeleton
///
public AdoNetAppender()
{
- m_connectionType = "System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
- m_useTransactions = true;
- m_commandType = System.Data.CommandType.Text;
+ ConnectionType = "System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
+ UseTransactions = true;
+ CommandType = System.Data.CommandType.Text;
m_parameters = new ArrayList();
- m_reconnectOnError = false;
+ ReconnectOnError = false;
}
#endregion // Public Instance Constructors
@@ -173,30 +173,30 @@ public string ConnectionString
set { m_connectionString = value; }
}
- ///
- /// The appSettings key from App.Config that contains the connection string.
- ///
- public string AppSettingsKey
- {
- get { return m_appSettingsKey; }
- set { m_appSettingsKey = value; }
- }
+ ///
+ /// The appSettings key from App.Config that contains the connection string.
+ ///
+ public string AppSettingsKey
+ {
+ get { return m_appSettingsKey; }
+ set { m_appSettingsKey = value; }
+ }
#if NET_2_0
- ///
- /// The connectionStrings key from App.Config that contains the connection string.
- ///
- ///
- /// This property requires at least .NET 2.0.
- ///
- public string ConnectionStringName
- {
- get { return m_connectionStringName; }
- set { m_connectionStringName = value; }
- }
+ ///
+ /// The connectionStrings key from App.Config that contains the connection string.
+ ///
+ ///
+ /// This property requires at least .NET 2.0.
+ ///
+ public string ConnectionStringName
+ {
+ get { return m_connectionStringName; }
+ set { m_connectionStringName = value; }
+ }
#endif
- ///
+ ///
/// Gets or sets the type name of the connection
/// that should be created.
///
@@ -252,6 +252,10 @@ public string ConnectionType
/// The property determines if
/// this text is a prepared statement or a stored procedure.
///
+ ///
+ /// If this property is not set, the command text is retrieved by invoking
+ /// .
+ ///
///
public string CommandText
{
@@ -321,7 +325,7 @@ public bool UseTransactions
/// of the current thread.
///
///
- public SecurityContext SecurityContext
+ public SecurityContext SecurityContext
{
get { return m_securityContext; }
set { m_securityContext = value; }
@@ -374,7 +378,7 @@ public bool ReconnectOnError
/// underlying returned from if
/// you require access beyond that which provides.
///
- protected IDbConnection Connection
+ protected IDbConnection Connection
{
get { return m_dbConnection; }
set { m_dbConnection = value; }
@@ -400,20 +404,16 @@ protected IDbConnection Connection
/// must be called again.
///
///
- override public void ActivateOptions()
+ override public void ActivateOptions()
{
base.ActivateOptions();
- // Are we using a command object
- m_usePreparedCommand = (m_commandText != null && m_commandText.Length > 0);
-
- if (m_securityContext == null)
+ if (SecurityContext == null)
{
- m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
+ SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
}
InitializeDatabaseConnection();
- InitializeDatabaseCommand();
}
#endregion
@@ -428,11 +428,10 @@ override public void ActivateOptions()
/// Closes the database command and database connection.
///
///
- override protected void OnClose()
+ override protected void OnClose()
{
base.OnClose();
- DisposeCommand(false);
- DiposeConnection();
+ DiposeConnection();
}
#endregion
@@ -451,48 +450,44 @@ override protected void OnClose()
///
override protected void SendBuffer(LoggingEvent[] events)
{
- if (m_reconnectOnError && (m_dbConnection == null || m_dbConnection.State != ConnectionState.Open))
+ if (ReconnectOnError && (Connection == null || Connection.State != ConnectionState.Open))
{
- LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((m_dbConnection==null)?SystemInfo.NullText:m_dbConnection.State.ToString()) );
+ LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((Connection == null) ? SystemInfo.NullText : Connection.State.ToString()));
InitializeDatabaseConnection();
- InitializeDatabaseCommand();
}
// Check that the connection exists and is open
- if (m_dbConnection != null && m_dbConnection.State == ConnectionState.Open)
+ if (Connection != null && Connection.State == ConnectionState.Open)
{
- if (m_useTransactions)
+ if (UseTransactions)
{
// Create transaction
// NJC - Do this on 2 lines because it can confuse the debugger
- IDbTransaction dbTran = null;
- try
+ using (IDbTransaction dbTran = Connection.BeginTransaction())
{
- dbTran = m_dbConnection.BeginTransaction();
-
- SendBuffer(dbTran, events);
+ try
+ {
+ SendBuffer(dbTran, events);
- // commit transaction
- dbTran.Commit();
- }
- catch(Exception ex)
- {
- // rollback the transaction
- if (dbTran != null)
+ // commit transaction
+ dbTran.Commit();
+ }
+ catch (Exception ex)
{
+ // rollback the transaction
try
{
dbTran.Rollback();
}
- catch(Exception)
+ catch (Exception)
{
// Ignore exception
}
- }
- // Can't insert into the database. That's a bad thing
- ErrorHandler.Error("Exception while writing to database", ex);
+ // Can't insert into the database. That's a bad thing
+ ErrorHandler.Error("Exception while writing to database", ex);
+ }
}
}
else
@@ -540,48 +535,57 @@ public void AddParameter(AdoNetAppenderParameter parameter)
///
virtual protected void SendBuffer(IDbTransaction dbTran, LoggingEvent[] events)
{
- if (m_usePreparedCommand)
+ // string.IsNotNullOrWhiteSpace() does not exist in ancient .NET frameworks
+ if (CommandText != null && CommandText.Trim() != "")
{
- // Send buffer using the prepared command object
-
- if (m_dbCommand != null)
+ using (IDbCommand dbCmd = Connection.CreateCommand())
{
+ // Set the command string
+ dbCmd.CommandText = CommandText;
+
+ // Set the command type
+ dbCmd.CommandType = CommandType;
+ // Send buffer using the prepared command object
if (dbTran != null)
{
- m_dbCommand.Transaction = dbTran;
+ dbCmd.Transaction = dbTran;
}
-
+ // prepare the command, which is significantly faster
+ dbCmd.Prepare();
// run for all events
- foreach(LoggingEvent e in events)
+ foreach (LoggingEvent e in events)
{
+ // clear parameters that have been set
+ dbCmd.Parameters.Clear();
+
// Set the parameter values
- foreach(AdoNetAppenderParameter param in m_parameters)
+ foreach (AdoNetAppenderParameter param in m_parameters)
{
- param.FormatValue(m_dbCommand, e);
+ param.Prepare(dbCmd);
+ param.FormatValue(dbCmd, e);
}
// Execute the query
- m_dbCommand.ExecuteNonQuery();
+ dbCmd.ExecuteNonQuery();
}
}
}
else
{
// create a new command
- using(IDbCommand dbCmd = m_dbConnection.CreateCommand())
+ using (IDbCommand dbCmd = Connection.CreateCommand())
{
if (dbTran != null)
{
dbCmd.Transaction = dbTran;
}
-
// run for all events
- foreach(LoggingEvent e in events)
+ foreach (LoggingEvent e in events)
{
// Get the command text from the Layout
string logStatement = GetLogStatement(e);
- LogLog.Debug(declaringType, "LogStatement ["+logStatement+"]");
+ LogLog.Debug(declaringType, "LogStatement [" + logStatement + "]");
dbCmd.CommandText = logStatement;
dbCmd.ExecuteNonQuery();
@@ -616,71 +620,71 @@ virtual protected string GetLogStatement(LoggingEvent logEvent)
}
}
- ///
- /// Creates an instance used to connect to the database.
- ///
- ///
- /// This method is called whenever a new IDbConnection is needed (i.e. when a reconnect is necessary).
- ///
- /// The of the object.
- /// The connectionString output from the ResolveConnectionString method.
- /// An instance with a valid connection string.
- virtual protected IDbConnection CreateConnection(Type connectionType, string connectionString)
- {
- IDbConnection connection = (IDbConnection)Activator.CreateInstance(connectionType);
- connection.ConnectionString = connectionString;
- return connection;
- }
-
- ///
- /// Resolves the connection string from the ConnectionString, ConnectionStringName, or AppSettingsKey
- /// property.
- ///
- ///
- /// ConnectiongStringName is only supported on .NET 2.0 and higher.
- ///
- /// Additional information describing the connection string.
- /// A connection string used to connect to the database.
- virtual protected string ResolveConnectionString(out string connectionStringContext)
- {
- if (m_connectionString != null && m_connectionString.Length > 0)
- {
- connectionStringContext = "ConnectionString";
- return m_connectionString;
- }
+ ///
+ /// Creates an instance used to connect to the database.
+ ///
+ ///
+ /// This method is called whenever a new IDbConnection is needed (i.e. when a reconnect is necessary).
+ ///
+ /// The of the object.
+ /// The connectionString output from the ResolveConnectionString method.
+ /// An instance with a valid connection string.
+ virtual protected IDbConnection CreateConnection(Type connectionType, string connectionString)
+ {
+ IDbConnection connection = (IDbConnection)Activator.CreateInstance(connectionType);
+ connection.ConnectionString = connectionString;
+ return connection;
+ }
+
+ ///
+ /// Resolves the connection string from the ConnectionString, ConnectionStringName, or AppSettingsKey
+ /// property.
+ ///
+ ///
+ /// ConnectiongStringName is only supported on .NET 2.0 and higher.
+ ///
+ /// Additional information describing the connection string.
+ /// A connection string used to connect to the database.
+ virtual protected string ResolveConnectionString(out string connectionStringContext)
+ {
+ if (ConnectionString != null && ConnectionString.Length > 0)
+ {
+ connectionStringContext = "ConnectionString";
+ return ConnectionString;
+ }
#if NET_2_0
- if (!String.IsNullOrEmpty(m_connectionStringName))
- {
- ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[m_connectionStringName];
- if (settings != null)
- {
- connectionStringContext = "ConnectionStringName";
- return settings.ConnectionString;
- }
- else
- {
- throw new LogException("Unable to find [" + m_connectionStringName + "] ConfigurationManager.ConnectionStrings item");
- }
- }
+ if (!String.IsNullOrEmpty(ConnectionStringName))
+ {
+ ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[ConnectionStringName];
+ if (settings != null)
+ {
+ connectionStringContext = "ConnectionStringName";
+ return settings.ConnectionString;
+ }
+ else
+ {
+ throw new LogException("Unable to find [" + ConnectionStringName + "] ConfigurationManager.ConnectionStrings item");
+ }
+ }
#endif
- if (m_appSettingsKey != null && m_appSettingsKey.Length > 0)
- {
- connectionStringContext = "AppSettingsKey";
- string appSettingsConnectionString = SystemInfo.GetAppSetting(m_appSettingsKey);
- if (appSettingsConnectionString == null || appSettingsConnectionString.Length == 0)
- {
- throw new LogException("Unable to find [" + m_appSettingsKey + "] AppSettings key.");
- }
- return appSettingsConnectionString;
- }
-
- connectionStringContext = "Unable to resolve connection string from ConnectionString, ConnectionStrings, or AppSettings.";
- return string.Empty;
- }
-
- ///
+ if (AppSettingsKey != null && AppSettingsKey.Length > 0)
+ {
+ connectionStringContext = "AppSettingsKey";
+ string appSettingsConnectionString = SystemInfo.GetAppSetting(AppSettingsKey);
+ if (appSettingsConnectionString == null || appSettingsConnectionString.Length == 0)
+ {
+ throw new LogException("Unable to find [" + AppSettingsKey + "] AppSettings key.");
+ }
+ return appSettingsConnectionString;
+ }
+
+ connectionStringContext = "Unable to resolve connection string from ConnectionString, ConnectionStrings, or AppSettings.";
+ return string.Empty;
+ }
+
+ ///
/// Retrieves the class type of the ADO.NET provider.
///
///
@@ -699,181 +703,76 @@ virtual protected Type ResolveConnectionType()
{
try
{
- return SystemInfo.GetTypeFromString(m_connectionType, true, false);
+ return SystemInfo.GetTypeFromString(ConnectionType, true, false);
}
- catch(Exception ex)
+ catch (Exception ex)
{
- ErrorHandler.Error("Failed to load connection type ["+m_connectionType+"]", ex);
+ ErrorHandler.Error("Failed to load connection type [" + ConnectionType + "]", ex);
throw;
}
}
#endregion // Protected Instance Methods
- #region Private Instance Methods
-
- ///
- /// Prepares the database command and initialize the parameters.
- ///
- private void InitializeDatabaseCommand()
- {
- if (m_dbConnection != null && m_usePreparedCommand)
- {
- try
- {
- DisposeCommand(false);
-
- // Create the command object
- m_dbCommand = m_dbConnection.CreateCommand();
-
- // Set the command string
- m_dbCommand.CommandText = m_commandText;
-
- // Set the command type
- m_dbCommand.CommandType = m_commandType;
- }
- catch (Exception e)
- {
- ErrorHandler.Error("Could not create database command [" + m_commandText + "]", e);
-
- DisposeCommand(true);
- }
-
- if (m_dbCommand != null)
- {
- try
- {
- foreach (AdoNetAppenderParameter param in m_parameters)
- {
- try
- {
- param.Prepare(m_dbCommand);
- }
- catch (Exception e)
- {
- ErrorHandler.Error("Could not add database command parameter [" + param.ParameterName + "]", e);
- throw;
- }
- }
- }
- catch
- {
- DisposeCommand(true);
- }
- }
-
- if (m_dbCommand != null)
- {
- try
- {
- // Prepare the command statement.
- m_dbCommand.Prepare();
- }
- catch (Exception e)
- {
- ErrorHandler.Error("Could not prepare database command [" + m_commandText + "]", e);
-
- DisposeCommand(true);
- }
- }
- }
- }
-
- ///
- /// Connects to the database.
- ///
- private void InitializeDatabaseConnection()
- {
- string connectionStringContext = "Unable to determine connection string context.";
- string resolvedConnectionString = string.Empty;
-
- try
- {
- DisposeCommand(true);
- DiposeConnection();
-
- // Set the connection string
- resolvedConnectionString = ResolveConnectionString(out connectionStringContext);
-
- m_dbConnection = CreateConnection(ResolveConnectionType(), resolvedConnectionString);
-
- using (SecurityContext.Impersonate(this))
- {
- // Open the database connection
- m_dbConnection.Open();
- }
- }
- catch (Exception e)
- {
- // Sadly, your connection string is bad.
- ErrorHandler.Error("Could not open database connection [" + resolvedConnectionString + "]. Connection string context [" + connectionStringContext + "].", e);
-
- m_dbConnection = null;
- }
- }
-
- ///
- /// Cleanup the existing command.
- ///
- ///
- /// If true, a message will be written using LogLog.Warn if an exception is encountered when calling Dispose.
- ///
- private void DisposeCommand(bool ignoreException)
- {
- // Cleanup any existing command or connection
- if (m_dbCommand != null)
- {
- try
- {
- m_dbCommand.Dispose();
- }
- catch (Exception ex)
- {
- if (!ignoreException)
- {
- LogLog.Warn(declaringType, "Exception while disposing cached command object", ex);
- }
- }
- m_dbCommand = null;
- }
- }
-
- ///
- /// Cleanup the existing connection.
- ///
- ///
- /// Calls the IDbConnection's method.
- ///
- private void DiposeConnection()
- {
- if (m_dbConnection != null)
- {
- try
- {
- m_dbConnection.Close();
- }
- catch (Exception ex)
- {
- LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex);
- }
- m_dbConnection = null;
- }
- }
-
- #endregion // Private Instance Methods
-
- #region Protected Instance Fields
-
- ///
- /// Flag to indicate if we are using a command object
+ #region Private Instance Methods
+
+ ///
+ /// Connects to the database.
+ ///
+ private void InitializeDatabaseConnection()
+ {
+ string connectionStringContext = "Unable to determine connection string context.";
+ string resolvedConnectionString = string.Empty;
+
+ try
+ {
+ DiposeConnection();
+
+ // Set the connection string
+ resolvedConnectionString = ResolveConnectionString(out connectionStringContext);
+
+ Connection = CreateConnection(ResolveConnectionType(), resolvedConnectionString);
+
+ using (SecurityContext.Impersonate(this))
+ {
+ // Open the database connection
+ Connection.Open();
+ }
+ }
+ catch (Exception e)
+ {
+ // Sadly, your connection string is bad.
+ ErrorHandler.Error("Could not open database connection [" + resolvedConnectionString + "]. Connection string context [" + connectionStringContext + "].", e);
+
+ Connection = null;
+ }
+ }
+
+ ///
+ /// Cleanup the existing connection.
///
///
- ///
- /// Set to true when the appender is to use a prepared
- /// statement or stored procedure to insert into the database.
- ///
+ /// Calls the IDbConnection's method.
///
- protected bool m_usePreparedCommand;
+ private void DiposeConnection()
+ {
+ if (Connection != null)
+ {
+ try
+ {
+ Connection.Close();
+ }
+ catch (Exception ex)
+ {
+ LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex);
+ }
+ Connection = null;
+ }
+ }
+
+ #endregion // Private Instance Methods
+
+ #region Protected Instance Fields
///
/// The list of objects.
@@ -900,29 +799,24 @@ private void DiposeConnection()
///
private IDbConnection m_dbConnection;
- ///
- /// The database command.
- ///
- private IDbCommand m_dbCommand;
-
///
/// Database connection string.
///
private string m_connectionString;
- ///
- /// The appSettings key from App.Config that contains the connection string.
- ///
- private string m_appSettingsKey;
+ ///
+ /// The appSettings key from App.Config that contains the connection string.
+ ///
+ private string m_appSettingsKey;
#if NET_2_0
- ///
- /// The connectionStrings key from App.Config that contains the connection string.
- ///
- private string m_connectionStringName;
+ ///
+ /// The connectionStrings key from App.Config that contains the connection string.
+ ///
+ private string m_connectionStringName;
#endif
- ///
+ ///
/// String type name of the type name.
///
private string m_connectionType;
@@ -943,24 +837,24 @@ private void DiposeConnection()
private bool m_useTransactions;
///
- /// Indicates whether to use transactions when writing to the database.
+ /// Indicates whether to reconnect when a connection is lost.
///
private bool m_reconnectOnError;
#endregion // Private Instance Fields
- #region Private Static Fields
+ #region Private Static Fields
- ///
- /// The fully qualified type of the AdoNetAppender class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(AdoNetAppender);
+ ///
+ /// The fully qualified type of the AdoNetAppender class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(AdoNetAppender);
- #endregion Private Static Fields
+ #endregion Private Static Fields
}
///
@@ -988,9 +882,9 @@ public class AdoNetAppenderParameter
///
public AdoNetAppenderParameter()
{
- m_precision = 0;
- m_scale = 0;
- m_size = 0;
+ Precision = 0;
+ Scale = 0;
+ Size = 0;
}
#endregion // Public Instance Constructors
@@ -1037,9 +931,9 @@ public string ParameterName
public DbType DbType
{
get { return m_dbType; }
- set
- {
- m_dbType = value;
+ set
+ {
+ m_dbType = value;
m_inferType = false;
}
}
@@ -1060,9 +954,9 @@ public DbType DbType
///
///
///
- public byte Precision
+ public byte Precision
{
- get { return m_precision; }
+ get { return m_precision; }
set { m_precision = value; }
}
@@ -1082,7 +976,7 @@ public byte Precision
///
///
///
- public byte Scale
+ public byte Scale
{
get { return m_scale; }
set { m_scale = value; }
@@ -1102,9 +996,12 @@ public byte Scale
/// This property is optional. If not specified the ADO.NET provider
/// will attempt to infer the size from the value.
///
+ ///
+ /// For BLOB data types like VARCHAR(max) it may be impossible to infer the value automatically, use -1 as the size in this case.
+ ///
///
///
- public int Size
+ public int Size
{
get { return m_size; }
set { m_size = value; }
@@ -1156,23 +1053,23 @@ virtual public void Prepare(IDbCommand command)
IDbDataParameter param = command.CreateParameter();
// Set the parameter properties
- param.ParameterName = m_parameterName;
+ param.ParameterName = ParameterName;
if (!m_inferType)
{
- param.DbType = m_dbType;
+ param.DbType = DbType;
}
- if (m_precision != 0)
+ if (Precision != 0)
{
- param.Precision = m_precision;
+ param.Precision = Precision;
}
- if (m_scale != 0)
+ if (Scale != 0)
{
- param.Scale = m_scale;
+ param.Scale = Scale;
}
- if (m_size != 0)
+ if (Size != 0)
{
- param.Size = m_size;
+ param.Size = Size;
}
// Add the parameter to the collection of params
@@ -1193,7 +1090,7 @@ virtual public void Prepare(IDbCommand command)
virtual public void FormatValue(IDbCommand command, LoggingEvent loggingEvent)
{
// Lookup the parameter
- IDbDataParameter param = (IDbDataParameter)command.Parameters[m_parameterName];
+ IDbDataParameter param = (IDbDataParameter)command.Parameters[ParameterName];
// Format the value
object formattedValue = Layout.Format(loggingEvent);
diff --git a/src/Appender/AnsiColorTerminalAppender.cs b/src/Appender/AnsiColorTerminalAppender.cs
old mode 100755
new mode 100644
index 89c4511a..3ad375fd
--- a/src/Appender/AnsiColorTerminalAppender.cs
+++ b/src/Appender/AnsiColorTerminalAppender.cs
@@ -153,7 +153,12 @@ public enum AnsiAttributes : int
///
/// text is displayed with a strikethrough
///
- Strikethrough = 64
+ Strikethrough = 64,
+
+ ///
+ /// text color is light
+ ///
+ Light = 128
}
///
@@ -176,7 +181,7 @@ public enum AnsiColor : int
///
/// color is red
///
- Red = 1,
+ Red = 1,
///
/// color is green
@@ -280,7 +285,7 @@ public void AddMapping(LevelColors mapping)
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
@@ -510,12 +515,14 @@ public override void ActivateOptions()
// Reset any existing codes
buf.Append("\x1b[0;");
+ int lightAdjustment = ((m_attributes & AnsiAttributes.Light) > 0) ? 60 : 0;
+
// set the foreground color
- buf.Append(30 + (int)m_foreColor);
+ buf.Append(30 + lightAdjustment + (int)m_foreColor);
buf.Append(';');
// set the background color
- buf.Append(40 + (int)m_backColor);
+ buf.Append(40 + lightAdjustment + (int)m_backColor);
// set the attributes
if ((m_attributes & AnsiAttributes.Bright) > 0)
diff --git a/src/Appender/AppenderCollection.cs b/src/Appender/AppenderCollection.cs
old mode 100755
new mode 100644
index 99f94ac6..53ea990e
--- a/src/Appender/AppenderCollection.cs
+++ b/src/Appender/AppenderCollection.cs
@@ -566,9 +566,9 @@ public virtual IAppender[] ToArray()
#region Implementation (helpers)
///
- /// is less than zero
+ /// is less than zero
/// -or-
- /// is equal to or greater than .
+ /// is equal to or greater than .
///
private void ValidateIndex(int i)
{
@@ -576,9 +576,9 @@ private void ValidateIndex(int i)
}
///
- /// is less than zero
+ /// is less than zero
/// -or-
- /// is equal to or greater than .
+ /// is equal to or greater than .
///
private void ValidateIndex(int i, bool allowEqualEnd)
{
@@ -883,6 +883,16 @@ public override int AddRange(IAppender[] x)
throw new NotSupportedException("This is a Read Only Collection and can not be modified");
}
+ public override IAppender[] ToArray()
+ {
+ return m_collection.ToArray();
+ }
+
+ public override void TrimToSize()
+ {
+ throw new NotSupportedException("This is a Read Only Collection and can not be modified");
+ }
+
#endregion
}
diff --git a/src/Appender/AppenderSkeleton.cs b/src/Appender/AppenderSkeleton.cs
old mode 100755
new mode 100644
index 6dc31920..bc116837
--- a/src/Appender/AppenderSkeleton.cs
+++ b/src/Appender/AppenderSkeleton.cs
@@ -38,7 +38,7 @@ namespace log4net.Appender
///
///
/// Appenders can also implement the interface. Therefore
- /// they would require that the method
+ /// they would require that the method
/// be called after the appenders properties have been configured.
///
///
@@ -249,13 +249,13 @@ public void Close()
///
/// Performs threshold checks and invokes filters before
/// delegating actual logging to the subclasses specific
- /// method.
+ /// method.
///
/// The event to log.
///
///
/// This method cannot be overridden by derived classes. A
- /// derived class should override the method
+ /// derived class should override the method
/// which is called by this method.
///
///
@@ -277,14 +277,14 @@ public void Close()
///
///
///
- /// Calls and checks that
+ /// Calls and checks that
/// it returns true.
///
///
///
///
/// If all of the above steps succeed then the
- /// will be passed to the abstract method.
+ /// will be passed to the abstract method.
///
///
public void DoAppend(LoggingEvent loggingEvent)
@@ -346,13 +346,13 @@ public void DoAppend(LoggingEvent loggingEvent)
///
/// Performs threshold checks and invokes filters before
/// delegating actual logging to the subclasses specific
- /// method.
+ /// method.
///
/// The array of events to log.
///
///
/// This method cannot be overridden by derived classes. A
- /// derived class should override the method
+ /// derived class should override the method
/// which is called by this method.
///
///
@@ -362,26 +362,26 @@ public void DoAppend(LoggingEvent loggingEvent)
///
///
///
- /// Checks that the severity of the
+ /// Checks that the severity of the
/// is greater than or equal to the of this
/// appender.
///
///
///
/// Checks that the chain accepts the
- /// .
+ /// .
///
///
///
///
- /// Calls and checks that
+ /// Calls and checks that
/// it returns true.
///
///
///
///
/// If all of the above steps succeed then the
- /// will be passed to the method.
+ /// will be passed to the method.
///
///
public void DoAppend(LoggingEvent[] loggingEvents)
@@ -604,12 +604,12 @@ virtual protected void OnClose()
/// A subclass must implement this method to perform
/// logging of the .
///
- /// This method will be called by
+ /// This method will be called by
/// if all the conditions listed for that method are met.
///
///
/// To restrict the logging of events in the appender
- /// override the method.
+ /// override the method.
///
///
abstract protected void Append(LoggingEvent loggingEvent);
@@ -620,12 +620,12 @@ virtual protected void OnClose()
/// the array of logging events
///
///
- /// This base class implementation calls the
+ /// This base class implementation calls the
/// method for each element in the bulk array.
///
///
/// A sub class that can better process a bulk array of events should
- /// override this method in addition to .
+ /// override this method in addition to .
///
///
virtual protected void Append(LoggingEvent[] loggingEvents)
@@ -637,23 +637,23 @@ virtual protected void Append(LoggingEvent[] loggingEvents)
}
///
- /// Called before as a precondition.
+ /// Called before as a precondition.
///
///
///
- /// This method is called by
- /// before the call to the abstract method.
+ /// This method is called by
+ /// before the call to the abstract method.
///
///
/// This method can be overridden in a subclass to extend the checks
- /// made before the event is passed to the method.
+ /// made before the event is passed to the method.
///
///
/// A subclass should ensure that they delegate this call to
/// this base class if it is overridden.
///
///
- /// true if the call to should proceed.
+ /// true if the call to should proceed.
virtual protected bool PreAppendCheck()
{
if ((m_layout == null) && RequiresLayout)
@@ -683,7 +683,7 @@ virtual protected bool PreAppendCheck()
///
///
/// Where possible use the alternative version of this method
- /// .
+ /// .
/// That method streams the rendering onto an existing Writer
/// which can give better performance if the caller already has
/// a open and ready for writing.
@@ -697,11 +697,14 @@ protected string RenderLoggingEvent(LoggingEvent loggingEvent)
m_renderWriter = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture);
}
- // Reset the writer so we can reuse it
- m_renderWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize);
+ lock (m_renderWriter)
+ {
+ // Reset the writer so we can reuse it
+ m_renderWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize);
- RenderLoggingEvent(m_renderWriter, loggingEvent);
- return m_renderWriter.ToString();
+ RenderLoggingEvent(m_renderWriter, loggingEvent);
+ return m_renderWriter.ToString();
+ }
}
///
@@ -721,9 +724,9 @@ protected string RenderLoggingEvent(LoggingEvent loggingEvent)
/// will append the exception text to the rendered string.
///
///
- /// Use this method in preference to
+ /// Use this method in preference to
/// where possible. If, however, the caller needs to render the event
- /// to a string then does
+ /// to a string then does
/// provide an efficient mechanism for doing so.
///
///
@@ -766,7 +769,7 @@ protected void RenderLoggingEvent(TextWriter writer, LoggingEvent loggingEvent)
/// then the appender should return true.
///
///
- /// This default implementation always returns true.
+ /// This default implementation always returns false.
///
///
///
diff --git a/src/Appender/AspNetTraceAppender.cs b/src/Appender/AspNetTraceAppender.cs
old mode 100755
new mode 100644
index e1bdbf44..82f9569e
--- a/src/Appender/AspNetTraceAppender.cs
+++ b/src/Appender/AspNetTraceAppender.cs
@@ -19,7 +19,7 @@
// .NET Compact Framework 1.0 has no support for ASP.NET
// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
using System.Web;
@@ -45,8 +45,8 @@ namespace log4net.Appender
/// whether tracing is displayed to a page, to the trace viewer, or both.
///
///
- /// The logging event is passed to the or
- /// method depending on the level of the logging event.
+ /// The logging event is passed to the or
+ /// method depending on the level of the logging event.
/// The event's logger name is the default value for the category parameter of the Write/Warn method.
///
///
diff --git a/src/Appender/BufferingAppenderSkeleton.cs b/src/Appender/BufferingAppenderSkeleton.cs
old mode 100755
new mode 100644
index 958dc0c2..fcb2b503
--- a/src/Appender/BufferingAppenderSkeleton.cs
+++ b/src/Appender/BufferingAppenderSkeleton.cs
@@ -37,7 +37,7 @@ namespace log4net.Appender
/// the underlying database in one go.
///
///
- /// Subclasses should override the
+ /// Subclasses should override the
/// method to deliver the buffered events.
///
/// The BufferingAppenderSkeleton maintains a fixed size cyclic
@@ -47,14 +47,14 @@ namespace log4net.Appender
/// A is used to inspect
/// each event as it arrives in the appender. If the
/// triggers, then the current buffer is sent immediately
- /// (see ). Otherwise the event
+ /// (see ). Otherwise the event
/// is stored in the buffer. For example, an evaluator can be used to
/// deliver the events immediately when an ERROR event arrives.
///
///
/// The buffering appender can be configured in a mode.
/// By default the appender is NOT lossy. When the buffer is full all
- /// the buffered events are sent with .
+ /// the buffered events are sent with .
/// If the property is set to true then the
/// buffer will not be sent when it is full, and new events arriving
/// in the appender will overwrite the oldest event in the buffer.
@@ -173,7 +173,7 @@ public int BufferSize
///
/// The evaluator will be called for each event that is appended to this
/// appender. If the evaluator triggers then the current buffer will
- /// immediately be sent (see ).
+ /// immediately be sent (see ).
///
/// If is set to true then an
/// must be specified.
@@ -194,7 +194,7 @@ public ITriggeringEventEvaluator Evaluator
///
/// The evaluator will be called for each event that is discarded from this
/// appender. If the evaluator triggers then the current buffer will immediately
- /// be sent (see ).
+ /// be sent (see ).
///
///
public ITriggeringEventEvaluator LossyEvaluator
@@ -217,7 +217,7 @@ public ITriggeringEventEvaluator LossyEvaluator
/// event data to be fixed and serialized. This will improve performance.
///
///
- /// See for more information.
+ /// See for more information.
///
///
[Obsolete("Use Fix property")]
@@ -412,7 +412,7 @@ override protected void OnClose()
}
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// the event to log
///
@@ -436,7 +436,7 @@ override protected void OnClose()
///
///
/// Before the event is stored in the buffer it is fixed
- /// (see ) to ensure that
+ /// (see ) to ensure that
/// any data referenced by the event will be valid when the buffer
/// is processed.
///
@@ -527,7 +527,7 @@ override protected void Append(LoggingEvent loggingEvent)
/// The buffer containing the events that need to be send.
///
///
- /// The subclass must override .
+ /// The subclass must override .
///
///
virtual protected void SendFromBuffer(LoggingEvent firstLoggingEvent, CyclicBuffer buffer)
diff --git a/src/Appender/BufferingForwardingAppender.cs b/src/Appender/BufferingForwardingAppender.cs
old mode 100755
new mode 100644
diff --git a/src/Appender/ColoredConsoleAppender.cs b/src/Appender/ColoredConsoleAppender.cs
old mode 100755
new mode 100644
index 0d587e3e..1c26a2c3
--- a/src/Appender/ColoredConsoleAppender.cs
+++ b/src/Appender/ColoredConsoleAppender.cs
@@ -254,7 +254,7 @@ public void AddMapping(LevelColors mapping)
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
@@ -265,7 +265,11 @@ public void AddMapping(LevelColors mapping)
/// The format of the output will depend on the appender's layout.
///
///
- override protected void Append(log4net.Core.LoggingEvent loggingEvent)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)]
+ override protected void Append(log4net.Core.LoggingEvent loggingEvent)
{
if (m_consoleOutputWriter != null)
{
@@ -430,7 +434,11 @@ override protected bool RequiresLayout
/// Initialize the level to color mappings set on this appender.
///
///
- public override void ActivateOptions()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode=true)]
+ public override void ActivateOptions()
{
base.ActivateOptions();
m_levelMapping.ActivateOptions();
diff --git a/src/Appender/ConsoleAppender.cs b/src/Appender/ConsoleAppender.cs
old mode 100755
new mode 100644
index b2090d98..84ad1723
--- a/src/Appender/ConsoleAppender.cs
+++ b/src/Appender/ConsoleAppender.cs
@@ -137,7 +137,7 @@ virtual public string Target
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
diff --git a/src/Appender/DebugAppender.cs b/src/Appender/DebugAppender.cs
old mode 100755
new mode 100644
index ab744706..c2c92268
--- a/src/Appender/DebugAppender.cs
+++ b/src/Appender/DebugAppender.cs
@@ -35,7 +35,7 @@ namespace log4net.Appender
/// debug system.
///
///
- /// Events are written using the
+ /// Events are written using the
/// method. The event's logger name is passed as the value for the category name to the Write method.
///
///
diff --git a/src/Appender/EventLogAppender.cs b/src/Appender/EventLogAppender.cs
old mode 100755
new mode 100644
index c17c2838..9cc031e0
--- a/src/Appender/EventLogAppender.cs
+++ b/src/Appender/EventLogAppender.cs
@@ -38,9 +38,18 @@ namespace log4net.Appender
/// Writes events to the system event log.
///
///
+ ///
+ /// The appender will fail if you try to write using an event source that doesn't exist unless it is running with local administrator privileges.
+ /// See also http://logging.apache.org/log4net/release/faq.html#trouble-EventLog
+ ///
///
/// The EventID of the event log entry can be
- /// set using the EventLogEventID property ()
+ /// set using the EventID property ()
+ /// on the .
+ ///
+ ///
+ /// The Category of the event log entry can be
+ /// set using the Category property ()
/// on the .
///
///
@@ -211,7 +220,40 @@ public SecurityContext SecurityContext
set { m_securityContext = value; }
}
- #endregion // Public Instance Properties
+ ///
+ /// Gets or sets the EventId to use unless one is explicitly specified via the LoggingEvent's properties.
+ ///
+ ///
+ ///
+ /// The EventID of the event log entry will normally be
+ /// set using the EventID property ()
+ /// on the .
+ /// This property provides the fallback value which defaults to 0.
+ ///
+ ///
+ public int EventId {
+ get { return m_eventId; }
+ set { m_eventId = value; }
+ }
+
+
+ ///
+ /// Gets or sets the Category to use unless one is explicitly specified via the LoggingEvent's properties.
+ ///
+ ///
+ ///
+ /// The Category of the event log entry will normally be
+ /// set using the Category property ()
+ /// on the .
+ /// This property provides the fallback value which defaults to 0.
+ ///
+ ///
+ public short Category
+ {
+ get { return m_category; }
+ set { m_category = value; }
+ }
+ #endregion // Public Instance Properties
#region Implementation of IOptionHandler
@@ -233,60 +275,71 @@ public SecurityContext SecurityContext
///
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.Debug(declaringType, "Changing event source [" + m_applicationName + "] from log [" + currentLogName + "] to log [" + m_logName + "]");
- }
- else if (!sourceAlreadyExists)
- {
- LogLog.Debug(declaringType, "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.Debug(declaringType, "Source [" + m_applicationName + "] is registered to log [" + registeredLogName + "]");
+ try
+ {
+ 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.Debug(declaringType, "Changing event source [" + m_applicationName + "] from log [" + currentLogName + "] to log [" + m_logName + "]");
+ }
+ else if (!sourceAlreadyExists)
+ {
+ LogLog.Debug(declaringType, "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.Debug(declaringType, "Source [" + m_applicationName + "] is registered to log [" + registeredLogName + "]");
+ }
+ catch (System.Security.SecurityException ex)
+ {
+ ErrorHandler.Error("Caught a SecurityException trying to access the EventLog. Most likely the event source "
+ + m_applicationName
+ + " doesn't exist and must be created by a local administrator. Will disable EventLogAppender."
+ + " See http://logging.apache.org/log4net/release/faq.html#trouble-EventLog",
+ ex);
+ Threshold = Level.Off;
+ }
}
#endregion // Implementation of IOptionHandler
@@ -311,7 +364,7 @@ private static void CreateEventSource(string source, string logName, string mach
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the
+ /// This method is called by the
/// method.
///
/// the event to log
@@ -331,9 +384,9 @@ override protected void Append(LoggingEvent loggingEvent)
//
// Write the resulting string to the event log system
//
- int eventID = 0;
+ int eventID = m_eventId;
- // Look for the EventLogEventID property
+ // Look for the EventID property
object eventIDPropertyObj = loggingEvent.LookupProperty("EventID");
if (eventIDPropertyObj != null)
{
@@ -344,6 +397,10 @@ override protected void Append(LoggingEvent loggingEvent)
else
{
string eventIDPropertyString = eventIDPropertyObj as string;
+ if (eventIDPropertyString == null)
+ {
+ eventIDPropertyString = eventIDPropertyObj.ToString();
+ }
if (eventIDPropertyString != null && eventIDPropertyString.Length > 0)
{
// Read the string property into a number
@@ -360,22 +417,54 @@ override protected void Append(LoggingEvent loggingEvent)
}
}
+ short category = m_category;
+ // Look for the Category property
+ object categoryPropertyObj = loggingEvent.LookupProperty("Category");
+ if (categoryPropertyObj != null)
+ {
+ if (categoryPropertyObj is short)
+ {
+ category = (short) categoryPropertyObj;
+ }
+ else
+ {
+ string categoryPropertyString = categoryPropertyObj as string;
+ if (categoryPropertyString == null)
+ {
+ categoryPropertyString = categoryPropertyObj.ToString();
+ }
+ if (categoryPropertyString != null && categoryPropertyString.Length > 0)
+ {
+ // Read the string property into a number
+ short shortVal;
+ if (SystemInfo.TryParse(categoryPropertyString, out shortVal))
+ {
+ category = shortVal;
+ }
+ else
+ {
+ ErrorHandler.Error("Unable to parse event category property [" + categoryPropertyString + "].");
+ }
+ }
+ }
+ }
+
// Write to the event log
try
{
string eventTxt = RenderLoggingEvent(loggingEvent);
- // There is a limit of 32K characters for an event log message
- if (eventTxt.Length > 32000)
+ // There is a limit of about 32K characters for an event log message
+ if (eventTxt.Length > MAX_EVENTLOG_MESSAGE_SIZE)
{
- eventTxt = eventTxt.Substring(0, 32000);
+ eventTxt = eventTxt.Substring(0, MAX_EVENTLOG_MESSAGE_SIZE);
}
EventLogEntryType entryType = GetEntryType(loggingEvent.Level);
using(SecurityContext.Impersonate(this))
{
- EventLog.WriteEntry(m_applicationName, eventTxt, entryType, eventID);
+ EventLog.WriteEntry(m_applicationName, eventTxt, entryType, eventID, category);
}
}
catch(Exception ex)
@@ -403,10 +492,10 @@ override protected bool RequiresLayout
#region Protected Instance Methods
///
- /// Get the equivalent for a
+ /// Get the equivalent for a
///
/// the Level to convert to an EventLogEntryType
- /// The equivalent for a
+ /// The equivalent for a
///
/// Because there are fewer applicable
/// values to use in logging levels than there are in the
@@ -469,7 +558,17 @@ virtual protected EventLogEntryType GetEntryType(Level level)
///
private SecurityContext m_securityContext;
- #endregion // Private Instance Fields
+ ///
+ /// The event ID to use unless one is explicitly specified via the LoggingEvent's properties.
+ ///
+ private int m_eventId = 0;
+
+ ///
+ /// The event category to use unless one is explicitly specified via the LoggingEvent's properties.
+ ///
+ private short m_category = 0;
+
+ #endregion // Private Instance Fields
#region Level2EventLogEntryType LevelMapping Entry
@@ -515,6 +614,74 @@ public EventLogEntryType EventLogEntryType
///
private readonly static Type declaringType = typeof(EventLogAppender);
+ ///
+ /// The maximum size supported by default.
+ ///
+ ///
+ /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx
+ /// The 32766 documented max size is two bytes shy of 32K (I'm assuming 32766
+ /// may leave space for a two byte null terminator of #0#0). The 32766 max
+ /// length is what the .NET 4.0 source code checks for, but this is WRONG!
+ /// Strings with a length > 31839 on Windows Vista or higher can CORRUPT
+ /// the event log! See: System.Diagnostics.EventLogInternal.InternalWriteEvent()
+ /// for the use of the 32766 max size.
+ ///
+ private readonly static int MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT = 32766;
+
+ ///
+ /// The maximum size supported by a windows operating system that is vista
+ /// or newer.
+ ///
+ ///
+ /// See ReportEvent API:
+ /// http://msdn.microsoft.com/en-us/library/aa363679(VS.85).aspx
+ /// ReportEvent's lpStrings parameter:
+ /// "A pointer to a buffer containing an array of
+ /// null-terminated strings that are merged into the message before Event Viewer
+ /// displays the string to the user. This parameter must be a valid pointer
+ /// (or NULL), even if wNumStrings is zero. Each string is limited to 31,839 characters."
+ ///
+ /// Going beyond the size of 31839 will (at some point) corrupt the event log on Windows
+ /// Vista or higher! It may succeed for a while...but you will eventually run into the
+ /// error: "System.ComponentModel.Win32Exception : A device attached to the system is
+ /// not functioning", and the event log will then be corrupt (I was able to corrupt
+ /// an event log using a length of 31877 on Windows 7).
+ ///
+ /// The max size for Windows Vista or higher is documented here:
+ /// http://msdn.microsoft.com/en-us/library/xzwc042w(v=vs.100).aspx.
+ /// Going over this size may succeed a few times but the buffer will overrun and
+ /// eventually corrupt the log (based on testing).
+ ///
+ /// The maxEventMsgSize size is based on the max buffer size of the lpStrings parameter of the ReportEvent API.
+ /// The documented max size for EventLog.WriteEntry for Windows Vista and higher is 31839, but I'm leaving room for a
+ /// terminator of #0#0, as we cannot see the source of ReportEvent (though we could use an API monitor to examine the
+ /// buffer, given enough time).
+ ///
+ private readonly static int MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER = 31839 - 2;
+
+ ///
+ /// The maximum size that the operating system supports for
+ /// a event log message.
+ ///
+ ///
+ /// Used to determine the maximum string length that can be written
+ /// to the operating system event log and eventually truncate a string
+ /// that exceeds the limits.
+ ///
+ private readonly static int MAX_EVENTLOG_MESSAGE_SIZE = GetMaxEventLogMessageSize();
+
+ ///
+ /// This method determines the maximum event log message size allowed for
+ /// the current environment.
+ ///
+ ///
+ private static int GetMaxEventLogMessageSize()
+ {
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6)
+ return MAX_EVENTLOG_MESSAGE_SIZE_VISTA_OR_NEWER;
+ return MAX_EVENTLOG_MESSAGE_SIZE_DEFAULT;
+ }
+
#endregion Private Static Fields
}
}
diff --git a/src/Appender/FileAppender.cs b/src/Appender/FileAppender.cs
old mode 100755
new mode 100644
index 8e3e1c57..65c4798a
--- a/src/Appender/FileAppender.cs
+++ b/src/Appender/FileAppender.cs
@@ -1,1271 +1,1466 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.IO;
-using System.Text;
-using System.Threading;
-using log4net.Util;
-using log4net.Layout;
-using log4net.Core;
-
-namespace log4net.Appender
-{
- ///
- /// Appends logging events to a file.
- ///
- ///
- ///
- /// Logging events are sent to the file specified by
- /// the property.
- ///
- ///
- /// The file can be opened in either append or overwrite mode
- /// by specifying the property.
- /// If the file path is relative it is taken as relative from
- /// the application base directory. The file encoding can be
- /// specified by setting the property.
- ///
- ///
- /// The layout's and
- /// values will be written each time the file is opened and closed
- /// respectively. If the property is
- /// then the file may contain multiple copies of the header and footer.
- ///
- ///
- /// This appender will first try to open the file for writing when
- /// is called. This will typically be during configuration.
- /// If the file cannot be opened for writing the appender will attempt
- /// to open the file again each time a message is logged to the appender.
- /// If the file cannot be opened for writing when a message is logged then
- /// the message will be discarded by this appender.
- ///
- ///
- /// The supports pluggable file locking models via
- /// the property.
- /// The default behavior, implemented by
- /// is to obtain an exclusive write lock on the file until this appender is closed.
- /// The alternative model, , only holds a
- /// write lock while the appender is writing a logging event.
- ///
- ///
- /// Nicko Cadell
- /// Gert Driesen
- /// Rodrigo B. de Oliveira
- /// Douglas de la Torre
- /// Niall Daley
- public class FileAppender : TextWriterAppender
- {
- #region LockingStream Inner Class
-
- ///
- /// Write only that uses the
- /// to manage access to an underlying resource.
- ///
- private sealed class LockingStream : Stream, IDisposable
- {
- public sealed class LockStateException : LogException
- {
- public LockStateException(string message): base(message)
- {
- }
- }
-
- private Stream m_realStream=null;
- private LockingModelBase m_lockingModel=null;
- private int m_readTotal=-1;
- private int m_lockLevel=0;
-
- public LockingStream(LockingModelBase locking) : base()
- {
- if (locking==null)
- {
- throw new ArgumentException("Locking model may not be null","locking");
- }
- m_lockingModel=locking;
- }
-
- #region Override Implementation of Stream
-
- // Methods
- public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- AssertLocked();
- IAsyncResult ret=m_realStream.BeginRead(buffer,offset,count,callback,state);
- m_readTotal=EndRead(ret);
- return ret;
- }
-
- ///
- /// True asynchronous writes are not supported, the implementation forces a synchronous write.
- ///
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- AssertLocked();
- IAsyncResult ret=m_realStream.BeginWrite(buffer,offset,count,callback,state);
- EndWrite(ret);
- return ret;
- }
-
- public override void Close()
- {
- m_lockingModel.CloseFile();
- }
-
- public override int EndRead(IAsyncResult asyncResult)
- {
- AssertLocked();
- return m_readTotal;
- }
- public override void EndWrite(IAsyncResult asyncResult)
- {
- //No-op, it has already been handled
- }
- public override void Flush()
- {
- AssertLocked();
- m_realStream.Flush();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- return m_realStream.Read(buffer,offset,count);
- }
- public override int ReadByte()
- {
- return m_realStream.ReadByte();
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- AssertLocked();
- return m_realStream.Seek(offset,origin);
- }
- public override void SetLength(long value)
- {
- AssertLocked();
- m_realStream.SetLength(value);
- }
- void IDisposable.Dispose()
- {
- Close();
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- AssertLocked();
- m_realStream.Write(buffer,offset,count);
- }
- public override void WriteByte(byte value)
- {
- AssertLocked();
- m_realStream.WriteByte(value);
- }
-
- // Properties
- public override bool CanRead
- {
- get { return false; }
- }
- public override bool CanSeek
- {
- get
- {
- AssertLocked();
- return m_realStream.CanSeek;
- }
- }
- public override bool CanWrite
- {
- get
- {
- AssertLocked();
- return m_realStream.CanWrite;
- }
- }
- public override long Length
- {
- get
- {
- AssertLocked();
- return m_realStream.Length;
- }
- }
- public override long Position
- {
- get
- {
- AssertLocked();
- return m_realStream.Position;
- }
- set
- {
- AssertLocked();
- m_realStream.Position=value;
- }
- }
-
- #endregion Override Implementation of Stream
-
- #region Locking Methods
-
- private void AssertLocked()
- {
- if (m_realStream == null)
- {
- throw new LockStateException("The file is not currently locked");
- }
- }
-
- public bool AcquireLock()
- {
- bool ret=false;
- lock(this)
- {
- if (m_lockLevel==0)
- {
- // If lock is already acquired, nop
- m_realStream=m_lockingModel.AcquireLock();
- }
- if (m_realStream!=null)
- {
- m_lockLevel++;
- ret=true;
- }
- }
- return ret;
- }
-
- public void ReleaseLock()
- {
- lock(this)
- {
- m_lockLevel--;
- if (m_lockLevel==0)
- {
- // If already unlocked, nop
- m_lockingModel.ReleaseLock();
- m_realStream=null;
- }
- }
- }
-
- #endregion Locking Methods
- }
-
- #endregion LockingStream Inner Class
-
- #region Locking Models
-
- ///
- /// Locking model base class
- ///
- ///
- ///
- /// Base class for the locking models available to the derived loggers.
- ///
- ///
- public abstract class LockingModelBase
- {
- private FileAppender m_appender=null;
-
- ///
- /// Open the output file
- ///
- /// The filename to use
- /// Whether to append to the file, or overwrite
- /// The encoding to use
- ///
- ///
- /// Open the file specified and prepare for logging.
- /// No writes will be made until is called.
- /// Must be called before any calls to ,
- /// and .
- ///
- ///
- public abstract void OpenFile(string filename, bool append,Encoding encoding);
-
- ///
- /// Close the file
- ///
- ///
- ///
- /// Close the file. No further writes will be made.
- ///
- ///
- public abstract void CloseFile();
-
- ///
- /// Acquire the lock on the file
- ///
- /// A stream that is ready to be written to.
- ///
- ///
- /// Acquire the lock on the file in preparation for writing to it.
- /// Return a stream pointing to the file.
- /// must be called to release the lock on the output file.
- ///
- ///
- public abstract Stream AcquireLock();
-
- ///
- /// Release the lock on the file
- ///
- ///
- ///
- /// Release the lock on the file. No further writes will be made to the
- /// stream until is called again.
- ///
- ///
- public abstract void ReleaseLock();
-
- ///
- /// Gets or sets the for this LockingModel
- ///
- ///
- /// The for this LockingModel
- ///
- ///
- ///
- /// The file appender this locking model is attached to and working on
- /// behalf of.
- ///
- ///
- /// The file appender is used to locate the security context and the error handler to use.
- ///
- ///
- /// The value of this property will be set before is
- /// called.
- ///
- ///
- public FileAppender CurrentAppender
- {
- get { return m_appender; }
- set { m_appender = value; }
- }
-
- ///
- /// Helper method that creates a FileStream under CurrentAppender's SecurityContext.
- ///
- ///
- ///
- /// Typically called during OpenFile or AcquireLock.
- ///
- ///
- /// If the directory portion of the does not exist, it is created
- /// via Directory.CreateDirecctory.
- ///
- ///
- ///
- ///
- ///
- ///
- protected Stream CreateStream(string filename, bool append, FileShare fileShare)
- {
- using (CurrentAppender.SecurityContext.Impersonate(this))
- {
- // Ensure that the directory structure exists
- string directoryFullName = Path.GetDirectoryName(filename);
-
- // Only create the directory if it does not exist
- // doing this check here resolves some permissions failures
- if (!Directory.Exists(directoryFullName))
- {
- Directory.CreateDirectory(directoryFullName);
- }
-
- FileMode fileOpenMode = append ? FileMode.Append : FileMode.Create;
- return new FileStream(filename, fileOpenMode, FileAccess.Write, FileShare.Read);
- }
- }
-
- ///
- /// Helper method to close under CurrentAppender's SecurityContext.
- ///
- ///
- /// Does not set to null.
- ///
- ///
- protected void CloseStream(Stream stream)
- {
- using (CurrentAppender.SecurityContext.Impersonate(this))
- {
- stream.Close();
- }
- }
- }
-
- ///
- /// Hold an exclusive lock on the output file
- ///
- ///
- ///
- /// Open the file once for writing and hold it open until is called.
- /// Maintains an exclusive lock on the file during this time.
- ///
- ///
- public class ExclusiveLock : LockingModelBase
- {
- private Stream m_stream = null;
-
- ///
- /// Open the file specified and prepare for logging.
- ///
- /// The filename to use
- /// Whether to append to the file, or overwrite
- /// The encoding to use
- ///
- ///
- /// Open the file specified and prepare for logging.
- /// No writes will be made until is called.
- /// Must be called before any calls to ,
- /// and .
- ///
- ///
- public override void OpenFile(string filename, bool append,Encoding encoding)
- {
- try
- {
- m_stream = CreateStream(filename, append, FileShare.Read);
- }
- catch (Exception e1)
- {
- CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file "+filename+". "+e1.Message);
- }
- }
-
- ///
- /// Close the file
- ///
- ///
- ///
- /// Close the file. No further writes will be made.
- ///
- ///
- public override void CloseFile()
- {
- CloseStream(m_stream);
- m_stream = null;
- }
-
- ///
- /// Acquire the lock on the file
- ///
- /// A stream that is ready to be written to.
- ///
- ///
- /// Does nothing. The lock is already taken
- ///
- ///
- public override Stream AcquireLock()
- {
- return m_stream;
- }
-
- ///
- /// Release the lock on the file
- ///
- ///
- ///
- /// Does nothing. The lock will be released when the file is closed.
- ///
- ///
- public override void ReleaseLock()
- {
- //NOP
- }
- }
-
- ///
- /// Acquires the file lock for each write
- ///
- ///
- ///
- /// Opens the file once for each / cycle,
- /// thus holding the lock for the minimal amount of time. This method of locking
- /// is considerably slower than but allows
- /// other processes to move/delete the log file whilst logging continues.
- ///
- ///
- public class MinimalLock : LockingModelBase
- {
- private string m_filename;
- private bool m_append;
- private Stream m_stream=null;
-
- ///
- /// Prepares to open the file when the first message is logged.
- ///
- /// The filename to use
- /// Whether to append to the file, or overwrite
- /// The encoding to use
- ///
- ///
- /// Open the file specified and prepare for logging.
- /// No writes will be made until is called.
- /// Must be called before any calls to ,
- /// and .
- ///
- ///
- public override void OpenFile(string filename, bool append, Encoding encoding)
- {
- m_filename=filename;
- m_append=append;
- }
-
- ///
- /// Close the file
- ///
- ///
- ///
- /// Close the file. No further writes will be made.
- ///
- ///
- public override void CloseFile()
- {
- // NOP
- }
-
- ///
- /// Acquire the lock on the file
- ///
- /// A stream that is ready to be written to.
- ///
- ///
- /// Acquire the lock on the file in preparation for writing to it.
- /// Return a stream pointing to the file.
- /// must be called to release the lock on the output file.
- ///
- ///
- public override Stream AcquireLock()
- {
- if (m_stream==null)
- {
- try
- {
- m_stream = CreateStream(m_filename, m_append, FileShare.Read);
- }
- catch (Exception e1)
- {
- CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file "+m_filename+". "+e1.Message);
- }
- }
- return m_stream;
- }
-
- ///
- /// Release the lock on the file
- ///
- ///
- ///
- /// Release the lock on the file. No further writes will be made to the
- /// stream until is called again.
- ///
- ///
- public override void ReleaseLock()
- {
- CloseStream(m_stream);
- m_stream = null;
- }
- }
-
- ///
- /// Provides cross-process file locking.
- ///
- /// Ron Grabowski
- /// Steve Wranovsky
- public class MutexLock : LockingModelBase
- {
- private Mutex m_mutex = null;
- private bool m_mutexClosed = false;
- private Stream m_stream = null;
-
- ///
- /// Open the file specified and prepare for logging.
- ///
- /// The filename to use
- /// Whether to append to the file, or overwrite
- /// The encoding to use
- ///
- ///
- /// Open the file specified and prepare for logging.
- /// No writes will be made until is called.
- /// Must be called before any calls to ,
- /// - and .
- ///
- ///
- public override void OpenFile(string filename, bool append, Encoding encoding)
- {
- try
- {
- m_stream = CreateStream(filename, append, FileShare.ReadWrite);
-
- string mutextFriendlyFilename = filename
- .Replace("\\", "_")
- .Replace(":", "_")
- .Replace("/", "_");
-
- m_mutex = new Mutex(false, mutextFriendlyFilename);
- }
- catch (Exception e1)
- {
- CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + e1.Message);
- }
- }
-
- ///
- /// Close the file
- ///
- ///
- ///
- /// Close the file. No further writes will be made.
- ///
- ///
- public override void CloseFile()
- {
- CloseStream(m_stream);
- m_stream = null;
-
- m_mutex.ReleaseMutex();
- m_mutex.Close();
- m_mutexClosed = true;
- }
-
- ///
- /// Acquire the lock on the file
- ///
- /// A stream that is ready to be written to.
- ///
- ///
- /// Does nothing. The lock is already taken
- ///
- ///
- public override Stream AcquireLock()
- {
- // TODO: add timeout?
- m_mutex.WaitOne();
-
- // should always be true (and fast) for FileStream
- if (m_stream.CanSeek)
- {
- m_stream.Seek(0, SeekOrigin.End);
- }
-
- return m_stream;
- }
-
- ///
- ///
- ///
- public override void ReleaseLock()
- {
- if (m_mutexClosed == false)
- {
- m_mutex.ReleaseMutex();
- }
- }
- }
-
- #endregion Locking Models
-
- #region Public Instance Constructors
-
- ///
- /// Default constructor
- ///
- ///
- ///
- /// Default constructor
- ///
- ///
- public FileAppender()
- {
- }
-
- ///
- /// Construct a new appender using the layout, file and append mode.
- ///
- /// the layout to use with this appender
- /// the full path to the file to write to
- /// flag to indicate if the file should be appended to
- ///
- ///
- /// Obsolete constructor.
- ///
- ///
- [Obsolete("Instead use the default constructor and set the Layout, File & AppendToFile properties")]
- public FileAppender(ILayout layout, string filename, bool append)
- {
- Layout = layout;
- File = filename;
- AppendToFile = append;
- ActivateOptions();
- }
-
- ///
- /// Construct a new appender using the layout and file specified.
- /// The file will be appended to.
- ///
- /// the layout to use with this appender
- /// the full path to the file to write to
- ///
- ///
- /// Obsolete constructor.
- ///
- ///
- [Obsolete("Instead use the default constructor and set the Layout & File properties")]
- public FileAppender(ILayout layout, string filename) : this(layout, filename, true)
- {
- }
-
- #endregion Public Instance Constructors
-
- #region Public Instance Properties
-
- ///
- /// Gets or sets the path to the file that logging will be written to.
- ///
- ///
- /// The path to the file that logging will be written to.
- ///
- ///
- ///
- /// If the path is relative it is taken as relative from
- /// the application base directory.
- ///
- ///
- virtual public string File
- {
- get { return m_fileName; }
- set { m_fileName = value; }
- }
-
- ///
- /// Gets or sets a flag that indicates whether the file should be
- /// appended to or overwritten.
- ///
- ///
- /// Indicates whether the file should be appended to or overwritten.
- ///
- ///
- ///
- /// If the value is set to false then the file will be overwritten, if
- /// it is set to true then the file will be appended to.
- ///
- /// The default value is true.
- ///
- public bool AppendToFile
- {
- get { return m_appendToFile; }
- set { m_appendToFile = value; }
- }
-
- ///
- /// Gets or sets used to write to the file.
- ///
- ///
- /// The used to write to the file.
- ///
- ///
- ///
- /// The default encoding set is
- /// which is the encoding for the system's current ANSI code page.
- ///
- ///
- public Encoding Encoding
- {
- get { return m_encoding; }
- set { m_encoding = value; }
- }
-
- ///
- /// Gets or sets the used to write to the file.
- ///
- ///
- /// The used to write to the file.
- ///
- ///
- ///
- /// Unless a specified here for this appender
- /// the is queried for the
- /// security context to use. The default behavior is to use the security context
- /// of the current thread.
- ///
- ///
- public SecurityContext SecurityContext
- {
- get { return m_securityContext; }
- set { m_securityContext = value; }
- }
-
- ///
- /// Gets or sets the used to handle locking of the file.
- ///
- ///
- /// The used to lock the file.
- ///
- ///
- ///
- /// Gets or sets the used to handle locking of the file.
- ///
- ///
- /// There are two built in locking models, and .
- /// The former locks the file from the start of logging to the end and the
- /// later lock only for the minimal amount of time when logging each message.
- ///
- ///
- /// The default locking model is the .
- ///
- ///
- public FileAppender.LockingModelBase LockingModel
- {
- get { return m_lockingModel; }
- set { m_lockingModel = value; }
- }
-
- #endregion Public Instance Properties
-
- #region Override implementation of AppenderSkeleton
-
- ///
- /// Activate the options on the file appender.
- ///
- ///
- ///
- /// This is part of the delayed object
- /// activation scheme. The method must
- /// be called on this object after the configuration properties have
- /// been set. Until is called this
- /// object is in an undefined state and must not be used.
- ///
- ///
- /// If any of the configuration properties are modified then
- /// must be called again.
- ///
- ///
- /// This will cause the file to be opened.
- ///
- ///
- override public void ActivateOptions()
- {
- base.ActivateOptions();
-
- if (m_securityContext == null)
- {
- m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
- }
-
- if (m_lockingModel == null)
- {
- m_lockingModel = new FileAppender.ExclusiveLock();
- }
-
- m_lockingModel.CurrentAppender=this;
-
- using(SecurityContext.Impersonate(this))
- {
- m_fileName = ConvertToFullPath(m_fileName.Trim());
- }
-
- if (m_fileName != null)
- {
- SafeOpenFile(m_fileName, m_appendToFile);
- }
- else
- {
- LogLog.Warn(declaringType, "FileAppender: File option not set for appender ["+Name+"].");
- LogLog.Warn(declaringType, "FileAppender: Are you using FileAppender instead of ConsoleAppender?");
- }
- }
-
- #endregion Override implementation of AppenderSkeleton
-
- #region Override implementation of TextWriterAppender
-
- ///
- /// Closes any previously opened file and calls the parent's .
- ///
- ///
- ///
- /// Resets the filename and the file stream.
- ///
- ///
- override protected void Reset()
- {
- base.Reset();
- m_fileName = null;
- }
-
- ///
- /// Called to initialize the file writer
- ///
- ///
- ///
- /// Will be called for each logged message until the file is
- /// successfully opened.
- ///
- ///
- override protected void PrepareWriter()
- {
- SafeOpenFile(m_fileName, m_appendToFile);
- }
-
- ///
- /// This method is called by the
- /// method.
- ///
- /// The event to log.
- ///
- ///
- /// Writes a log statement to the output stream if the output stream exists
- /// and is writable.
- ///
- ///
- /// The format of the output will depend on the appender's layout.
- ///
- ///
- override protected void Append(LoggingEvent loggingEvent)
- {
- if (m_stream.AcquireLock())
- {
- try
- {
- base.Append(loggingEvent);
- }
- finally
- {
- m_stream.ReleaseLock();
- }
- }
- }
-
- ///
- /// This method is called by the
- /// method.
- ///
- /// The array of events to log.
- ///
- ///
- /// Acquires the output file locks once before writing all the events to
- /// the stream.
- ///
- ///
- override protected void Append(LoggingEvent[] loggingEvents)
- {
- if (m_stream.AcquireLock())
- {
- try
- {
- base.Append(loggingEvents);
- }
- finally
- {
- m_stream.ReleaseLock();
- }
- }
- }
-
- ///
- /// Writes a footer as produced by the embedded layout's property.
- ///
- ///
- ///
- /// Writes a footer as produced by the embedded layout's property.
- ///
- ///
- protected override void WriteFooter()
- {
- if (m_stream!=null)
- {
- //WriteFooter can be called even before a file is opened
- m_stream.AcquireLock();
- try
- {
- base.WriteFooter();
- }
- finally
- {
- m_stream.ReleaseLock();
- }
- }
- }
-
- ///
- /// Writes a header produced by the embedded layout's property.
- ///
- ///
- ///
- /// Writes a header produced by the embedded layout's property.
- ///
- ///
- protected override void WriteHeader()
- {
- if (m_stream!=null)
- {
- if (m_stream.AcquireLock())
- {
- try
- {
- base.WriteHeader();
- }
- finally
- {
- m_stream.ReleaseLock();
- }
- }
- }
- }
-
- ///
- /// Closes the underlying .
- ///
- ///
- ///
- /// Closes the underlying .
- ///
- ///
- protected override void CloseWriter()
- {
- if (m_stream!=null)
- {
- m_stream.AcquireLock();
- try
- {
- base.CloseWriter();
- }
- finally
- {
- m_stream.ReleaseLock();
- }
- }
- }
-
- #endregion Override implementation of TextWriterAppender
-
- #region Public Instance Methods
-
- ///
- /// Closes the previously opened file.
- ///
- ///
- ///
- /// Writes the to the file and then
- /// closes the file.
- ///
- ///
- protected void CloseFile()
- {
- WriteFooterAndCloseWriter();
- }
-
- #endregion Public Instance Methods
-
- #region Protected Instance Methods
-
- ///
- /// Sets and opens the file where the log output will go. The specified file must be writable.
- ///
- /// The path to the log file. Must be a fully qualified path.
- /// If true will append to fileName. Otherwise will truncate fileName
- ///
- ///
- /// Calls but guarantees not to throw an exception.
- /// Errors are passed to the .
- ///
- ///
- virtual protected void SafeOpenFile(string fileName, bool append)
- {
- try
- {
- OpenFile(fileName, append);
- }
- catch(Exception e)
- {
- ErrorHandler.Error("OpenFile("+fileName+","+append+") call failed.", e, ErrorCode.FileOpenFailure);
- }
- }
-
- ///
- /// Sets and opens the file where the log output will go. The specified file must be writable.
- ///
- /// The path to the log file. Must be a fully qualified path.
- /// If true will append to fileName. Otherwise will truncate fileName
- ///
- ///
- /// If there was already an opened file, then the previous file
- /// is closed first.
- ///
- ///
- /// This method will ensure that the directory structure
- /// for the specified exists.
- ///
- ///
- 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(declaringType, "INTERNAL ERROR. OpenFile("+fileName+"): File name is not fully qualified.");
- }
- }
-
- lock(this)
- {
- Reset();
-
- LogLog.Debug(declaringType, "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();
- }
- }
-
- ///
- /// Sets the quiet writer used for file output
- ///
- /// the file stream that has been opened for writing
- ///
- ///
- /// This implementation of creates a
- /// over the and passes it to the
- /// method.
- ///
- ///
- /// This method can be overridden by sub classes that want to wrap the
- /// in some way, for example to encrypt the output
- /// data using a System.Security.Cryptography.CryptoStream.
- ///
- ///
- virtual protected void SetQWForFiles(Stream fileStream)
- {
- SetQWForFiles(new StreamWriter(fileStream, m_encoding));
- }
-
- ///
- /// Sets the quiet writer being used.
- ///
- /// the writer over the file stream that has been opened for writing
- ///
- ///
- /// This method can be overridden by sub classes that want to
- /// wrap the in some way.
- ///
- ///
- virtual protected void SetQWForFiles(TextWriter writer)
- {
- QuietWriter = new QuietTextWriter(writer, ErrorHandler);
- }
-
- #endregion Protected Instance Methods
-
- #region Protected Static Methods
-
- ///
- /// Convert a path into a fully qualified path.
- ///
- /// The path to convert.
- /// The fully qualified path.
- ///
- ///
- /// Converts the path specified to a fully
- /// qualified path. If the path is relative it is
- /// taken as relative from the application base
- /// directory.
- ///
- ///
- protected static string ConvertToFullPath(string path)
- {
- return SystemInfo.ConvertToFullPath(path);
- }
-
- #endregion Protected Static Methods
-
- #region Private Instance Fields
-
- ///
- /// Flag to indicate if we should append to the file
- /// or overwrite the file. The default is to append.
- ///
- private bool m_appendToFile = true;
-
- ///
- /// The name of the log file.
- ///
- private string m_fileName = null;
-
- ///
- /// The encoding to use for the file stream.
- ///
- private Encoding m_encoding = Encoding.Default;
-
- ///
- /// The security context to use for privileged calls
- ///
- private SecurityContext m_securityContext;
-
- ///
- /// The stream to log to. Has added locking semantics
- ///
- private FileAppender.LockingStream m_stream = null;
-
- ///
- /// The locking model to use
- ///
- private FileAppender.LockingModelBase m_lockingModel = new FileAppender.ExclusiveLock();
-
- #endregion Private Instance Fields
-
- #region Private Static Fields
-
- ///
- /// The fully qualified type of the FileAppender class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(FileAppender);
-
- #endregion Private Static Fields
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using log4net.Util;
+using log4net.Layout;
+using log4net.Core;
+
+namespace log4net.Appender
+{
+#if !NETCF
+ ///
+ /// Appends logging events to a file.
+ ///
+ ///
+ ///
+ /// Logging events are sent to the file specified by
+ /// the property.
+ ///
+ ///
+ /// The file can be opened in either append or overwrite mode
+ /// by specifying the property.
+ /// If the file path is relative it is taken as relative from
+ /// the application base directory. The file encoding can be
+ /// specified by setting the property.
+ ///
+ ///
+ /// The layout's and
+ /// values will be written each time the file is opened and closed
+ /// respectively. If the property is
+ /// then the file may contain multiple copies of the header and footer.
+ ///
+ ///
+ /// This appender will first try to open the file for writing when
+ /// is called. This will typically be during configuration.
+ /// If the file cannot be opened for writing the appender will attempt
+ /// to open the file again each time a message is logged to the appender.
+ /// If the file cannot be opened for writing when a message is logged then
+ /// the message will be discarded by this appender.
+ ///
+ ///
+ /// The supports pluggable file locking models via
+ /// the property.
+ /// The default behavior, implemented by
+ /// is to obtain an exclusive write lock on the file until this appender is closed.
+ /// The alternative models only hold a
+ /// write lock while the appender is writing a logging event ()
+ /// or synchronize by using a named system wide Mutex ().
+ ///
+ ///
+ /// All locking strategies have issues and you should seriously consider using a different strategy that
+ /// avoids having multiple processes logging to the same file.
+ ///
+ ///
+ /// Nicko Cadell
+ /// Gert Driesen
+ /// Rodrigo B. de Oliveira
+ /// Douglas de la Torre
+ /// Niall Daley
+#else
+ ///
+ /// Appends logging events to a file.
+ ///
+ ///
+ ///
+ /// Logging events are sent to the file specified by
+ /// the property.
+ ///
+ ///
+ /// The file can be opened in either append or overwrite mode
+ /// by specifying the property.
+ /// If the file path is relative it is taken as relative from
+ /// the application base directory. The file encoding can be
+ /// specified by setting the property.
+ ///
+ ///
+ /// The layout's and
+ /// values will be written each time the file is opened and closed
+ /// respectively. If the property is
+ /// then the file may contain multiple copies of the header and footer.
+ ///
+ ///
+ /// This appender will first try to open the file for writing when
+ /// is called. This will typically be during configuration.
+ /// If the file cannot be opened for writing the appender will attempt
+ /// to open the file again each time a message is logged to the appender.
+ /// If the file cannot be opened for writing when a message is logged then
+ /// the message will be discarded by this appender.
+ ///
+ ///
+ /// The supports pluggable file locking models via
+ /// the property.
+ /// The default behavior, implemented by
+ /// is to obtain an exclusive write lock on the file until this appender is closed.
+ /// The alternative model only holds a
+ /// write lock while the appender is writing a logging event ().
+ ///
+ ///
+ /// All locking strategies have issues and you should seriously consider using a different strategy that
+ /// avoids having multiple processes logging to the same file.
+ ///
+ ///
+ /// Nicko Cadell
+ /// Gert Driesen
+ /// Rodrigo B. de Oliveira
+ /// Douglas de la Torre
+ /// Niall Daley
+#endif
+ public class FileAppender : TextWriterAppender
+ {
+ #region LockingStream Inner Class
+
+ ///
+ /// Write only that uses the
+ /// to manage access to an underlying resource.
+ ///
+ private sealed class LockingStream : Stream, IDisposable
+ {
+ public sealed class LockStateException : LogException
+ {
+ public LockStateException(string message)
+ : base(message)
+ {
+ }
+ }
+
+ private Stream m_realStream = null;
+ private LockingModelBase m_lockingModel = null;
+ private int m_readTotal = -1;
+ private int m_lockLevel = 0;
+
+ public LockingStream(LockingModelBase locking)
+ : base()
+ {
+ if (locking == null)
+ {
+ throw new ArgumentException("Locking model may not be null", "locking");
+ }
+ m_lockingModel = locking;
+ }
+
+ #region Override Implementation of Stream
+
+ // Methods
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ AssertLocked();
+ IAsyncResult ret = m_realStream.BeginRead(buffer, offset, count, callback, state);
+ m_readTotal = EndRead(ret);
+ return ret;
+ }
+
+ ///
+ /// True asynchronous writes are not supported, the implementation forces a synchronous write.
+ ///
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ AssertLocked();
+ IAsyncResult ret = m_realStream.BeginWrite(buffer, offset, count, callback, state);
+ EndWrite(ret);
+ return ret;
+ }
+
+ public override void Close()
+ {
+ m_lockingModel.CloseFile();
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ AssertLocked();
+ return m_readTotal;
+ }
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ //No-op, it has already been handled
+ }
+ public override void Flush()
+ {
+ AssertLocked();
+ m_realStream.Flush();
+ }
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return m_realStream.Read(buffer, offset, count);
+ }
+ public override int ReadByte()
+ {
+ return m_realStream.ReadByte();
+ }
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ AssertLocked();
+ return m_realStream.Seek(offset, origin);
+ }
+ public override void SetLength(long value)
+ {
+ AssertLocked();
+ m_realStream.SetLength(value);
+ }
+ void IDisposable.Dispose()
+ {
+ Close();
+ }
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ AssertLocked();
+ m_realStream.Write(buffer, offset, count);
+ }
+ public override void WriteByte(byte value)
+ {
+ AssertLocked();
+ m_realStream.WriteByte(value);
+ }
+
+ // Properties
+ public override bool CanRead
+ {
+ get { return false; }
+ }
+ public override bool CanSeek
+ {
+ get
+ {
+ AssertLocked();
+ return m_realStream.CanSeek;
+ }
+ }
+ public override bool CanWrite
+ {
+ get
+ {
+ AssertLocked();
+ return m_realStream.CanWrite;
+ }
+ }
+ public override long Length
+ {
+ get
+ {
+ AssertLocked();
+ return m_realStream.Length;
+ }
+ }
+ public override long Position
+ {
+ get
+ {
+ AssertLocked();
+ return m_realStream.Position;
+ }
+ set
+ {
+ AssertLocked();
+ m_realStream.Position = value;
+ }
+ }
+
+ #endregion Override Implementation of Stream
+
+ #region Locking Methods
+
+ private void AssertLocked()
+ {
+ if (m_realStream == null)
+ {
+ throw new LockStateException("The file is not currently locked");
+ }
+ }
+
+ public bool AcquireLock()
+ {
+ bool ret = false;
+ lock (this)
+ {
+ if (m_lockLevel == 0)
+ {
+ // If lock is already acquired, nop
+ m_realStream = m_lockingModel.AcquireLock();
+ }
+ if (m_realStream != null)
+ {
+ m_lockLevel++;
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+ public void ReleaseLock()
+ {
+ lock (this)
+ {
+ m_lockLevel--;
+ if (m_lockLevel == 0)
+ {
+ // If already unlocked, nop
+ m_lockingModel.ReleaseLock();
+ m_realStream = null;
+ }
+ }
+ }
+
+ #endregion Locking Methods
+ }
+
+ #endregion LockingStream Inner Class
+
+ #region Locking Models
+
+ ///
+ /// Locking model base class
+ ///
+ ///
+ ///
+ /// Base class for the locking models available to the derived loggers.
+ ///
+ ///
+ public abstract class LockingModelBase
+ {
+ private FileAppender m_appender = null;
+
+ ///
+ /// Open the output file
+ ///
+ /// The filename to use
+ /// Whether to append to the file, or overwrite
+ /// The encoding to use
+ ///
+ ///
+ /// Open the file specified and prepare for logging.
+ /// No writes will be made until is called.
+ /// Must be called before any calls to ,
+ /// and .
+ ///
+ ///
+ public abstract void OpenFile(string filename, bool append, Encoding encoding);
+
+ ///
+ /// Close the file
+ ///
+ ///
+ ///
+ /// Close the file. No further writes will be made.
+ ///
+ ///
+ public abstract void CloseFile();
+
+ ///
+ /// Initializes all resources used by this locking model.
+ ///
+ public abstract void ActivateOptions();
+
+ ///
+ /// Disposes all resources that were initialized by this locking model.
+ ///
+ public abstract void OnClose();
+
+ ///
+ /// Acquire the lock on the file
+ ///
+ /// A stream that is ready to be written to.
+ ///
+ ///
+ /// Acquire the lock on the file in preparation for writing to it.
+ /// Return a stream pointing to the file.
+ /// must be called to release the lock on the output file.
+ ///
+ ///
+ public abstract Stream AcquireLock();
+
+ ///
+ /// Release the lock on the file
+ ///
+ ///
+ ///
+ /// Release the lock on the file. No further writes will be made to the
+ /// stream until is called again.
+ ///
+ ///
+ public abstract void ReleaseLock();
+
+ ///
+ /// Gets or sets the for this LockingModel
+ ///
+ ///
+ /// The for this LockingModel
+ ///
+ ///
+ ///
+ /// The file appender this locking model is attached to and working on
+ /// behalf of.
+ ///
+ ///
+ /// The file appender is used to locate the security context and the error handler to use.
+ ///
+ ///
+ /// The value of this property will be set before is
+ /// called.
+ ///
+ ///
+ public FileAppender CurrentAppender
+ {
+ get { return m_appender; }
+ set { m_appender = value; }
+ }
+
+ ///
+ /// Helper method that creates a FileStream under CurrentAppender's SecurityContext.
+ ///
+ ///
+ ///
+ /// Typically called during OpenFile or AcquireLock.
+ ///
+ ///
+ /// If the directory portion of the does not exist, it is created
+ /// via Directory.CreateDirecctory.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected Stream CreateStream(string filename, bool append, FileShare fileShare)
+ {
+ using (CurrentAppender.SecurityContext.Impersonate(this))
+ {
+ // Ensure that the directory structure exists
+ string directoryFullName = Path.GetDirectoryName(filename);
+
+ // Only create the directory if it does not exist
+ // doing this check here resolves some permissions failures
+ if (!Directory.Exists(directoryFullName))
+ {
+ Directory.CreateDirectory(directoryFullName);
+ }
+
+ FileMode fileOpenMode = append ? FileMode.Append : FileMode.Create;
+ return new FileStream(filename, fileOpenMode, FileAccess.Write, fileShare);
+ }
+ }
+
+ ///
+ /// Helper method to close under CurrentAppender's SecurityContext.
+ ///
+ ///
+ /// Does not set to null.
+ ///
+ ///
+ protected void CloseStream(Stream stream)
+ {
+ using (CurrentAppender.SecurityContext.Impersonate(this))
+ {
+ stream.Close();
+ }
+ }
+ }
+
+ ///
+ /// Hold an exclusive lock on the output file
+ ///
+ ///
+ ///
+ /// Open the file once for writing and hold it open until is called.
+ /// Maintains an exclusive lock on the file during this time.
+ ///
+ ///
+ public class ExclusiveLock : LockingModelBase
+ {
+ private Stream m_stream = null;
+
+ ///
+ /// Open the file specified and prepare for logging.
+ ///
+ /// The filename to use
+ /// Whether to append to the file, or overwrite
+ /// The encoding to use
+ ///
+ ///
+ /// Open the file specified and prepare for logging.
+ /// No writes will be made until is called.
+ /// Must be called before any calls to ,
+ /// and .
+ ///
+ ///
+ public override void OpenFile(string filename, bool append, Encoding encoding)
+ {
+ try
+ {
+ m_stream = CreateStream(filename, append, FileShare.Read);
+ }
+ catch (Exception e1)
+ {
+ CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + e1.Message);
+ }
+ }
+
+ ///
+ /// Close the file
+ ///
+ ///
+ ///
+ /// Close the file. No further writes will be made.
+ ///
+ ///
+ public override void CloseFile()
+ {
+ CloseStream(m_stream);
+ m_stream = null;
+ }
+
+ ///
+ /// Acquire the lock on the file
+ ///
+ /// A stream that is ready to be written to.
+ ///
+ ///
+ /// Does nothing. The lock is already taken
+ ///
+ ///
+ public override Stream AcquireLock()
+ {
+ return m_stream;
+ }
+
+ ///
+ /// Release the lock on the file
+ ///
+ ///
+ ///
+ /// Does nothing. The lock will be released when the file is closed.
+ ///
+ ///
+ public override void ReleaseLock()
+ {
+ //NOP
+ }
+
+ ///
+ /// Initializes all resources used by this locking model.
+ ///
+ public override void ActivateOptions()
+ {
+ //NOP
+ }
+
+ ///
+ /// Disposes all resources that were initialized by this locking model.
+ ///
+ public override void OnClose()
+ {
+ //NOP
+ }
+ }
+
+ ///
+ /// Acquires the file lock for each write
+ ///
+ ///
+ ///
+ /// Opens the file once for each / cycle,
+ /// thus holding the lock for the minimal amount of time. This method of locking
+ /// is considerably slower than but allows
+ /// other processes to move/delete the log file whilst logging continues.
+ ///
+ ///
+ public class MinimalLock : LockingModelBase
+ {
+ private string m_filename;
+ private bool m_append;
+ private Stream m_stream = null;
+
+ ///
+ /// Prepares to open the file when the first message is logged.
+ ///
+ /// The filename to use
+ /// Whether to append to the file, or overwrite
+ /// The encoding to use
+ ///
+ ///
+ /// Open the file specified and prepare for logging.
+ /// No writes will be made until is called.
+ /// Must be called before any calls to ,
+ /// and .
+ ///
+ ///
+ public override void OpenFile(string filename, bool append, Encoding encoding)
+ {
+ m_filename = filename;
+ m_append = append;
+ }
+
+ ///
+ /// Close the file
+ ///
+ ///
+ ///
+ /// Close the file. No further writes will be made.
+ ///
+ ///
+ public override void CloseFile()
+ {
+ // NOP
+ }
+
+ ///
+ /// Acquire the lock on the file
+ ///
+ /// A stream that is ready to be written to.
+ ///
+ ///
+ /// Acquire the lock on the file in preparation for writing to it.
+ /// Return a stream pointing to the file.
+ /// must be called to release the lock on the output file.
+ ///
+ ///
+ public override Stream AcquireLock()
+ {
+ if (m_stream == null)
+ {
+ try
+ {
+ m_stream = CreateStream(m_filename, m_append, FileShare.Read);
+ m_append = true;
+ }
+ catch (Exception e1)
+ {
+ CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + m_filename + ". " + e1.Message);
+ }
+ }
+ return m_stream;
+ }
+
+ ///
+ /// Release the lock on the file
+ ///
+ ///
+ ///
+ /// Release the lock on the file. No further writes will be made to the
+ /// stream until is called again.
+ ///
+ ///
+ public override void ReleaseLock()
+ {
+ CloseStream(m_stream);
+ m_stream = null;
+ }
+
+ ///
+ /// Initializes all resources used by this locking model.
+ ///
+ public override void ActivateOptions()
+ {
+ //NOP
+ }
+
+ ///
+ /// Disposes all resources that were initialized by this locking model.
+ ///
+ public override void OnClose()
+ {
+ //NOP
+ }
+ }
+
+#if !NETCF
+ ///
+ /// Provides cross-process file locking.
+ ///
+ /// Ron Grabowski
+ /// Steve Wranovsky
+ public class InterProcessLock : LockingModelBase
+ {
+ private Mutex m_mutex = null;
+ private Stream m_stream = null;
+ private int m_recursiveWatch = 0;
+
+ ///
+ /// Open the file specified and prepare for logging.
+ ///
+ /// The filename to use
+ /// Whether to append to the file, or overwrite
+ /// The encoding to use
+ ///
+ ///
+ /// Open the file specified and prepare for logging.
+ /// No writes will be made until is called.
+ /// Must be called before any calls to ,
+ /// - and .
+ ///
+ ///
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override void OpenFile(string filename, bool append, Encoding encoding)
+ {
+ try
+ {
+ m_stream = CreateStream(filename, append, FileShare.ReadWrite);
+ }
+ catch (Exception e1)
+ {
+ CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + e1.Message);
+ }
+ }
+
+ ///
+ /// Close the file
+ ///
+ ///
+ ///
+ /// Close the file. No further writes will be made.
+ ///
+ ///
+ public override void CloseFile()
+ {
+ try
+ {
+ CloseStream(m_stream);
+ m_stream = null;
+ }
+ finally
+ {
+ ReleaseLock();
+ }
+ }
+
+ ///
+ /// Acquire the lock on the file
+ ///
+ /// A stream that is ready to be written to.
+ ///
+ ///
+ /// Does nothing. The lock is already taken
+ ///
+ ///
+ public override Stream AcquireLock()
+ {
+ if (m_mutex != null)
+ {
+ // TODO: add timeout?
+ m_mutex.WaitOne();
+
+ // increment recursive watch
+ m_recursiveWatch++;
+
+ // should always be true (and fast) for FileStream
+ if (m_stream != null)
+ {
+ if (m_stream.CanSeek)
+ {
+ m_stream.Seek(0, SeekOrigin.End);
+ }
+ }
+ else
+ {
+ // this can happen when the file appender cannot open a file for writing
+ }
+ }
+ else
+ {
+ CurrentAppender.ErrorHandler.Error("Programming error, no mutex available to acquire lock! From here on things will be dangerous!");
+ }
+ return m_stream;
+ }
+
+ ///
+ /// Releases the lock and allows others to acquire a lock.
+ ///
+ public override void ReleaseLock()
+ {
+ if (m_mutex != null)
+ {
+ if (m_recursiveWatch > 0)
+ {
+ m_recursiveWatch--;
+ m_mutex.ReleaseMutex();
+ }
+ }
+ else
+ {
+ CurrentAppender.ErrorHandler.Error("Programming error, no mutex available to release the lock!");
+ }
+ }
+
+ ///
+ /// Initializes all resources used by this locking model.
+ ///
+ public override void ActivateOptions()
+ {
+ if (m_mutex == null)
+ {
+ string mutexFriendlyFilename = CurrentAppender.File
+ .Replace("\\", "_")
+ .Replace(":", "_")
+ .Replace("/", "_");
+
+ m_mutex = new Mutex(false, mutexFriendlyFilename);
+ }
+ else
+ {
+ CurrentAppender.ErrorHandler.Error("Programming error, mutex already initialized!");
+ }
+ }
+
+ ///
+ /// Disposes all resources that were initialized by this locking model.
+ ///
+ public override void OnClose()
+ {
+ if (m_mutex != null)
+ {
+ m_mutex.Close();
+ m_mutex = null;
+ }
+ else
+ {
+ CurrentAppender.ErrorHandler.Error("Programming error, mutex not initialized!");
+ }
+ }
+ }
+#endif
+
+ #endregion Locking Models
+
+ #region Public Instance Constructors
+
+ ///
+ /// Default constructor
+ ///
+ ///
+ ///
+ /// Default constructor
+ ///
+ ///
+ public FileAppender()
+ {
+ }
+
+ ///
+ /// Construct a new appender using the layout, file and append mode.
+ ///
+ /// the layout to use with this appender
+ /// the full path to the file to write to
+ /// flag to indicate if the file should be appended to
+ ///
+ ///
+ /// Obsolete constructor.
+ ///
+ ///
+ [Obsolete("Instead use the default constructor and set the Layout, File & AppendToFile properties")]
+ public FileAppender(ILayout layout, string filename, bool append)
+ {
+ Layout = layout;
+ File = filename;
+ AppendToFile = append;
+ ActivateOptions();
+ }
+
+ ///
+ /// Construct a new appender using the layout and file specified.
+ /// The file will be appended to.
+ ///
+ /// the layout to use with this appender
+ /// the full path to the file to write to
+ ///
+ ///
+ /// Obsolete constructor.
+ ///
+ ///
+ [Obsolete("Instead use the default constructor and set the Layout & File properties")]
+ public FileAppender(ILayout layout, string filename)
+ : this(layout, filename, true)
+ {
+ }
+
+ #endregion Public Instance Constructors
+
+ #region Public Instance Properties
+
+ ///
+ /// Gets or sets the path to the file that logging will be written to.
+ ///
+ ///
+ /// The path to the file that logging will be written to.
+ ///
+ ///
+ ///
+ /// If the path is relative it is taken as relative from
+ /// the application base directory.
+ ///
+ ///
+ virtual public string File
+ {
+ get { return m_fileName; }
+ set { m_fileName = value; }
+ }
+
+ ///
+ /// Gets or sets a flag that indicates whether the file should be
+ /// appended to or overwritten.
+ ///
+ ///
+ /// Indicates whether the file should be appended to or overwritten.
+ ///
+ ///
+ ///
+ /// If the value is set to false then the file will be overwritten, if
+ /// it is set to true then the file will be appended to.
+ ///
+ /// The default value is true.
+ ///
+ public bool AppendToFile
+ {
+ get { return m_appendToFile; }
+ set { m_appendToFile = value; }
+ }
+
+ ///
+ /// Gets or sets used to write to the file.
+ ///
+ ///
+ /// The used to write to the file.
+ ///
+ ///
+ ///
+ /// The default encoding set is
+ /// which is the encoding for the system's current ANSI code page.
+ ///
+ ///
+ public Encoding Encoding
+ {
+ get { return m_encoding; }
+ set { m_encoding = value; }
+ }
+
+ ///
+ /// Gets or sets the used to write to the file.
+ ///
+ ///
+ /// The used to write to the file.
+ ///
+ ///
+ ///
+ /// Unless a specified here for this appender
+ /// the is queried for the
+ /// security context to use. The default behavior is to use the security context
+ /// of the current thread.
+ ///
+ ///
+ public SecurityContext SecurityContext
+ {
+ get { return m_securityContext; }
+ set { m_securityContext = value; }
+ }
+
+#if NETCF
+ ///
+ /// Gets or sets the used to handle locking of the file.
+ ///
+ ///
+ /// The used to lock the file.
+ ///
+ ///
+ ///
+ /// Gets or sets the used to handle locking of the file.
+ ///
+ ///
+ /// There are two built in locking models, and .
+ /// The first locks the file from the start of logging to the end, the
+ /// second locks only for the minimal amount of time when logging each message
+ /// and the last synchronizes processes using a named system wide Mutex.
+ ///
+ ///
+ /// The default locking model is the .
+ ///
+ ///
+#else
+ ///
+ /// Gets or sets the used to handle locking of the file.
+ ///
+ ///
+ /// The used to lock the file.
+ ///
+ ///
+ ///
+ /// Gets or sets the used to handle locking of the file.
+ ///
+ ///
+ /// There are three built in locking models, , and .
+ /// The first locks the file from the start of logging to the end, the
+ /// second locks only for the minimal amount of time when logging each message
+ /// and the last synchronizes processes using a named system wide Mutex.
+ ///
+ ///
+ /// The default locking model is the .
+ ///
+ ///
+#endif
+ public FileAppender.LockingModelBase LockingModel
+ {
+ get { return m_lockingModel; }
+ set { m_lockingModel = value; }
+ }
+
+ #endregion Public Instance Properties
+
+ #region Override implementation of AppenderSkeleton
+
+ ///
+ /// Activate the options on the file appender.
+ ///
+ ///
+ ///
+ /// This is part of the delayed object
+ /// activation scheme. The method must
+ /// be called on this object after the configuration properties have
+ /// been set. Until is called this
+ /// object is in an undefined state and must not be used.
+ ///
+ ///
+ /// If any of the configuration properties are modified then
+ /// must be called again.
+ ///
+ ///
+ /// This will cause the file to be opened.
+ ///
+ ///
+ override public void ActivateOptions()
+ {
+ base.ActivateOptions();
+
+ if (m_securityContext == null)
+ {
+ m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
+ }
+
+ if (m_lockingModel == null)
+ {
+ m_lockingModel = new FileAppender.ExclusiveLock();
+ }
+
+ m_lockingModel.CurrentAppender = this;
+ m_lockingModel.ActivateOptions();
+
+ if (m_fileName != null)
+ {
+ using (SecurityContext.Impersonate(this))
+ {
+ m_fileName = ConvertToFullPath(m_fileName.Trim());
+ }
+ SafeOpenFile(m_fileName, m_appendToFile);
+ }
+ else
+ {
+ LogLog.Warn(declaringType, "FileAppender: File option not set for appender [" + Name + "].");
+ LogLog.Warn(declaringType, "FileAppender: Are you using FileAppender instead of ConsoleAppender?");
+ }
+ }
+
+ #endregion Override implementation of AppenderSkeleton
+
+ #region Override implementation of TextWriterAppender
+
+ ///
+ /// Closes any previously opened file and calls the parent's .
+ ///
+ ///
+ ///
+ /// Resets the filename and the file stream.
+ ///
+ ///
+ override protected void Reset()
+ {
+ base.Reset();
+ m_fileName = null;
+ }
+
+ ///
+ /// Close this appender instance. The underlying stream or writer is also closed.
+ ///
+ override protected void OnClose()
+ {
+ base.OnClose();
+ m_lockingModel.OnClose();
+ }
+
+ ///
+ /// Called to initialize the file writer
+ ///
+ ///
+ ///
+ /// Will be called for each logged message until the file is
+ /// successfully opened.
+ ///
+ ///
+ override protected void PrepareWriter()
+ {
+ SafeOpenFile(m_fileName, m_appendToFile);
+ }
+
+ ///
+ /// This method is called by the
+ /// method.
+ ///
+ /// The event to log.
+ ///
+ ///
+ /// Writes a log statement to the output stream if the output stream exists
+ /// and is writable.
+ ///
+ ///
+ /// The format of the output will depend on the appender's layout.
+ ///
+ ///
+ override protected void Append(LoggingEvent loggingEvent)
+ {
+ if (m_stream.AcquireLock())
+ {
+ try
+ {
+ base.Append(loggingEvent);
+ }
+ finally
+ {
+ m_stream.ReleaseLock();
+ }
+ }
+ }
+
+ ///
+ /// This method is called by the
+ /// method.
+ ///
+ /// The array of events to log.
+ ///
+ ///
+ /// Acquires the output file locks once before writing all the events to
+ /// the stream.
+ ///
+ ///
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ if (m_stream.AcquireLock())
+ {
+ try
+ {
+ base.Append(loggingEvents);
+ }
+ finally
+ {
+ m_stream.ReleaseLock();
+ }
+ }
+ }
+
+ ///
+ /// Writes a footer as produced by the embedded layout's property.
+ ///
+ ///
+ ///
+ /// Writes a footer as produced by the embedded layout's property.
+ ///
+ ///
+ protected override void WriteFooter()
+ {
+ if (m_stream != null)
+ {
+ //WriteFooter can be called even before a file is opened
+ m_stream.AcquireLock();
+ try
+ {
+ base.WriteFooter();
+ }
+ finally
+ {
+ m_stream.ReleaseLock();
+ }
+ }
+ }
+
+ ///
+ /// Writes a header produced by the embedded layout's property.
+ ///
+ ///
+ ///
+ /// Writes a header produced by the embedded layout's property.
+ ///
+ ///
+ protected override void WriteHeader()
+ {
+ if (m_stream != null)
+ {
+ if (m_stream.AcquireLock())
+ {
+ try
+ {
+ base.WriteHeader();
+ }
+ finally
+ {
+ m_stream.ReleaseLock();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Closes the underlying .
+ ///
+ ///
+ ///
+ /// Closes the underlying .
+ ///
+ ///
+ protected override void CloseWriter()
+ {
+ if (m_stream != null)
+ {
+ m_stream.AcquireLock();
+ try
+ {
+ base.CloseWriter();
+ }
+ finally
+ {
+ m_stream.ReleaseLock();
+ }
+ }
+ }
+
+ #endregion Override implementation of TextWriterAppender
+
+ #region Public Instance Methods
+
+ ///
+ /// Closes the previously opened file.
+ ///
+ ///
+ ///
+ /// Writes the to the file and then
+ /// closes the file.
+ ///
+ ///
+ protected void CloseFile()
+ {
+ WriteFooterAndCloseWriter();
+ }
+
+ #endregion Public Instance Methods
+
+ #region Protected Instance Methods
+
+ ///
+ /// Sets and opens the file where the log output will go. The specified file must be writable.
+ ///
+ /// The path to the log file. Must be a fully qualified path.
+ /// If true will append to fileName. Otherwise will truncate fileName
+ ///
+ ///
+ /// Calls but guarantees not to throw an exception.
+ /// Errors are passed to the .
+ ///
+ ///
+ virtual protected void SafeOpenFile(string fileName, bool append)
+ {
+ try
+ {
+ OpenFile(fileName, append);
+ }
+ catch (Exception e)
+ {
+ ErrorHandler.Error("OpenFile(" + fileName + "," + append + ") call failed.", e, ErrorCode.FileOpenFailure);
+ }
+ }
+
+ ///
+ /// Sets and opens the file where the log output will go. The specified file must be writable.
+ ///
+ /// The path to the log file. Must be a fully qualified path.
+ /// If true will append to fileName. Otherwise will truncate fileName
+ ///
+ ///
+ /// If there was already an opened file, then the previous file
+ /// is closed first.
+ ///
+ ///
+ /// This method will ensure that the directory structure
+ /// for the specified exists.
+ ///
+ ///
+ 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(declaringType, "INTERNAL ERROR. OpenFile(" + fileName + "): File name is not fully qualified.");
+ }
+ }
+
+ lock (this)
+ {
+ Reset();
+
+ LogLog.Debug(declaringType, "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();
+ }
+ }
+
+ ///
+ /// Sets the quiet writer used for file output
+ ///
+ /// the file stream that has been opened for writing
+ ///
+ ///
+ /// This implementation of creates a
+ /// over the and passes it to the
+ /// method.
+ ///
+ ///
+ /// This method can be overridden by sub classes that want to wrap the
+ /// in some way, for example to encrypt the output
+ /// data using a System.Security.Cryptography.CryptoStream.
+ ///
+ ///
+ virtual protected void SetQWForFiles(Stream fileStream)
+ {
+ SetQWForFiles(new StreamWriter(fileStream, m_encoding));
+ }
+
+ ///
+ /// Sets the quiet writer being used.
+ ///
+ /// the writer over the file stream that has been opened for writing
+ ///
+ ///
+ /// This method can be overridden by sub classes that want to
+ /// wrap the in some way.
+ ///
+ ///
+ virtual protected void SetQWForFiles(TextWriter writer)
+ {
+ QuietWriter = new QuietTextWriter(writer, ErrorHandler);
+ }
+
+ #endregion Protected Instance Methods
+
+ #region Protected Static Methods
+
+ ///
+ /// Convert a path into a fully qualified path.
+ ///
+ /// The path to convert.
+ /// The fully qualified path.
+ ///
+ ///
+ /// Converts the path specified to a fully
+ /// qualified path. If the path is relative it is
+ /// taken as relative from the application base
+ /// directory.
+ ///
+ ///
+ protected static string ConvertToFullPath(string path)
+ {
+ return SystemInfo.ConvertToFullPath(path);
+ }
+
+ #endregion Protected Static Methods
+
+ #region Private Instance Fields
+
+ ///
+ /// Flag to indicate if we should append to the file
+ /// or overwrite the file. The default is to append.
+ ///
+ private bool m_appendToFile = true;
+
+ ///
+ /// The name of the log file.
+ ///
+ private string m_fileName = null;
+
+ ///
+ /// The encoding to use for the file stream.
+ ///
+ private Encoding m_encoding = Encoding.Default;
+
+ ///
+ /// The security context to use for privileged calls
+ ///
+ private SecurityContext m_securityContext;
+
+ ///
+ /// The stream to log to. Has added locking semantics
+ ///
+ private FileAppender.LockingStream m_stream = null;
+
+ ///
+ /// The locking model to use
+ ///
+ private FileAppender.LockingModelBase m_lockingModel = new FileAppender.ExclusiveLock();
+
+ #endregion Private Instance Fields
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the FileAppender class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(FileAppender);
+
+ #endregion Private Static Fields
+ }
+}
diff --git a/src/Appender/ForwardingAppender.cs b/src/Appender/ForwardingAppender.cs
old mode 100755
new mode 100644
diff --git a/src/Appender/IAppender.cs b/src/Appender/IAppender.cs
old mode 100755
new mode 100644
index 88ec426e..a644f072
--- a/src/Appender/IAppender.cs
+++ b/src/Appender/IAppender.cs
@@ -33,7 +33,7 @@ namespace log4net.Appender
///
///
/// Appenders can also implement the interface. Therefore
- /// they would require that the method
+ /// they would require that the method
/// be called after the appenders properties have been configured.
///
///
diff --git a/src/Appender/IBulkAppender.cs b/src/Appender/IBulkAppender.cs
old mode 100755
new mode 100644
diff --git a/src/Appender/LocalSyslogAppender.cs b/src/Appender/LocalSyslogAppender.cs
old mode 100755
new mode 100644
index e5b4f4bd..e31b1ca3
--- a/src/Appender/LocalSyslogAppender.cs
+++ b/src/Appender/LocalSyslogAppender.cs
@@ -337,7 +337,10 @@ public void AddMapping(LevelSeverity mapping)
/// must be called again.
///
///
- public override void ActivateOptions()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override void ActivateOptions()
{
base.ActivateOptions();
@@ -364,7 +367,7 @@ public override void ActivateOptions()
#region AppenderSkeleton Implementation
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
@@ -375,7 +378,11 @@ public override void ActivateOptions()
/// The format of the output will depend on the appender's layout.
///
///
- protected override void Append(LoggingEvent loggingEvent)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)]
+ protected override void Append(LoggingEvent loggingEvent)
{
int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
string message = RenderLoggingEvent(loggingEvent);
@@ -393,7 +400,10 @@ protected override void Append(LoggingEvent loggingEvent)
/// Close the syslog when the appender is closed
///
///
- protected override void OnClose()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ protected override void OnClose()
{
base.OnClose();
diff --git a/src/Appender/ManagedColoredConsoleAppender.cs b/src/Appender/ManagedColoredConsoleAppender.cs
new file mode 100644
index 00000000..a1a06ac1
--- /dev/null
+++ b/src/Appender/ManagedColoredConsoleAppender.cs
@@ -0,0 +1,348 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+// Compatibility:
+// http://msdn.microsoft.com/en-us/library/system.console.foregroundcolor.aspx
+// Disable for unsupported targets
+#if !NETCF
+#if !SSCLI
+#if !CLI_1_0
+#if !MONO_1_0
+#if !NET_1_0
+#if !NET_1_1
+
+// The original ColoredConsoleAppender was written before the .NET framework
+// (and Mono) had built-in support for console colors so it was written using
+// Win32 API calls. The AnsiColorTerminalAppender, while it works, isn't
+// understood by the Windows command prompt.
+// This is a replacement for both that uses the new (.NET 2) Console colors
+// and works on both platforms.
+
+// On Mono/Linux (at least), setting the background color to 'Black' is
+// not the same as the default background color, as it is after
+// Console.Reset(). The difference becomes apparent while running in a
+// terminal application that supports background transparency; the
+// default color is treated as transparent while 'Black' isn't.
+// For this reason, we always reset the colors and only set those
+// explicitly specified in the configuration (Console.BackgroundColor
+// isn't set if ommited).
+
+using System;
+using log4net.Layout;
+using log4net.Util;
+using System.Globalization;
+
+namespace log4net.Appender
+{
+ ///
+ /// Appends colorful logging events to the console, using the .NET 2
+ /// built-in capabilities.
+ ///
+ ///
+ ///
+ /// ManagedColoredConsoleAppender appends log events to the standard output stream
+ /// or the error output stream using a layout specified by the
+ /// user. It also allows the color of a specific type of message to be set.
+ ///
+ ///
+ /// By default, all output is written to the console's standard output stream.
+ /// The property can be set to direct the output to the
+ /// error stream.
+ ///
+ ///
+ /// When configuring the colored console appender, mappings should be
+ /// specified to map logging levels to colors. For example:
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// The Level is the standard log4net logging level while
+ /// ForeColor and BackColor are the values of
+ /// enumeration.
+ ///
+ ///
+ /// Based on the ColoredConsoleAppender
+ ///
+ ///
+ /// Rick Hobbs
+ /// Nicko Cadell
+ /// Pavlos Touboulidis
+ public class ManagedColoredConsoleAppender: AppenderSkeleton
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The instance of the class is set up to write
+ /// to the standard output stream.
+ ///
+ public ManagedColoredConsoleAppender()
+ {
+ }
+
+ #region Public Instance Properties
+ ///
+ /// Target is the value of the console output stream.
+ /// This is either "Console.Out" or "Console.Error".
+ ///
+ ///
+ /// Target is the value of the console output stream.
+ /// This is either "Console.Out" or "Console.Error".
+ ///
+ ///
+ ///
+ /// Target is the value of the console output stream.
+ /// This is either "Console.Out" or "Console.Error".
+ ///
+ ///
+ virtual public string Target
+ {
+ get { return m_writeToErrorStream ? ConsoleError : ConsoleOut; }
+ set
+ {
+ string v = value.Trim();
+
+ if (string.Compare(ConsoleError, v, true, CultureInfo.InvariantCulture) == 0)
+ {
+ m_writeToErrorStream = true;
+ }
+ else
+ {
+ m_writeToErrorStream = false;
+ }
+ }
+ }
+
+ ///
+ /// Add a mapping of level to color - done by the config file
+ ///
+ /// The mapping to add
+ ///
+ ///
+ /// Add a mapping to this appender.
+ /// Each mapping defines the foreground and background colors
+ /// for a level.
+ ///
+ ///
+ public void AddMapping(LevelColors mapping)
+ {
+ m_levelMapping.Add(mapping);
+ }
+ #endregion // Public Instance Properties
+
+ #region Override implementation of AppenderSkeleton
+ ///
+ /// This method is called by the method.
+ ///
+ /// The event to log.
+ ///
+ ///
+ /// Writes the event to the console.
+ ///
+ ///
+ /// The format of the output will depend on the appender's layout.
+ ///
+ ///
+ override protected void Append(log4net.Core.LoggingEvent loggingEvent)
+ {
+ System.IO.TextWriter writer;
+
+ if (m_writeToErrorStream)
+ writer = Console.Error;
+ else
+ writer = Console.Out;
+
+ // Reset color
+ Console.ResetColor();
+
+ // see if there is a specified lookup
+ LevelColors levelColors = m_levelMapping.Lookup(loggingEvent.Level) as LevelColors;
+ if (levelColors != null)
+ {
+ // if the backColor has been explicitly set
+ if (levelColors.HasBackColor)
+ Console.BackgroundColor = levelColors.BackColor;
+ // if the foreColor has been explicitly set
+ if (levelColors.HasForeColor)
+ Console.ForegroundColor = levelColors.ForeColor;
+ }
+
+ // Render the event to a string
+ string strLoggingMessage = RenderLoggingEvent(loggingEvent);
+ // and write it
+ writer.Write(strLoggingMessage);
+
+ // Reset color again
+ Console.ResetColor();
+ }
+
+ ///
+ /// This appender requires a to be set.
+ ///
+ /// true
+ ///
+ ///
+ /// This appender requires a to be set.
+ ///
+ ///
+ override protected bool RequiresLayout
+ {
+ get { return true; }
+ }
+
+ ///
+ /// Initialize the options for this appender
+ ///
+ ///
+ ///
+ /// Initialize the level to color mappings set on this appender.
+ ///
+ ///
+ public override void ActivateOptions()
+ {
+ base.ActivateOptions();
+ m_levelMapping.ActivateOptions();
+ }
+ #endregion // Override implementation of AppenderSkeleton
+
+ #region Public Static Fields
+ ///
+ /// The to use when writing to the Console
+ /// standard output stream.
+ ///
+ ///
+ ///
+ /// The to use when writing to the Console
+ /// standard output stream.
+ ///
+ ///
+ public const string ConsoleOut = "Console.Out";
+
+ ///
+ /// The to use when writing to the Console
+ /// standard error output stream.
+ ///
+ ///
+ ///
+ /// The to use when writing to the Console
+ /// standard error output stream.
+ ///
+ ///
+ public const string ConsoleError = "Console.Error";
+ #endregion // Public Static Fields
+
+ #region Private Instances Fields
+ ///
+ /// Flag to write output to the error stream rather than the standard output stream
+ ///
+ private bool m_writeToErrorStream = false;
+
+ ///
+ /// Mapping from level object to color value
+ ///
+ private LevelMapping m_levelMapping = new LevelMapping();
+ #endregion // Private Instances Fields
+
+ #region LevelColors LevelMapping Entry
+ ///
+ /// A class to act as a mapping between the level that a logging call is made at and
+ /// the color it should be displayed as.
+ ///
+ ///
+ ///
+ /// Defines the mapping between a level and the color it should be displayed in.
+ ///
+ ///
+ public class LevelColors : LevelMappingEntry
+ {
+ ///
+ /// The mapped foreground color for the specified level
+ ///
+ ///
+ ///
+ /// Required property.
+ /// The mapped foreground color for the specified level.
+ ///
+ ///
+ public ConsoleColor ForeColor
+ {
+ get { return (this.foreColor); }
+ // Keep a flag that the color has been set
+ // and is no longer the default.
+ set { this.foreColor = value; this.hasForeColor = true; }
+ }
+ private ConsoleColor foreColor;
+ private bool hasForeColor;
+ internal bool HasForeColor {
+ get {
+ return hasForeColor;
+ }
+ }
+
+ ///
+ /// The mapped background color for the specified level
+ ///
+ ///
+ ///
+ /// Required property.
+ /// The mapped background color for the specified level.
+ ///
+ ///
+ public ConsoleColor BackColor
+ {
+ get { return (this.backColor); }
+ // Keep a flag that the color has been set
+ // and is no longer the default.
+ set { this.backColor = value; this.hasBackColor = true; }
+ }
+ private ConsoleColor backColor;
+ private bool hasBackColor;
+ internal bool HasBackColor {
+ get {
+ return hasBackColor;
+ }
+ }
+ }
+ #endregion // LevelColors LevelMapping Entry
+ }
+}
+
+#endif
+#endif
+#endif // !MONO_1_0
+#endif // !CLI_1_0
+#endif // !SSCLI
+#endif // !NETCF
diff --git a/src/Appender/MemoryAppender.cs b/src/Appender/MemoryAppender.cs
old mode 100755
new mode 100644
index 0402e8f6..e0ec7413
--- a/src/Appender/MemoryAppender.cs
+++ b/src/Appender/MemoryAppender.cs
@@ -33,12 +33,22 @@ namespace log4net.Appender
/// that are appended in an in-memory array.
///
///
- /// Use the method to get
- /// the current list of events that have been appended.
+ /// Use the method to get
+ /// and clear the current list of events that have been appended.
///
///
- /// Use the method to clear the
- /// current list of events.
+ /// Use the method to get the current
+ /// list of events that have been appended. Note there is a
+ /// race-condition when calling and
+ /// in pairs, you better use in that case.
+ ///
+ ///
+ /// Use the method to clear the
+ /// current list of events. Note there is a
+ /// race-condition when calling and
+ /// in pairs, you better use in that case.
///
///
/// Julian Biddle
@@ -76,7 +86,10 @@ public MemoryAppender() : base()
///
virtual public LoggingEvent[] GetEvents()
{
- return (LoggingEvent[])m_eventsList.ToArray(typeof(LoggingEvent));
+ lock (m_eventsList.SyncRoot)
+ {
+ return (LoggingEvent[]) m_eventsList.ToArray(typeof(LoggingEvent));
+ }
}
///
@@ -93,7 +106,7 @@ virtual public LoggingEvent[] GetEvents()
/// data to be fixed and stored in the appender, hereby improving performance.
///
///
- /// See for more information.
+ /// See for more information.
///
///
[Obsolete("Use Fix property")]
@@ -134,7 +147,7 @@ virtual public FixFlags Fix
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// the event to log
///
@@ -147,7 +160,10 @@ override protected void Append(LoggingEvent loggingEvent)
// volatile data in the event.
loggingEvent.Fix = this.Fix;
- m_eventsList.Add(loggingEvent);
+ lock (m_eventsList.SyncRoot)
+ {
+ m_eventsList.Add(loggingEvent);
+ }
}
#endregion Override implementation of AppenderSkeleton
@@ -162,9 +178,31 @@ override protected void Append(LoggingEvent loggingEvent)
///
virtual public void Clear()
{
- m_eventsList.Clear();
+ lock (m_eventsList.SyncRoot)
+ {
+ m_eventsList.Clear();
+ }
}
+ ///
+ /// Gets the events that have been logged and clears the list of events.
+ ///
+ /// The events that have been logged
+ ///
+ ///
+ /// Gets the events that have been logged and clears the list of events.
+ ///
+ ///
+ virtual public LoggingEvent[] PopAllEvents()
+ {
+ lock (m_eventsList.SyncRoot)
+ {
+ LoggingEvent[] tmp = (LoggingEvent[]) m_eventsList.ToArray(typeof (LoggingEvent));
+ m_eventsList.Clear();
+ return tmp;
+ }
+ }
+
#endregion Public Instance Methods
#region Protected Instance Fields
diff --git a/src/Appender/NetSendAppender.cs b/src/Appender/NetSendAppender.cs
old mode 100755
new mode 100644
index c0e0369f..f7fa627a
--- a/src/Appender/NetSendAppender.cs
+++ b/src/Appender/NetSendAppender.cs
@@ -68,10 +68,10 @@ namespace log4net.Appender
/// Send a message to a user account on the local machine
///
///
- /// = <name of the local machine>
+ /// = <name of the local machine>
///
///
- /// = <user name>
+ /// = <user name>
///
///
///
@@ -79,10 +79,10 @@ namespace log4net.Appender
/// Send a message to a user account on a remote machine
///
///
- /// = <name of the remote machine>
+ /// = <name of the remote machine>
///
///
- /// = <user name>
+ /// = <user name>
///
///
///
@@ -90,10 +90,10 @@ namespace log4net.Appender
/// Send a message to a domain user account
///
///
- /// = <name of a domain controller | uninitialized>
+ /// = <name of a domain controller | uninitialized>
///
///
- /// = <user name>
+ /// = <user name>
///
///
///
@@ -101,7 +101,7 @@ namespace log4net.Appender
/// Send a message to all the names in a workgroup or domain
///
///
- /// = <workgroup name | domain name>*
+ /// = <workgroup name | domain name>*
///
///
///
@@ -109,10 +109,10 @@ namespace log4net.Appender
/// Send a message from the local machine to a remote machine
///
///
- /// = <name of the local machine | uninitialized>
+ /// = <name of the local machine | uninitialized>
///
///
- /// = <name of the remote machine>
+ /// = <name of the remote machine>
///
///
///
@@ -296,7 +296,7 @@ public override void ActivateOptions()
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
@@ -304,7 +304,11 @@ public override void ActivateOptions()
/// Sends the event using a network message.
///
///
- protected override void Append(LoggingEvent loggingEvent)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)]
+ protected override void Append(LoggingEvent loggingEvent)
{
NativeError nativeError = null;
diff --git a/src/Appender/OutputDebugStringAppender.cs b/src/Appender/OutputDebugStringAppender.cs
old mode 100755
new mode 100644
index c9c20f30..2242afb2
--- a/src/Appender/OutputDebugStringAppender.cs
+++ b/src/Appender/OutputDebugStringAppender.cs
@@ -75,7 +75,12 @@ public OutputDebugStringAppender()
/// Write the logging event to the output debug string API
///
///
- override protected void Append(LoggingEvent loggingEvent)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#elif !NETCF
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)]
+#endif
+ override protected void Append(LoggingEvent loggingEvent)
{
OutputDebugString(RenderLoggingEvent(loggingEvent));
}
diff --git a/src/Appender/RemoteSyslogAppender.cs b/src/Appender/RemoteSyslogAppender.cs
old mode 100755
new mode 100644
index 018cbd0e..2f23875c
--- a/src/Appender/RemoteSyslogAppender.cs
+++ b/src/Appender/RemoteSyslogAppender.cs
@@ -23,8 +23,9 @@
using log4net.Appender;
using log4net.Util;
using log4net.Layout;
+using System.Text;
-namespace log4net.Appender
+namespace log4net.Appender
{
///
/// Logs events to a remote syslog daemon.
@@ -66,7 +67,7 @@ namespace log4net.Appender
///
/// Rob Lyon
/// Nicko Cadell
- public class RemoteSyslogAppender : UdpAppender
+ public class RemoteSyslogAppender : UdpAppender
{
///
/// Syslog port 514
@@ -268,7 +269,7 @@ public enum SyslogFacility
/// This instance of the class is set up to write
/// to a remote syslog daemon.
///
- public RemoteSyslogAppender()
+ public RemoteSyslogAppender()
{
// syslog udp defaults
this.RemotePort = DefaultSyslogPort;
@@ -279,7 +280,7 @@ public RemoteSyslogAppender()
#endregion Public Instance Constructors
#region Public Instance Properties
-
+
///
/// Message identity
///
@@ -310,7 +311,7 @@ public SyslogFacility Facility
get { return m_facility; }
set { m_facility = value; }
}
-
+
#endregion Public Instance Properties
///
@@ -330,7 +331,7 @@ public void AddMapping(LevelSeverity mapping)
#region AppenderSkeleton Implementation
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
@@ -341,48 +342,86 @@ public void AddMapping(LevelSeverity mapping)
/// The format of the output will depend on the appender's layout.
///
///
- protected override void Append(LoggingEvent loggingEvent)
+ protected override void Append(LoggingEvent loggingEvent)
{
- try
- {
- System.IO.StringWriter writer = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture);
-
- // Priority
- int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
- writer.Write('<');
- writer.Write(priority);
- writer.Write('>');
-
- // Identity
- if (m_identity != null)
- {
- m_identity.Format(writer, loggingEvent);
- }
- else
- {
- writer.Write(loggingEvent.Domain);
- }
- writer.Write(": ");
-
- // Message. The message goes after the tag/identity
- RenderLoggingEvent(writer, loggingEvent);
-
- // Grab as a byte array
- string fullMessage = writer.ToString();
- Byte [] buffer = this.Encoding.GetBytes(fullMessage.ToCharArray());
-
- this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
- }
- catch (Exception e)
- {
- ErrorHandler.Error(
- "Unable to send logging event to remote syslog " +
- this.RemoteAddress.ToString() +
- " on port " +
- this.RemotePort + ".",
- e,
- ErrorCode.WriteFailure);
- }
+ try
+ {
+ // Priority
+ int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
+
+ // Identity
+ string identity;
+
+ if (m_identity != null)
+ {
+ identity = m_identity.Format(loggingEvent);
+ }
+ else
+ {
+ identity = loggingEvent.Domain;
+ }
+
+ // Message. The message goes after the tag/identity
+ string message = RenderLoggingEvent(loggingEvent);
+
+ Byte[] buffer;
+ int i = 0;
+ char c;
+
+ StringBuilder builder = new StringBuilder();
+
+ while (i < message.Length)
+ {
+ // Clear StringBuilder
+ builder.Length = 0;
+
+ // Write priority
+ builder.Append('<');
+ builder.Append(priority);
+ builder.Append('>');
+
+ // Write identity
+ builder.Append(identity);
+ builder.Append(": ");
+
+ for (; i < message.Length; i++)
+ {
+ c = message[i];
+
+ // Accept only visible ASCII characters and space. See RFC 3164 section 4.1.3
+ if (((int)c >= 32) && ((int)c <= 126))
+ {
+ builder.Append(c);
+ }
+ // If character is newline, break and send the current line
+ else if ((c == '\r') || (c == '\n'))
+ {
+ // Check the next character to handle \r\n or \n\r
+ if ((message.Length > i + 1) && ((message[i + 1] == '\r') || (message[i + 1] == '\n')))
+ {
+ i++;
+ }
+ i++;
+ break;
+ }
+ }
+
+ // Grab as a byte array
+ buffer = this.Encoding.GetBytes(builder.ToString());
+
+ this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
+ }
+ }
+ catch (Exception e)
+ {
+ ErrorHandler.Error(
+ "Unable to send logging event to remote syslog " +
+ this.RemoteAddress.ToString() +
+ " on port " +
+ this.RemotePort + ".",
+ e,
+ ErrorCode.WriteFailure);
+ }
}
///
@@ -425,30 +464,30 @@ virtual protected SyslogSeverity GetSeverity(Level level)
// Fallback to sensible default values
//
- if (level >= Level.Alert)
+ if (level >= Level.Alert)
{
return SyslogSeverity.Alert;
- }
- else if (level >= Level.Critical)
+ }
+ else if (level >= Level.Critical)
{
return SyslogSeverity.Critical;
- }
- else if (level >= Level.Error)
+ }
+ else if (level >= Level.Error)
{
return SyslogSeverity.Error;
- }
- else if (level >= Level.Warn)
+ }
+ else if (level >= Level.Warn)
{
return SyslogSeverity.Warning;
- }
- else if (level >= Level.Notice)
+ }
+ else if (level >= Level.Notice)
{
return SyslogSeverity.Notice;
- }
- else if (level >= Level.Info)
+ }
+ else if (level >= Level.Info)
{
return SyslogSeverity.Informational;
- }
+ }
// Default setting
return SyslogSeverity.Debug;
}
@@ -505,10 +544,19 @@ public static int GeneratePriority(SyslogFacility facility, SyslogSeverity sever
///
private LevelMapping m_levelMapping = new LevelMapping();
+ ///
+ /// Initial buffer size
+ ///
+ private const int c_renderBufferSize = 256;
+
+ ///
+ /// Maximum buffer size before it is recycled
+ ///
+ private const int c_renderBufferMaxCapacity = 1024;
+
#endregion Private Instances Fields
#region LevelSeverity LevelMapping Entry
-
///
/// A class to act as a mapping between the level that a logging call is made at and
/// the syslog severity that is should be logged at.
diff --git a/src/Appender/RemotingAppender.cs b/src/Appender/RemotingAppender.cs
old mode 100755
new mode 100644
index d1834e7d..a517c614
--- a/src/Appender/RemotingAppender.cs
+++ b/src/Appender/RemotingAppender.cs
@@ -138,7 +138,10 @@ public string Sink
/// must be called again.
///
///
- override public void ActivateOptions()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ override public void ActivateOptions()
{
base.ActivateOptions();
diff --git a/src/Appender/RollingFileAppender.cs b/src/Appender/RollingFileAppender.cs
old mode 100755
new mode 100644
index 0f636c75..816549c5
--- a/src/Appender/RollingFileAppender.cs
+++ b/src/Appender/RollingFileAppender.cs
@@ -1,1692 +1,1764 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.Collections;
-using System.Globalization;
-using System.IO;
-
-using log4net.Util;
-using log4net.Core;
-
-namespace log4net.Appender
-{
-#if CONFIRM_WIN32_FILE_SHAREMODES
- // The following sounds good, and I though it was the case, but after
- // further testing on Windows I have not been able to confirm it.
-
- /// On the Windows platform if another process has a write lock on the file
- /// that is to be deleted, but allows shared read access to the file then the
- /// file can be moved, but cannot be deleted. If the other process also allows
- /// shared delete access to the file then the file will be deleted once that
- /// process closes the file. If it is necessary to open the log file or any
- /// of the backup files outside of this appender for either read or
- /// write access please ensure that read and delete share modes are enabled.
-#endif
-
- ///
- /// Appender that rolls log files based on size or date or both.
- ///
- ///
- ///
- /// RollingFileAppender can roll log files based on size or date or both
- /// depending on the setting of the property.
- /// When set to the log file will be rolled
- /// once its size exceeds the .
- /// When set to the log file will be rolled
- /// once the date boundary specified in the property
- /// is crossed.
- /// When set to the log file will be
- /// rolled once the date boundary specified in the property
- /// is crossed, but within a date boundary the file will also be rolled
- /// once its size exceeds the .
- /// When set to the log file will be rolled when
- /// the appender is configured. This effectively means that the log file can be
- /// rolled once per program execution.
- ///
- ///
- /// A of few additional optional features have been added:
- ///
- /// Attach date pattern for current log file
- /// Backup number increments for newer files
- /// Infinite number of backups by file size
- ///
- ///
- ///
- ///
- ///
- /// For large or infinite numbers of backup files a
- /// greater than zero is highly recommended, otherwise all the backup files need
- /// to be renamed each time a new backup is created.
- ///
- ///
- /// When Date/Time based rolling is used setting
- /// to will reduce the number of file renamings to few or none.
- ///
- ///
- ///
- ///
- ///
- /// Changing or without clearing
- /// the log file directory of backup files will cause unexpected and unwanted side effects.
- ///
- ///
- ///
- ///
- /// If Date/Time based rolling is enabled this appender will attempt to roll existing files
- /// in the directory without a Date/Time tag based on the last write date of the base log file.
- /// The appender only rolls the log file when a message is logged. If Date/Time based rolling
- /// is enabled then the appender will not roll the log file at the Date/Time boundary but
- /// at the point when the next message is logged after the boundary has been crossed.
- ///
- ///
- ///
- /// The extends the and
- /// has the same behavior when opening the log file.
- /// The appender will first try to open the file for writing when
- /// is called. This will typically be during configuration.
- /// If the file cannot be opened for writing the appender will attempt
- /// to open the file again each time a message is logged to the appender.
- /// If the file cannot be opened for writing when a message is logged then
- /// the message will be discarded by this appender.
- ///
- ///
- /// When rolling a backup file necessitates deleting an older backup file the
- /// file to be deleted is moved to a temporary name before being deleted.
- ///
- ///
- ///
- ///
- /// A maximum number of backup files when rolling on date/time boundaries is not supported.
- ///
- ///
- ///
- /// Nicko Cadell
- /// Gert Driesen
- /// Aspi Havewala
- /// Douglas de la Torre
- /// Edward Smit
- public class RollingFileAppender : FileAppender
- {
- #region Public Enums
-
- ///
- /// Style of rolling to use
- ///
- ///
- ///
- /// Style of rolling to use
- ///
- ///
- public enum RollingMode
- {
- ///
- /// Roll files once per program execution
- ///
- ///
- ///
- /// Roll files once per program execution.
- /// Well really once each time this appender is
- /// configured.
- ///
- ///
- /// Setting this option also sets AppendToFile to
- /// false on the RollingFileAppender, otherwise
- /// this appender would just be a normal file appender.
- ///
- ///
- Once = 0,
-
- ///
- /// Roll files based only on the size of the file
- ///
- Size = 1,
-
- ///
- /// Roll files based only on the date
- ///
- Date = 2,
-
- ///
- /// Roll files based on both the size and date of the file
- ///
- Composite = 3
- }
-
- #endregion
-
- #region Protected Enums
-
- ///
- /// The code assumes that the following 'time' constants are in a increasing sequence.
- ///
- ///
- ///
- /// The code assumes that the following 'time' constants are in a increasing sequence.
- ///
- ///
- protected enum RollPoint
- {
- ///
- /// Roll the log not based on the date
- ///
- InvalidRollPoint =-1,
-
- ///
- /// Roll the log for each minute
- ///
- TopOfMinute = 0,
-
- ///
- /// Roll the log for each hour
- ///
- TopOfHour = 1,
-
- ///
- /// Roll the log twice a day (midday and midnight)
- ///
- HalfDay = 2,
-
- ///
- /// Roll the log each day (midnight)
- ///
- TopOfDay = 3,
-
- ///
- /// Roll the log each week
- ///
- TopOfWeek = 4,
-
- ///
- /// Roll the log each month
- ///
- TopOfMonth = 5
- }
-
- #endregion Protected Enums
-
- #region Public Instance Constructors
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- /// Default constructor.
- ///
- ///
- public RollingFileAppender()
- {
- }
-
- #endregion Public Instance Constructors
-
- #region Public Instance Properties
-
- ///
- /// Gets or sets the strategy for determining the current date and time. The default
- /// implementation is to use LocalDateTime which internally calls through to DateTime.Now.
- /// DateTime.UtcNow may be used by specifying
- /// .
- ///
- ///
- /// An implementation of the interface which returns the current date and time.
- ///
- ///
- ///
- /// Gets or sets the used to return the current date and time.
- ///
- ///
- /// There are two built strategies for determining the current date and time,
- /// and .
- ///
- ///
- /// The default strategy is .
- ///
- ///
- public IDateTime DateTimeStrategy
- {
- get { return m_dateTime; }
- set { m_dateTime = value; }
- }
-
- ///
- /// Gets or sets the date pattern to be used for generating file names
- /// when rolling over on date.
- ///
- ///
- /// The date pattern to be used for generating file names when rolling
- /// over on date.
- ///
- ///
- ///
- /// Takes a string in the same format as expected by
- /// .
- ///
- ///
- /// This property determines the rollover schedule when rolling over
- /// on date.
- ///
- ///
- public string DatePattern
- {
- get { return m_datePattern; }
- set { m_datePattern = value; }
- }
-
- ///
- /// Gets or sets the maximum number of backup files that are kept before
- /// the oldest is erased.
- ///
- ///
- /// The maximum number of backup files that are kept before the oldest is
- /// erased.
- ///
- ///
- ///
- /// If set to zero, then there will be no backup files and the log file
- /// will be truncated when it reaches .
- ///
- ///
- /// If a negative number is supplied then no deletions will be made. Note
- /// that this could result in very slow performance as a large number of
- /// files are rolled over unless is used.
- ///
- ///
- /// The maximum applies to each time based group of files and
- /// not the total.
- ///
- ///
- public int MaxSizeRollBackups
- {
- get { return m_maxSizeRollBackups; }
- set { m_maxSizeRollBackups = value; }
- }
-
- ///
- /// Gets or sets the maximum size that the output file is allowed to reach
- /// before being rolled over to backup files.
- ///
- ///
- /// The maximum size in bytes that the output file is allowed to reach before being
- /// rolled over to backup files.
- ///
- ///
- ///
- /// This property is equivalent to except
- /// that it is required for differentiating the setter taking a
- /// argument from the setter taking a
- /// argument.
- ///
- ///
- /// The default maximum file size is 10MB (10*1024*1024).
- ///
- ///
- public long MaxFileSize
- {
- get { return m_maxFileSize; }
- set { m_maxFileSize = value; }
- }
-
- ///
- /// Gets or sets the maximum size that the output file is allowed to reach
- /// before being rolled over to backup files.
- ///
- ///
- /// The maximum size that the output file is allowed to reach before being
- /// rolled over to backup files.
- ///
- ///
- ///
- /// This property allows you to specify the maximum size with the
- /// suffixes "KB", "MB" or "GB" so that the size is interpreted being
- /// expressed respectively in kilobytes, megabytes or gigabytes.
- ///
- ///
- /// For example, the value "10KB" will be interpreted as 10240 bytes.
- ///
- ///
- /// The default maximum file size is 10MB.
- ///
- ///
- /// If you have the option to set the maximum file size programmatically
- /// consider using the property instead as this
- /// allows you to set the size in bytes as a .
- ///
- ///
- public string MaximumFileSize
- {
- get { return m_maxFileSize.ToString(NumberFormatInfo.InvariantInfo); }
- set { m_maxFileSize = OptionConverter.ToFileSize(value, m_maxFileSize + 1); }
- }
-
- ///
- /// Gets or sets the rolling file count direction.
- ///
- ///
- /// The rolling file count direction.
- ///
- ///
- ///
- /// Indicates if the current file is the lowest numbered file or the
- /// highest numbered file.
- ///
- ///
- /// By default newer files have lower numbers ( < 0),
- /// i.e. log.1 is most recent, log.5 is the 5th backup, etc...
- ///
- ///
- /// >= 0 does the opposite i.e.
- /// log.1 is the first backup made, log.5 is the 5th backup made, etc.
- /// For infinite backups use >= 0 to reduce
- /// rollover costs.
- ///
- /// The default file count direction is -1.
- ///
- public int CountDirection
- {
- get { return m_countDirection; }
- set { m_countDirection = value; }
- }
-
- ///
- /// Gets or sets the rolling style.
- ///
- /// The rolling style.
- ///
- ///
- /// The default rolling style is .
- ///
- ///
- /// When set to this appender's
- /// property is set to false, otherwise
- /// the appender would append to a single file rather than rolling
- /// the file each time it is opened.
- ///
- ///
- public RollingMode RollingStyle
- {
- get { return m_rollingStyle; }
- set
- {
- m_rollingStyle = value;
- switch (m_rollingStyle)
- {
- case RollingMode.Once:
- m_rollDate = false;
- m_rollSize = false;
-
- this.AppendToFile = false;
- break;
-
- case RollingMode.Size:
- m_rollDate = false;
- m_rollSize = true;
- break;
-
- case RollingMode.Date:
- m_rollDate = true;
- m_rollSize = false;
- break;
-
- case RollingMode.Composite:
- m_rollDate = true;
- m_rollSize = true;
- break;
- }
- }
- }
-
- ///
- /// Gets or sets a value indicating whether to preserve the file name extension when rolling.
- ///
- ///
- /// true if the file name extension should be preserved.
- ///
- ///
- ///
- /// By default file.log is rolled to file.log.yyyy-MM-dd or file.log.curSizeRollBackup.
- /// However, under Windows the new file name will loose any program associations as the
- /// extension is changed. Optionally file.log can be renamed to file.yyyy-MM-dd.log or
- /// file.curSizeRollBackup.log to maintain any program associations.
- ///
- ///
- public bool PreserveLogFileNameExtension
- {
- get { return m_preserveLogFileNameExtension; }
- set { m_preserveLogFileNameExtension = value; }
- }
-
- ///
- /// Gets or sets a value indicating whether to always log to
- /// the same file.
- ///
- ///
- /// true if always should be logged to the same file, otherwise false.
- ///
- ///
- ///
- /// By default file.log is always the current file. Optionally
- /// file.log.yyyy-mm-dd for current formatted datePattern can by the currently
- /// logging file (or file.log.curSizeRollBackup or even
- /// file.log.yyyy-mm-dd.curSizeRollBackup).
- ///
- ///
- /// This will make time based rollovers with a large number of backups
- /// much faster as the appender it won't have to rename all the backups!
- ///
- ///
- public bool StaticLogFileName
- {
- get { return m_staticLogFileName; }
- set { m_staticLogFileName = value; }
- }
-
- #endregion Public Instance Properties
-
- #region Private Static Fields
-
- ///
- /// The fully qualified type of the RollingFileAppender class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(RollingFileAppender);
-
- #endregion Private Static Fields
-
- #region Override implementation of FileAppender
-
- ///
- /// Sets the quiet writer being used.
- ///
- ///
- /// This method can be overridden by sub classes.
- ///
- /// the writer to set
- override protected void SetQWForFiles(TextWriter writer)
- {
- QuietWriter = new CountingQuietTextWriter(writer, ErrorHandler);
- }
-
- ///
- /// Write out a logging event.
- ///
- /// the event to write to file.
- ///
- ///
- /// Handles append time behavior for RollingFileAppender. This checks
- /// if a roll over either by date (checked first) or time (checked second)
- /// is need and then appends to the file last.
- ///
- ///
- override protected void Append(LoggingEvent loggingEvent)
- {
- AdjustFileBeforeAppend();
- base.Append(loggingEvent);
- }
-
- ///
- /// Write out an array of logging events.
- ///
- /// the events to write to file.
- ///
- ///
- /// Handles append time behavior for RollingFileAppender. This checks
- /// if a roll over either by date (checked first) or time (checked second)
- /// is need and then appends to the file last.
- ///
- ///
- override protected void Append(LoggingEvent[] loggingEvents)
- {
- AdjustFileBeforeAppend();
- base.Append(loggingEvents);
- }
-
- ///
- /// Performs any required rolling before outputting the next event
- ///
- ///
- ///
- /// Handles append time behavior for RollingFileAppender. This checks
- /// if a roll over either by date (checked first) or time (checked second)
- /// is need and then appends to the file last.
- ///
- ///
- virtual protected void AdjustFileBeforeAppend()
- {
- if (m_rollDate)
- {
- DateTime n = m_dateTime.Now;
- if (n >= m_nextCheck)
- {
- m_now = n;
- m_nextCheck = NextCheckDate(m_now, m_rollPoint);
-
- RollOverTime(true);
- }
- }
-
- if (m_rollSize)
- {
- if ((File != null) && ((CountingQuietTextWriter)QuietWriter).Count >= m_maxFileSize)
- {
- RollOverSize();
- }
- }
- }
-
- ///
- /// Creates and opens the file for logging. If
- /// is false then the fully qualified name is determined and used.
- ///
- /// the name of the file to open
- /// true to append to existing file
- ///
- /// This method will ensure that the directory structure
- /// for the specified exists.
- ///
- override protected void OpenFile(string fileName, bool append)
- {
- lock(this)
- {
- fileName = GetNextOutputFileName(fileName);
-
- // Calculate the current size of the file
- long currentCount = 0;
- if (append)
- {
- using(SecurityContext.Impersonate(this))
- {
- if (System.IO.File.Exists(fileName))
- {
- currentCount = (new FileInfo(fileName)).Length;
- }
- }
- }
- else
- {
- if (LogLog.IsErrorEnabled)
- {
- // Internal check that the file is not being overwritten
- // If not Appending to an existing file we should have rolled the file out of the
- // way. Therefore we should not be over-writing an existing file.
- // The only exception is if we are not allowed to roll the existing file away.
- if (m_maxSizeRollBackups != 0 && FileExists(fileName))
- {
- LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is False but OutputFile ["+fileName+"] already exists.");
- }
- }
- }
-
- if (!m_staticLogFileName)
- {
- m_scheduledFilename = fileName;
- }
-
- // Open the file (call the base class to do it)
- base.OpenFile(fileName, append);
-
- // Set the file size onto the counting writer
- ((CountingQuietTextWriter)QuietWriter).Count = currentCount;
- }
- }
-
- ///
- /// Get the current output file name
- ///
- /// the base file name
- /// the output file name
- ///
- /// The output file name is based on the base fileName specified.
- /// If is set then the output
- /// file name is the same as the base file passed in. Otherwise
- /// the output file depends on the date pattern, on the count
- /// direction or both.
- ///
- protected string GetNextOutputFileName(string fileName)
- {
- if (!m_staticLogFileName)
- {
- fileName = fileName.Trim();
-
- if (m_rollDate)
- {
- fileName = CombinePath(fileName, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
- }
-
- if (m_countDirection >= 0)
- {
- fileName = CombinePath(fileName, "." + m_curSizeRollBackups);
- }
- }
-
- return fileName;
- }
-
- #endregion
-
- #region Initialize Options
-
- ///
- /// Determines curSizeRollBackups (only within the current roll point)
- ///
- private void DetermineCurSizeRollBackups()
- {
- m_curSizeRollBackups = 0;
-
- string fullPath = null;
- string fileName = null;
-
- using(SecurityContext.Impersonate(this))
- {
- fullPath = System.IO.Path.GetFullPath(m_baseFileName);
- fileName = System.IO.Path.GetFileName(fullPath);
- }
-
- ArrayList arrayFiles = GetExistingFiles(fullPath);
- InitializeRollBackups(fileName, arrayFiles);
-
- LogLog.Debug(declaringType, "curSizeRollBackups starts at ["+m_curSizeRollBackups+"]");
- }
-
- ///
- /// Generates a wildcard pattern that can be used to find all files
- /// that are similar to the base file name.
- ///
- ///
- ///
- private string GetWildcardPatternForFile(string baseFileName)
- {
- if (m_preserveLogFileNameExtension)
- {
- return Path.GetFileNameWithoutExtension(baseFileName) + ".*" + Path.GetExtension(baseFileName);
- }
- else
- {
- return baseFileName + '*';
- }
- }
-
- ///
- /// Builds a list of filenames for all files matching the base filename plus a file
- /// pattern.
- ///
- ///
- ///
- private ArrayList GetExistingFiles(string baseFilePath)
- {
- ArrayList alFiles = new ArrayList();
-
- string directory = null;
-
- using(SecurityContext.Impersonate(this))
- {
- string fullPath = Path.GetFullPath(baseFilePath);
-
- directory = Path.GetDirectoryName(fullPath);
- if (Directory.Exists(directory))
- {
- string baseFileName = Path.GetFileName(fullPath);
-
- string[] files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName));
-
- if (files != null)
- {
- for (int i = 0; i < files.Length; i++)
- {
- string curFileName = Path.GetFileName(files[i]);
- if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName)))
- {
- alFiles.Add(curFileName);
- }
- }
- }
- }
- }
- LogLog.Debug(declaringType, "Searched for existing files in ["+directory+"]");
- return alFiles;
- }
-
- ///
- /// Initiates a roll over if needed for crossing a date boundary since the last run.
- ///
- private void RollOverIfDateBoundaryCrossing()
- {
- if (m_staticLogFileName && m_rollDate)
- {
- if (FileExists(m_baseFileName))
- {
- DateTime last;
- using(SecurityContext.Impersonate(this))
- {
- last = System.IO.File.GetLastWriteTime(m_baseFileName);
- }
- LogLog.Debug(declaringType, "["+last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"] vs. ["+m_now.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"]");
-
- if (!(last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo))))
- {
- m_scheduledFilename = m_baseFileName + last.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
- LogLog.Debug(declaringType, "Initial roll over to ["+m_scheduledFilename+"]");
- RollOverTime(false);
- LogLog.Debug(declaringType, "curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]");
- }
- }
- }
- }
-
- ///
- /// Initializes based on existing conditions at time of .
- ///
- ///
- ///
- /// Initializes based on existing conditions at time of .
- /// The following is done
- ///
- /// determine curSizeRollBackups (only within the current roll point)
- /// initiates a roll over if needed for crossing a date boundary since the last run.
- ///
- ///
- ///
- protected void ExistingInit()
- {
- DetermineCurSizeRollBackups();
- RollOverIfDateBoundaryCrossing();
-
- // If file exists and we are not appending then roll it out of the way
- if (AppendToFile == false)
- {
- bool fileExists = false;
- string fileName = GetNextOutputFileName(m_baseFileName);
-
- using(SecurityContext.Impersonate(this))
- {
- fileExists = System.IO.File.Exists(fileName);
- }
-
- if (fileExists)
- {
- if (m_maxSizeRollBackups == 0)
- {
- LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot roll. Overwriting existing file.");
- }
- else
- {
- LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. Not appending to file. Rolling existing file out of the way.");
-
- RollOverRenameFiles(fileName);
- }
- }
- }
- }
-
- ///
- /// Does the work of bumping the 'current' file counter higher
- /// to the highest count when an incremental file name is seen.
- /// The highest count is either the first file (when count direction
- /// is greater than 0) or the last file (when count direction less than 0).
- /// In either case, we want to know the highest count that is present.
- ///
- ///
- ///
- private void InitializeFromOneFile(string baseFile, string curFileName)
- {
- if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false)
- {
- // This is not a log file, so ignore
- return;
- }
- if (curFileName.Equals(baseFile))
- {
- // Base log file is not an incremented logfile (.1 or .2, etc)
- return;
- }
-
- /*
- if (m_staticLogFileName)
- {
- int endLength = curFileName.Length - index;
- if (baseFile.Length + endLength != curFileName.Length)
- {
- // file is probably scheduledFilename + .x so I don't care
- return;
- }
- }
- */
-
- // Only look for files in the current roll point
- if (m_rollDate && !m_staticLogFileName)
- {
- if (! curFileName.StartsWith(CombinePath(baseFile, m_dateTime.Now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo))))
- {
- LogLog.Debug(declaringType, "Ignoring file ["+curFileName+"] because it is from a different date period");
- return;
- }
- }
-
- try
- {
- // Bump the counter up to the highest count seen so far
- int backup = GetBackUpIndex(curFileName);
-
- // caution: we might get a false positive when certain
- // date patterns such as yyyyMMdd are used...those are
- // valid number but aren't the kind of back up index
- // we're looking for
- if (backup > m_curSizeRollBackups)
- {
- if (0 == m_maxSizeRollBackups)
- {
- // Stay at zero when zero backups are desired
- }
- else if (-1 == m_maxSizeRollBackups)
- {
- // Infinite backups, so go as high as the highest value
- m_curSizeRollBackups = backup;
- }
- else
- {
- // Backups limited to a finite number
- if (m_countDirection >= 0)
- {
- // Go with the highest file when counting up
- m_curSizeRollBackups = backup;
- }
- else
- {
- // Clip to the limit when counting down
- if (backup <= m_maxSizeRollBackups)
- {
- m_curSizeRollBackups = backup;
- }
- }
- }
- LogLog.Debug(declaringType, "File name [" + curFileName + "] moves current count to [" + m_curSizeRollBackups + "]");
- }
- }
- catch(FormatException)
- {
- //this happens when file.log -> file.log.yyyy-MM-dd which is normal
- //when staticLogFileName == false
- LogLog.Debug(declaringType, "Encountered a backup file not ending in .x ["+curFileName+"]");
- }
- }
-
- ///
- /// Attempts to extract a number from the end of the file name that indicates
- /// the number of the times the file has been rolled over.
- ///
- ///
- /// Certain date pattern extensions like yyyyMMdd will be parsed as valid backup indexes.
- ///
- ///
- ///
- private int GetBackUpIndex(string curFileName)
- {
- int backUpIndex = -1;
- string fileName = curFileName;
-
- if (m_preserveLogFileNameExtension)
- {
- fileName = Path.GetFileNameWithoutExtension(fileName);
- }
-
- int index = fileName.LastIndexOf(".");
- if (index > 0)
- {
- // if the "yyyy-MM-dd" component of file.log.yyyy-MM-dd is passed to TryParse
- // it will gracefully fail and return backUpIndex will be 0
- SystemInfo.TryParse(fileName.Substring(index + 1), out backUpIndex);
- }
-
- return backUpIndex;
- }
-
- ///
- /// Takes a list of files and a base file name, and looks for
- /// 'incremented' versions of the base file. Bumps the max
- /// count up to the highest count seen.
- ///
- ///
- ///
- private void InitializeRollBackups(string baseFile, ArrayList arrayFiles)
- {
- if (null != arrayFiles)
- {
- string baseFileLower = baseFile.ToLower(System.Globalization.CultureInfo.InvariantCulture);
-
- foreach(string curFileName in arrayFiles)
- {
- InitializeFromOneFile(baseFileLower, curFileName.ToLower(System.Globalization.CultureInfo.InvariantCulture));
- }
- }
- }
-
- ///
- /// Calculates the RollPoint for the datePattern supplied.
- ///
- /// the date pattern to calculate the check period for
- /// The RollPoint that is most accurate for the date pattern supplied
- ///
- /// Essentially the date pattern is examined to determine what the
- /// most suitable roll point is. The roll point chosen is the roll point
- /// with the smallest period that can be detected using the date pattern
- /// supplied. i.e. if the date pattern only outputs the year, month, day
- /// and hour then the smallest roll point that can be detected would be
- /// and hourly roll point as minutes could not be detected.
- ///
- private RollPoint ComputeCheckPeriod(string datePattern)
- {
- // s_date1970 is 1970-01-01 00:00:00 this is UniversalSortableDateTimePattern
- // (based on ISO 8601) using universal time. This date is used for reference
- // purposes to calculate the resolution of the date pattern.
-
- // Get string representation of base line date
- string r0 = s_date1970.ToString(datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
-
- // Check each type of rolling mode starting with the smallest increment.
- for(int i = (int)RollPoint.TopOfMinute; i <= (int)RollPoint.TopOfMonth; i++)
- {
- // Get string representation of next pattern
- string r1 = NextCheckDate(s_date1970, (RollPoint)i).ToString(datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
-
- LogLog.Debug(declaringType, "Type = ["+i+"], r0 = ["+r0+"], r1 = ["+r1+"]");
-
- // Check if the string representations are different
- if (r0 != null && r1 != null && !r0.Equals(r1))
- {
- // Found highest precision roll point
- return (RollPoint)i;
- }
- }
-
- return RollPoint.InvalidRollPoint; // Deliberately head for trouble...
- }
-
- ///
- /// Initialize the appender based on the options set
- ///
- ///
- ///
- /// This is part of the delayed object
- /// activation scheme. The method must
- /// be called on this object after the configuration properties have
- /// been set. Until is called this
- /// object is in an undefined state and must not be used.
- ///
- ///
- /// If any of the configuration properties are modified then
- /// must be called again.
- ///
- ///
- /// Sets initial conditions including date/time roll over information, first check,
- /// scheduledFilename, and calls to initialize
- /// the current number of backups.
- ///
- ///
- override public void ActivateOptions()
- {
- if (m_dateTime == null)
- {
- m_dateTime = new LocalDateTime();
- }
-
- if (m_rollDate && m_datePattern != null)
- {
- m_now = m_dateTime.Now;
- m_rollPoint = ComputeCheckPeriod(m_datePattern);
-
- if (m_rollPoint == RollPoint.InvalidRollPoint)
- {
- throw new ArgumentException("Invalid RollPoint, unable to parse ["+m_datePattern+"]");
- }
-
- // next line added as this removes the name check in rollOver
- m_nextCheck = NextCheckDate(m_now, m_rollPoint);
- }
- else
- {
- if (m_rollDate)
- {
- ErrorHandler.Error("Either DatePattern or rollingStyle options are not set for ["+Name+"].");
- }
- }
-
- if (SecurityContext == null)
- {
- SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
- }
-
- using(SecurityContext.Impersonate(this))
- {
- // Must convert the FileAppender's m_filePath to an absolute path before we
- // call ExistingInit(). This will be done by the base.ActivateOptions() but
- // we need to duplicate that functionality here first.
- base.File = ConvertToFullPath(base.File.Trim());
-
- // Store fully qualified base file name
- m_baseFileName = base.File;
- }
-
- if (m_rollDate && File != null && m_scheduledFilename == null)
- {
- m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
- }
-
- ExistingInit();
-
- base.ActivateOptions();
- }
-
- #endregion
-
- #region Roll File
-
- ///
- ///
- ///
- ///
- /// .1, .2, .3, etc.
- ///
- private string CombinePath(string path1, string path2)
- {
- string extension = Path.GetExtension(path1);
- if (m_preserveLogFileNameExtension && extension.Length > 0)
- {
- return Path.Combine(Path.GetDirectoryName(path1), Path.GetFileNameWithoutExtension(path1) + path2 + extension);
- }
- else
- {
- return path1 + path2;
- }
- }
-
- ///
- /// Rollover the file(s) to date/time tagged file(s).
- ///
- /// set to true if the file to be rolled is currently open
- ///
- ///
- /// Rollover the file(s) to date/time tagged file(s).
- /// Resets curSizeRollBackups.
- /// If fileIsOpen is set then the new file is opened (through SafeOpenFile).
- ///
- ///
- protected void RollOverTime(bool fileIsOpen)
- {
- if (m_staticLogFileName)
- {
- // Compute filename, but only if datePattern is specified
- if (m_datePattern == null)
- {
- ErrorHandler.Error("Missing DatePattern option in rollOver().");
- return;
- }
-
- //is the new file name equivalent to the 'current' one
- //something has gone wrong if we hit this -- we should only
- //roll over if the new file will be different from the old
- string dateFormat = m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
- if (m_scheduledFilename.Equals(CombinePath(File, dateFormat)))
- {
- ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + CombinePath(File, dateFormat));
- return;
- }
-
- if (fileIsOpen)
- {
- // close current file, and rename it to datedFilename
- this.CloseFile();
- }
-
- //we may have to roll over a large number of backups here
- for (int i = 1; i <= m_curSizeRollBackups; i++)
- {
- string from = CombinePath(File, "." + i);
- string to = CombinePath(m_scheduledFilename, "." + i);
- RollFile(from, to);
- }
-
- RollFile(File, m_scheduledFilename);
- }
-
- //We've cleared out the old date and are ready for the new
- m_curSizeRollBackups = 0;
-
- //new scheduled name
- m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
-
- if (fileIsOpen)
- {
- // This will also close the file. This is OK since multiple close operations are safe.
- SafeOpenFile(m_baseFileName, false);
- }
- }
-
- ///
- /// Renames file to file .
- ///
- /// Name of existing file to roll.
- /// New name for file.
- ///
- ///
- /// Renames file to file . It
- /// also checks for existence of target file and deletes if it does.
- ///
- ///
- protected void RollFile(string fromFile, string toFile)
- {
- if (FileExists(fromFile))
- {
- // Delete the toFile if it exists
- DeleteFile(toFile);
-
- // We may not have permission to move the file, or the file may be locked
- try
- {
- LogLog.Debug(declaringType, "Moving [" + fromFile + "] -> [" + toFile + "]");
- using(SecurityContext.Impersonate(this))
- {
- System.IO.File.Move(fromFile, toFile);
- }
- }
- catch(Exception moveEx)
- {
- ErrorHandler.Error("Exception while rolling file [" + fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure);
- }
- }
- else
- {
- LogLog.Warn(declaringType, "Cannot RollFile [" + fromFile + "] -> [" + toFile + "]. Source does not exist");
- }
- }
-
- ///
- /// Test if a file exists at a specified path
- ///
- /// the path to the file
- /// true if the file exists
- ///
- ///
- /// Test if a file exists at a specified path
- ///
- ///
- protected bool FileExists(string path)
- {
- using(SecurityContext.Impersonate(this))
- {
- return System.IO.File.Exists(path);
- }
- }
-
- ///
- /// Deletes the specified file if it exists.
- ///
- /// The file to delete.
- ///
- ///
- /// Delete a file if is exists.
- /// The file is first moved to a new filename then deleted.
- /// This allows the file to be removed even when it cannot
- /// be deleted, but it still can be moved.
- ///
- ///
- protected void DeleteFile(string fileName)
- {
- if (FileExists(fileName))
- {
- // We may not have permission to delete the file, or the file may be locked
-
- string fileToDelete = fileName;
-
- // Try to move the file to temp name.
- // If the file is locked we may still be able to move it
- string tempFileName = fileName + "." + Environment.TickCount + ".DeletePending";
- try
- {
- using(SecurityContext.Impersonate(this))
- {
- System.IO.File.Move(fileName, tempFileName);
- }
- fileToDelete = tempFileName;
- }
- catch(Exception moveEx)
- {
- LogLog.Debug(declaringType, "Exception while moving file to be deleted [" + fileName + "] -> [" + tempFileName + "]", moveEx);
- }
-
- // Try to delete the file (either the original or the moved file)
- try
- {
- using(SecurityContext.Impersonate(this))
- {
- System.IO.File.Delete(fileToDelete);
- }
- LogLog.Debug(declaringType, "Deleted file [" + fileName + "]");
- }
- catch(Exception deleteEx)
- {
- if (fileToDelete == fileName)
- {
- // Unable to move or delete the file
- ErrorHandler.Error("Exception while deleting file [" + fileToDelete + "]", deleteEx, ErrorCode.GenericFailure);
- }
- else
- {
- // Moved the file, but the delete failed. File is probably locked.
- // The file should automatically be deleted when the lock is released.
- LogLog.Debug(declaringType, "Exception while deleting temp file [" + fileToDelete + "]", deleteEx);
- }
- }
- }
- }
-
- ///
- /// Implements file roll base on file size.
- ///
- ///
- ///
- /// If the maximum number of size based backups is reached
- /// (curSizeRollBackups == maxSizeRollBackups) then the oldest
- /// file is deleted -- its index determined by the sign of countDirection.
- /// If countDirection < 0, then files
- /// {File.1, ..., File.curSizeRollBackups -1}
- /// are renamed to {File.2, ...,
- /// File.curSizeRollBackups}. Moreover, File is
- /// renamed File.1 and closed.
- ///
- ///
- /// A new file is created to receive further log output.
- ///
- ///
- /// If maxSizeRollBackups is equal to zero, then the
- /// File is truncated with no backup files created.
- ///
- ///
- /// If maxSizeRollBackups < 0, then File is
- /// renamed if needed and no files are deleted.
- ///
- ///
- protected void RollOverSize()
- {
- this.CloseFile(); // keep windows happy.
-
- LogLog.Debug(declaringType, "rolling over count ["+((CountingQuietTextWriter)QuietWriter).Count+"]");
- LogLog.Debug(declaringType, "maxSizeRollBackups ["+m_maxSizeRollBackups+"]");
- LogLog.Debug(declaringType, "curSizeRollBackups ["+m_curSizeRollBackups+"]");
- LogLog.Debug(declaringType, "countDirection ["+m_countDirection+"]");
-
- RollOverRenameFiles(File);
-
- if (!m_staticLogFileName && m_countDirection >= 0)
- {
- m_curSizeRollBackups++;
- }
-
- // This will also close the file. This is OK since multiple close operations are safe.
- SafeOpenFile(m_baseFileName, false);
- }
-
- ///
- /// Implements file roll.
- ///
- /// the base name to rename
- ///
- ///
- /// If the maximum number of size based backups is reached
- /// (curSizeRollBackups == maxSizeRollBackups) then the oldest
- /// file is deleted -- its index determined by the sign of countDirection.
- /// If countDirection < 0, then files
- /// {File.1, ..., File.curSizeRollBackups -1}
- /// are renamed to {File.2, ...,
- /// File.curSizeRollBackups}.
- ///
- ///
- /// If maxSizeRollBackups is equal to zero, then the
- /// File is truncated with no backup files created.
- ///
- ///
- /// If maxSizeRollBackups < 0, then File is
- /// renamed if needed and no files are deleted.
- ///
- ///
- /// This is called by to rename the files.
- ///
- ///
- protected void RollOverRenameFiles(string baseFileName)
- {
- // If maxBackups <= 0, then there is no file renaming to be done.
- if (m_maxSizeRollBackups != 0)
- {
- if (m_countDirection < 0)
- {
- // Delete the oldest file, to keep Windows happy.
- if (m_curSizeRollBackups == m_maxSizeRollBackups)
- {
- DeleteFile(CombinePath(baseFileName, "." + m_maxSizeRollBackups));
- m_curSizeRollBackups--;
- }
-
- // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
- for (int i = m_curSizeRollBackups; i >= 1; i--)
- {
- RollFile((CombinePath(baseFileName, "." + i)), (CombinePath(baseFileName, "." + (i + 1))));
- }
-
- m_curSizeRollBackups++;
-
- // Rename fileName to fileName.1
- RollFile(baseFileName, CombinePath(baseFileName, ".1"));
- }
- else
- {
- //countDirection >= 0
- if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0)
- {
- //delete the first and keep counting up.
- int oldestFileIndex = m_curSizeRollBackups - m_maxSizeRollBackups;
-
- // If static then there is 1 file without a number, therefore 1 less archive
- if (m_staticLogFileName)
- {
- oldestFileIndex++;
- }
-
- // If using a static log file then the base for the numbered sequence is the baseFileName passed in
- // If not using a static log file then the baseFileName will already have a numbered postfix which
- // we must remove, however it may have a date postfix which we must keep!
- string archiveFileBaseName = baseFileName;
- if (!m_staticLogFileName)
- {
- int lastDotIndex = archiveFileBaseName.LastIndexOf(".");
- if (lastDotIndex >= 0)
- {
- archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex);
- }
- }
-
- // Delete the archive file
- DeleteFile(CombinePath(archiveFileBaseName, "." + oldestFileIndex));
- }
-
- if (m_staticLogFileName)
- {
- m_curSizeRollBackups++;
- RollFile(baseFileName, CombinePath(baseFileName, "." + m_curSizeRollBackups));
- }
- }
- }
- }
-
- #endregion
-
- #region NextCheckDate
-
- ///
- /// Get the start time of the next window for the current rollpoint
- ///
- /// the current date
- /// the type of roll point we are working with
- /// the start time for the next roll point an interval after the currentDateTime date
- ///
- ///
- /// Returns the date of the next roll point after the currentDateTime date passed to the method.
- ///
- ///
- /// The basic strategy is to subtract the time parts that are less significant
- /// than the rollpoint from the current time. This should roll the time back to
- /// the start of the time window for the current rollpoint. Then we add 1 window
- /// worth of time and get the start time of the next window for the rollpoint.
- ///
- ///
- protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint)
- {
- // Local variable to work on (this does not look very efficient)
- DateTime current = currentDateTime;
-
- // Do slightly different things depending on what the type of roll point we want.
- switch(rollPoint)
- {
- case RollPoint.TopOfMinute:
- current = current.AddMilliseconds(-current.Millisecond);
- current = current.AddSeconds(-current.Second);
- current = current.AddMinutes(1);
- break;
-
- case RollPoint.TopOfHour:
- current = current.AddMilliseconds(-current.Millisecond);
- current = current.AddSeconds(-current.Second);
- current = current.AddMinutes(-current.Minute);
- current = current.AddHours(1);
- break;
-
- case RollPoint.HalfDay:
- current = current.AddMilliseconds(-current.Millisecond);
- current = current.AddSeconds(-current.Second);
- current = current.AddMinutes(-current.Minute);
-
- if (current.Hour < 12)
- {
- current = current.AddHours(12 - current.Hour);
- }
- else
- {
- current = current.AddHours(-current.Hour);
- current = current.AddDays(1);
- }
- break;
-
- case RollPoint.TopOfDay:
- current = current.AddMilliseconds(-current.Millisecond);
- current = current.AddSeconds(-current.Second);
- current = current.AddMinutes(-current.Minute);
- current = current.AddHours(-current.Hour);
- current = current.AddDays(1);
- break;
-
- case RollPoint.TopOfWeek:
- current = current.AddMilliseconds(-current.Millisecond);
- current = current.AddSeconds(-current.Second);
- current = current.AddMinutes(-current.Minute);
- current = current.AddHours(-current.Hour);
- current = current.AddDays(7 - (int)current.DayOfWeek);
- break;
-
- case RollPoint.TopOfMonth:
- current = current.AddMilliseconds(-current.Millisecond);
- current = current.AddSeconds(-current.Second);
- current = current.AddMinutes(-current.Minute);
- current = current.AddHours(-current.Hour);
- current = current.AddDays(1 - current.Day); /* first day of month is 1 not 0 */
- current = current.AddMonths(1);
- break;
- }
- return current;
- }
-
- #endregion
-
- #region Private Instance Fields
-
- ///
- /// This object supplies the current date/time. Allows test code to plug in
- /// a method to control this class when testing date/time based rolling. The default
- /// implementation uses the underlying value of DateTime.Now.
- ///
- private IDateTime m_dateTime = null;
-
- ///
- /// The date pattern. By default, the pattern is set to ".yyyy-MM-dd"
- /// meaning daily rollover.
- ///
- private string m_datePattern = ".yyyy-MM-dd";
-
- ///
- /// The actual formatted filename that is currently being written to
- /// or will be the file transferred to on roll over
- /// (based on staticLogFileName).
- ///
- private string m_scheduledFilename = null;
-
- ///
- /// The timestamp when we shall next recompute the filename.
- ///
- private DateTime m_nextCheck = DateTime.MaxValue;
-
- ///
- /// Holds date of last roll over
- ///
- private DateTime m_now;
-
- ///
- /// The type of rolling done
- ///
- private RollPoint m_rollPoint;
-
- ///
- /// The default maximum file size is 10MB
- ///
- private long m_maxFileSize = 10*1024*1024;
-
- ///
- /// There is zero backup files by default
- ///
- private int m_maxSizeRollBackups = 0;
-
- ///
- /// How many sized based backups have been made so far
- ///
- private int m_curSizeRollBackups = 0;
-
- ///
- /// The rolling file count direction.
- ///
- private int m_countDirection = -1;
-
- ///
- /// The rolling mode used in this appender.
- ///
- private RollingMode m_rollingStyle = RollingMode.Composite;
-
- ///
- /// Cache flag set if we are rolling by date.
- ///
- private bool m_rollDate = true;
-
- ///
- /// Cache flag set if we are rolling by size.
- ///
- private bool m_rollSize = true;
-
- ///
- /// Value indicating whether to always log to the same file.
- ///
- private bool m_staticLogFileName = true;
-
- ///
- /// Value indicating whether to preserve the file name extension when rolling.
- ///
- private bool m_preserveLogFileNameExtension = false;
-
-
- ///
- /// FileName provided in configuration. Used for rolling properly
- ///
- private string m_baseFileName;
-
- #endregion Private Instance Fields
-
- #region Static Members
-
- ///
- /// The 1st of January 1970 in UTC
- ///
- private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1);
-
- #endregion
-
- #region DateTime
-
- ///
- /// This interface is used to supply Date/Time information to the .
- ///
- ///
- /// This interface is used to supply Date/Time information to the .
- /// Used primarily to allow test classes to plug themselves in so they can
- /// supply test date/times.
- ///
- public interface IDateTime
- {
- ///
- /// Gets the current time.
- ///
- /// The current time.
- ///
- ///
- /// Gets the current time.
- ///
- ///
- DateTime Now { get; }
- }
-
- ///
- /// Default implementation of that returns the current time.
- ///
- private class LocalDateTime : IDateTime
- {
- ///
- /// Gets the current time.
- ///
- /// The current time.
- ///
- ///
- /// Gets the current time.
- ///
- ///
- public DateTime Now
- {
- get { return DateTime.Now; }
- }
- }
-
- ///
- /// Implementation of that returns the current time as the coordinated universal time (UTC).
- ///
- private class UniversalDateTime : IDateTime
- {
- ///
- /// Gets the current time.
- ///
- /// The current time.
- ///
- ///
- /// Gets the current time.
- ///
- ///
- public DateTime Now
- {
- get { return DateTime.UtcNow; }
- }
- }
-
- #endregion DateTime
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+
+using log4net.Util;
+using log4net.Core;
+using System.Threading;
+
+namespace log4net.Appender
+{
+#if CONFIRM_WIN32_FILE_SHAREMODES
+ // The following sounds good, and I though it was the case, but after
+ // further testing on Windows I have not been able to confirm it.
+
+ /// On the Windows platform if another process has a write lock on the file
+ /// that is to be deleted, but allows shared read access to the file then the
+ /// file can be moved, but cannot be deleted. If the other process also allows
+ /// shared delete access to the file then the file will be deleted once that
+ /// process closes the file. If it is necessary to open the log file or any
+ /// of the backup files outside of this appender for either read or
+ /// write access please ensure that read and delete share modes are enabled.
+#endif
+
+ ///
+ /// Appender that rolls log files based on size or date or both.
+ ///
+ ///
+ ///
+ /// RollingFileAppender can roll log files based on size or date or both
+ /// depending on the setting of the property.
+ /// When set to the log file will be rolled
+ /// once its size exceeds the .
+ /// When set to the log file will be rolled
+ /// once the date boundary specified in the property
+ /// is crossed.
+ /// When set to the log file will be
+ /// rolled once the date boundary specified in the property
+ /// is crossed, but within a date boundary the file will also be rolled
+ /// once its size exceeds the .
+ /// When set to the log file will be rolled when
+ /// the appender is configured. This effectively means that the log file can be
+ /// rolled once per program execution.
+ ///
+ ///
+ /// A of few additional optional features have been added:
+ ///
+ /// Attach date pattern for current log file
+ /// Backup number increments for newer files
+ /// Infinite number of backups by file size
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// For large or infinite numbers of backup files a
+ /// greater than zero is highly recommended, otherwise all the backup files need
+ /// to be renamed each time a new backup is created.
+ ///
+ ///
+ /// When Date/Time based rolling is used setting
+ /// to will reduce the number of file renamings to few or none.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Changing or without clearing
+ /// the log file directory of backup files will cause unexpected and unwanted side effects.
+ ///
+ ///
+ ///
+ ///
+ /// If Date/Time based rolling is enabled this appender will attempt to roll existing files
+ /// in the directory without a Date/Time tag based on the last write date of the base log file.
+ /// The appender only rolls the log file when a message is logged. If Date/Time based rolling
+ /// is enabled then the appender will not roll the log file at the Date/Time boundary but
+ /// at the point when the next message is logged after the boundary has been crossed.
+ ///
+ ///
+ ///
+ /// The extends the and
+ /// has the same behavior when opening the log file.
+ /// The appender will first try to open the file for writing when
+ /// is called. This will typically be during configuration.
+ /// If the file cannot be opened for writing the appender will attempt
+ /// to open the file again each time a message is logged to the appender.
+ /// If the file cannot be opened for writing when a message is logged then
+ /// the message will be discarded by this appender.
+ ///
+ ///
+ /// When rolling a backup file necessitates deleting an older backup file the
+ /// file to be deleted is moved to a temporary name before being deleted.
+ ///
+ ///
+ ///
+ ///
+ /// A maximum number of backup files when rolling on date/time boundaries is not supported.
+ ///
+ ///
+ ///
+ /// Nicko Cadell
+ /// Gert Driesen
+ /// Aspi Havewala
+ /// Douglas de la Torre
+ /// Edward Smit
+ public class RollingFileAppender : FileAppender
+ {
+ #region Public Enums
+
+ ///
+ /// Style of rolling to use
+ ///
+ ///
+ ///
+ /// Style of rolling to use
+ ///
+ ///
+ public enum RollingMode
+ {
+ ///
+ /// Roll files once per program execution
+ ///
+ ///
+ ///
+ /// Roll files once per program execution.
+ /// Well really once each time this appender is
+ /// configured.
+ ///
+ ///
+ /// Setting this option also sets AppendToFile to
+ /// false on the RollingFileAppender, otherwise
+ /// this appender would just be a normal file appender.
+ ///
+ ///
+ Once = 0,
+
+ ///
+ /// Roll files based only on the size of the file
+ ///
+ Size = 1,
+
+ ///
+ /// Roll files based only on the date
+ ///
+ Date = 2,
+
+ ///
+ /// Roll files based on both the size and date of the file
+ ///
+ Composite = 3
+ }
+
+ #endregion
+
+ #region Protected Enums
+
+ ///
+ /// The code assumes that the following 'time' constants are in a increasing sequence.
+ ///
+ ///
+ ///
+ /// The code assumes that the following 'time' constants are in a increasing sequence.
+ ///
+ ///
+ protected enum RollPoint
+ {
+ ///
+ /// Roll the log not based on the date
+ ///
+ InvalidRollPoint =-1,
+
+ ///
+ /// Roll the log for each minute
+ ///
+ TopOfMinute = 0,
+
+ ///
+ /// Roll the log for each hour
+ ///
+ TopOfHour = 1,
+
+ ///
+ /// Roll the log twice a day (midday and midnight)
+ ///
+ HalfDay = 2,
+
+ ///
+ /// Roll the log each day (midnight)
+ ///
+ TopOfDay = 3,
+
+ ///
+ /// Roll the log each week
+ ///
+ TopOfWeek = 4,
+
+ ///
+ /// Roll the log each month
+ ///
+ TopOfMonth = 5
+ }
+
+ #endregion Protected Enums
+
+ #region Public Instance Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ /// Default constructor.
+ ///
+ ///
+ public RollingFileAppender()
+ {
+ }
+
+ ///
+ /// Cleans up all resources used by this appender.
+ ///
+ ~RollingFileAppender()
+ {
+ if (m_mutexForRolling != null)
+ {
+ m_mutexForRolling.Close();
+ m_mutexForRolling = null;
+ }
+ }
+
+ #endregion Public Instance Constructors
+
+ #region Public Instance Properties
+
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+ ///
+ /// Gets or sets the strategy for determining the current date and time. The default
+ /// implementation is to use LocalDateTime which internally calls through to DateTime.Now.
+ /// DateTime.UtcNow may be used on frameworks newer than .NET 1.0 by specifying
+ /// .
+ ///
+ ///
+ /// An implementation of the interface which returns the current date and time.
+ ///
+ ///
+ ///
+ /// Gets or sets the used to return the current date and time.
+ ///
+ ///
+ /// There are two built strategies for determining the current date and time,
+ ///
+ /// and .
+ ///
+ ///
+ /// The default strategy is .
+ ///
+ ///
+#else
+ ///
+ /// Gets or sets the strategy for determining the current date and time. The default
+ /// implementation is to use LocalDateTime which internally calls through to DateTime.Now.
+ ///
+ ///
+ /// An implementation of the interface which returns the current date and time.
+ ///
+ ///
+ ///
+ /// Gets or sets the used to return the current date and time.
+ ///
+ ///
+ /// The default strategy is .
+ ///
+ ///
+#endif
+ public IDateTime DateTimeStrategy
+ {
+ get { return m_dateTime; }
+ set { m_dateTime = value; }
+ }
+
+ ///
+ /// Gets or sets the date pattern to be used for generating file names
+ /// when rolling over on date.
+ ///
+ ///
+ /// The date pattern to be used for generating file names when rolling
+ /// over on date.
+ ///
+ ///
+ ///
+ /// Takes a string in the same format as expected by
+ /// .
+ ///
+ ///
+ /// This property determines the rollover schedule when rolling over
+ /// on date.
+ ///
+ ///
+ public string DatePattern
+ {
+ get { return m_datePattern; }
+ set { m_datePattern = value; }
+ }
+
+ ///
+ /// Gets or sets the maximum number of backup files that are kept before
+ /// the oldest is erased.
+ ///
+ ///
+ /// The maximum number of backup files that are kept before the oldest is
+ /// erased.
+ ///
+ ///
+ ///
+ /// If set to zero, then there will be no backup files and the log file
+ /// will be truncated when it reaches .
+ ///
+ ///
+ /// If a negative number is supplied then no deletions will be made. Note
+ /// that this could result in very slow performance as a large number of
+ /// files are rolled over unless is used.
+ ///
+ ///
+ /// The maximum applies to each time based group of files and
+ /// not the total.
+ ///
+ ///
+ public int MaxSizeRollBackups
+ {
+ get { return m_maxSizeRollBackups; }
+ set { m_maxSizeRollBackups = value; }
+ }
+
+ ///
+ /// Gets or sets the maximum size that the output file is allowed to reach
+ /// before being rolled over to backup files.
+ ///
+ ///
+ /// The maximum size in bytes that the output file is allowed to reach before being
+ /// rolled over to backup files.
+ ///
+ ///
+ ///
+ /// This property is equivalent to except
+ /// that it is required for differentiating the setter taking a
+ /// argument from the setter taking a
+ /// argument.
+ ///
+ ///
+ /// The default maximum file size is 10MB (10*1024*1024).
+ ///
+ ///
+ public long MaxFileSize
+ {
+ get { return m_maxFileSize; }
+ set { m_maxFileSize = value; }
+ }
+
+ ///
+ /// Gets or sets the maximum size that the output file is allowed to reach
+ /// before being rolled over to backup files.
+ ///
+ ///
+ /// The maximum size that the output file is allowed to reach before being
+ /// rolled over to backup files.
+ ///
+ ///
+ ///
+ /// This property allows you to specify the maximum size with the
+ /// suffixes "KB", "MB" or "GB" so that the size is interpreted being
+ /// expressed respectively in kilobytes, megabytes or gigabytes.
+ ///
+ ///
+ /// For example, the value "10KB" will be interpreted as 10240 bytes.
+ ///
+ ///
+ /// The default maximum file size is 10MB.
+ ///
+ ///
+ /// If you have the option to set the maximum file size programmatically
+ /// consider using the property instead as this
+ /// allows you to set the size in bytes as a .
+ ///
+ ///
+ public string MaximumFileSize
+ {
+ get { return m_maxFileSize.ToString(NumberFormatInfo.InvariantInfo); }
+ set { m_maxFileSize = OptionConverter.ToFileSize(value, m_maxFileSize + 1); }
+ }
+
+ ///
+ /// Gets or sets the rolling file count direction.
+ ///
+ ///
+ /// The rolling file count direction.
+ ///
+ ///
+ ///
+ /// Indicates if the current file is the lowest numbered file or the
+ /// highest numbered file.
+ ///
+ ///
+ /// By default newer files have lower numbers ( < 0),
+ /// i.e. log.1 is most recent, log.5 is the 5th backup, etc...
+ ///
+ ///
+ /// >= 0 does the opposite i.e.
+ /// log.1 is the first backup made, log.5 is the 5th backup made, etc.
+ /// For infinite backups use >= 0 to reduce
+ /// rollover costs.
+ ///
+ /// The default file count direction is -1.
+ ///
+ public int CountDirection
+ {
+ get { return m_countDirection; }
+ set { m_countDirection = value; }
+ }
+
+ ///
+ /// Gets or sets the rolling style.
+ ///
+ /// The rolling style.
+ ///
+ ///
+ /// The default rolling style is .
+ ///
+ ///
+ /// When set to this appender's
+ /// property is set to false, otherwise
+ /// the appender would append to a single file rather than rolling
+ /// the file each time it is opened.
+ ///
+ ///
+ public RollingMode RollingStyle
+ {
+ get { return m_rollingStyle; }
+ set
+ {
+ m_rollingStyle = value;
+ switch (m_rollingStyle)
+ {
+ case RollingMode.Once:
+ m_rollDate = false;
+ m_rollSize = false;
+
+ this.AppendToFile = false;
+ break;
+
+ case RollingMode.Size:
+ m_rollDate = false;
+ m_rollSize = true;
+ break;
+
+ case RollingMode.Date:
+ m_rollDate = true;
+ m_rollSize = false;
+ break;
+
+ case RollingMode.Composite:
+ m_rollDate = true;
+ m_rollSize = true;
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether to preserve the file name extension when rolling.
+ ///
+ ///
+ /// true if the file name extension should be preserved.
+ ///
+ ///
+ ///
+ /// By default file.log is rolled to file.log.yyyy-MM-dd or file.log.curSizeRollBackup.
+ /// However, under Windows the new file name will loose any program associations as the
+ /// extension is changed. Optionally file.log can be renamed to file.yyyy-MM-dd.log or
+ /// file.curSizeRollBackup.log to maintain any program associations.
+ ///
+ ///
+ public bool PreserveLogFileNameExtension
+ {
+ get { return m_preserveLogFileNameExtension; }
+ set { m_preserveLogFileNameExtension = value; }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether to always log to
+ /// the same file.
+ ///
+ ///
+ /// true if always should be logged to the same file, otherwise false.
+ ///
+ ///
+ ///
+ /// By default file.log is always the current file. Optionally
+ /// file.log.yyyy-mm-dd for current formatted datePattern can by the currently
+ /// logging file (or file.log.curSizeRollBackup or even
+ /// file.log.yyyy-mm-dd.curSizeRollBackup).
+ ///
+ ///
+ /// This will make time based rollovers with a large number of backups
+ /// much faster as the appender it won't have to rename all the backups!
+ ///
+ ///
+ public bool StaticLogFileName
+ {
+ get { return m_staticLogFileName; }
+ set { m_staticLogFileName = value; }
+ }
+
+ #endregion Public Instance Properties
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the RollingFileAppender class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(RollingFileAppender);
+
+ #endregion Private Static Fields
+
+ #region Override implementation of FileAppender
+
+ ///
+ /// Sets the quiet writer being used.
+ ///
+ ///
+ /// This method can be overridden by sub classes.
+ ///
+ /// the writer to set
+ override protected void SetQWForFiles(TextWriter writer)
+ {
+ QuietWriter = new CountingQuietTextWriter(writer, ErrorHandler);
+ }
+
+ ///
+ /// Write out a logging event.
+ ///
+ /// the event to write to file.
+ ///
+ ///
+ /// Handles append time behavior for RollingFileAppender. This checks
+ /// if a roll over either by date (checked first) or time (checked second)
+ /// is need and then appends to the file last.
+ ///
+ ///
+ override protected void Append(LoggingEvent loggingEvent)
+ {
+ AdjustFileBeforeAppend();
+ base.Append(loggingEvent);
+ }
+
+ ///
+ /// Write out an array of logging events.
+ ///
+ /// the events to write to file.
+ ///
+ ///
+ /// Handles append time behavior for RollingFileAppender. This checks
+ /// if a roll over either by date (checked first) or time (checked second)
+ /// is need and then appends to the file last.
+ ///
+ ///
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ AdjustFileBeforeAppend();
+ base.Append(loggingEvents);
+ }
+
+ ///
+ /// Performs any required rolling before outputting the next event
+ ///
+ ///
+ ///
+ /// Handles append time behavior for RollingFileAppender. This checks
+ /// if a roll over either by date (checked first) or time (checked second)
+ /// is need and then appends to the file last.
+ ///
+ ///
+ virtual protected void AdjustFileBeforeAppend()
+ {
+ // reuse the file appenders locking model to lock the rolling
+ try
+ {
+ // if rolling should be locked, acquire the lock
+ if (m_mutexForRolling != null)
+ {
+ m_mutexForRolling.WaitOne();
+ }
+ if (m_rollDate)
+ {
+ DateTime n = m_dateTime.Now;
+ if (n >= m_nextCheck)
+ {
+ m_now = n;
+ m_nextCheck = NextCheckDate(m_now, m_rollPoint);
+
+ RollOverTime(true);
+ }
+ }
+
+ if (m_rollSize)
+ {
+ if ((File != null) && ((CountingQuietTextWriter)QuietWriter).Count >= m_maxFileSize)
+ {
+ RollOverSize();
+ }
+ }
+ }
+ finally
+ {
+ // if rolling should be locked, release the lock
+ if (m_mutexForRolling != null)
+ {
+ m_mutexForRolling.ReleaseMutex();
+ }
+ }
+ }
+
+ ///
+ /// Creates and opens the file for logging. If
+ /// is false then the fully qualified name is determined and used.
+ ///
+ /// the name of the file to open
+ /// true to append to existing file
+ ///
+ /// This method will ensure that the directory structure
+ /// for the specified exists.
+ ///
+ override protected void OpenFile(string fileName, bool append)
+ {
+ lock(this)
+ {
+ fileName = GetNextOutputFileName(fileName);
+
+ // Calculate the current size of the file
+ long currentCount = 0;
+ if (append)
+ {
+ using(SecurityContext.Impersonate(this))
+ {
+ if (System.IO.File.Exists(fileName))
+ {
+ currentCount = (new FileInfo(fileName)).Length;
+ }
+ }
+ }
+ else
+ {
+ if (LogLog.IsErrorEnabled)
+ {
+ // Internal check that the file is not being overwritten
+ // If not Appending to an existing file we should have rolled the file out of the
+ // way. Therefore we should not be over-writing an existing file.
+ // The only exception is if we are not allowed to roll the existing file away.
+ if (m_maxSizeRollBackups != 0 && FileExists(fileName))
+ {
+ LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is False but OutputFile ["+fileName+"] already exists.");
+ }
+ }
+ }
+
+ if (!m_staticLogFileName)
+ {
+ m_scheduledFilename = fileName;
+ }
+
+ // Open the file (call the base class to do it)
+ base.OpenFile(fileName, append);
+
+ // Set the file size onto the counting writer
+ ((CountingQuietTextWriter)QuietWriter).Count = currentCount;
+ }
+ }
+
+ ///
+ /// Get the current output file name
+ ///
+ /// the base file name
+ /// the output file name
+ ///
+ /// The output file name is based on the base fileName specified.
+ /// If is set then the output
+ /// file name is the same as the base file passed in. Otherwise
+ /// the output file depends on the date pattern, on the count
+ /// direction or both.
+ ///
+ protected string GetNextOutputFileName(string fileName)
+ {
+ if (!m_staticLogFileName)
+ {
+ fileName = fileName.Trim();
+
+ if (m_rollDate)
+ {
+ fileName = CombinePath(fileName, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
+ }
+
+ if (m_countDirection >= 0)
+ {
+ fileName = CombinePath(fileName, "." + m_curSizeRollBackups);
+ }
+ }
+
+ return fileName;
+ }
+
+ #endregion
+
+ #region Initialize Options
+
+ ///
+ /// Determines curSizeRollBackups (only within the current roll point)
+ ///
+ private void DetermineCurSizeRollBackups()
+ {
+ m_curSizeRollBackups = 0;
+
+ string fullPath = null;
+ string fileName = null;
+
+ using(SecurityContext.Impersonate(this))
+ {
+ fullPath = System.IO.Path.GetFullPath(m_baseFileName);
+ fileName = System.IO.Path.GetFileName(fullPath);
+ }
+
+ ArrayList arrayFiles = GetExistingFiles(fullPath);
+ InitializeRollBackups(fileName, arrayFiles);
+
+ LogLog.Debug(declaringType, "curSizeRollBackups starts at ["+m_curSizeRollBackups+"]");
+ }
+
+ ///
+ /// Generates a wildcard pattern that can be used to find all files
+ /// that are similar to the base file name.
+ ///
+ ///
+ ///
+ private string GetWildcardPatternForFile(string baseFileName)
+ {
+ if (m_preserveLogFileNameExtension)
+ {
+ return Path.GetFileNameWithoutExtension(baseFileName) + "*" + Path.GetExtension(baseFileName);
+ }
+ else
+ {
+ return baseFileName + '*';
+ }
+ }
+
+ ///
+ /// Builds a list of filenames for all files matching the base filename plus a file
+ /// pattern.
+ ///
+ ///
+ ///
+ private ArrayList GetExistingFiles(string baseFilePath)
+ {
+ ArrayList alFiles = new ArrayList();
+
+ string directory = null;
+
+ using(SecurityContext.Impersonate(this))
+ {
+ string fullPath = Path.GetFullPath(baseFilePath);
+
+ directory = Path.GetDirectoryName(fullPath);
+ if (Directory.Exists(directory))
+ {
+ string baseFileName = Path.GetFileName(fullPath);
+
+ string[] files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName));
+
+ if (files != null)
+ {
+ for (int i = 0; i < files.Length; i++)
+ {
+ string curFileName = Path.GetFileName(files[i]);
+ if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName)))
+ {
+ alFiles.Add(curFileName);
+ }
+ }
+ }
+ }
+ }
+ LogLog.Debug(declaringType, "Searched for existing files in ["+directory+"]");
+ return alFiles;
+ }
+
+ ///
+ /// Initiates a roll over if needed for crossing a date boundary since the last run.
+ ///
+ private void RollOverIfDateBoundaryCrossing()
+ {
+ if (m_staticLogFileName && m_rollDate)
+ {
+ if (FileExists(m_baseFileName))
+ {
+ DateTime last;
+ using(SecurityContext.Impersonate(this)) {
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+ if (DateTimeStrategy is UniversalDateTime)
+ {
+ last = System.IO.File.GetLastWriteTimeUtc(m_baseFileName);
+ }
+ else
+ {
+#endif
+ last = System.IO.File.GetLastWriteTime(m_baseFileName);
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+ }
+#endif
+ }
+ LogLog.Debug(declaringType, "["+last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"] vs. ["+m_now.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"]");
+
+ if (!(last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo))))
+ {
+ m_scheduledFilename = CombinePath(m_baseFileName, last.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
+ LogLog.Debug(declaringType, "Initial roll over to ["+m_scheduledFilename+"]");
+ RollOverTime(false);
+ LogLog.Debug(declaringType, "curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Initializes based on existing conditions at time of .
+ ///
+ ///
+ ///
+ /// Initializes based on existing conditions at time of .
+ /// The following is done
+ ///
+ /// determine curSizeRollBackups (only within the current roll point)
+ /// initiates a roll over if needed for crossing a date boundary since the last run.
+ ///
+ ///
+ ///
+ protected void ExistingInit()
+ {
+ DetermineCurSizeRollBackups();
+ RollOverIfDateBoundaryCrossing();
+
+ // If file exists and we are not appending then roll it out of the way
+ if (AppendToFile == false)
+ {
+ bool fileExists = false;
+ string fileName = GetNextOutputFileName(m_baseFileName);
+
+ using(SecurityContext.Impersonate(this))
+ {
+ fileExists = System.IO.File.Exists(fileName);
+ }
+
+ if (fileExists)
+ {
+ if (m_maxSizeRollBackups == 0)
+ {
+ LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot roll. Overwriting existing file.");
+ }
+ else
+ {
+ LogLog.Debug(declaringType, "Output file ["+fileName+"] already exists. Not appending to file. Rolling existing file out of the way.");
+
+ RollOverRenameFiles(fileName);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Does the work of bumping the 'current' file counter higher
+ /// to the highest count when an incremental file name is seen.
+ /// The highest count is either the first file (when count direction
+ /// is greater than 0) or the last file (when count direction less than 0).
+ /// In either case, we want to know the highest count that is present.
+ ///
+ ///
+ ///
+ private void InitializeFromOneFile(string baseFile, string curFileName)
+ {
+ if (curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false)
+ {
+ // This is not a log file, so ignore
+ return;
+ }
+ if (curFileName.Equals(baseFile))
+ {
+ // Base log file is not an incremented logfile (.1 or .2, etc)
+ return;
+ }
+
+ /*
+ if (m_staticLogFileName)
+ {
+ int endLength = curFileName.Length - index;
+ if (baseFile.Length + endLength != curFileName.Length)
+ {
+ // file is probably scheduledFilename + .x so I don't care
+ return;
+ }
+ }
+ */
+
+ // Only look for files in the current roll point
+ if (m_rollDate && !m_staticLogFileName)
+ {
+ string date = m_dateTime.Now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ string prefix = m_preserveLogFileNameExtension ? Path.GetFileNameWithoutExtension(baseFile) + date : baseFile + date;
+ string suffix = m_preserveLogFileNameExtension ? Path.GetExtension(baseFile) : "";
+ if (!curFileName.StartsWith(prefix) || !curFileName.EndsWith(suffix))
+ {
+ LogLog.Debug(declaringType, "Ignoring file ["+curFileName+"] because it is from a different date period");
+ return;
+ }
+ }
+
+ try
+ {
+ // Bump the counter up to the highest count seen so far
+ int backup = GetBackUpIndex(curFileName);
+
+ // caution: we might get a false positive when certain
+ // date patterns such as yyyyMMdd are used...those are
+ // valid number but aren't the kind of back up index
+ // we're looking for
+ if (backup > m_curSizeRollBackups)
+ {
+ if (0 == m_maxSizeRollBackups)
+ {
+ // Stay at zero when zero backups are desired
+ }
+ else if (-1 == m_maxSizeRollBackups)
+ {
+ // Infinite backups, so go as high as the highest value
+ m_curSizeRollBackups = backup;
+ }
+ else
+ {
+ // Backups limited to a finite number
+ if (m_countDirection >= 0)
+ {
+ // Go with the highest file when counting up
+ m_curSizeRollBackups = backup;
+ }
+ else
+ {
+ // Clip to the limit when counting down
+ if (backup <= m_maxSizeRollBackups)
+ {
+ m_curSizeRollBackups = backup;
+ }
+ }
+ }
+ LogLog.Debug(declaringType, "File name [" + curFileName + "] moves current count to [" + m_curSizeRollBackups + "]");
+ }
+ }
+ catch(FormatException)
+ {
+ //this happens when file.log -> file.log.yyyy-MM-dd which is normal
+ //when staticLogFileName == false
+ LogLog.Debug(declaringType, "Encountered a backup file not ending in .x ["+curFileName+"]");
+ }
+ }
+
+ ///
+ /// Attempts to extract a number from the end of the file name that indicates
+ /// the number of the times the file has been rolled over.
+ ///
+ ///
+ /// Certain date pattern extensions like yyyyMMdd will be parsed as valid backup indexes.
+ ///
+ ///
+ ///
+ private int GetBackUpIndex(string curFileName)
+ {
+ int backUpIndex = -1;
+ string fileName = curFileName;
+
+ if (m_preserveLogFileNameExtension)
+ {
+ fileName = Path.GetFileNameWithoutExtension(fileName);
+ }
+
+ int index = fileName.LastIndexOf(".");
+ if (index > 0)
+ {
+ // if the "yyyy-MM-dd" component of file.log.yyyy-MM-dd is passed to TryParse
+ // it will gracefully fail and return backUpIndex will be 0
+ SystemInfo.TryParse(fileName.Substring(index + 1), out backUpIndex);
+ }
+
+ return backUpIndex;
+ }
+
+ ///
+ /// Takes a list of files and a base file name, and looks for
+ /// 'incremented' versions of the base file. Bumps the max
+ /// count up to the highest count seen.
+ ///
+ ///
+ ///
+ private void InitializeRollBackups(string baseFile, ArrayList arrayFiles)
+ {
+ if (null != arrayFiles)
+ {
+ string baseFileLower = baseFile.ToLower(System.Globalization.CultureInfo.InvariantCulture);
+
+ foreach(string curFileName in arrayFiles)
+ {
+ InitializeFromOneFile(baseFileLower, curFileName.ToLower(System.Globalization.CultureInfo.InvariantCulture));
+ }
+ }
+ }
+
+ ///
+ /// Calculates the RollPoint for the datePattern supplied.
+ ///
+ /// the date pattern to calculate the check period for
+ /// The RollPoint that is most accurate for the date pattern supplied
+ ///
+ /// Essentially the date pattern is examined to determine what the
+ /// most suitable roll point is. The roll point chosen is the roll point
+ /// with the smallest period that can be detected using the date pattern
+ /// supplied. i.e. if the date pattern only outputs the year, month, day
+ /// and hour then the smallest roll point that can be detected would be
+ /// and hourly roll point as minutes could not be detected.
+ ///
+ private RollPoint ComputeCheckPeriod(string datePattern)
+ {
+ // s_date1970 is 1970-01-01 00:00:00 this is UniversalSortableDateTimePattern
+ // (based on ISO 8601) using universal time. This date is used for reference
+ // purposes to calculate the resolution of the date pattern.
+
+ // Get string representation of base line date
+ string r0 = s_date1970.ToString(datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+
+ // Check each type of rolling mode starting with the smallest increment.
+ for(int i = (int)RollPoint.TopOfMinute; i <= (int)RollPoint.TopOfMonth; i++)
+ {
+ // Get string representation of next pattern
+ string r1 = NextCheckDate(s_date1970, (RollPoint)i).ToString(datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+
+ LogLog.Debug(declaringType, "Type = ["+i+"], r0 = ["+r0+"], r1 = ["+r1+"]");
+
+ // Check if the string representations are different
+ if (r0 != null && r1 != null && !r0.Equals(r1))
+ {
+ // Found highest precision roll point
+ return (RollPoint)i;
+ }
+ }
+
+ return RollPoint.InvalidRollPoint; // Deliberately head for trouble...
+ }
+
+ ///
+ /// Initialize the appender based on the options set
+ ///
+ ///
+ ///
+ /// This is part of the delayed object
+ /// activation scheme. The method must
+ /// be called on this object after the configuration properties have
+ /// been set. Until is called this
+ /// object is in an undefined state and must not be used.
+ ///
+ ///
+ /// If any of the configuration properties are modified then
+ /// must be called again.
+ ///
+ ///
+ /// Sets initial conditions including date/time roll over information, first check,
+ /// scheduledFilename, and calls to initialize
+ /// the current number of backups.
+ ///
+ ///
+ override public void ActivateOptions()
+ {
+ if (m_dateTime == null)
+ {
+ m_dateTime = new LocalDateTime();
+ }
+
+ if (m_rollDate && m_datePattern != null)
+ {
+ m_now = m_dateTime.Now;
+ m_rollPoint = ComputeCheckPeriod(m_datePattern);
+
+ if (m_rollPoint == RollPoint.InvalidRollPoint)
+ {
+ throw new ArgumentException("Invalid RollPoint, unable to parse ["+m_datePattern+"]");
+ }
+
+ // next line added as this removes the name check in rollOver
+ m_nextCheck = NextCheckDate(m_now, m_rollPoint);
+ }
+ else
+ {
+ if (m_rollDate)
+ {
+ ErrorHandler.Error("Either DatePattern or rollingStyle options are not set for ["+Name+"].");
+ }
+ }
+
+ if (SecurityContext == null)
+ {
+ SecurityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
+ }
+
+ using(SecurityContext.Impersonate(this))
+ {
+ // Must convert the FileAppender's m_filePath to an absolute path before we
+ // call ExistingInit(). This will be done by the base.ActivateOptions() but
+ // we need to duplicate that functionality here first.
+ base.File = ConvertToFullPath(base.File.Trim());
+
+ // Store fully qualified base file name
+ m_baseFileName = base.File;
+ }
+
+ // initialize the mutex that is used to lock rolling
+ m_mutexForRolling = new Mutex(false, m_baseFileName.Replace("\\", "_").Replace(":", "_").Replace("/", "_"));
+
+ if (m_rollDate && File != null && m_scheduledFilename == null)
+ {
+ m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
+ }
+
+ ExistingInit();
+
+ base.ActivateOptions();
+ }
+
+ #endregion
+
+ #region Roll File
+
+ ///
+ ///
+ ///
+ ///
+ /// .1, .2, .3, etc.
+ ///
+ private string CombinePath(string path1, string path2)
+ {
+ string extension = Path.GetExtension(path1);
+ if (m_preserveLogFileNameExtension && extension.Length > 0)
+ {
+ return Path.Combine(Path.GetDirectoryName(path1), Path.GetFileNameWithoutExtension(path1) + path2 + extension);
+ }
+ else
+ {
+ return path1 + path2;
+ }
+ }
+
+ ///
+ /// Rollover the file(s) to date/time tagged file(s).
+ ///
+ /// set to true if the file to be rolled is currently open
+ ///
+ ///
+ /// Rollover the file(s) to date/time tagged file(s).
+ /// Resets curSizeRollBackups.
+ /// If fileIsOpen is set then the new file is opened (through SafeOpenFile).
+ ///
+ ///
+ protected void RollOverTime(bool fileIsOpen)
+ {
+ if (m_staticLogFileName)
+ {
+ // Compute filename, but only if datePattern is specified
+ if (m_datePattern == null)
+ {
+ ErrorHandler.Error("Missing DatePattern option in rollOver().");
+ return;
+ }
+
+ //is the new file name equivalent to the 'current' one
+ //something has gone wrong if we hit this -- we should only
+ //roll over if the new file will be different from the old
+ string dateFormat = m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ if (m_scheduledFilename.Equals(CombinePath(File, dateFormat)))
+ {
+ ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + CombinePath(File, dateFormat));
+ return;
+ }
+
+ if (fileIsOpen)
+ {
+ // close current file, and rename it to datedFilename
+ this.CloseFile();
+ }
+
+ //we may have to roll over a large number of backups here
+ for (int i = 1; i <= m_curSizeRollBackups; i++)
+ {
+ string from = CombinePath(File, "." + i);
+ string to = CombinePath(m_scheduledFilename, "." + i);
+ RollFile(from, to);
+ }
+
+ RollFile(File, m_scheduledFilename);
+ }
+
+ //We've cleared out the old date and are ready for the new
+ m_curSizeRollBackups = 0;
+
+ //new scheduled name
+ m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
+
+ if (fileIsOpen)
+ {
+ // This will also close the file. This is OK since multiple close operations are safe.
+ SafeOpenFile(m_baseFileName, false);
+ }
+ }
+
+ ///
+ /// Renames file to file .
+ ///
+ /// Name of existing file to roll.
+ /// New name for file.
+ ///
+ ///
+ /// Renames file to file . It
+ /// also checks for existence of target file and deletes if it does.
+ ///
+ ///
+ protected void RollFile(string fromFile, string toFile)
+ {
+ if (FileExists(fromFile))
+ {
+ // Delete the toFile if it exists
+ DeleteFile(toFile);
+
+ // We may not have permission to move the file, or the file may be locked
+ try
+ {
+ LogLog.Debug(declaringType, "Moving [" + fromFile + "] -> [" + toFile + "]");
+ using(SecurityContext.Impersonate(this))
+ {
+ System.IO.File.Move(fromFile, toFile);
+ }
+ }
+ catch(Exception moveEx)
+ {
+ ErrorHandler.Error("Exception while rolling file [" + fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure);
+ }
+ }
+ else
+ {
+ LogLog.Warn(declaringType, "Cannot RollFile [" + fromFile + "] -> [" + toFile + "]. Source does not exist");
+ }
+ }
+
+ ///
+ /// Test if a file exists at a specified path
+ ///
+ /// the path to the file
+ /// true if the file exists
+ ///
+ ///
+ /// Test if a file exists at a specified path
+ ///
+ ///
+ protected bool FileExists(string path)
+ {
+ using(SecurityContext.Impersonate(this))
+ {
+ return System.IO.File.Exists(path);
+ }
+ }
+
+ ///
+ /// Deletes the specified file if it exists.
+ ///
+ /// The file to delete.
+ ///
+ ///
+ /// Delete a file if is exists.
+ /// The file is first moved to a new filename then deleted.
+ /// This allows the file to be removed even when it cannot
+ /// be deleted, but it still can be moved.
+ ///
+ ///
+ protected void DeleteFile(string fileName)
+ {
+ if (FileExists(fileName))
+ {
+ // We may not have permission to delete the file, or the file may be locked
+
+ string fileToDelete = fileName;
+
+ // Try to move the file to temp name.
+ // If the file is locked we may still be able to move it
+ string tempFileName = fileName + "." + Environment.TickCount + ".DeletePending";
+ try
+ {
+ using(SecurityContext.Impersonate(this))
+ {
+ System.IO.File.Move(fileName, tempFileName);
+ }
+ fileToDelete = tempFileName;
+ }
+ catch(Exception moveEx)
+ {
+ LogLog.Debug(declaringType, "Exception while moving file to be deleted [" + fileName + "] -> [" + tempFileName + "]", moveEx);
+ }
+
+ // Try to delete the file (either the original or the moved file)
+ try
+ {
+ using(SecurityContext.Impersonate(this))
+ {
+ System.IO.File.Delete(fileToDelete);
+ }
+ LogLog.Debug(declaringType, "Deleted file [" + fileName + "]");
+ }
+ catch(Exception deleteEx)
+ {
+ if (fileToDelete == fileName)
+ {
+ // Unable to move or delete the file
+ ErrorHandler.Error("Exception while deleting file [" + fileToDelete + "]", deleteEx, ErrorCode.GenericFailure);
+ }
+ else
+ {
+ // Moved the file, but the delete failed. File is probably locked.
+ // The file should automatically be deleted when the lock is released.
+ LogLog.Debug(declaringType, "Exception while deleting temp file [" + fileToDelete + "]", deleteEx);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Implements file roll base on file size.
+ ///
+ ///
+ ///
+ /// If the maximum number of size based backups is reached
+ /// (curSizeRollBackups == maxSizeRollBackups) then the oldest
+ /// file is deleted -- its index determined by the sign of countDirection.
+ /// If countDirection < 0, then files
+ /// {File.1, ..., File.curSizeRollBackups -1}
+ /// are renamed to {File.2, ...,
+ /// File.curSizeRollBackups}. Moreover, File is
+ /// renamed File.1 and closed.
+ ///
+ ///
+ /// A new file is created to receive further log output.
+ ///
+ ///
+ /// If maxSizeRollBackups is equal to zero, then the
+ /// File is truncated with no backup files created.
+ ///
+ ///
+ /// If maxSizeRollBackups < 0, then File is
+ /// renamed if needed and no files are deleted.
+ ///
+ ///
+ protected void RollOverSize()
+ {
+ this.CloseFile(); // keep windows happy.
+
+ LogLog.Debug(declaringType, "rolling over count ["+((CountingQuietTextWriter)QuietWriter).Count+"]");
+ LogLog.Debug(declaringType, "maxSizeRollBackups ["+m_maxSizeRollBackups+"]");
+ LogLog.Debug(declaringType, "curSizeRollBackups ["+m_curSizeRollBackups+"]");
+ LogLog.Debug(declaringType, "countDirection ["+m_countDirection+"]");
+
+ RollOverRenameFiles(File);
+
+ if (!m_staticLogFileName && m_countDirection >= 0)
+ {
+ m_curSizeRollBackups++;
+ }
+
+ // This will also close the file. This is OK since multiple close operations are safe.
+ SafeOpenFile(m_baseFileName, false);
+ }
+
+ ///
+ /// Implements file roll.
+ ///
+ /// the base name to rename
+ ///
+ ///
+ /// If the maximum number of size based backups is reached
+ /// (curSizeRollBackups == maxSizeRollBackups) then the oldest
+ /// file is deleted -- its index determined by the sign of countDirection.
+ /// If countDirection < 0, then files
+ /// {File.1, ..., File.curSizeRollBackups -1}
+ /// are renamed to {File.2, ...,
+ /// File.curSizeRollBackups}.
+ ///
+ ///
+ /// If maxSizeRollBackups is equal to zero, then the
+ /// File is truncated with no backup files created.
+ ///
+ ///
+ /// If maxSizeRollBackups < 0, then File is
+ /// renamed if needed and no files are deleted.
+ ///
+ ///
+ /// This is called by to rename the files.
+ ///
+ ///
+ protected void RollOverRenameFiles(string baseFileName)
+ {
+ // If maxBackups <= 0, then there is no file renaming to be done.
+ if (m_maxSizeRollBackups != 0)
+ {
+ if (m_countDirection < 0)
+ {
+ // Delete the oldest file, to keep Windows happy.
+ if (m_curSizeRollBackups == m_maxSizeRollBackups)
+ {
+ DeleteFile(CombinePath(baseFileName, "." + m_maxSizeRollBackups));
+ m_curSizeRollBackups--;
+ }
+
+ // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
+ for (int i = m_curSizeRollBackups; i >= 1; i--)
+ {
+ RollFile((CombinePath(baseFileName, "." + i)), (CombinePath(baseFileName, "." + (i + 1))));
+ }
+
+ m_curSizeRollBackups++;
+
+ // Rename fileName to fileName.1
+ RollFile(baseFileName, CombinePath(baseFileName, ".1"));
+ }
+ else
+ {
+ //countDirection >= 0
+ if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0)
+ {
+ //delete the first and keep counting up.
+ int oldestFileIndex = m_curSizeRollBackups - m_maxSizeRollBackups;
+
+ // If static then there is 1 file without a number, therefore 1 less archive
+ if (m_staticLogFileName)
+ {
+ oldestFileIndex++;
+ }
+
+ // If using a static log file then the base for the numbered sequence is the baseFileName passed in
+ // If not using a static log file then the baseFileName will already have a numbered postfix which
+ // we must remove, however it may have a date postfix which we must keep!
+ string archiveFileBaseName = baseFileName;
+ if (!m_staticLogFileName)
+ {
+ int lastDotIndex = archiveFileBaseName.LastIndexOf(".");
+ if (lastDotIndex >= 0)
+ {
+ archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex);
+ }
+ }
+
+ // Delete the archive file
+ DeleteFile(CombinePath(archiveFileBaseName, "." + oldestFileIndex));
+ }
+
+ if (m_staticLogFileName)
+ {
+ m_curSizeRollBackups++;
+ RollFile(baseFileName, CombinePath(baseFileName, "." + m_curSizeRollBackups));
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region NextCheckDate
+
+ ///
+ /// Get the start time of the next window for the current rollpoint
+ ///
+ /// the current date
+ /// the type of roll point we are working with
+ /// the start time for the next roll point an interval after the currentDateTime date
+ ///
+ ///
+ /// Returns the date of the next roll point after the currentDateTime date passed to the method.
+ ///
+ ///
+ /// The basic strategy is to subtract the time parts that are less significant
+ /// than the rollpoint from the current time. This should roll the time back to
+ /// the start of the time window for the current rollpoint. Then we add 1 window
+ /// worth of time and get the start time of the next window for the rollpoint.
+ ///
+ ///
+ protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint)
+ {
+ // Local variable to work on (this does not look very efficient)
+ DateTime current = currentDateTime;
+
+ // Do slightly different things depending on what the type of roll point we want.
+ switch(rollPoint)
+ {
+ case RollPoint.TopOfMinute:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(1);
+ break;
+
+ case RollPoint.TopOfHour:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(1);
+ break;
+
+ case RollPoint.HalfDay:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+
+ if (current.Hour < 12)
+ {
+ current = current.AddHours(12 - current.Hour);
+ }
+ else
+ {
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(1);
+ }
+ break;
+
+ case RollPoint.TopOfDay:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(1);
+ break;
+
+ case RollPoint.TopOfWeek:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(7 - (int)current.DayOfWeek);
+ break;
+
+ case RollPoint.TopOfMonth:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(1 - current.Day); /* first day of month is 1 not 0 */
+ current = current.AddMonths(1);
+ break;
+ }
+ return current;
+ }
+
+ #endregion
+
+ #region Private Instance Fields
+
+ ///
+ /// This object supplies the current date/time. Allows test code to plug in
+ /// a method to control this class when testing date/time based rolling. The default
+ /// implementation uses the underlying value of DateTime.Now.
+ ///
+ private IDateTime m_dateTime = null;
+
+ ///
+ /// The date pattern. By default, the pattern is set to ".yyyy-MM-dd"
+ /// meaning daily rollover.
+ ///
+ private string m_datePattern = ".yyyy-MM-dd";
+
+ ///
+ /// The actual formatted filename that is currently being written to
+ /// or will be the file transferred to on roll over
+ /// (based on staticLogFileName).
+ ///
+ private string m_scheduledFilename = null;
+
+ ///
+ /// The timestamp when we shall next recompute the filename.
+ ///
+ private DateTime m_nextCheck = DateTime.MaxValue;
+
+ ///
+ /// Holds date of last roll over
+ ///
+ private DateTime m_now;
+
+ ///
+ /// The type of rolling done
+ ///
+ private RollPoint m_rollPoint;
+
+ ///
+ /// The default maximum file size is 10MB
+ ///
+ private long m_maxFileSize = 10*1024*1024;
+
+ ///
+ /// There is zero backup files by default
+ ///
+ private int m_maxSizeRollBackups = 0;
+
+ ///
+ /// How many sized based backups have been made so far
+ ///
+ private int m_curSizeRollBackups = 0;
+
+ ///
+ /// The rolling file count direction.
+ ///
+ private int m_countDirection = -1;
+
+ ///
+ /// The rolling mode used in this appender.
+ ///
+ private RollingMode m_rollingStyle = RollingMode.Composite;
+
+ ///
+ /// Cache flag set if we are rolling by date.
+ ///
+ private bool m_rollDate = true;
+
+ ///
+ /// Cache flag set if we are rolling by size.
+ ///
+ private bool m_rollSize = true;
+
+ ///
+ /// Value indicating whether to always log to the same file.
+ ///
+ private bool m_staticLogFileName = true;
+
+ ///
+ /// Value indicating whether to preserve the file name extension when rolling.
+ ///
+ private bool m_preserveLogFileNameExtension = false;
+
+
+ ///
+ /// FileName provided in configuration. Used for rolling properly
+ ///
+ private string m_baseFileName;
+
+ ///
+ /// A mutex that is used to lock rolling of files.
+ ///
+ private Mutex m_mutexForRolling;
+
+ #endregion Private Instance Fields
+
+ #region Static Members
+
+ ///
+ /// The 1st of January 1970 in UTC
+ ///
+ private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1);
+
+ #endregion
+
+ #region DateTime
+
+ ///
+ /// This interface is used to supply Date/Time information to the .
+ ///
+ ///
+ /// This interface is used to supply Date/Time information to the .
+ /// Used primarily to allow test classes to plug themselves in so they can
+ /// supply test date/times.
+ ///
+ public interface IDateTime
+ {
+ ///
+ /// Gets the current time.
+ ///
+ /// The current time.
+ ///
+ ///
+ /// Gets the current time.
+ ///
+ ///
+ DateTime Now { get; }
+ }
+
+ ///
+ /// Default implementation of that returns the current time.
+ ///
+ private class LocalDateTime : IDateTime
+ {
+ ///
+ /// Gets the current time.
+ ///
+ /// The current time.
+ ///
+ ///
+ /// Gets the current time.
+ ///
+ ///
+ public DateTime Now
+ {
+ get { return DateTime.Now; }
+ }
+ }
+
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+ ///
+ /// Implementation of that returns the current time as the coordinated universal time (UTC).
+ ///
+ private class UniversalDateTime : IDateTime
+ {
+ ///
+ /// Gets the current time.
+ ///
+ /// The current time.
+ ///
+ ///
+ /// Gets the current time.
+ ///
+ ///
+ public DateTime Now
+ {
+ get { return DateTime.UtcNow; }
+ }
+ }
+#endif
+
+ #endregion DateTime
+ }
+}
diff --git a/src/Appender/SmtpAppender.cs b/src/Appender/SmtpAppender.cs
old mode 100755
new mode 100644
index 3ef90d73..491807c1
--- a/src/Appender/SmtpAppender.cs
+++ b/src/Appender/SmtpAppender.cs
@@ -23,8 +23,9 @@
using System;
using System.IO;
+using System.Text;
-#if NET_2_0
+#if NET_2_0 || MONO_2_0
using System.Net.Mail;
#else
using System.Web.Mail;
@@ -89,7 +90,7 @@ public SmtpAppender()
#region Public Instance Properties
///
- /// Gets or sets a semicolon-delimited list of recipient e-mail addresses.
+ /// Gets or sets a comma- or semicolon-delimited list of recipient e-mail addresses (use semicolon on .NET 1.1 and comma for later versions).
///
///
///
@@ -110,12 +111,12 @@ public SmtpAppender()
public string To
{
get { return m_to; }
- set { m_to = value; }
+ set { m_to = MaybeTrimSeparators(value); }
}
///
- /// Gets or sets a semicolon-delimited list of recipient e-mail addresses
- /// that will be carbon copied.
+ /// Gets or sets a comma- or semicolon-delimited list of recipient e-mail addresses
+ /// that will be carbon copied (use semicolon on .NET 1.1 and comma for later versions).
///
///
///
@@ -136,7 +137,7 @@ public string To
public string Cc
{
get { return m_cc; }
- set { m_cc = value; }
+ set { m_cc = MaybeTrimSeparators(value); }
}
///
@@ -154,7 +155,7 @@ public string Cc
public string Bcc
{
get { return m_bcc; }
- set { m_bcc = value; }
+ set { m_bcc = MaybeTrimSeparators(value); }
}
///
@@ -323,7 +324,7 @@ public MailPriority Priority
set { m_mailPriority = value; }
}
-#if NET_2_0
+#if NET_2_0 || MONO_2_0
///
/// Enable or disable use of SSL when sending e-mail message
///
@@ -349,6 +350,30 @@ public string ReplyTo
}
#endif
+ ///
+ /// Gets or sets the subject encoding to be used.
+ ///
+ ///
+ /// The default encoding is the operating system's current ANSI codepage.
+ ///
+ public Encoding SubjectEncoding
+ {
+ get { return m_subjectEncoding; }
+ set { m_subjectEncoding = value; }
+ }
+
+ ///
+ /// Gets or sets the body encoding to be used.
+ ///
+ ///
+ /// The default encoding is the operating system's current ANSI codepage.
+ ///
+ public Encoding BodyEncoding
+ {
+ get { return m_bodyEncoding; }
+ set { m_bodyEncoding = value; }
+ }
+
#endregion // Public Instance Properties
#region Override implementation of BufferingAppenderSkeleton
@@ -419,7 +444,7 @@ override protected bool RequiresLayout
/// the body text to include in the mail
virtual protected void SendEmail(string messageBody)
{
-#if NET_2_0
+#if NET_2_0 || MONO_2_0
// .NET 2.0 has a new API for SMTP email System.Net.Mail
// This API supports credentials and multiple hosts correctly.
// The old API is deprecated.
@@ -448,6 +473,7 @@ virtual protected void SendEmail(string messageBody)
using (MailMessage mailMessage = new MailMessage())
{
mailMessage.Body = messageBody;
+ mailMessage.BodyEncoding = m_bodyEncoding;
mailMessage.From = new MailAddress(m_from);
mailMessage.To.Add(m_to);
if (!String.IsNullOrEmpty(m_cc))
@@ -460,9 +486,16 @@ virtual protected void SendEmail(string messageBody)
}
if (!String.IsNullOrEmpty(m_replyTo))
{
+ // .NET 4.0 warning CS0618: 'System.Net.Mail.MailMessage.ReplyTo' is obsolete:
+ // 'ReplyTo is obsoleted for this type. Please use ReplyToList instead which can accept multiple addresses. http://go.microsoft.com/fwlink/?linkid=14202'
+#if !NET_4_0 && !MONO_4_0
mailMessage.ReplyTo = new MailAddress(m_replyTo);
+#else
+ mailMessage.ReplyToList.Add(new MailAddress(m_replyTo));
+#endif
}
mailMessage.Subject = m_subject;
+ mailMessage.SubjectEncoding = m_subjectEncoding;
mailMessage.Priority = m_mailPriority;
// TODO: Consider using SendAsync to send the message without blocking. This would be a change in
@@ -474,6 +507,7 @@ virtual protected void SendEmail(string messageBody)
MailMessage mailMessage = new MailMessage();
mailMessage.Body = messageBody;
+ mailMessage.BodyEncoding = m_bodyEncoding;
mailMessage.From = m_from;
mailMessage.To = m_to;
if (m_cc != null && m_cc.Length > 0)
@@ -485,6 +519,9 @@ virtual protected void SendEmail(string messageBody)
mailMessage.Bcc = m_bcc;
}
mailMessage.Subject = m_subject;
+#if !MONO && !NET_1_0 && !NET_1_1 && !CLI_1_0
+ mailMessage.SubjectEncoding = m_subjectEncoding;
+#endif
mailMessage.Priority = m_mailPriority;
#if NET_1_1
@@ -542,7 +579,7 @@ virtual protected void SendEmail(string messageBody)
SmtpMail.Send(mailMessage);
#endif // if NET_2_0
- }
+ }
#endregion // Protected Methods
@@ -554,6 +591,8 @@ virtual protected void SendEmail(string messageBody)
private string m_from;
private string m_subject;
private string m_smtpHost;
+ private Encoding m_subjectEncoding = Encoding.UTF8;
+ private Encoding m_bodyEncoding = Encoding.UTF8;
// authentication fields
private SmtpAuthentication m_authentication = SmtpAuthentication.None;
@@ -565,7 +604,7 @@ virtual protected void SendEmail(string messageBody)
private MailPriority m_mailPriority = MailPriority.Normal;
-#if NET_2_0
+#if NET_2_0 || MONO_2_0
private bool m_enableSsl = false;
private string m_replyTo;
#endif
@@ -607,7 +646,20 @@ public enum SmtpAuthentication
}
#endregion // SmtpAuthentication Enum
- }
+
+ private static readonly char[] ADDRESS_DELIMITERS = new char[] { ',', ';' };
+
+ ///
+ /// trims leading and trailing commas or semicolons
+ ///
+ private static string MaybeTrimSeparators(string s) {
+#if NET_2_0 || MONO_2_0
+ return string.IsNullOrEmpty(s) ? s : s.Trim(ADDRESS_DELIMITERS);
+#else
+ return s != null && s.Length > 0 ? s : s.Trim(ADDRESS_DELIMITERS);
+#endif
+ }
+ }
}
#endif // !NETCF && !SSCLI
diff --git a/src/Appender/SmtpPickupDirAppender.cs b/src/Appender/SmtpPickupDirAppender.cs
old mode 100755
new mode 100644
index 288d5b23..6d8efa63
--- a/src/Appender/SmtpPickupDirAppender.cs
+++ b/src/Appender/SmtpPickupDirAppender.cs
@@ -64,6 +64,7 @@ public class SmtpPickupDirAppender : BufferingAppenderSkeleton
///
public SmtpPickupDirAppender()
{
+ m_fileExtension = string.Empty; // Default to empty string, not null
}
#endregion Public Instance Constructors
@@ -136,6 +137,39 @@ public string PickupDir
set { m_pickupDir = value; }
}
+ ///
+ /// Gets or sets the file extension for the generated files
+ ///
+ ///
+ /// The file extension for the generated files
+ ///
+ ///
+ ///
+ /// The file extension for the generated files
+ ///
+ ///
+ public string FileExtension
+ {
+ get { return m_fileExtension; }
+ set
+ {
+ m_fileExtension = value;
+ if (m_fileExtension == null)
+ {
+ m_fileExtension = string.Empty;
+ }
+ // Make sure any non empty extension starts with a dot
+#if NET_2_0 || MONO_2_0
+ if (!string.IsNullOrEmpty(m_fileExtension) && !m_fileExtension.StartsWith("."))
+#else
+ if (m_fileExtension != null && m_fileExtension.Length > 0 && !m_fileExtension.StartsWith("."))
+#endif
+ {
+ m_fileExtension = "." + m_fileExtension;
+ }
+ }
+ }
+
///
/// Gets or sets the used to write to the pickup directory.
///
@@ -181,7 +215,7 @@ override protected void SendBuffer(LoggingEvent[] events)
// Impersonate to open the file
using(SecurityContext.Impersonate(this))
{
- filePath = Path.Combine(m_pickupDir, SystemInfo.NewGuid().ToString("N"));
+ filePath = Path.Combine(m_pickupDir, SystemInfo.NewGuid().ToString("N") + m_fileExtension);
writer = File.CreateText(filePath);
}
@@ -196,6 +230,7 @@ override protected void SendBuffer(LoggingEvent[] events)
writer.WriteLine("To: " + m_to);
writer.WriteLine("From: " + m_from);
writer.WriteLine("Subject: " + m_subject);
+ writer.WriteLine("Date: " + DateTime.UtcNow.ToString("r"));
writer.WriteLine("");
string t = Layout.Header;
@@ -306,6 +341,7 @@ protected static string ConvertToFullPath(string path)
private string m_from;
private string m_subject;
private string m_pickupDir;
+ private string m_fileExtension;
///
/// The security context to use for privileged calls
diff --git a/src/Appender/TelnetAppender.cs b/src/Appender/TelnetAppender.cs
old mode 100755
new mode 100644
diff --git a/src/Appender/TextWriterAppender.cs b/src/Appender/TextWriterAppender.cs
old mode 100755
new mode 100644
index 9f303cb0..e566c8fe
--- a/src/Appender/TextWriterAppender.cs
+++ b/src/Appender/TextWriterAppender.cs
@@ -203,7 +203,7 @@ override protected bool PreAppendCheck()
}
///
- /// This method is called by the
+ /// This method is called by the
/// method.
///
/// The event to log.
@@ -227,7 +227,7 @@ override protected void Append(LoggingEvent loggingEvent)
}
///
- /// This method is called by the
+ /// This method is called by the
/// method.
///
/// The array of events to log.
diff --git a/src/Appender/TraceAppender.cs b/src/Appender/TraceAppender.cs
old mode 100755
new mode 100644
diff --git a/src/Appender/UdpAppender.cs b/src/Appender/UdpAppender.cs
old mode 100755
new mode 100644
index e01b2356..ce5342b7
--- a/src/Appender/UdpAppender.cs
+++ b/src/Appender/UdpAppender.cs
@@ -387,7 +387,7 @@ public override void ActivateOptions()
#region Override implementation of AppenderSkeleton
///
- /// This method is called by the method.
+ /// This method is called by the method.
///
/// The event to log.
///
diff --git a/src/AssemblyInfo.cs b/src/AssemblyInfo.cs
old mode 100755
new mode 100644
index 89e04cd9..dd01f89d
--- a/src/AssemblyInfo.cs
+++ b/src/AssemblyInfo.cs
@@ -39,6 +39,14 @@
[assembly: System.Security.AllowPartiallyTrustedCallers]
#endif
+#if (NET_4_0)
+//
+// Allows partial trust applications (e.g. ASP.NET shared hosting) on .NET 4.0 to work
+// given our implementation of ISerializable.
+//
+[assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]
+#endif
+
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -46,35 +54,51 @@
//
#if (CLI_1_0)
-[assembly: AssemblyTitle("log4net for CLI 1.0 Compatible Frameworks")]
+[assembly: AssemblyTitle("Apache log4net for CLI 1.0 Compatible Frameworks")]
#elif (NET_1_0)
-[assembly: AssemblyTitle("log4net for .NET Framework 1.0")]
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 1.0")]
#elif (NET_1_1)
-[assembly: AssemblyTitle("log4net for .NET Framework 1.1")]
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 1.1")]
+#elif (NET_4_5)
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 4.5")]
+#elif (NET_4_0)
+#if CLIENT_PROFILE
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 4.0 Client Profile")]
+#else
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 4.0")]
+#endif // Client Profile
#elif (NET_2_0)
-[assembly: AssemblyTitle("log4net for .NET Framework 2.0")]
+#if CLIENT_PROFILE
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 3.5 Client Profile")]
+#else
+[assembly: AssemblyTitle("Apache log4net for .NET Framework 2.0")]
+#endif // Client Profile
#elif (NETCF_1_0)
-[assembly: AssemblyTitle("log4net for .NET Compact Framework 1.0")]
+[assembly: AssemblyTitle("Apache log4net for .NET Compact Framework 1.0")]
#elif (NETCF_2_0)
-[assembly: AssemblyTitle("log4net for .NET Compact Framework 2.0")]
+[assembly: AssemblyTitle("Apache log4net for .NET Compact Framework 2.0")]
#elif (MONO_1_0)
-[assembly: AssemblyTitle("log4net for Mono 1.0")]
+[assembly: AssemblyTitle("Apache log4net for Mono 1.0")]
#elif (MONO_2_0)
-[assembly: AssemblyTitle("log4net for Mono 2.0")]
+[assembly: AssemblyTitle("Apache log4net for Mono 2.0")]
+#elif (MONO_3_5)
+[assembly: AssemblyTitle("Apache log4net for Mono 3.5")]
+#elif (MONO_4_0)
+[assembly: AssemblyTitle("Apache log4net for Mono 4.0")]
#elif (SSCLI_1_0)
-[assembly: AssemblyTitle("log4net for Shared Source CLI 1.0")]
+[assembly: AssemblyTitle("Apache log4net for Shared Source CLI 1.0")]
#elif (CLI_1_0)
-[assembly: AssemblyTitle("log4net for CLI Compatible Frameworks")]
+[assembly: AssemblyTitle("Apache log4net for CLI Compatible Frameworks")]
#elif (NET)
-[assembly: AssemblyTitle("log4net for .NET Framework")]
+[assembly: AssemblyTitle("Apache log4net for .NET Framework")]
#elif (NETCF)
-[assembly: AssemblyTitle("log4net for .NET Compact Framework")]
+[assembly: AssemblyTitle("Apache log4net for .NET Compact Framework")]
#elif (MONO)
-[assembly: AssemblyTitle("log4net for Mono")]
+[assembly: AssemblyTitle("Apache log4net for Mono")]
#elif (SSCLI)
-[assembly: AssemblyTitle("log4net for Shared Source CLI")]
+[assembly: AssemblyTitle("Apache log4net for Shared Source CLI")]
#else
-[assembly: AssemblyTitle("log4net")]
+[assembly: AssemblyTitle("Apache log4net")]
#endif
#if DEBUG
@@ -83,7 +107,6 @@
[assembly: AssemblyConfiguration("Retail")]
#endif
-[assembly: AssemblyDescription("The Apache Software Foundation log4net Logging Framework")]
[assembly: AssemblyProduct("log4net")]
[assembly: AssemblyDefaultAlias("log4net")]
[assembly: AssemblyCulture("")]
diff --git a/src/AssemblyVersionInfo.cpp b/src/AssemblyVersionInfo.cpp
old mode 100755
new mode 100644
index 0bd84df3..f2ed861d
--- a/src/AssemblyVersionInfo.cpp
+++ b/src/AssemblyVersionInfo.cpp
@@ -31,12 +31,12 @@ using namespace System::Runtime::CompilerServices;
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersionAttribute("1.2.10.0")];
+[assembly: AssemblyVersionAttribute("1.2.15.0")];
[assembly: AssemblyInformationalVersionAttribute("1.2")];
#if !NETCF
#if !SSCLI
-[assembly: AssemblyFileVersionAttribute("1.2.10.0")]
+[assembly: AssemblyFileVersionAttribute("1.2.15.0")]
#endif
#endif
@@ -45,5 +45,5 @@ using namespace System::Runtime::CompilerServices;
//
[assembly: AssemblyCompany("The Apache Software Foundation")];
-[assembly: AssemblyCopyright("Copyright 2001-2007 The Apache Software Foundation.")];
-[assembly: AssemblyTrademark("Copyright 2001-2007 The Apache Software Foundation.")];
+[assembly: AssemblyCopyright("Copyright 2004-2015 The Apache Software Foundation.")];
+[assembly: AssemblyTrademark("Apache and Apache log4net are trademarks of The Apache Software Foundation")];
diff --git a/src/AssemblyVersionInfo.cs b/src/AssemblyVersionInfo.cs
old mode 100755
new mode 100644
index 86db947f..013ec888
--- a/src/AssemblyVersionInfo.cs
+++ b/src/AssemblyVersionInfo.cs
@@ -28,12 +28,12 @@
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: System.Reflection.AssemblyVersion("1.2.10.0")]
+[assembly: System.Reflection.AssemblyVersion("1.2.15.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.2")]
#if !NETCF
#if !SSCLI
-[assembly: System.Reflection.AssemblyFileVersion("1.2.10.0")]
+[assembly: System.Reflection.AssemblyFileVersion("1.2.15.0")]
#endif
#endif
@@ -42,5 +42,5 @@
//
[assembly: System.Reflection.AssemblyCompany("The Apache Software Foundation")]
-[assembly: System.Reflection.AssemblyCopyright("Copyright 2001-2007 The Apache Software Foundation.")]
-[assembly: System.Reflection.AssemblyTrademark("Copyright 2001-2007 The Apache Software Foundation.")]
+[assembly: System.Reflection.AssemblyCopyright("Copyright 2004-2015 The Apache Software Foundation.")]
+[assembly: System.Reflection.AssemblyTrademark("Apache and Apache log4net are trademarks of The Apache Software Foundation")]
diff --git a/src/AssemblyVersionInfo.js b/src/AssemblyVersionInfo.js
old mode 100755
new mode 100644
index f4ab3b2d..f3560d4e
--- a/src/AssemblyVersionInfo.js
+++ b/src/AssemblyVersionInfo.js
@@ -31,12 +31,12 @@
// an import functions as a workaround for this issue.
import System.Reflection;
-[assembly: AssemblyVersion("1.2.10.0")]
+[assembly: AssemblyVersion("1.2.15.0")]
[assembly: AssemblyInformationalVersionAttribute("1.2")]
@if (!@NETCF)
@if (!@SSCLI)
-[assembly: AssemblyFileVersion("1.2.10.0")]
+[assembly: AssemblyFileVersion("1.2.15.0")]
@end
@end
@@ -45,5 +45,5 @@ import System.Reflection;
//
[assembly: AssemblyCompany("The Apache Software Foundation")]
-[assembly: AssemblyCopyright("Copyright 2001-2007 The Apache Software Foundation.")]
-[assembly: AssemblyTrademark("Copyright 2001-2007 The Apache Software Foundation.")]
+[assembly: AssemblyCopyright("Copyright 2004-2015 The Apache Software Foundation.")]
+[assembly: AssemblyTrademark("Apache and Apache log4net are trademarks of The Apache Software Foundation")]
diff --git a/src/AssemblyVersionInfo.vb b/src/AssemblyVersionInfo.vb
old mode 100755
new mode 100644
index 60746364..2cac8527
--- a/src/AssemblyVersionInfo.vb
+++ b/src/AssemblyVersionInfo.vb
@@ -28,12 +28,12 @@
' You can specify all the values or you can default the Revision and Build Numbers
' by using the '*' as shown below:
-
+
#If NOT NETCF Then
#If NOT SSCLI Then
-
+
#End If
#End If
@@ -42,5 +42,5 @@
'
-
-
+
+
diff --git a/src/Config/AliasDomainAttribute.cs b/src/Config/AliasDomainAttribute.cs
old mode 100755
new mode 100644
diff --git a/src/Config/AliasRepositoryAttribute.cs b/src/Config/AliasRepositoryAttribute.cs
old mode 100755
new mode 100644
diff --git a/src/Config/BasicConfigurator.cs b/src/Config/BasicConfigurator.cs
old mode 100755
new mode 100644
index 5e97a0a9..8d617b4c
--- a/src/Config/BasicConfigurator.cs
+++ b/src/Config/BasicConfigurator.cs
@@ -43,7 +43,7 @@ namespace log4net.Config
///
///
/// Appenders can also implement the interface. Therefore
- /// they would require that the method
+ /// they would require that the method
/// be called after the appenders properties have been configured.
///
///
diff --git a/src/Config/ConfiguratorAttribute.cs b/src/Config/ConfiguratorAttribute.cs
old mode 100755
new mode 100644
diff --git a/src/Config/DOMConfigurator.cs b/src/Config/DOMConfigurator.cs
old mode 100755
new mode 100644
index eab029bb..54551af1
--- a/src/Config/DOMConfigurator.cs
+++ b/src/Config/DOMConfigurator.cs
@@ -309,10 +309,10 @@ static public void Configure(ILoggerRepository repository, Stream configStream)
///
///
/// For more information on how to configure log4net using
- /// a separate configuration file, see .
+ /// a separate configuration file, see .
///
///
- ///
+ ///
[Obsolete("Use XmlConfigurator.ConfigureAndWatch instead of DOMConfigurator.ConfigureAndWatch")]
static public void ConfigureAndWatch(FileInfo configFile)
{
@@ -341,10 +341,10 @@ static public void ConfigureAndWatch(FileInfo configFile)
///
///
/// For more information on how to configure log4net using
- /// a separate configuration file, see .
+ /// a separate configuration file, see .
///
///
- ///
+ ///
[Obsolete("Use XmlConfigurator.ConfigureAndWatch instead of DOMConfigurator.ConfigureAndWatch")]
static public void ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile)
{
diff --git a/src/Config/DOMConfiguratorAttribute.cs b/src/Config/DOMConfiguratorAttribute.cs
old mode 100755
new mode 100644
index beef7e16..e996b0e0
--- a/src/Config/DOMConfiguratorAttribute.cs
+++ b/src/Config/DOMConfiguratorAttribute.cs
@@ -43,7 +43,7 @@ namespace log4net.Config
///
///
/// Use this attribute to configure the
- /// without calling one of the
+ /// without calling one of the
/// methods.
///
///
diff --git a/src/Config/DomainAttribute.cs b/src/Config/DomainAttribute.cs
old mode 100755
new mode 100644
diff --git a/src/Config/Log4NetConfigurationSectionHandler.cs b/src/Config/Log4NetConfigurationSectionHandler.cs
old mode 100755
new mode 100644
diff --git a/src/Config/PluginAttribute.cs b/src/Config/PluginAttribute.cs
old mode 100755
new mode 100644
index 302a83a6..3533b253
--- a/src/Config/PluginAttribute.cs
+++ b/src/Config/PluginAttribute.cs
@@ -167,7 +167,7 @@ public IPlugin CreatePlugin()
///
///
///
- /// Overrides base class method to
+ /// Overrides base class method to
/// return a representation of the properties of this object.
///
///
diff --git a/src/Config/RepositoryAttribute.cs b/src/Config/RepositoryAttribute.cs
old mode 100755
new mode 100644
diff --git a/src/Config/SecurityContextProviderAttribute.cs b/src/Config/SecurityContextProviderAttribute.cs
old mode 100755
new mode 100644
index fd790c5b..c6f85572
--- a/src/Config/SecurityContextProviderAttribute.cs
+++ b/src/Config/SecurityContextProviderAttribute.cs
@@ -39,7 +39,7 @@ namespace log4net.Config
///
///
/// Use this attribute to configure the
- /// without calling one of the
+ /// without calling one of the
/// methods.
///
///
diff --git a/src/Config/XmlConfigurator.cs b/src/Config/XmlConfigurator.cs
old mode 100755
new mode 100644
index c7192bc3..03bdf599
--- a/src/Config/XmlConfigurator.cs
+++ b/src/Config/XmlConfigurator.cs
@@ -728,7 +728,13 @@ static private void InternalConfigure(ILoggerRepository repository, Stream confi
#elif NET_2_0
// Allow the DTD to specify entity includes
XmlReaderSettings settings = new XmlReaderSettings();
+ // .NET 4.0 warning CS0618: 'System.Xml.XmlReaderSettings.ProhibitDtd'
+ // is obsolete: 'Use XmlReaderSettings.DtdProcessing property instead.'
+#if !NET_4_0 && !MONO_4_0
settings.ProhibitDtd = false;
+#else
+ settings.DtdProcessing = DtdProcessing.Parse;
+#endif
// Create a reader over the input stream
XmlReader xmlReader = XmlReader.Create(configStream, settings);
@@ -798,10 +804,10 @@ static private void InternalConfigure(ILoggerRepository repository, Stream confi
///
///
/// For more information on how to configure log4net using
- /// a separate configuration file, see .
+ /// a separate configuration file, see .
///
///
- ///
+ ///
static public ICollection ConfigureAndWatch(FileInfo configFile)
{
ArrayList configurationMessages = new ArrayList();
@@ -837,10 +843,10 @@ static public ICollection ConfigureAndWatch(FileInfo configFile)
///
///
/// For more information on how to configure log4net using
- /// a separate configuration file, see .
+ /// a separate configuration file, see .
///
///
- ///
+ ///
static public ICollection ConfigureAndWatch(ILoggerRepository repository, FileInfo configFile)
{
ArrayList configurationMessages = new ArrayList();
@@ -874,18 +880,18 @@ static private void InternalConfigureAndWatch(ILoggerRepository repository, File
{
// support multiple repositories each having their own watcher
ConfigureAndWatchHandler handler =
- (ConfigureAndWatchHandler)m_repositoryName2ConfigAndWatchHandler[repository.Name];
+ (ConfigureAndWatchHandler)m_repositoryName2ConfigAndWatchHandler[configFile.FullName];
if (handler != null)
{
- m_repositoryName2ConfigAndWatchHandler.Remove(repository.Name);
+ m_repositoryName2ConfigAndWatchHandler.Remove(configFile.FullName);
handler.Dispose();
}
// Create and start a watch handler that will reload the
// configuration whenever the config file is modified.
handler = new ConfigureAndWatchHandler(repository, configFile);
- m_repositoryName2ConfigAndWatchHandler[repository.Name] = handler;
+ m_repositoryName2ConfigAndWatchHandler[configFile.FullName] = handler;
}
}
catch(Exception ex)
@@ -957,7 +963,10 @@ private sealed class ConfigureAndWatchHandler : IDisposable
/// Initializes a new instance of the class.
///
///
- public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile)
{
m_repository = repository;
m_configFile = configFile;
@@ -1034,6 +1043,9 @@ private void OnWatchedFileChange(object state)
///
/// Release the handles held by the watcher and timer.
///
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
public void Dispose()
{
m_watcher.EnableRaisingEvents = false;
diff --git a/src/Config/XmlConfiguratorAttribute.cs b/src/Config/XmlConfiguratorAttribute.cs
old mode 100755
new mode 100644
index 830610ba..6c3ea3e3
--- a/src/Config/XmlConfiguratorAttribute.cs
+++ b/src/Config/XmlConfiguratorAttribute.cs
@@ -41,7 +41,7 @@ namespace log4net.Config
///
///
/// Use this attribute to configure the
- /// without calling one of the
+ /// without calling one of the
/// methods.
///
///
@@ -72,7 +72,7 @@ namespace log4net.Config
///
/// If you cannot guarantee the order in which log4net calls will be made from
/// different assemblies you must use programmatic configuration instead, i.e.
- /// call the method directly.
+ /// call the method directly.
///
///
///
diff --git a/src/Core/CompactRepositorySelector.cs b/src/Core/CompactRepositorySelector.cs
old mode 100755
new mode 100644
index cd0486c0..dd46f6d5
--- a/src/Core/CompactRepositorySelector.cs
+++ b/src/Core/CompactRepositorySelector.cs
@@ -124,7 +124,7 @@ public ILoggerRepository GetRepository(Assembly assembly)
///
/// Get the named . The default
/// repository is log4net-default-repository. Other repositories
- /// must be created using the .
+ /// must be created using the .
/// If the named repository does not exist an exception is thrown.
///
///
@@ -203,7 +203,7 @@ public ILoggerRepository CreateRepository(Assembly assembly, Type repositoryType
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same repository specified will return the same repository instance.
///
///
@@ -267,8 +267,8 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository
/// true if the repository exists
///
///
- /// Test if a named repository exists. Use
- /// to create a new repository and to retrieve
+ /// Test if a named repository exists. Use
+ /// to create a new repository and to retrieve
/// a repository.
///
///
diff --git a/src/Core/DefaultRepositorySelector.cs b/src/Core/DefaultRepositorySelector.cs
old mode 100755
new mode 100644
index c0abf21c..a92a9792
--- a/src/Core/DefaultRepositorySelector.cs
+++ b/src/Core/DefaultRepositorySelector.cs
@@ -24,6 +24,7 @@
using System;
using System.Collections;
using System.Configuration;
+using System.IO;
using System.Reflection;
using log4net.Config;
@@ -150,7 +151,7 @@ public ILoggerRepository GetRepository(Assembly repositoryAssembly)
/// does not exist a is thrown.
///
///
- /// Use to create a repository.
+ /// Use to create a repository.
///
///
/// is .
@@ -183,7 +184,7 @@ public ILoggerRepository GetRepository(string repositoryName)
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
@@ -226,7 +227,7 @@ public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repo
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
@@ -346,7 +347,7 @@ public ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repo
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same repository specified will return the same repository instance.
///
///
@@ -432,8 +433,8 @@ public ILoggerRepository CreateRepository(string repositoryName, Type repository
/// true if the repository exists
///
///
- /// Test if a named repository exists. Use
- /// to create a new repository and to retrieve
+ /// Test if a named repository exists. Use
+ /// to create a new repository and to retrieve
/// a repository.
///
///
@@ -696,21 +697,66 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository
LogLog.Warn(declaringType, "Exception getting ApplicationBaseDirectory. appSettings log4net.Config path ["+repositoryConfigFile+"] will be treated as an absolute URI", ex);
}
- // As we are not going to watch the config file it is easiest to just resolve it as a
- // URI and pass that to the Configurator
- Uri repositoryConfigUri = null;
- try
+ string repositoryConfigFilePath = repositoryConfigFile;
+ if (applicationBaseDirectory != null)
+ {
+ repositoryConfigFilePath = Path.Combine(applicationBaseDirectory, repositoryConfigFile);
+ }
+
+ // Determine whether to watch the file or not based on an app setting value:
+ bool watchRepositoryConfigFile = false;
+#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
+ Boolean.TryParse(SystemInfo.GetAppSetting("log4net.Config.Watch"), out watchRepositoryConfigFile);
+#else
+ {
+ string watch = SystemInfo.GetAppSetting("log4net.Config.Watch");
+ if (watch != null && watch.Length > 0)
+ {
+ try
+ {
+ watchRepositoryConfigFile = Boolean.Parse(watch);
+ }
+ catch (FormatException)
+ {
+ // simply not a Boolean
+ }
+ }
+ }
+#endif
+
+ if (watchRepositoryConfigFile)
{
- if (applicationBaseDirectory != null)
+ // As we are going to watch the config file it is required to resolve it as a
+ // physical file system path pass that in a FileInfo object to the Configurator
+ FileInfo repositoryConfigFileInfo = null;
+ try
{
- // Resolve the config path relative to the application base directory URI
- repositoryConfigUri = new Uri(new Uri(applicationBaseDirectory), repositoryConfigFile);
+ repositoryConfigFileInfo = new FileInfo(repositoryConfigFilePath);
}
- else
+ catch (Exception ex)
+ {
+ LogLog.Error(declaringType, "DefaultRepositorySelector: Exception while parsing log4net.Config file physical path [" + repositoryConfigFilePath + "]", ex);
+ }
+ try
+ {
+ LogLog.Debug(declaringType, "Loading and watching configuration for default repository from AppSettings specified Config path [" + repositoryConfigFilePath + "]");
+
+ XmlConfigurator.ConfigureAndWatch(repository, repositoryConfigFileInfo);
+ }
+ catch (Exception ex)
{
- repositoryConfigUri = new Uri(repositoryConfigFile);
+ LogLog.Error(declaringType, "DefaultRepositorySelector: Exception calling XmlConfigurator.ConfigureAndWatch method with ConfigFilePath [" + repositoryConfigFilePath + "]", ex);
}
}
+ else
+ {
+ // As we are not going to watch the config file it is easiest to just resolve it as a
+ // URI and pass that to the Configurator
+ Uri repositoryConfigUri = null;
+ try
+ {
+ repositoryConfigUri = new Uri(repositoryConfigFilePath);
+ }
catch(Exception ex)
{
LogLog.Error(declaringType, "Exception while parsing log4net.Config file path ["+repositoryConfigFile+"]", ex);
@@ -730,6 +776,7 @@ private void ConfigureRepository(Assembly assembly, ILoggerRepository repository
LogLog.Error(declaringType, "Exception calling XmlConfigurator.Configure method with ConfigUri ["+repositoryConfigUri+"]", ex);
}
}
+ }
}
}
}
diff --git a/src/Core/ErrorCode.cs b/src/Core/ErrorCode.cs
old mode 100755
new mode 100644
index 22e0458c..9107a249
--- a/src/Core/ErrorCode.cs
+++ b/src/Core/ErrorCode.cs
@@ -22,11 +22,11 @@
namespace log4net.Core
{
///
- /// Defined error codes that can be passed to the method.
+ /// Defined error codes that can be passed to the method.
///
///
///
- /// Values passed to the method.
+ /// Values passed to the method.
///
///
/// Nicko Cadell
diff --git a/src/Core/ExceptionEvaluator.cs b/src/Core/ExceptionEvaluator.cs
index 106e453d..1b462f09 100644
--- a/src/Core/ExceptionEvaluator.cs
+++ b/src/Core/ExceptionEvaluator.cs
@@ -1,130 +1,130 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-
-namespace log4net.Core
-{
- ///
- /// An evaluator that triggers on an Exception type
- ///
- ///
- ///
- /// This evaluator will trigger if the type of the Exception
- /// passed to
- /// is equal to a Type in . ///
- ///
- ///
- /// Drew Schaeffer
- public class ExceptionEvaluator : ITriggeringEventEvaluator
- {
- ///
- /// The type that causes the trigger to fire.
- ///
- private Type m_type;
-
- ///
- /// Causes subclasses of to cause the trigger to fire.
- ///
- private bool m_triggerOnSubclass;
-
- ///
- /// Default ctor to allow dynamic creation through a configurator.
- ///
- public ExceptionEvaluator()
- {
- // empty
- }
-
- ///
- /// Constructs an evaluator and initializes to trigger on
- ///
- /// the type that triggers this evaluator.
- /// If true, this evaluator will trigger on subclasses of .
- public ExceptionEvaluator(Type exType, bool triggerOnSubClass)
- {
- if (exType == null)
- {
- throw new ArgumentNullException("exType");
- }
-
- m_type = exType;
- m_triggerOnSubclass = triggerOnSubClass;
- }
-
- ///
- /// The type that triggers this evaluator.
- ///
- public Type ExceptionType
- {
- get { return m_type; }
- set { m_type = value; }
- }
-
- ///
- /// If true, this evaluator will trigger on subclasses of .
- ///
- public bool TriggerOnSubclass
- {
- get { return m_triggerOnSubclass; }
- set { m_triggerOnSubclass = value; }
- }
-
- #region ITriggeringEventEvaluator Members
-
- ///
- /// Is this the triggering event?
- ///
- /// The event to check
- /// This method returns true, if the logging event Exception
- /// Type is .
- /// Otherwise it returns false
- ///
- ///
- /// This evaluator will trigger if the Exception Type of the event
- /// passed to
- /// is .
- ///
- ///
- public bool IsTriggeringEvent(LoggingEvent loggingEvent)
- {
- if (loggingEvent == null)
- {
- throw new ArgumentNullException("loggingEvent");
- }
-
- if (m_triggerOnSubclass && loggingEvent.ExceptionObject != null)
- {
- // check if loggingEvent.ExceptionObject is of type ExceptionType or subclass of ExceptionType
- Type exceptionObjectType = loggingEvent.ExceptionObject.GetType();
- return exceptionObjectType == m_type || exceptionObjectType.IsSubclassOf(m_type);
- }
- else if (!m_triggerOnSubclass && loggingEvent.ExceptionObject != null)
- { // check if loggingEvent.ExceptionObject is of type ExceptionType
- return loggingEvent.ExceptionObject.GetType() == m_type;
- }
- else
- { // loggingEvent.ExceptionObject is null
- return false;
- }
- }
-
- #endregion
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+
+namespace log4net.Core
+{
+ ///
+ /// An evaluator that triggers on an Exception type
+ ///
+ ///
+ ///
+ /// This evaluator will trigger if the type of the Exception
+ /// passed to
+ /// is equal to a Type in . ///
+ ///
+ ///
+ /// Drew Schaeffer
+ public class ExceptionEvaluator : ITriggeringEventEvaluator
+ {
+ ///
+ /// The type that causes the trigger to fire.
+ ///
+ private Type m_type;
+
+ ///
+ /// Causes subclasses of to cause the trigger to fire.
+ ///
+ private bool m_triggerOnSubclass;
+
+ ///
+ /// Default ctor to allow dynamic creation through a configurator.
+ ///
+ public ExceptionEvaluator()
+ {
+ // empty
+ }
+
+ ///
+ /// Constructs an evaluator and initializes to trigger on
+ ///
+ /// the type that triggers this evaluator.
+ /// If true, this evaluator will trigger on subclasses of .
+ public ExceptionEvaluator(Type exType, bool triggerOnSubClass)
+ {
+ if (exType == null)
+ {
+ throw new ArgumentNullException("exType");
+ }
+
+ m_type = exType;
+ m_triggerOnSubclass = triggerOnSubClass;
+ }
+
+ ///
+ /// The type that triggers this evaluator.
+ ///
+ public Type ExceptionType
+ {
+ get { return m_type; }
+ set { m_type = value; }
+ }
+
+ ///
+ /// If true, this evaluator will trigger on subclasses of .
+ ///
+ public bool TriggerOnSubclass
+ {
+ get { return m_triggerOnSubclass; }
+ set { m_triggerOnSubclass = value; }
+ }
+
+ #region ITriggeringEventEvaluator Members
+
+ ///
+ /// Is this the triggering event?
+ ///
+ /// The event to check
+ /// This method returns true, if the logging event Exception
+ /// Type is .
+ /// Otherwise it returns false
+ ///
+ ///
+ /// This evaluator will trigger if the Exception Type of the event
+ /// passed to
+ /// is .
+ ///
+ ///
+ public bool IsTriggeringEvent(LoggingEvent loggingEvent)
+ {
+ if (loggingEvent == null)
+ {
+ throw new ArgumentNullException("loggingEvent");
+ }
+
+ if (m_triggerOnSubclass && loggingEvent.ExceptionObject != null)
+ {
+ // check if loggingEvent.ExceptionObject is of type ExceptionType or subclass of ExceptionType
+ Type exceptionObjectType = loggingEvent.ExceptionObject.GetType();
+ return exceptionObjectType == m_type || exceptionObjectType.IsSubclassOf(m_type);
+ }
+ else if (!m_triggerOnSubclass && loggingEvent.ExceptionObject != null)
+ { // check if loggingEvent.ExceptionObject is of type ExceptionType
+ return loggingEvent.ExceptionObject.GetType() == m_type;
+ }
+ else
+ { // loggingEvent.ExceptionObject is null
+ return false;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Core/IAppenderAttachable.cs b/src/Core/IAppenderAttachable.cs
old mode 100755
new mode 100644
diff --git a/src/Core/IErrorHandler.cs b/src/Core/IErrorHandler.cs
old mode 100755
new mode 100644
index 9378f5fc..763e5186
--- a/src/Core/IErrorHandler.cs
+++ b/src/Core/IErrorHandler.cs
@@ -56,7 +56,7 @@ public interface IErrorHandler
/// The that was thrown when the error occurred.
///
///
- /// See .
+ /// See .
///
///
void Error(string message, Exception e);
@@ -67,7 +67,7 @@ public interface IErrorHandler
/// The message associated with the error.
///
///
- /// See .
+ /// See .
///
///
void Error(string message);
diff --git a/src/Core/IFixingRequired.cs b/src/Core/IFixingRequired.cs
old mode 100755
new mode 100644
diff --git a/src/Core/ILogger.cs b/src/Core/ILogger.cs
old mode 100755
new mode 100644
diff --git a/src/Core/ILoggerWrapper.cs b/src/Core/ILoggerWrapper.cs
old mode 100755
new mode 100644
diff --git a/src/Core/IOptionHandler.cs b/src/Core/IOptionHandler.cs
old mode 100755
new mode 100644
diff --git a/src/Core/IRepositorySelector.cs b/src/Core/IRepositorySelector.cs
old mode 100755
new mode 100644
index 22ebfdaa..55e393a3
--- a/src/Core/IRepositorySelector.cs
+++ b/src/Core/IRepositorySelector.cs
@@ -128,7 +128,7 @@ public interface IRepositorySelector
/// The named
///
/// Lookup a named . This is the repository created by
- /// calling .
+ /// calling .
///
ILoggerRepository GetRepository(string repositoryName);
@@ -141,7 +141,7 @@ public interface IRepositorySelector
///
///
/// The created will be associated with the domain
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
@@ -161,7 +161,7 @@ public interface IRepositorySelector
///
///
/// The created will be associated with the name
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same name will return the same repository instance.
///
///
@@ -174,8 +174,8 @@ public interface IRepositorySelector
/// true if the repository exists
///
///
- /// Test if a named repository exists. Use
- /// to create a new repository and to retrieve
+ /// Test if a named repository exists. Use
+ /// to create a new repository and to retrieve
/// a repository.
///
///
diff --git a/src/Core/ITriggeringEventEvaluator.cs b/src/Core/ITriggeringEventEvaluator.cs
old mode 100755
new mode 100644
diff --git a/src/Core/Level.cs b/src/Core/Level.cs
old mode 100755
new mode 100644
diff --git a/src/Core/LevelCollection.cs b/src/Core/LevelCollection.cs
old mode 100755
new mode 100644
index 1428c67c..1287ac01
--- a/src/Core/LevelCollection.cs
+++ b/src/Core/LevelCollection.cs
@@ -541,9 +541,9 @@ public virtual void TrimToSize()
#region Implementation (helpers)
///
- /// is less than zero
+ /// is less than zero
/// -or-
- /// is equal to or greater than .
+ /// is equal to or greater than .
///
private void ValidateIndex(int i)
{
@@ -551,9 +551,9 @@ private void ValidateIndex(int i)
}
///
- /// is less than zero
+ /// is less than zero
/// -or-
- /// is equal to or greater than .
+ /// is equal to or greater than .
///
private void ValidateIndex(int i, bool allowEqualEnd)
{
diff --git a/src/Core/LevelEvaluator.cs b/src/Core/LevelEvaluator.cs
old mode 100755
new mode 100644
index ec35ea71..35706df8
--- a/src/Core/LevelEvaluator.cs
+++ b/src/Core/LevelEvaluator.cs
@@ -29,7 +29,7 @@ namespace log4net.Core
///
///
/// This evaluator will trigger if the level of the event
- /// passed to
+ /// passed to
/// is equal to or greater than the
/// level.
///
@@ -51,7 +51,7 @@ public class LevelEvaluator : ITriggeringEventEvaluator
///
///
/// This evaluator will trigger if the level of the event
- /// passed to
+ /// passed to
/// is equal to or greater than the
/// level.
///
@@ -70,7 +70,7 @@ public LevelEvaluator() : this(Level.Off)
///
///
/// This evaluator will trigger if the level of the event
- /// passed to
+ /// passed to
/// is equal to or greater than the
/// level.
///
@@ -94,7 +94,7 @@ public LevelEvaluator(Level threshold)
///
///
/// This evaluator will trigger if the level of the event
- /// passed to
+ /// passed to
/// is equal to or greater than the
/// level.
///
@@ -115,7 +115,7 @@ public Level Threshold
///
///
/// This evaluator will trigger if the level of the event
- /// passed to
+ /// passed to
/// is equal to or greater than the
/// level.
///
diff --git a/src/Core/LevelMap.cs b/src/Core/LevelMap.cs
old mode 100755
new mode 100644
index c48b28c3..d458533a
--- a/src/Core/LevelMap.cs
+++ b/src/Core/LevelMap.cs
@@ -112,7 +112,7 @@ public Level this[string name]
/// Create a new Level and add it to the map
///
///
- ///
+ ///
public void Add(string name, int value)
{
Add(name, value, null);
diff --git a/src/Core/LocationInfo.cs b/src/Core/LocationInfo.cs
old mode 100755
new mode 100644
index 7afc02fc..8f96c4e8
--- a/src/Core/LocationInfo.cs
+++ b/src/Core/LocationInfo.cs
@@ -118,10 +118,10 @@ public LocationInfo(Type callerStackBoundaryDeclaringType)
// take into account the frames we skip above
int adjustedFrameCount = st.FrameCount - frameIndex;
ArrayList stackFramesList = new ArrayList(adjustedFrameCount);
- m_stackFrames = new StackFrame[adjustedFrameCount];
+ m_stackFrames = new StackFrameItem[adjustedFrameCount];
for (int i=frameIndex; i < st.FrameCount; i++)
{
- stackFramesList.Add(st.GetFrame(i));
+ stackFramesList.Add(new StackFrameItem(st.GetFrame(i)));
}
stackFramesList.CopyTo(m_stackFrames, 0);
@@ -271,13 +271,15 @@ public string FullInfo
get { return m_fullInfo; }
}
+#if !NETCF
///
/// Gets the stack frames from the stack trace of the caller making the log request
///
- public StackFrame[] StackFrames
+ public StackFrameItem[] StackFrames
{
get { return m_stackFrames; }
}
+#endif
#endregion Public Instance Properties
@@ -288,7 +290,9 @@ public StackFrame[] StackFrames
private readonly string m_lineNumber;
private readonly string m_methodName;
private readonly string m_fullInfo;
- private readonly StackFrame[] m_stackFrames;
+#if !NETCF
+ private readonly StackFrameItem[] m_stackFrames;
+#endif
#endregion Private Instance Fields
diff --git a/src/Core/LogException.cs b/src/Core/LogException.cs
old mode 100755
new mode 100644
diff --git a/src/Core/LogImpl.cs b/src/Core/LogImpl.cs
old mode 100755
new mode 100644
index 36427dcf..64c2edf9
--- a/src/Core/LogImpl.cs
+++ b/src/Core/LogImpl.cs
@@ -41,7 +41,7 @@ namespace log4net.Core
///
/// DEBUG
///
- /// The and methods log messages
+ /// The and methods log messages
/// at the DEBUG level. That is the level with that name defined in the
/// repositories . The default value
/// for this level is . The
@@ -51,7 +51,7 @@ namespace log4net.Core
///
/// INFO
///
- /// The and methods log messages
+ /// The and methods log messages
/// at the INFO level. That is the level with that name defined in the
/// repositories . The default value
/// for this level is . The
@@ -61,7 +61,7 @@ namespace log4net.Core
///
/// WARN
///
- /// The and methods log messages
+ /// The and methods log messages
/// at the WARN level. That is the level with that name defined in the
/// repositories . The default value
/// for this level is . The
@@ -71,7 +71,7 @@ namespace log4net.Core
///
/// ERROR
///
- /// The and methods log messages
+ /// The and methods log messages
/// at the ERROR level. That is the level with that name defined in the
/// repositories . The default value
/// for this level is . The
@@ -81,7 +81,7 @@ namespace log4net.Core
///
/// FATAL
///
- /// The and methods log messages
+ /// The and methods log messages
/// at the FATAL level. That is the level with that name defined in the
/// repositories . The default value
/// for this level is . The
@@ -162,7 +162,7 @@ protected virtual void ReloadLevels(ILoggerRepository repository)
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
virtual public void Debug(object message)
@@ -182,10 +182,10 @@ virtual public void Debug(object message)
/// as a parameter.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
virtual public void Debug(object message, Exception exception)
{
Logger.Log(ThisDeclaringType, m_levelDebug, message, exception);
@@ -198,18 +198,18 @@ virtual public void Debug(object message, Exception exception)
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -228,18 +228,18 @@ virtual public void DebugFormat(string format, params object[] args)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -259,18 +259,18 @@ virtual public void DebugFormat(string format, object arg0)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -291,18 +291,18 @@ virtual public void DebugFormat(string format, object arg0, object arg1)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -322,13 +322,13 @@ virtual public void DebugFormat(string format, object arg0, object arg1, object
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -360,7 +360,7 @@ virtual public void DebugFormat(IFormatProvider provider, string format, params
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
virtual public void Info(object message)
@@ -380,10 +380,10 @@ virtual public void Info(object message)
/// passed as a parameter.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
virtual public void Info(object message, Exception exception)
{
Logger.Log(ThisDeclaringType, m_levelInfo, message, exception);
@@ -396,18 +396,18 @@ virtual public void Info(object message, Exception exception)
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -426,18 +426,18 @@ virtual public void InfoFormat(string format, params object[] args)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -457,18 +457,18 @@ virtual public void InfoFormat(string format, object arg0)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -489,18 +489,18 @@ virtual public void InfoFormat(string format, object arg0, object arg1)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -520,13 +520,13 @@ virtual public void InfoFormat(string format, object arg0, object arg1, object a
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -558,7 +558,7 @@ virtual public void InfoFormat(IFormatProvider provider, string format, params o
/// WARNING Note that passing an to this
/// method will print the name of the but no
/// stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
virtual public void Warn(object message)
@@ -578,10 +578,10 @@ virtual public void Warn(object message)
/// passed as a parameter.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
virtual public void Warn(object message, Exception exception)
{
Logger.Log(ThisDeclaringType, m_levelWarn, message, exception);
@@ -594,18 +594,18 @@ virtual public void Warn(object message, Exception exception)
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -624,18 +624,18 @@ virtual public void WarnFormat(string format, params object[] args)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -655,18 +655,18 @@ virtual public void WarnFormat(string format, object arg0)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -687,18 +687,18 @@ virtual public void WarnFormat(string format, object arg0, object arg1)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -718,13 +718,13 @@ virtual public void WarnFormat(string format, object arg0, object arg1, object a
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -756,7 +756,7 @@ virtual public void WarnFormat(IFormatProvider provider, string format, params o
/// WARNING Note that passing an to this
/// method will print the name of the but no
/// stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
virtual public void Error(object message)
@@ -776,10 +776,10 @@ virtual public void Error(object message)
/// passed as a parameter.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
virtual public void Error(object message, Exception exception)
{
Logger.Log(ThisDeclaringType, m_levelError, message, exception);
@@ -792,18 +792,18 @@ virtual public void Error(object message, Exception exception)
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -822,18 +822,18 @@ virtual public void ErrorFormat(string format, params object[] args)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -853,18 +853,18 @@ virtual public void ErrorFormat(string format, object arg0)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -885,18 +885,18 @@ virtual public void ErrorFormat(string format, object arg0, object arg1)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -916,13 +916,13 @@ virtual public void ErrorFormat(string format, object arg0, object arg1, object
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -954,7 +954,7 @@ virtual public void ErrorFormat(IFormatProvider provider, string format, params
/// WARNING Note that passing an to this
/// method will print the name of the but no
/// stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
virtual public void Fatal(object message)
@@ -974,10 +974,10 @@ virtual public void Fatal(object message)
/// passed as a parameter.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
virtual public void Fatal(object message, Exception exception)
{
Logger.Log(ThisDeclaringType, m_levelFatal, message, exception);
@@ -990,18 +990,18 @@ virtual public void Fatal(object message, Exception exception)
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -1020,18 +1020,18 @@ virtual public void FatalFormat(string format, params object[] args)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -1051,18 +1051,18 @@ virtual public void FatalFormat(string format, object arg0)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -1083,18 +1083,18 @@ virtual public void FatalFormat(string format, object arg0, object arg1)
/// An Object to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// The string is formatted using the
/// format provider. To specify a localized provider use the
- /// method.
+ /// method.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
@@ -1114,13 +1114,13 @@ virtual public void FatalFormat(string format, object arg0, object arg1, object
/// An Object array containing zero or more objects to format
///
///
- /// The message is formatted using the method. See
+ /// The message is formatted using the method. See
/// String.Format for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
diff --git a/src/Core/LoggerManager.cs b/src/Core/LoggerManager.cs
old mode 100755
new mode 100644
index 678666de..9a3afedd
--- a/src/Core/LoggerManager.cs
+++ b/src/Core/LoggerManager.cs
@@ -404,7 +404,7 @@ public static ILogger GetLogger(Assembly repositoryAssembly, string name)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
/// The repository to lookup in.
/// The of which the fullname will be used as the name of the logger to retrieve.
@@ -428,7 +428,7 @@ public static ILogger GetLogger(string repository, Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
/// the assembly to use to lookup the repository
/// The of which the fullname will be used as the name of the logger to retrieve.
@@ -702,7 +702,7 @@ public static ILoggerRepository CreateRepository(string repository, Type reposit
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
@@ -723,7 +723,7 @@ public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type r
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
@@ -769,7 +769,7 @@ public static ILoggerRepository[] GetAllRepositories()
///
/// The caller to supplies either a string name
/// or an assembly (if not supplied the assembly is inferred using
- /// ).
+ /// ).
///
///
/// This context is used by the selector to lookup a specific repository.
@@ -823,7 +823,7 @@ private static string GetVersionInfo()
/// Called when the event fires.
///
///
- /// When the event is triggered the log4net system is .
+ /// When the event is triggered the log4net system is .
///
///
private static void OnDomainUnload(object sender, EventArgs e)
@@ -841,7 +841,7 @@ private static void OnDomainUnload(object sender, EventArgs e)
/// Called when the event fires.
///
///
- /// When the event is triggered the log4net system is .
+ /// When the event is triggered the log4net system is .
///
///
private static void OnProcessExit(object sender, EventArgs e)
diff --git a/src/Core/LoggerWrapperImpl.cs b/src/Core/LoggerWrapperImpl.cs
old mode 100755
new mode 100644
diff --git a/src/Core/LoggingEvent.cs b/src/Core/LoggingEvent.cs
old mode 100755
new mode 100644
index 0cbc025b..787aa84a
--- a/src/Core/LoggingEvent.cs
+++ b/src/Core/LoggingEvent.cs
@@ -278,8 +278,8 @@ [Flags] public enum FixFlags
/// time the event is delivered to appenders, but will not be consistent
/// at any time afterwards. If an event is to be stored and then processed
/// at a later time these volatile values must be fixed by calling
- /// . There is a performance penalty
- /// for incurred by calling but it
+ /// . There is a performance penalty
+ /// for incurred by calling but it
/// is essential to maintaining data consistency.
///
///
@@ -314,7 +314,7 @@ public class LoggingEvent
///
/// Except , and ,
/// all fields of LoggingEvent are filled when actually needed. Call
- /// to cache all data locally
+ /// to cache all data locally
/// to prevent inconsistencies.
///
/// This method is called by the log4net framework
@@ -351,7 +351,7 @@ public LoggingEvent(Type callerStackBoundaryDeclaringType, log4net.Repository.IL
/// be useful if you require a custom serialization scheme.
///
///
- /// Use the method to obtain an
+ /// Use the method to obtain an
/// instance of the class.
///
///
@@ -384,7 +384,7 @@ public LoggingEvent(Type callerStackBoundaryDeclaringType, log4net.Repository.IL
/// be useful if you require a custom serialization scheme.
///
///
- /// Use the method to obtain an
+ /// Use the method to obtain an
/// instance of the class.
///
///
@@ -409,7 +409,7 @@ public LoggingEvent(Type callerStackBoundaryDeclaringType, log4net.Repository.IL
/// be useful if you require a custom serialization scheme.
///
///
- /// Use the method to obtain an
+ /// Use the method to obtain an
/// instance of the class.
///
///
@@ -893,7 +893,16 @@ public string Identity
m_data.Identity = "";
}
}
- catch(System.Security.SecurityException)
+ catch (ObjectDisposedException)
+ {
+ // This exception will occur if System.Threading.Thread.CurrentPrincipal.Identity is not null but
+ // the getter of the property Name tries to access disposed objects.
+ // Seen to happen on IIS 7 or greater with windows authentication.
+ LogLog.Debug(declaringType, "Object disposed exception while trying to get current thread principal. Error Ignored. Empty identity name.");
+
+ m_data.Identity = "";
+ }
+ catch (System.Security.SecurityException)
{
// This security exception will occur if the caller does not have
// some undefined set of SecurityPermission flags.
@@ -1008,12 +1017,16 @@ public FixFlags Fix
/// The data in this event must be fixed before it can be serialized.
///
///
- /// The method must be called during the
+ /// The method must be called during the
/// method call if this event
/// is to be used outside that method.
///
///
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecurityCritical]
+#else
[System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter=true)]
+#endif
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
// The caller must call FixVolatileData before this object
@@ -1140,17 +1153,17 @@ public string GetExceptionString()
/// time the event is delivered to appenders, but will not be consistent
/// at any time afterwards. If an event is to be stored and then processed
/// at a later time these volatile values must be fixed by calling
- /// . There is a performance penalty
- /// incurred by calling but it
+ /// . There is a performance penalty
+ /// incurred by calling but it
/// is essential to maintaining data consistency.
///
///
- /// Calling is equivalent to
- /// calling passing the parameter
+ /// Calling is equivalent to
+ /// calling passing the parameter
/// false.
///
///
- /// See for more
+ /// See for more
/// information.
///
///
@@ -1171,8 +1184,8 @@ public void FixVolatileData()
/// time the event is delivered to appenders, but will not be consistent
/// at any time afterwards. If an event is to be stored and then processed
/// at a later time these volatile values must be fixed by calling
- /// . There is a performance penalty
- /// for incurred by calling but it
+ /// . There is a performance penalty
+ /// for incurred by calling but it
/// is essential to maintaining data consistency.
///
///
@@ -1322,6 +1335,12 @@ private void CreateCompositeProperties()
// TODO: Add Repository Properties
+ // event properties
+ PropertiesDictionary eventProperties = new PropertiesDictionary();
+ eventProperties[UserNameProperty] = UserName;
+ eventProperties[IdentityProperty] = Identity;
+ m_compositeProperties.Add(eventProperties);
+
m_compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties());
}
@@ -1526,4 +1545,4 @@ public PropertiesDictionary GetProperties()
#endregion
}
-}
+}
\ No newline at end of file
diff --git a/src/Core/MethodItem.cs b/src/Core/MethodItem.cs
new file mode 100644
index 00000000..a8b90c65
--- /dev/null
+++ b/src/Core/MethodItem.cs
@@ -0,0 +1,171 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+using System;
+using System.Text;
+using System.Collections;
+
+using log4net.Util;
+
+namespace log4net.Core
+{
+ ///
+ /// provides method information without actually referencing a System.Reflection.MethodBase
+ /// as that would require that the containing assembly is loaded.
+ ///
+ ///
+#if !NETCF
+ [Serializable]
+#endif
+ public class MethodItem
+ {
+ #region Public Instance Constructors
+
+ ///
+ /// constructs a method item for an unknown method.
+ ///
+ public MethodItem()
+ {
+ m_name = NA;
+ m_parameters = new string[0];
+ }
+
+ ///
+ /// constructs a method item from the name of the method.
+ ///
+ ///
+ public MethodItem(string name)
+ : this()
+ {
+ m_name = name;
+ }
+
+ ///
+ /// constructs a method item from the name of the method and its parameters.
+ ///
+ ///
+ ///
+ public MethodItem(string name, string[] parameters)
+ : this(name)
+ {
+ m_parameters = parameters;
+ }
+
+ ///
+ /// constructs a method item from a method base by determining the method name and its parameters.
+ ///
+ ///
+ public MethodItem(System.Reflection.MethodBase methodBase)
+ : this(methodBase.Name, GetMethodParameterNames(methodBase))
+ {
+ }
+
+ #endregion
+
+ private static string[] GetMethodParameterNames(System.Reflection.MethodBase methodBase)
+ {
+ ArrayList methodParameterNames = new ArrayList();
+ try
+ {
+ System.Reflection.ParameterInfo[] methodBaseGetParameters = methodBase.GetParameters();
+
+ int methodBaseGetParametersCount = methodBaseGetParameters.GetUpperBound(0);
+
+ for (int i = 0; i <= methodBaseGetParametersCount; i++)
+ {
+ methodParameterNames.Add(methodBaseGetParameters[i].ParameterType + " " + methodBaseGetParameters[i].Name);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogLog.Error(declaringType, "An exception ocurred while retreiving method parameters.", ex);
+ }
+
+ return (string[])methodParameterNames.ToArray(typeof(string));
+ }
+
+ #region Public Instance Properties
+
+ ///
+ /// Gets the method name of the caller making the logging
+ /// request.
+ ///
+ ///
+ /// The method name of the caller making the logging
+ /// request.
+ ///
+ ///
+ ///
+ /// Gets the method name of the caller making the logging
+ /// request.
+ ///
+ ///
+ public string Name
+ {
+ get { return m_name; }
+ }
+
+ ///
+ /// Gets the method parameters of the caller making
+ /// the logging request.
+ ///
+ ///
+ /// The method parameters of the caller making
+ /// the logging request
+ ///
+ ///
+ ///
+ /// Gets the method parameters of the caller making
+ /// the logging request.
+ ///
+ ///
+ public string[] Parameters
+ {
+ get { return m_parameters; }
+ }
+
+ #endregion
+
+ #region Private Instance Fields
+
+ private readonly string m_name;
+ private readonly string[] m_parameters;
+
+ #endregion
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the StackFrameItem class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(MethodItem);
+
+ ///
+ /// When location information is not available the constant
+ /// NA is returned. Current value of this string
+ /// constant is ?.
+ ///
+ private const string NA = "?";
+
+ #endregion Private Static Fields
+ }
+}
diff --git a/src/Core/SecurityContext.cs b/src/Core/SecurityContext.cs
old mode 100755
new mode 100644
diff --git a/src/Core/SecurityContextProvider.cs b/src/Core/SecurityContextProvider.cs
old mode 100755
new mode 100644
diff --git a/src/Core/StackFrameItem.cs b/src/Core/StackFrameItem.cs
new file mode 100644
index 00000000..0a3e1d08
--- /dev/null
+++ b/src/Core/StackFrameItem.cs
@@ -0,0 +1,196 @@
+#if !NETCF
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+using System;
+using System.Text;
+using System.Diagnostics;
+using System.Reflection;
+using log4net.Util;
+
+namespace log4net.Core
+{
+ ///
+ /// provides stack frame information without actually referencing a System.Diagnostics.StackFrame
+ /// as that would require that the containing assembly is loaded.
+ ///
+ ///
+ [Serializable]
+ public class StackFrameItem
+ {
+ #region Public Instance Constructors
+
+ ///
+ /// returns a stack frame item from a stack frame. This
+ ///
+ ///
+ ///
+ public StackFrameItem(StackFrame frame)
+ {
+ // set default values
+ m_lineNumber = NA;
+ m_fileName = NA;
+ m_method = new MethodItem();
+ m_className = NA;
+
+ try
+ {
+ // get frame values
+ m_lineNumber = frame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
+ m_fileName = frame.GetFileName();
+ // get method values
+ MethodBase method = frame.GetMethod();
+ if (method != null)
+ {
+ if(method.DeclaringType != null)
+ m_className = method.DeclaringType.FullName;
+ m_method = new MethodItem(method);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogLog.Error(declaringType, "An exception ocurred while retreiving stack frame information.", ex);
+ }
+
+ // set full info
+ m_fullInfo = m_className + '.' + m_method.Name + '(' + m_fileName + ':' + m_lineNumber + ')';
+ }
+
+ #endregion
+
+ #region Public Instance Properties
+
+ ///
+ /// Gets the fully qualified class name of the caller making the logging
+ /// request.
+ ///
+ ///
+ /// The fully qualified class name of the caller making the logging
+ /// request.
+ ///
+ ///
+ ///
+ /// Gets the fully qualified class name of the caller making the logging
+ /// request.
+ ///
+ ///
+ public string ClassName
+ {
+ get { return m_className; }
+ }
+
+ ///
+ /// Gets the file name of the caller.
+ ///
+ ///
+ /// The file name of the caller.
+ ///
+ ///
+ ///
+ /// Gets the file name of the caller.
+ ///
+ ///
+ public string FileName
+ {
+ get { return m_fileName; }
+ }
+
+ ///
+ /// Gets the line number of the caller.
+ ///
+ ///
+ /// The line number of the caller.
+ ///
+ ///
+ ///
+ /// Gets the line number of the caller.
+ ///
+ ///
+ public string LineNumber
+ {
+ get { return m_lineNumber; }
+ }
+
+ ///
+ /// Gets the method name of the caller.
+ ///
+ ///
+ /// The method name of the caller.
+ ///
+ ///
+ ///
+ /// Gets the method name of the caller.
+ ///
+ ///
+ public MethodItem Method
+ {
+ get { return m_method; }
+ }
+
+ ///
+ /// Gets all available caller information
+ ///
+ ///
+ /// All available caller information, in the format
+ /// fully.qualified.classname.of.caller.methodName(Filename:line)
+ ///
+ ///
+ ///
+ /// Gets all available caller information, in the format
+ /// fully.qualified.classname.of.caller.methodName(Filename:line)
+ ///
+ ///
+ public string FullInfo
+ {
+ get { return m_fullInfo; }
+ }
+
+ #endregion Public Instance Properties
+
+ #region Private Instance Fields
+
+ private readonly string m_lineNumber;
+ private readonly string m_fileName;
+ private readonly string m_className;
+ private readonly string m_fullInfo;
+ private readonly MethodItem m_method;
+
+ #endregion
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the StackFrameItem class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(StackFrameItem);
+
+ ///
+ /// When location information is not available the constant
+ /// NA is returned. Current value of this string
+ /// constant is ?.
+ ///
+ private const string NA = "?";
+
+ #endregion Private Static Fields
+ }
+}
+#endif
diff --git a/src/Core/TimeEvaluator.cs b/src/Core/TimeEvaluator.cs
index bfa60dd8..66ec8f68 100644
--- a/src/Core/TimeEvaluator.cs
+++ b/src/Core/TimeEvaluator.cs
@@ -1,147 +1,148 @@
-#region Copyright & License
-//
-// Copyright 2001-2005 The Apache Software Foundation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-
-namespace log4net.Core
-{
- ///
- /// An evaluator that triggers after specified number of seconds.
- ///
- ///
- ///
- /// This evaluator will trigger if the specified time period
- /// has passed since last check.
- ///
- ///
- /// Robert Sevcik
- public class TimeEvaluator : ITriggeringEventEvaluator
- {
- ///
- /// The time threshold for triggering in seconds. Zero means it won't trigger at all.
- ///
- private int m_interval;
-
- ///
- /// The time of last check. This gets updated when the object is created and when the evaluator triggers.
- ///
- private DateTime m_lasttime;
-
- ///
- /// The default time threshold for triggering in seconds. Zero means it won't trigger at all.
- ///
- const int DEFAULT_INTERVAL = 0;
-
- ///
- /// Create a new evaluator using the time threshold in seconds.
- ///
- ///
- ///
- /// Create a new evaluator using the time threshold in seconds.
- ///
- ///
- /// This evaluator will trigger if the specified time period
- /// has passed since last check.
- ///
- ///
- public TimeEvaluator()
- : this(DEFAULT_INTERVAL)
- {
- }
-
- ///
- /// Create a new evaluator using the specified time threshold in seconds.
- ///
- ///
- /// The time threshold in seconds to trigger after.
- /// Zero means it won't trigger at all.
- ///
- ///
- ///
- /// Create a new evaluator using the specified time threshold in seconds.
- ///
- ///
- /// This evaluator will trigger if the specified time period
- /// has passed since last check.
- ///
- ///
- public TimeEvaluator(int interval)
- {
- m_interval = interval;
- m_lasttime = DateTime.Now;
- }
-
- ///
- /// The time threshold in seconds to trigger after
- ///
- ///
- /// The time threshold in seconds to trigger after.
- /// Zero means it won't trigger at all.
- ///
- ///
- ///
- /// This evaluator will trigger if the specified time period
- /// has passed since last check.
- ///
- ///
- public int Interval
- {
- get { return m_interval; }
- set { m_interval = value; }
- }
-
- ///
- /// Is this the triggering event?
- ///
- /// The event to check
- /// This method returns true, if the specified time period
- /// has passed since last check..
- /// Otherwise it returns false
- ///
- ///
- /// This evaluator will trigger if the specified time period
- /// has passed since last check.
- ///
- ///
- public bool IsTriggeringEvent(LoggingEvent loggingEvent)
- {
- if (loggingEvent == null)
- {
- throw new ArgumentNullException("loggingEvent");
- }
-
- // disable the evaluator if threshold is zero
- if (m_interval == 0) return false;
-
- lock (this) // avoid triggering multiple times
- {
- TimeSpan passed = DateTime.Now.Subtract(m_lasttime);
-
- if (passed.TotalSeconds > m_interval)
- {
- m_lasttime = DateTime.Now;
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- }
-}
+#region Copyright & License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+
+namespace log4net.Core
+{
+ ///
+ /// An evaluator that triggers after specified number of seconds.
+ ///
+ ///
+ ///
+ /// This evaluator will trigger if the specified time period
+ /// has passed since last check.
+ ///
+ ///
+ /// Robert Sevcik
+ public class TimeEvaluator : ITriggeringEventEvaluator
+ {
+ ///
+ /// The time threshold for triggering in seconds. Zero means it won't trigger at all.
+ ///
+ private int m_interval;
+
+ ///
+ /// The time of last check. This gets updated when the object is created and when the evaluator triggers.
+ ///
+ private DateTime m_lasttime;
+
+ ///
+ /// The default time threshold for triggering in seconds. Zero means it won't trigger at all.
+ ///
+ const int DEFAULT_INTERVAL = 0;
+
+ ///
+ /// Create a new evaluator using the time threshold in seconds.
+ ///
+ ///
+ ///
+ /// Create a new evaluator using the time threshold in seconds.
+ ///
+ ///
+ /// This evaluator will trigger if the specified time period
+ /// has passed since last check.
+ ///
+ ///
+ public TimeEvaluator()
+ : this(DEFAULT_INTERVAL)
+ {
+ }
+
+ ///
+ /// Create a new evaluator using the specified time threshold in seconds.
+ ///
+ ///
+ /// The time threshold in seconds to trigger after.
+ /// Zero means it won't trigger at all.
+ ///
+ ///
+ ///
+ /// Create a new evaluator using the specified time threshold in seconds.
+ ///
+ ///
+ /// This evaluator will trigger if the specified time period
+ /// has passed since last check.
+ ///
+ ///
+ public TimeEvaluator(int interval)
+ {
+ m_interval = interval;
+ m_lasttime = DateTime.Now;
+ }
+
+ ///
+ /// The time threshold in seconds to trigger after
+ ///
+ ///
+ /// The time threshold in seconds to trigger after.
+ /// Zero means it won't trigger at all.
+ ///
+ ///
+ ///
+ /// This evaluator will trigger if the specified time period
+ /// has passed since last check.
+ ///
+ ///
+ public int Interval
+ {
+ get { return m_interval; }
+ set { m_interval = value; }
+ }
+
+ ///
+ /// Is this the triggering event?
+ ///
+ /// The event to check
+ /// This method returns true, if the specified time period
+ /// has passed since last check..
+ /// Otherwise it returns false
+ ///
+ ///
+ /// This evaluator will trigger if the specified time period
+ /// has passed since last check.
+ ///
+ ///
+ public bool IsTriggeringEvent(LoggingEvent loggingEvent)
+ {
+ if (loggingEvent == null)
+ {
+ throw new ArgumentNullException("loggingEvent");
+ }
+
+ // disable the evaluator if threshold is zero
+ if (m_interval == 0) return false;
+
+ lock (this) // avoid triggering multiple times
+ {
+ TimeSpan passed = DateTime.Now.Subtract(m_lasttime);
+
+ if (passed.TotalSeconds > m_interval)
+ {
+ m_lasttime = DateTime.Now;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Core/WrapperMap.cs b/src/Core/WrapperMap.cs
old mode 100755
new mode 100644
diff --git a/src/DateFormatter/AbsoluteTimeDateFormatter.cs b/src/DateFormatter/AbsoluteTimeDateFormatter.cs
old mode 100755
new mode 100644
index 460aa6d8..11741073
--- a/src/DateFormatter/AbsoluteTimeDateFormatter.cs
+++ b/src/DateFormatter/AbsoluteTimeDateFormatter.cs
@@ -18,6 +18,7 @@
#endregion
using System;
+using System.Collections;
using System.IO;
using System.Text;
@@ -100,22 +101,36 @@ virtual protected void FormatDateWithoutMillis(DateTime dateToFormat, StringBuil
///
virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
{
+ lock (s_lastTimeStrings)
+ {
// Calculate the current time precise only to the second
long currentTimeToTheSecond = (dateToFormat.Ticks - (dateToFormat.Ticks % TimeSpan.TicksPerSecond));
+ string timeString = null;
// Compare this time with the stored last time
// If we are in the same second then append
// the previously calculated time string
- if (s_lastTimeToTheSecond != currentTimeToTheSecond)
- {
+ if (s_lastTimeToTheSecond != currentTimeToTheSecond)
+ {
+ s_lastTimeStrings.Clear();
+ }
+ else
+ {
+ timeString = (string) s_lastTimeStrings[GetType()];
+ }
+
+ if (timeString == null)
+ {
// lock so that only one thread can use the buffer and
- // update the s_lastTimeToTheSecond and s_lastTimeString
+ // update the s_lastTimeToTheSecond and s_lastTimeStrings
// PERF: Try removing this lock and using a new StringBuilder each time
lock(s_lastTimeBuf)
{
- if (s_lastTimeToTheSecond != currentTimeToTheSecond)
- {
+ timeString = (string) s_lastTimeStrings[GetType()];
+
+ if (timeString == null)
+ {
// We are in a new second.
s_lastTimeBuf.Length = 0;
@@ -123,7 +138,7 @@ virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf);
// Render the string buffer to a string
- string currentDateWithoutMillis = s_lastTimeBuf.ToString();
+ timeString = s_lastTimeBuf.ToString();
#if NET_1_1
// Ensure that the above string is written into the variable NOW on all threads.
@@ -131,12 +146,12 @@ virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
System.Threading.Thread.MemoryBarrier();
#endif
// Store the time as a string (we only have to do this once per second)
- s_lastTimeString = currentDateWithoutMillis;
+ s_lastTimeStrings[GetType()] = timeString;
s_lastTimeToTheSecond = currentTimeToTheSecond;
}
}
}
- writer.Write(s_lastTimeString);
+ writer.Write(timeString);
// Append the current millisecond info
writer.Write(',');
@@ -150,6 +165,7 @@ virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
writer.Write('0');
}
writer.Write(millis);
+ }
}
#endregion Implementation of IDateFormatter
@@ -190,7 +206,7 @@ virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
/// Last stored time with precision up to the second, formatted
/// as a string.
///
- private static string s_lastTimeString;
+ private static Hashtable s_lastTimeStrings = new Hashtable();
#endregion Private Static Fields
}
diff --git a/src/DateFormatter/DateTimeDateFormatter.cs b/src/DateFormatter/DateTimeDateFormatter.cs
old mode 100755
new mode 100644
diff --git a/src/DateFormatter/IDateFormatter.cs b/src/DateFormatter/IDateFormatter.cs
old mode 100755
new mode 100644
diff --git a/src/DateFormatter/Iso8601DateFormatter.cs b/src/DateFormatter/Iso8601DateFormatter.cs
old mode 100755
new mode 100644
diff --git a/src/DateFormatter/SimpleDateFormatter.cs b/src/DateFormatter/SimpleDateFormatter.cs
old mode 100755
new mode 100644
index 79f5318e..c112ca1a
--- a/src/DateFormatter/SimpleDateFormatter.cs
+++ b/src/DateFormatter/SimpleDateFormatter.cs
@@ -23,11 +23,11 @@
namespace log4net.DateFormatter
{
///
- /// Formats the using the method.
+ /// Formats the using the method.
///
///
///
- /// Formats the using the method.
+ /// Formats the using the method.
///
///
/// Nicko Cadell
@@ -47,7 +47,7 @@ public class SimpleDateFormatter : IDateFormatter
///
///
/// The format string must be compatible with the options
- /// that can be supplied to .
+ /// that can be supplied to .
///
///
public SimpleDateFormatter(string format)
@@ -60,14 +60,14 @@ public SimpleDateFormatter(string format)
#region Implementation of IDateFormatter
///
- /// Formats the date using .
+ /// Formats the date using .
///
/// The date to convert to a string.
/// The writer to write to.
///
///
/// Uses the date format string supplied to the constructor to call
- /// the method to format the date.
+ /// the method to format the date.
///
///
virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
@@ -85,7 +85,7 @@ virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
///
///
/// The format string must be compatible with the options
- /// that can be supplied to .
+ /// that can be supplied to .
///
///
private readonly string m_formatString;
diff --git a/src/Filter/DenyAllFilter.cs b/src/Filter/DenyAllFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/FilterDecision.cs b/src/Filter/FilterDecision.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/FilterSkeleton.cs b/src/Filter/FilterSkeleton.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/IFilter.cs b/src/Filter/IFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/LevelMatchFilter.cs b/src/Filter/LevelMatchFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/LevelRangeFilter.cs b/src/Filter/LevelRangeFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/LoggerMatchFilter.cs b/src/Filter/LoggerMatchFilter.cs
old mode 100755
new mode 100644
index 247a9772..828a304e
--- a/src/Filter/LoggerMatchFilter.cs
+++ b/src/Filter/LoggerMatchFilter.cs
@@ -96,7 +96,7 @@ public bool AcceptOnMatch
///
/// This filter will attempt to match this value against logger name in
/// the following way. The match will be done against the beginning of the
- /// logger name (using ). The match is
+ /// logger name (using ). The match is
/// case sensitive. If a match is found then
/// the result depends on the value of .
///
@@ -120,7 +120,7 @@ public string LoggerToMatch
///
/// The rendered message is matched against the .
/// If the equals the beginning of
- /// the incoming ()
+ /// the incoming ()
/// then a match will have occurred. If no match occurs
/// this function will return
/// allowing other filters to check the event. If a match occurs then
diff --git a/src/Filter/MdcFilter.cs b/src/Filter/MdcFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/NdcFilter.cs b/src/Filter/NdcFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/PropertyFilter.cs b/src/Filter/PropertyFilter.cs
old mode 100755
new mode 100644
diff --git a/src/Filter/StringMatchFilter.cs b/src/Filter/StringMatchFilter.cs
old mode 100755
new mode 100644
diff --git a/src/GlobalContext.cs b/src/GlobalContext.cs
old mode 100755
new mode 100644
diff --git a/src/ILog.cs b/src/ILog.cs
old mode 100755
new mode 100644
index 2e81e85b..89d01c75
--- a/src/ILog.cs
+++ b/src/ILog.cs
@@ -31,7 +31,7 @@ namespace log4net
///
///
/// Use the to obtain logger instances
- /// that implement this interface. The
+ /// that implement this interface. The
/// static method is used to get logger instances.
///
///
@@ -60,7 +60,7 @@ namespace log4net
///
///
///
- ///
+ ///
/// Nicko Cadell
/// Gert Driesen
public interface ILog : ILoggerWrapper
@@ -85,10 +85,10 @@ public interface ILog : ILoggerWrapper
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
- ///
+ ///
///
void Debug(object message);
@@ -101,10 +101,10 @@ public interface ILog : ILoggerWrapper
/// The exception to log, including its stack trace.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
///
void Debug(object message, Exception exception);
@@ -117,16 +117,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void DebugFormat(string format, params object[] args);
@@ -138,16 +138,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void DebugFormat(string format, object arg0);
@@ -160,16 +160,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void DebugFormat(string format, object arg0, object arg1);
@@ -183,16 +183,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void DebugFormat(string format, object arg0, object arg1, object arg2);
@@ -205,16 +205,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void DebugFormat(IFormatProvider provider, string format, params object[] args);
@@ -237,11 +237,11 @@ public interface ILog : ILoggerWrapper
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
/// The message object to log.
- ///
+ ///
///
void Info(object message);
@@ -254,10 +254,10 @@ public interface ILog : ILoggerWrapper
/// The exception to log, including its stack trace.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
///
void Info(object message, Exception exception);
@@ -270,16 +270,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void InfoFormat(string format, params object[] args);
@@ -291,16 +291,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void InfoFormat(string format, object arg0);
@@ -313,16 +313,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void InfoFormat(string format, object arg0, object arg1);
@@ -336,16 +336,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void InfoFormat(string format, object arg0, object arg1, object arg2);
@@ -358,16 +358,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void InfoFormat(IFormatProvider provider, string format, params object[] args);
@@ -390,11 +390,11 @@ public interface ILog : ILoggerWrapper
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
/// The message object to log.
- ///
+ ///
///
void Warn(object message);
@@ -407,10 +407,10 @@ public interface ILog : ILoggerWrapper
/// The exception to log, including its stack trace.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
///
void Warn(object message, Exception exception);
@@ -423,16 +423,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void WarnFormat(string format, params object[] args);
@@ -444,16 +444,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void WarnFormat(string format, object arg0);
@@ -466,16 +466,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void WarnFormat(string format, object arg0, object arg1);
@@ -489,16 +489,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void WarnFormat(string format, object arg0, object arg1, object arg2);
@@ -511,16 +511,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void WarnFormat(IFormatProvider provider, string format, params object[] args);
@@ -544,10 +544,10 @@ public interface ILog : ILoggerWrapper
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
- ///
+ ///
///
void Error(object message);
@@ -560,10 +560,10 @@ public interface ILog : ILoggerWrapper
/// The exception to log, including its stack trace.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
///
void Error(object message, Exception exception);
@@ -576,16 +576,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void ErrorFormat(string format, params object[] args);
@@ -597,16 +597,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void ErrorFormat(string format, object arg0);
@@ -619,16 +619,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void ErrorFormat(string format, object arg0, object arg1);
@@ -642,16 +642,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void ErrorFormat(string format, object arg0, object arg1, object arg2);
@@ -664,16 +664,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void ErrorFormat(IFormatProvider provider, string format, params object[] args);
@@ -696,11 +696,11 @@ public interface ILog : ILoggerWrapper
/// WARNING Note that passing an
/// to this method will print the name of the
/// but no stack trace. To print a stack trace use the
- /// form instead.
+ /// form instead.
///
///
/// The message object to log.
- ///
+ ///
///
void Fatal(object message);
@@ -713,10 +713,10 @@ public interface ILog : ILoggerWrapper
/// The exception to log, including its stack trace.
///
///
- /// See the form for more detailed information.
+ /// See the form for more detailed information.
///
///
- ///
+ ///
///
void Fatal(object message, Exception exception);
@@ -729,16 +729,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void FatalFormat(string format, params object[] args);
@@ -750,16 +750,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void FatalFormat(string format, object arg0);
@@ -772,16 +772,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void FatalFormat(string format, object arg0, object arg1);
@@ -795,16 +795,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void FatalFormat(string format, object arg0, object arg1, object arg2);
@@ -817,16 +817,16 @@ public interface ILog : ILoggerWrapper
///
///
/// The message is formatted using the String.Format method. See
- /// for details of the syntax of the format string and the behavior
+ /// for details of the syntax of the format string and the behavior
/// of the formatting.
///
///
/// This method does not take an object to include in the
- /// log event. To pass an use one of the
+ /// log event. To pass an use one of the
/// methods instead.
///
///
- ///
+ ///
///
void FatalFormat(IFormatProvider provider, string format, params object[] args);
@@ -864,7 +864,7 @@ public interface ILog : ILoggerWrapper
/// the other hand, if the log is debug enabled, you
/// will incur the cost of evaluating whether the logger is debug
/// enabled twice. Once in and once in
- /// the . This is an insignificant overhead
+ /// the . This is an insignificant overhead
/// since evaluating a logger takes about 1% of the time it
/// takes to actually log. This is the preferred style of logging.
///
@@ -897,8 +897,8 @@ public interface ILog : ILoggerWrapper
/// speed or runtime flexibility.
///
///
- ///
- ///
+ ///
+ ///
bool IsDebugEnabled { get; }
///
@@ -910,8 +910,8 @@ public interface ILog : ILoggerWrapper
///
/// For more information see .
///
- ///
- ///
+ ///
+ ///
///
bool IsInfoEnabled { get; }
@@ -924,8 +924,8 @@ public interface ILog : ILoggerWrapper
///
/// For more information see .
///
- ///
- ///
+ ///
+ ///
///
bool IsWarnEnabled { get; }
@@ -938,8 +938,8 @@ public interface ILog : ILoggerWrapper
///
/// For more information see .
///
- ///
- ///
+ ///
+ ///
///
bool IsErrorEnabled { get; }
@@ -952,8 +952,8 @@ public interface ILog : ILoggerWrapper
///
/// For more information see .
///
- ///
- ///
+ ///
+ ///
///
bool IsFatalEnabled { get; }
}
diff --git a/src/Layout/DynamicPatternLayout.cs b/src/Layout/DynamicPatternLayout.cs
new file mode 100644
index 00000000..28174be1
--- /dev/null
+++ b/src/Layout/DynamicPatternLayout.cs
@@ -0,0 +1,143 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+
+using System;
+using System.Collections;
+using System.IO;
+
+using log4net.Core;
+using log4net.Layout.Pattern;
+using log4net.Util;
+
+namespace log4net.Layout
+{
+ ///
+ /// A flexible layout configurable with pattern string that re-evaluates on each call.
+ ///
+ ///
+ /// This class is built on and provides all the
+ /// features and capabilities of PatternLayout. PatternLayout is a 'static' class
+ /// in that its layout is done once at configuration time. This class will recreate
+ /// the layout on each reference.
+ /// One important difference between PatternLayout and DynamicPatternLayout is the
+ /// treatment of the Header and Footer parameters in the configuration. The Header and Footer
+ /// parameters for DynamicPatternLayout must be syntactically in the form of a PatternString,
+ /// but should not be marked as type log4net.Util.PatternString. Doing so causes the
+ /// pattern to be statically converted at configuration time and causes DynamicPatternLayout
+ /// to perform the same as PatternLayout.
+ /// Please see for complete documentation.
+ ///
+ /// <layout type="log4net.Layout.DynamicPatternLayout">
+ /// <param name="Header" value="%newline**** Trace Opened Local: %date{yyyy-MM-dd HH:mm:ss.fff} UTC: %utcdate{yyyy-MM-dd HH:mm:ss.fff} ****%newline" />
+ /// <param name="Footer" value="**** Trace Closed %date{yyyy-MM-dd HH:mm:ss.fff} ****%newline" />
+ /// </layout>
+ ///
+ ///
+ public class DynamicPatternLayout: PatternLayout
+ {
+ #region Member Variables
+ ///
+ /// The header PatternString
+ ///
+ private PatternString m_headerPatternString = new PatternString("");
+
+ ///
+ /// The footer PatternString
+ ///
+ private PatternString m_footerPatternString = new PatternString("");
+ #endregion
+
+ #region Constructors
+ ///
+ /// Constructs a DynamicPatternLayout using the DefaultConversionPattern
+ ///
+ ///
+ ///
+ /// The default pattern just produces the application supplied message.
+ ///
+ ///
+ public DynamicPatternLayout()
+ : base()
+ {
+ }
+
+ ///
+ /// Constructs a DynamicPatternLayout using the supplied conversion pattern
+ ///
+ /// the pattern to use
+ ///
+ ///
+ public DynamicPatternLayout (string pattern)
+ : base(pattern)
+ {
+ }
+ #endregion
+
+ #region Override implementation of LayoutSkeleton
+ ///
+ /// The header for the layout format.
+ ///
+ /// the layout header
+ ///
+ ///
+ /// The Header text will be appended before any logging events
+ /// are formatted and appended.
+ ///
+ /// The pattern will be formatted on each get operation.
+ ///
+ public override string Header
+ {
+ get
+ {
+ return m_headerPatternString.Format();
+ }
+ set
+ {
+ base.Header = value;
+ m_headerPatternString = new PatternString(value);
+ }
+ } /* property DynamicPatternLayout Header */
+
+ ///
+ /// The footer for the layout format.
+ ///
+ /// the layout footer
+ ///
+ ///
+ /// The Footer text will be appended after all the logging events
+ /// have been formatted and appended.
+ ///
+ /// The pattern will be formatted on each get operation.
+ ///
+ public override string Footer
+ {
+ get
+ {
+ return m_footerPatternString.Format();
+ }
+ set
+ {
+ base.Footer = value;
+ m_footerPatternString = new PatternString(value);
+ }
+ } /* property DynamicPatternLayout Footer */
+ #endregion
+ } /* class DynamicPatternLayout */
+} /* namespace log4net.Layout */
diff --git a/src/Layout/ExceptionLayout.cs b/src/Layout/ExceptionLayout.cs
old mode 100755
new mode 100644
index b64b34dd..06c4509b
--- a/src/Layout/ExceptionLayout.cs
+++ b/src/Layout/ExceptionLayout.cs
@@ -90,7 +90,7 @@ override public void ActivateOptions()
///
///
/// Write the exception string to the .
- /// The exception string is retrieved from .
+ /// The exception string is retrieved from .
///
///
override public void Format(TextWriter writer, LoggingEvent loggingEvent)
diff --git a/src/Layout/ILayout.cs b/src/Layout/ILayout.cs
old mode 100755
new mode 100644
index 88c758a9..2bb6aef4
--- a/src/Layout/ILayout.cs
+++ b/src/Layout/ILayout.cs
@@ -31,7 +31,7 @@ namespace log4net.Layout
///
///
/// An object is used to format a
- /// as text. The method is called by an
+ /// as text. The method is called by an
/// appender to transform the into a string.
///
///
diff --git a/src/Layout/IRawLayout.cs b/src/Layout/IRawLayout.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Layout2RawLayoutAdapter.cs b/src/Layout/Layout2RawLayoutAdapter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/LayoutSkeleton.cs b/src/Layout/LayoutSkeleton.cs
old mode 100755
new mode 100644
index da68b9b8..b373ee14
--- a/src/Layout/LayoutSkeleton.cs
+++ b/src/Layout/LayoutSkeleton.cs
@@ -37,7 +37,7 @@ namespace log4net.Layout
///
///
///
- /// Subclasses must implement the
+ /// Subclasses must implement the
/// method.
///
///
diff --git a/src/Layout/Pattern/AppDomainPatternConverter.cs b/src/Layout/Pattern/AppDomainPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/AspNetCachePatternConverter.cs b/src/Layout/Pattern/AspNetCachePatternConverter.cs
index a8905fc8..4452a5b9 100644
--- a/src/Layout/Pattern/AspNetCachePatternConverter.cs
+++ b/src/Layout/Pattern/AspNetCachePatternConverter.cs
@@ -1,77 +1,77 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-// .NET Compact Framework 1.0 has no support for ASP.NET
-// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
-
-using System.IO;
-using System.Web;
-using log4net.Core;
-using log4net.Util;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Converter for items in the ASP.Net Cache.
- ///
- ///
- ///
- /// Outputs an item from the .
- ///
- ///
- /// Ron Grabowski
- internal sealed class AspNetCachePatternConverter : AspNetPatternLayoutConverter
- {
- ///
- /// Write the ASP.Net Cache item to the output
- ///
- /// that will receive the formatted result.
- /// The on which the pattern converter should be executed.
- /// The under which the ASP.Net request is running.
- ///
- ///
- /// Writes out the value of a named property. The property name
- /// should be set in the
- /// property. If no property has been set, all key value pairs from the Cache will
- /// be written to the output.
- ///
- ///
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
- {
- if (HttpRuntime.Cache != null)
- {
- if (Option != null)
- {
- WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache[Option]);
- }
- else
- {
- WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache.GetEnumerator());
- }
- }
- else
- {
- writer.Write(SystemInfo.NotAvailableText);
- }
- }
- }
-}
-
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+// .NET Compact Framework 1.0 has no support for ASP.NET
+// SSCLI 1.0 has no support for ASP.NET
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
+
+using System.IO;
+using System.Web;
+using log4net.Core;
+using log4net.Util;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Converter for items in the ASP.Net Cache.
+ ///
+ ///
+ ///
+ /// Outputs an item from the .
+ ///
+ ///
+ /// Ron Grabowski
+ internal sealed class AspNetCachePatternConverter : AspNetPatternLayoutConverter
+ {
+ ///
+ /// Write the ASP.Net Cache item to the output
+ ///
+ /// that will receive the formatted result.
+ /// The on which the pattern converter should be executed.
+ /// The under which the ASP.Net request is running.
+ ///
+ ///
+ /// Writes out the value of a named property. The property name
+ /// should be set in the
+ /// property. If no property has been set, all key value pairs from the Cache will
+ /// be written to the output.
+ ///
+ ///
+ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
+ {
+ if (HttpRuntime.Cache != null)
+ {
+ if (Option != null)
+ {
+ WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache[Option]);
+ }
+ else
+ {
+ WriteObject(writer, loggingEvent.Repository, HttpRuntime.Cache.GetEnumerator());
+ }
+ }
+ else
+ {
+ writer.Write(SystemInfo.NotAvailableText);
+ }
+ }
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/src/Layout/Pattern/AspNetContextPatternConverter.cs b/src/Layout/Pattern/AspNetContextPatternConverter.cs
index 0075f357..61a9e179 100644
--- a/src/Layout/Pattern/AspNetContextPatternConverter.cs
+++ b/src/Layout/Pattern/AspNetContextPatternConverter.cs
@@ -1,68 +1,68 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-// .NET Compact Framework 1.0 has no support for ASP.NET
-// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
-
-using System.IO;
-using System.Web;
-using log4net.Core;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Converter for items in the .
- ///
- ///
- ///
- /// Outputs an item from the .
- ///
- ///
- /// Ron Grabowski
- internal sealed class AspNetContextPatternConverter : AspNetPatternLayoutConverter
- {
- ///
- /// Write the ASP.Net HttpContext item to the output
- ///
- /// that will receive the formatted result.
- /// The on which the pattern converter should be executed.
- /// The under which the ASP.Net request is running.
- ///
- ///
- /// Writes out the value of a named property. The property name
- /// should be set in the
- /// property.
- ///
- ///
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
- {
- if (Option != null)
- {
- WriteObject(writer, loggingEvent.Repository, httpContext.Items[Option]);
- }
- else
- {
- WriteObject(writer, loggingEvent.Repository, httpContext.Items);
- }
- }
- }
-}
-
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+// .NET Compact Framework 1.0 has no support for ASP.NET
+// SSCLI 1.0 has no support for ASP.NET
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
+
+using System.IO;
+using System.Web;
+using log4net.Core;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Converter for items in the .
+ ///
+ ///
+ ///
+ /// Outputs an item from the .
+ ///
+ ///
+ /// Ron Grabowski
+ internal sealed class AspNetContextPatternConverter : AspNetPatternLayoutConverter
+ {
+ ///
+ /// Write the ASP.Net HttpContext item to the output
+ ///
+ /// that will receive the formatted result.
+ /// The on which the pattern converter should be executed.
+ /// The under which the ASP.Net request is running.
+ ///
+ ///
+ /// Writes out the value of a named property. The property name
+ /// should be set in the
+ /// property.
+ ///
+ ///
+ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
+ {
+ if (Option != null)
+ {
+ WriteObject(writer, loggingEvent.Repository, httpContext.Items[Option]);
+ }
+ else
+ {
+ WriteObject(writer, loggingEvent.Repository, httpContext.Items);
+ }
+ }
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/src/Layout/Pattern/AspNetPatternConverter.cs b/src/Layout/Pattern/AspNetPatternConverter.cs
index 9499ef1f..7201ecd4 100644
--- a/src/Layout/Pattern/AspNetPatternConverter.cs
+++ b/src/Layout/Pattern/AspNetPatternConverter.cs
@@ -1,65 +1,65 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-// .NET Compact Framework 1.0 has no support for ASP.NET
-// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
-
-using System.IO;
-using System.Web;
-using log4net.Core;
-using log4net.Util;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Abstract class that provides access to the current HttpContext () that
- /// derived classes need.
- ///
- ///
- /// This class handles the case when HttpContext.Current is null by writing
- /// to the writer.
- ///
- /// Ron Grabowski
- internal abstract class AspNetPatternLayoutConverter : PatternLayoutConverter
- {
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
- {
- if (HttpContext.Current == null)
- {
- writer.Write(SystemInfo.NotAvailableText);
- }
- else
- {
- Convert(writer, loggingEvent, HttpContext.Current);
- }
- }
-
- ///
- /// Derived pattern converters must override this method in order to
- /// convert conversion specifiers in the correct way.
- ///
- /// that will receive the formatted result.
- /// The on which the pattern converter should be executed.
- /// The under which the ASP.Net request is running.
- protected abstract void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext);
- }
-}
-
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+// .NET Compact Framework 1.0 has no support for ASP.NET
+// SSCLI 1.0 has no support for ASP.NET
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
+
+using System.IO;
+using System.Web;
+using log4net.Core;
+using log4net.Util;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Abstract class that provides access to the current HttpContext () that
+ /// derived classes need.
+ ///
+ ///
+ /// This class handles the case when HttpContext.Current is null by writing
+ /// to the writer.
+ ///
+ /// Ron Grabowski
+ internal abstract class AspNetPatternLayoutConverter : PatternLayoutConverter
+ {
+ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
+ {
+ if (HttpContext.Current == null)
+ {
+ writer.Write(SystemInfo.NotAvailableText);
+ }
+ else
+ {
+ Convert(writer, loggingEvent, HttpContext.Current);
+ }
+ }
+
+ ///
+ /// Derived pattern converters must override this method in order to
+ /// convert conversion specifiers in the correct way.
+ ///
+ /// that will receive the formatted result.
+ /// The on which the pattern converter should be executed.
+ /// The under which the ASP.Net request is running.
+ protected abstract void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext);
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/src/Layout/Pattern/AspNetRequestPatternConverter.cs b/src/Layout/Pattern/AspNetRequestPatternConverter.cs
index 912ab545..ca810f60 100644
--- a/src/Layout/Pattern/AspNetRequestPatternConverter.cs
+++ b/src/Layout/Pattern/AspNetRequestPatternConverter.cs
@@ -1,76 +1,86 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-// .NET Compact Framework 1.0 has no support for ASP.NET
-// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
-
-using System.IO;
-using System.Web;
-using log4net.Core;
-using log4net.Util;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Converter for items in the ASP.Net Cache.
- ///
- ///
- ///
- /// Outputs an item from the .
- ///
- ///
- /// Ron Grabowski
- internal sealed class AspNetRequestPatternConverter : AspNetPatternLayoutConverter
- {
- ///
- /// Write the ASP.Net Cache item to the output
- ///
- /// that will receive the formatted result.
- /// The on which the pattern converter should be executed.
- /// The under which the ASP.Net request is running.
- ///
- ///
- /// Writes out the value of a named property. The property name
- /// should be set in the
- /// property.
- ///
- ///
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
- {
- if (httpContext.Request != null)
- {
- if (Option != null)
- {
- WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params[Option]);
- }
- else
- {
- WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params);
- }
- }
- else
- {
- writer.Write(SystemInfo.NotAvailableText);
- }
- }
- }
-}
-
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+// .NET Compact Framework 1.0 has no support for ASP.NET
+// SSCLI 1.0 has no support for ASP.NET
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
+
+using System.IO;
+using System.Web;
+using log4net.Core;
+using log4net.Util;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Converter for items in the ASP.Net Cache.
+ ///
+ ///
+ ///
+ /// Outputs an item from the .
+ ///
+ ///
+ /// Ron Grabowski
+ internal sealed class AspNetRequestPatternConverter : AspNetPatternLayoutConverter
+ {
+ ///
+ /// Write the ASP.Net Cache item to the output
+ ///
+ /// that will receive the formatted result.
+ /// The on which the pattern converter should be executed.
+ /// The under which the ASP.Net request is running.
+ ///
+ ///
+ /// Writes out the value of a named property. The property name
+ /// should be set in the
+ /// property.
+ ///
+ ///
+ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
+ {
+ HttpRequest request = null;
+ try {
+ request = httpContext.Request;
+ } catch (HttpException) {
+ // likely a case of running in IIS integrated mode
+ // when inside an Application_Start event.
+ // treat it like a case of the Request
+ // property returning null
+ }
+
+ if (request != null)
+ {
+ if (Option != null)
+ {
+ WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params[Option]);
+ }
+ else
+ {
+ WriteObject(writer, loggingEvent.Repository, httpContext.Request.Params);
+ }
+ }
+ else
+ {
+ writer.Write(SystemInfo.NotAvailableText);
+ }
+ }
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/src/Layout/Pattern/AspNetSessionPatternConverter.cs b/src/Layout/Pattern/AspNetSessionPatternConverter.cs
index 52fb2d0e..f50ad8a5 100644
--- a/src/Layout/Pattern/AspNetSessionPatternConverter.cs
+++ b/src/Layout/Pattern/AspNetSessionPatternConverter.cs
@@ -1,77 +1,77 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-// .NET Compact Framework 1.0 has no support for ASP.NET
-// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
-
-using System.IO;
-using System.Web;
-using log4net.Core;
-using log4net.Util;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Converter for items in the ASP.Net Cache.
- ///
- ///
- ///
- /// Outputs an item from the .
- ///
- ///
- /// Ron Grabowski
- internal sealed class AspNetSessionPatternConverter : AspNetPatternLayoutConverter
- {
- ///
- /// Write the ASP.Net Cache item to the output
- ///
- /// that will receive the formatted result.
- /// The on which the pattern converter should be executed.
- /// The under which the ASP.Net request is running.
- ///
- ///
- /// Writes out the value of a named property. The property name
- /// should be set in the
- /// property. If no property has been set, all key value pairs from the Session will
- /// be written to the output.
- ///
- ///
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
- {
- if (httpContext.Session != null)
- {
- if (Option != null)
- {
- WriteObject(writer, loggingEvent.Repository, httpContext.Session.Contents[Option]);
- }
- else
- {
- WriteObject(writer, loggingEvent.Repository, httpContext.Session);
- }
- }
- else
- {
- writer.Write(SystemInfo.NotAvailableText);
- }
- }
- }
-}
-
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+// .NET Compact Framework 1.0 has no support for ASP.NET
+// SSCLI 1.0 has no support for ASP.NET
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
+
+using System.IO;
+using System.Web;
+using log4net.Core;
+using log4net.Util;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Converter for items in the ASP.Net Cache.
+ ///
+ ///
+ ///
+ /// Outputs an item from the .
+ ///
+ ///
+ /// Ron Grabowski
+ internal sealed class AspNetSessionPatternConverter : AspNetPatternLayoutConverter
+ {
+ ///
+ /// Write the ASP.Net Cache item to the output
+ ///
+ /// that will receive the formatted result.
+ /// The on which the pattern converter should be executed.
+ /// The under which the ASP.Net request is running.
+ ///
+ ///
+ /// Writes out the value of a named property. The property name
+ /// should be set in the
+ /// property. If no property has been set, all key value pairs from the Session will
+ /// be written to the output.
+ ///
+ ///
+ protected override void Convert(TextWriter writer, LoggingEvent loggingEvent, HttpContext httpContext)
+ {
+ if (httpContext.Session != null)
+ {
+ if (Option != null)
+ {
+ WriteObject(writer, loggingEvent.Repository, httpContext.Session.Contents[Option]);
+ }
+ else
+ {
+ WriteObject(writer, loggingEvent.Repository, httpContext.Session);
+ }
+ }
+ else
+ {
+ writer.Write(SystemInfo.NotAvailableText);
+ }
+ }
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/src/Layout/Pattern/DatePatternConverter.cs b/src/Layout/Pattern/DatePatternConverter.cs
old mode 100755
new mode 100644
index a56c694d..91a4caa0
--- a/src/Layout/Pattern/DatePatternConverter.cs
+++ b/src/Layout/Pattern/DatePatternConverter.cs
@@ -69,7 +69,7 @@ namespace log4net.Layout.Pattern
///
/// Any other pattern string uses the formatter.
/// This formatter passes the pattern string to the
- /// method.
+ /// method.
/// For details on valid patterns see
/// DateTimeFormatInfo Class.
///
diff --git a/src/Layout/Pattern/ExceptionPatternConverter.cs b/src/Layout/Pattern/ExceptionPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/FileLocationPatternConverter.cs b/src/Layout/Pattern/FileLocationPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/FullLocationPatternConverter.cs b/src/Layout/Pattern/FullLocationPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/IdentityPatternConverter.cs b/src/Layout/Pattern/IdentityPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/LevelPatternConverter.cs b/src/Layout/Pattern/LevelPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/LineLocationPatternConverter.cs b/src/Layout/Pattern/LineLocationPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/LoggerPatternConverter.cs b/src/Layout/Pattern/LoggerPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/MessagePatternConverter.cs b/src/Layout/Pattern/MessagePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/MethodLocationPatternConverter.cs b/src/Layout/Pattern/MethodLocationPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/NamedPatternConverter.cs b/src/Layout/Pattern/NamedPatternConverter.cs
old mode 100755
new mode 100644
index 9d973261..8338706e
--- a/src/Layout/Pattern/NamedPatternConverter.cs
+++ b/src/Layout/Pattern/NamedPatternConverter.cs
@@ -42,9 +42,9 @@ namespace log4net.Layout.Pattern
///
///
/// Nicko Cadell
- internal abstract class NamedPatternConverter : PatternLayoutConverter, IOptionHandler
+ public abstract class NamedPatternConverter : PatternLayoutConverter, IOptionHandler
{
- protected int m_precision = 0;
+ private int m_precision = 0;
#region Implementation of IOptionHandler
@@ -120,31 +120,37 @@ public void ActivateOptions()
/// Render the to the precision
/// specified by the property.
///
- override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
+ sealed override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
string name = GetFullyQualifiedName(loggingEvent);
- if (m_precision <= 0)
+ if (m_precision <= 0 || name == null || name.Length < 2)
{
writer.Write(name);
}
else
{
int len = name.Length;
+ string trailingDot = string.Empty;
+ if (name.EndsWith(DOT))
+ {
+ trailingDot = DOT;
+ name = name.Substring(0, len - 1);
+ len--;
+ }
- // We subtract 1 from 'len' when assigning to 'end' to avoid out of
- // bounds exception in return name.Substring(end+1, len). This can happen if
- // precision is 1 and the logger name ends with a dot.
- int end = len - 1;
- for(int i=m_precision; i>0; i--)
- {
- end = name.LastIndexOf('.', end-1);
- if (end == -1)
- {
- writer.Write(name);
- return;
- }
- }
- writer.Write(name.Substring(end+1, len-end-1));
+ int end = name.LastIndexOf(DOT);
+ for(int i = 1; end > 0 && i < m_precision; i++)
+ {
+ end = name.LastIndexOf('.', end - 1);
+ }
+ if (end == -1)
+ {
+ writer.Write(name + trailingDot);
+ }
+ else
+ {
+ writer.Write(name.Substring(end + 1, len - end - 1) + trailingDot);
+ }
}
}
@@ -159,6 +165,7 @@ override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
///
private readonly static Type declaringType = typeof(NamedPatternConverter);
+ private const string DOT = ".";
#endregion Private Static Fields
}
}
diff --git a/src/Layout/Pattern/NdcPatternConverter.cs b/src/Layout/Pattern/NdcPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/PatternLayoutConverter.cs b/src/Layout/Pattern/PatternLayoutConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/PropertyPatternConverter.cs b/src/Layout/Pattern/PropertyPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/RelativeTimePatternConverter.cs b/src/Layout/Pattern/RelativeTimePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/StackTraceDetailPatternConverter.cs b/src/Layout/Pattern/StackTraceDetailPatternConverter.cs
index 6fec5f20..2bc54934 100644
--- a/src/Layout/Pattern/StackTraceDetailPatternConverter.cs
+++ b/src/Layout/Pattern/StackTraceDetailPatternConverter.cs
@@ -1,90 +1,91 @@
-using System;
-using System.Collections;
-using System.Text;
-
-using log4net.Util;
-using log4net.Core;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Write the caller stack frames to the output
- ///
- ///
- ///
- /// Writes the to the output writer, using format:
- /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...)
- ///
- ///
- /// Adam Davies
- internal class StackTraceDetailPatternConverter : StackTracePatternConverter
- {
- internal override string GetMethodInformation(System.Reflection.MethodBase method)
- {
- string returnValue="";
-
- try
- {
- string param = "";
- string[] names = GetMethodParameterNames(method);
- StringBuilder sb = new StringBuilder();
- if (names != null && names.GetUpperBound(0) > 0)
- {
- for (int i = 0; i <= names.GetUpperBound(0); i++)
- {
- sb.AppendFormat("{0}, ", names[i]);
- }
- }
-
- if (sb.Length > 0)
- {
- sb.Remove(sb.Length - 2, 2);
- param = sb.ToString();
- }
-
- returnValue=base.GetMethodInformation(method) + "(" + param + ")";
- }
- catch (Exception ex)
- {
- LogLog.Error(declaringType, "An exception ocurred while retreiving method information.", ex);
- }
-
- return returnValue;
- }
-
- private string[] GetMethodParameterNames(System.Reflection.MethodBase methodBase)
- {
- ArrayList methodParameterNames = new ArrayList();
- try
- {
- System.Reflection.ParameterInfo[] methodBaseGetParameters = methodBase.GetParameters();
-
- int methodBaseGetParametersCount = methodBaseGetParameters.GetUpperBound(0);
-
- for (int i = 0; i <= methodBaseGetParametersCount; i++)
- {
- methodParameterNames.Add(methodBaseGetParameters[i].ParameterType + " " + methodBaseGetParameters[i].Name);
- }
- }
- catch (Exception ex)
- {
- LogLog.Error(declaringType, "An exception ocurred while retreiving method parameters.", ex);
- }
-
- return (string[])methodParameterNames.ToArray(typeof (string));
- }
-
- #region Private Static Fields
-
- ///
- /// The fully qualified type of the StackTraceDetailPatternConverter class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(StackTracePatternConverter);
-
- #endregion Private Static Fields
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+#if !NETCF
+
+using System;
+using System.Collections;
+using System.Text;
+
+using log4net.Util;
+using log4net.Core;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Write the caller stack frames to the output
+ ///
+ ///
+ ///
+ /// Writes the to the output writer, using format:
+ /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...)
+ ///
+ ///
+ /// Adam Davies
+ internal class StackTraceDetailPatternConverter : StackTracePatternConverter
+ {
+ internal override string GetMethodInformation(MethodItem method)
+ {
+ string returnValue="";
+
+ try
+ {
+ string param = "";
+ string[] names = method.Parameters;
+ StringBuilder sb = new StringBuilder();
+ if (names != null && names.GetUpperBound(0) > 0)
+ {
+ for (int i = 0; i <= names.GetUpperBound(0); i++)
+ {
+ sb.AppendFormat("{0}, ", names[i]);
+ }
+ }
+
+ if (sb.Length > 0)
+ {
+ sb.Remove(sb.Length - 2, 2);
+ param = sb.ToString();
+ }
+
+ returnValue=base.GetMethodInformation(method) + "(" + param + ")";
+ }
+ catch (Exception ex)
+ {
+ LogLog.Error(declaringType, "An exception ocurred while retreiving method information.", ex);
+ }
+
+ return returnValue;
+ }
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the StackTraceDetailPatternConverter class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(StackTracePatternConverter);
+
+ #endregion Private Static Fields
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/Layout/Pattern/StackTracePatternConverter.cs b/src/Layout/Pattern/StackTracePatternConverter.cs
index 6e57242a..747b6628 100644
--- a/src/Layout/Pattern/StackTracePatternConverter.cs
+++ b/src/Layout/Pattern/StackTracePatternConverter.cs
@@ -1,149 +1,150 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.IO;
-using System.Diagnostics;
-
-using log4net.Util;
-using log4net.Core;
-
-namespace log4net.Layout.Pattern
-{
- ///
- /// Write the caller stack frames to the output
- ///
- ///
- ///
- /// Writes the to the output writer, using format:
- /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1
- ///
- ///
- /// Michael Cromwell
- internal class StackTracePatternConverter : PatternLayoutConverter, IOptionHandler
- {
- private int m_stackFrameLevel = 1;
-
- ///
- /// Initialize the converter
- ///
- ///
- ///
- /// This is part of the delayed object
- /// activation scheme. The method must
- /// be called on this object after the configuration properties have
- /// been set. Until is called this
- /// object is in an undefined state and must not be used.
- ///
- ///
- /// If any of the configuration properties are modified then
- /// must be called again.
- ///
- ///
- public void ActivateOptions()
- {
- if (Option == null)
- return;
-
- string optStr = Option.Trim();
- if (optStr.Length != 0)
- {
- int stackLevelVal;
- if (SystemInfo.TryParse(optStr, out stackLevelVal))
- {
- if (stackLevelVal <= 0)
- {
- LogLog.Error(declaringType, "StackTracePatternConverter: StackeFrameLevel option (" + optStr + ") isn't a positive integer.");
- }
- else
- {
- m_stackFrameLevel = stackLevelVal;
- }
- }
- else
- {
- LogLog.Error(declaringType, "StackTracePatternConverter: StackFrameLevel option \"" + optStr + "\" not a decimal integer.");
- }
- }
- }
-
- ///
- /// Write the strack frames to the output
- ///
- /// that will receive the formatted result.
- /// the event being logged
- ///
- ///
- /// Writes the to the output writer.
- ///
- ///
- override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
- {
- StackFrame[] stackframes = loggingEvent.LocationInformation.StackFrames;
- if ((stackframes == null) || (stackframes.Length <= 0))
- {
- LogLog.Error(declaringType, "loggingEvent.LocationInformation.StackFrames was null or empty.");
- return;
- }
-
- int stackFrameIndex = m_stackFrameLevel - 1;
- while (stackFrameIndex >= 0)
- {
- if (stackFrameIndex > stackframes.Length)
- {
- stackFrameIndex--;
- continue;
- }
-
- StackFrame stackFrame = stackframes[stackFrameIndex];
- writer.Write("{0}.{1}", stackFrame.GetMethod().DeclaringType.Name, GetMethodInformation(stackFrame.GetMethod()));
- if (stackFrameIndex > 0)
- {
- // TODO: make this user settable?
- writer.Write(" > ");
- }
- stackFrameIndex--;
- }
- }
-
- ///
- /// Returns the Name of the method
- ///
- ///
- /// This method was created, so this class could be used as a base class for StackTraceDetailPatternConverter
- /// string
- internal virtual string GetMethodInformation(System.Reflection.MethodBase method)
- {
- return method.Name;
- }
-
- #region Private Static Fields
-
- ///
- /// The fully qualified type of the StackTracePatternConverter class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(StackTracePatternConverter);
-
- #endregion Private Static Fields
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+#if !NETCF
+using System;
+using System.IO;
+using System.Diagnostics;
+
+using log4net.Util;
+using log4net.Core;
+
+namespace log4net.Layout.Pattern
+{
+ ///
+ /// Write the caller stack frames to the output
+ ///
+ ///
+ ///
+ /// Writes the to the output writer, using format:
+ /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1
+ ///
+ ///
+ /// Michael Cromwell
+ internal class StackTracePatternConverter : PatternLayoutConverter, IOptionHandler
+ {
+ private int m_stackFrameLevel = 1;
+
+ ///
+ /// Initialize the converter
+ ///
+ ///
+ ///
+ /// This is part of the delayed object
+ /// activation scheme. The method must
+ /// be called on this object after the configuration properties have
+ /// been set. Until is called this
+ /// object is in an undefined state and must not be used.
+ ///
+ ///
+ /// If any of the configuration properties are modified then
+ /// must be called again.
+ ///
+ ///
+ public void ActivateOptions()
+ {
+ if (Option == null)
+ return;
+
+ string optStr = Option.Trim();
+ if (optStr.Length != 0)
+ {
+ int stackLevelVal;
+ if (SystemInfo.TryParse(optStr, out stackLevelVal))
+ {
+ if (stackLevelVal <= 0)
+ {
+ LogLog.Error(declaringType, "StackTracePatternConverter: StackeFrameLevel option (" + optStr + ") isn't a positive integer.");
+ }
+ else
+ {
+ m_stackFrameLevel = stackLevelVal;
+ }
+ }
+ else
+ {
+ LogLog.Error(declaringType, "StackTracePatternConverter: StackFrameLevel option \"" + optStr + "\" not a decimal integer.");
+ }
+ }
+ }
+
+ ///
+ /// Write the strack frames to the output
+ ///
+ /// that will receive the formatted result.
+ /// the event being logged
+ ///
+ ///
+ /// Writes the to the output writer.
+ ///
+ ///
+ override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
+ {
+ StackFrameItem[] stackframes = loggingEvent.LocationInformation.StackFrames;
+ if ((stackframes == null) || (stackframes.Length <= 0))
+ {
+ LogLog.Error(declaringType, "loggingEvent.LocationInformation.StackFrames was null or empty.");
+ return;
+ }
+
+ int stackFrameIndex = m_stackFrameLevel - 1;
+ while (stackFrameIndex >= 0)
+ {
+ if (stackFrameIndex >= stackframes.Length)
+ {
+ stackFrameIndex--;
+ continue;
+ }
+
+ StackFrameItem stackFrame = stackframes[stackFrameIndex];
+ writer.Write("{0}.{1}", stackFrame.ClassName, GetMethodInformation(stackFrame.Method));
+ if (stackFrameIndex > 0)
+ {
+ // TODO: make this user settable?
+ writer.Write(" > ");
+ }
+ stackFrameIndex--;
+ }
+ }
+
+ ///
+ /// Returns the Name of the method
+ ///
+ ///
+ /// This method was created, so this class could be used as a base class for StackTraceDetailPatternConverter
+ /// string
+ internal virtual string GetMethodInformation(MethodItem method)
+ {
+ return method.Name;
+ }
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the StackTracePatternConverter class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(StackTracePatternConverter);
+
+ #endregion Private Static Fields
+ }
+}
+#endif
diff --git a/src/Layout/Pattern/ThreadPatternConverter.cs b/src/Layout/Pattern/ThreadPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/TypeNamePatternConverter.cs b/src/Layout/Pattern/TypeNamePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/UserNamePatternConverter.cs b/src/Layout/Pattern/UserNamePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/Pattern/UtcDatePatternConverter.cs b/src/Layout/Pattern/UtcDatePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/PatternLayout.cs b/src/Layout/PatternLayout.cs
old mode 100755
new mode 100644
index 863087be..9e15921e
--- a/src/Layout/PatternLayout.cs
+++ b/src/Layout/PatternLayout.cs
@@ -39,7 +39,7 @@ namespace log4net.Layout
///
///
///
- /// The goal of this class is to a
+ /// The goal of this class is to a
/// as a string. The results
/// depend on the conversion pattern.
///
@@ -106,26 +106,46 @@ namespace log4net.Layout
///
/// aspnet-cache
///
- /// TODO
+ ///
+ /// Used to output all cache items in the case of %aspnet-cache or just one named item if used as %aspnet-cache{key}
+ ///
+ ///
+ /// This pattern is not available for Compact Framework or Client Profile assemblies.
+ ///
///
///
///
/// aspnet-context
///
- /// TODO
- ///
+ ///
+ /// Used to output all context items in the case of %aspnet-context or just one named item if used as %aspnet-context{key}
+ ///
+ ///
+ /// This pattern is not available for Compact Framework or Client Profile assemblies.
+ ///
+ ///
///
///
/// aspnet-request
///
- /// TODO
- ///
+ ///
+ /// Used to output all request parameters in the case of %aspnet-request or just one named param if used as %aspnet-request{key}
+ ///
+ ///
+ /// This pattern is not available for Compact Framework or Client Profile assemblies.
+ ///
+ ///
///
///
/// aspnet-session
///
- /// TODO
- ///
+ ///
+ /// Used to output all session items in the case of %aspnet-session or just one named item if used as %aspnet-session{key}
+ ///
+ ///
+ /// This pattern is not available for Compact Framework or Client Profile assemblies.
+ ///
+ ///
///
///
/// c
@@ -158,7 +178,7 @@ namespace log4net.Layout
///
///
/// The date format specifier admits the same syntax as the
- /// time pattern string of the .
+ /// time pattern string of the .
///
///
/// For better results it is recommended to use the log4net date
@@ -171,7 +191,7 @@ namespace log4net.Layout
///
///
/// These dedicated date formatters perform significantly
- /// better than .
+ /// better than .
///
///
///
@@ -446,9 +466,34 @@ namespace log4net.Layout
/// between braces. For example, %stacktrace{level}.
/// If no stack trace level specifier is given then 1 is assumed
///
- ///
+ ///
+ /// Output uses the format:
+ /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1
+ ///
+ ///
+ /// This pattern is not available for Compact Framework assemblies.
+ ///
+ ///
///
- ///
+ ///
+ /// stacktracedetail
+ ///
+ ///
+ /// Used to output the stack trace of the logging event
+ /// The stack trace level specifier may be enclosed
+ /// between braces. For example, %stacktracedetail{level}.
+ /// If no stack trace level specifier is given then 1 is assumed
+ ///
+ ///
+ /// Output uses the format:
+ /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...)
+ ///
+ ///
+ /// This pattern is not available for Compact Framework assemblies.
+ ///
+ ///
+ ///
+ ///
/// t
/// Equivalent to thread
///
@@ -530,7 +575,7 @@ namespace log4net.Layout
///
///
/// The date format specifier admits the same syntax as the
- /// time pattern string of the .
+ /// time pattern string of the .
///
///
/// For better results it is recommended to use the log4net date
@@ -543,7 +588,7 @@ namespace log4net.Layout
///
///
/// These dedicated date formatters perform significantly
- /// better than .
+ /// better than .
///
///
///
@@ -715,7 +760,7 @@ namespace log4net.Layout
///
///
/// Additional pattern converters may be registered with a specific
- /// instance using the method.
+ /// instance using the method.
///
///
///
@@ -816,7 +861,7 @@ static PatternLayout()
// .NET Compact Framework 1.0 has no support for ASP.NET
// SSCLI 1.0 has no support for ASP.NET
-#if !NETCF && !SSCLI
+#if !NETCF && !SSCLI && !CLIENT_PROFILE
s_globalRulesRegistry.Add("aspnet-cache", typeof(AspNetCachePatternConverter));
s_globalRulesRegistry.Add("aspnet-context", typeof(AspNetContextPatternConverter));
s_globalRulesRegistry.Add("aspnet-request", typeof(AspNetRequestPatternConverter));
@@ -860,8 +905,10 @@ static PatternLayout()
s_globalRulesRegistry.Add("r", typeof(RelativeTimePatternConverter));
s_globalRulesRegistry.Add("timestamp", typeof(RelativeTimePatternConverter));
+#if !NETCF
s_globalRulesRegistry.Add("stacktrace", typeof(StackTracePatternConverter));
s_globalRulesRegistry.Add("stacktracedetail", typeof(StackTraceDetailPatternConverter));
+#endif
s_globalRulesRegistry.Add("t", typeof(ThreadPatternConverter));
s_globalRulesRegistry.Add("thread", typeof(ThreadPatternConverter));
@@ -1078,7 +1125,7 @@ override public void Format(TextWriter writer, LoggingEvent loggingEvent)
///
///
/// This version of the method is used by the configurator.
- /// Programmatic users should use the alternative method.
+ /// Programmatic users should use the alternative method.
///
///
public void AddConverter(ConverterInfo converterInfo)
diff --git a/src/Layout/RawLayoutConverter.cs b/src/Layout/RawLayoutConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/RawPropertyLayout.cs b/src/Layout/RawPropertyLayout.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/RawTimeStampLayout.cs b/src/Layout/RawTimeStampLayout.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/RawUtcTimeStampLayout.cs b/src/Layout/RawUtcTimeStampLayout.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/SimpleLayout.cs b/src/Layout/SimpleLayout.cs
old mode 100755
new mode 100644
diff --git a/src/Layout/XMLLayout.cs b/src/Layout/XmlLayout.cs
old mode 100755
new mode 100644
similarity index 100%
rename from src/Layout/XMLLayout.cs
rename to src/Layout/XmlLayout.cs
diff --git a/src/Layout/XMLLayoutBase.cs b/src/Layout/XmlLayoutBase.cs
old mode 100755
new mode 100644
similarity index 94%
rename from src/Layout/XMLLayoutBase.cs
rename to src/Layout/XmlLayoutBase.cs
index 4a5cebcf..2ec0e8c9
--- a/src/Layout/XMLLayoutBase.cs
+++ b/src/Layout/XmlLayoutBase.cs
@@ -197,10 +197,7 @@ override public void Format(TextWriter writer, LoggingEvent loggingEvent)
throw new ArgumentNullException("loggingEvent");
}
- // Attach the protected writer to the TextWriter passed in
- m_protectCloseTextWriter.Attach(writer);
-
- XmlTextWriter xmlWriter = new XmlTextWriter(m_protectCloseTextWriter);
+ XmlTextWriter xmlWriter = new XmlTextWriter(new ProtectCloseTextWriter(writer));
xmlWriter.Formatting = Formatting.None;
xmlWriter.Namespaces = false;
@@ -212,9 +209,6 @@ override public void Format(TextWriter writer, LoggingEvent loggingEvent)
// Close on xmlWriter will ensure xml is flushed
// the protected writer will ignore the actual close
xmlWriter.Close();
-
- // detach from the writer
- m_protectCloseTextWriter.Attach(null);
}
#endregion Override implementation of LayoutSkeleton
@@ -244,11 +238,6 @@ override public void Format(TextWriter writer, LoggingEvent loggingEvent)
///
private bool m_locationInfo = false;
- ///
- /// Writer adapter that ignores Close
- ///
- private readonly ProtectCloseTextWriter m_protectCloseTextWriter = new ProtectCloseTextWriter(null);
-
///
/// The string to replace invalid chars with
///
diff --git a/src/Layout/XmlLayoutSchemaLog4j.cs b/src/Layout/XmlLayoutSchemaLog4j.cs
old mode 100755
new mode 100644
diff --git a/src/Log4netAssemblyInfo.cs b/src/Log4netAssemblyInfo.cs
new file mode 100644
index 00000000..cf56f18e
--- /dev/null
+++ b/src/Log4netAssemblyInfo.cs
@@ -0,0 +1,94 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+namespace log4net {
+
+ ///
+ /// Provides information about the environment the assembly has
+ /// been built for.
+ ///
+ public sealed class AssemblyInfo {
+ /// Version of the assembly
+ public const string Version = "1.2.15";
+
+ /// Version of the framework targeted
+#if NET_1_1
+ public const decimal TargetFrameworkVersion = 1.1M;
+#elif NET_4_5
+ public const decimal TargetFrameworkVersion = 4.5M;
+#elif NET_4_0 || MONO_4_0
+ public const decimal TargetFrameworkVersion = 4.5M;
+#elif FRAMEWORK_4_0_OR_ABOVE
+ public const decimal TargetFrameworkVersion = 4.0M;
+#elif MONO_3_5
+ public const decimal TargetFrameworkVersion = 3.5M;
+#elif NET_2_0 || NETCF_2_0 || MONO_2_0
+#if !CLIENT_PROFILE
+ public const decimal TargetFrameworkVersion = 2.0M;
+#else
+ public const decimal TargetFrameworkVersion = 3.5M;
+#endif // Client Profile
+#else
+ public const decimal TargetFrameworkVersion = 1.0M;
+#endif
+
+ /// Type of framework targeted
+#if CLI
+ public const string TargetFramework = "CLI Compatible Frameworks";
+#elif NET
+ public const string TargetFramework = ".NET Framework";
+#elif NETCF
+ public const string TargetFramework = ".NET Compact Framework";
+#elif MONO
+ public const string TargetFramework = "Mono";
+#elif SSCLI
+ public const string TargetFramework = "Shared Source CLI";
+#else
+ public const string TargetFramework = "Unknown";
+#endif
+
+ /// Does it target a client profile?
+#if !CLIENT_PROFILE
+ public const bool ClientProfile = false;
+#else
+ public const bool ClientProfile = true;
+#endif
+
+ ///
+ /// Identifies the version and target for this assembly.
+ ///
+ public static string Info {
+ get {
+ return string.Format("Apache log4net version {0} compiled for {1}{2} {3}",
+ Version, TargetFramework,
+ /* Can't use
+ ClientProfile && true ? " Client Profile" :
+ or the compiler whines about unreachable expressions
+ */
+#if !CLIENT_PROFILE
+ string.Empty,
+#else
+ " Client Profile",
+#endif
+ TargetFrameworkVersion);
+ }
+ }
+ }
+
+}
diff --git a/src/LogManager.cs b/src/LogManager.cs
old mode 100755
new mode 100644
index b1c399d2..1e024e73
--- a/src/LogManager.cs
+++ b/src/LogManager.cs
@@ -31,7 +31,7 @@ namespace log4net
///
///
/// This class has static methods that are used by a client to request
- /// a logger instance. The method is
+ /// a logger instance. The method is
/// used to retrieve a logger.
///
///
@@ -243,7 +243,7 @@ public static ILog GetLogger(Assembly repositoryAssembly, string name)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Get the logger for the fully qualified name of the type specified.
@@ -256,7 +256,7 @@ public static ILog GetLogger(Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Gets the logger for the fully qualified name of the type specified.
@@ -270,7 +270,7 @@ public static ILog GetLogger(string repository, Type type)
}
///
- /// Shorthand for .
+ /// Shorthand for .
///
///
/// Gets the logger for the fully qualified name of the type specified.
@@ -451,7 +451,7 @@ public static void ResetConfiguration(Assembly repositoryAssembly)
///
///
/// Gets the for the repository specified
- /// by the callers assembly ().
+ /// by the callers assembly ().
///
///
/// The instance for the default repository.
@@ -502,7 +502,7 @@ public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly)
///
///
/// Gets the for the repository specified
- /// by the callers assembly ().
+ /// by the callers assembly ().
///
///
/// The instance for the default repository.
@@ -553,7 +553,7 @@ public static ILoggerRepository GetRepository(Assembly repositoryAssembly)
///
///
/// The created will be associated with the repository
- /// specified such that a call to will return
+ /// specified such that a call to will return
/// the same repository instance.
///
///
@@ -578,7 +578,7 @@ public static ILoggerRepository CreateDomain(Type repositoryType)
///
///
/// The created will be associated with the repository
- /// specified such that a call to will return
+ /// specified such that a call to will return
/// the same repository instance.
///
///
@@ -686,7 +686,7 @@ public static ILoggerRepository CreateRepository(string repository, Type reposit
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
@@ -707,7 +707,7 @@ public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type r
///
///
/// The created will be associated with the repository
- /// specified such that a call to with the
+ /// specified such that a call to with the
/// same assembly specified will return the same repository instance.
///
///
diff --git a/src/LogicalThreadContext.cs b/src/LogicalThreadContext.cs
old mode 100755
new mode 100644
index d23e4fa0..40357c46
--- a/src/LogicalThreadContext.cs
+++ b/src/LogicalThreadContext.cs
@@ -125,7 +125,7 @@ public static LogicalThreadContextProperties Properties
/// The logical thread stacks.
///
///
- public static ThreadContextStacks Stacks
+ public static LogicalThreadContextStacks Stacks
{
get { return s_stacks; }
}
@@ -142,7 +142,7 @@ public static ThreadContextStacks Stacks
///
/// The thread context stacks instance
///
- private readonly static ThreadContextStacks s_stacks = new ThreadContextStacks(s_properties);
+ private readonly static LogicalThreadContextStacks s_stacks = new LogicalThreadContextStacks(s_properties);
#endregion Private Static Fields
}
diff --git a/src/MDC.cs b/src/MDC.cs
old mode 100755
new mode 100644
index 2baef8dd..06e1b1db
--- a/src/MDC.cs
+++ b/src/MDC.cs
@@ -107,13 +107,13 @@ public static string Get(string key)
///
///
///
- /// Puts a context value (the parameter) as identified
+ /// Puts a context value (the parameter) as identified
/// with the parameter into the current thread's
/// context map.
///
///
/// If a value is already defined for the
- /// specified then the value will be replaced. If the
+ /// specified then the value will be replaced. If the
/// is specified as null then the key value mapping will be removed.
///
///
diff --git a/src/NDC.cs b/src/NDC.cs
old mode 100755
new mode 100644
diff --git a/src/ObjectRenderer/DefaultRenderer.cs b/src/ObjectRenderer/DefaultRenderer.cs
old mode 100755
new mode 100644
index f0ed54a9..8dc603df
--- a/src/ObjectRenderer/DefaultRenderer.cs
+++ b/src/ObjectRenderer/DefaultRenderer.cs
@@ -73,7 +73,7 @@ public DefaultRenderer()
/// The parameter is
/// provided to lookup and render other objects. This is
/// very useful where contains
- /// nested objects of unknown type. The
+ /// nested objects of unknown type. The
/// method can be used to render these objects.
///
///
diff --git a/src/ObjectRenderer/IObjectRenderer.cs b/src/ObjectRenderer/IObjectRenderer.cs
old mode 100755
new mode 100644
index eabfd4e0..3a79d1e1
--- a/src/ObjectRenderer/IObjectRenderer.cs
+++ b/src/ObjectRenderer/IObjectRenderer.cs
@@ -52,7 +52,7 @@ public interface IObjectRenderer
/// The parameter is
/// provided to lookup and render other objects. This is
/// very useful where contains
- /// nested objects of unknown type. The
+ /// nested objects of unknown type. The
/// method can be used to render these objects.
///
///
diff --git a/src/ObjectRenderer/RendererMap.cs b/src/ObjectRenderer/RendererMap.cs
old mode 100755
new mode 100644
index fa6236a9..122a6c10
--- a/src/ObjectRenderer/RendererMap.cs
+++ b/src/ObjectRenderer/RendererMap.cs
@@ -33,7 +33,7 @@ namespace log4net.ObjectRenderer
/// is used to render them.
///
///
- /// The method is used to render an
+ /// The method is used to render an
/// object using the appropriate renderers defined in this map.
///
///
@@ -77,7 +77,7 @@ public RendererMap()
///
///
/// This is a convenience method used to render an object to a string.
- /// The alternative method
+ /// The alternative method
/// should be used when streaming output to a .
///
///
@@ -104,7 +104,7 @@ public string FindAndRender(object obj)
///
/// Find the appropriate renderer for the type of the
/// parameter. This is accomplished by calling the
- /// method. Once a renderer is found, it is
+ /// method. Once a renderer is found, it is
/// applied on the object and the result is returned
/// as a .
///
@@ -174,7 +174,7 @@ public void FindAndRender(object obj, TextWriter writer)
/// Gets the renderer for the specified object type.
///
///
- /// Syntactic sugar method that calls
+ /// Syntactic sugar method that calls
/// with the type of the object parameter.
///
///
@@ -303,7 +303,7 @@ public void Clear()
///
///
/// Register an object renderer for a specific source type.
- /// This renderer will be returned from a call to
+ /// This renderer will be returned from a call to
/// specifying the same as an argument.
///
///
diff --git a/src/Plugin/IPlugin.cs b/src/Plugin/IPlugin.cs
old mode 100755
new mode 100644
diff --git a/src/Plugin/IPluginFactory.cs b/src/Plugin/IPluginFactory.cs
old mode 100755
new mode 100644
diff --git a/src/Plugin/PluginCollection.cs b/src/Plugin/PluginCollection.cs
old mode 100755
new mode 100644
index 56cc3f5c..d068f550
--- a/src/Plugin/PluginCollection.cs
+++ b/src/Plugin/PluginCollection.cs
@@ -553,9 +553,9 @@ public virtual void TrimToSize()
#region Implementation (helpers)
///
- /// is less than zero.
+ /// is less than zero.
/// -or-
- /// is equal to or greater than .
+ /// is equal to or greater than .
///
private void ValidateIndex(int i)
{
@@ -563,9 +563,9 @@ private void ValidateIndex(int i)
}
///
- /// is less than zero.
+ /// is less than zero.
/// -or-
- /// is equal to or greater than .
+ /// is equal to or greater than .
///
private void ValidateIndex(int i, bool allowEqualEnd)
{
diff --git a/src/Plugin/PluginMap.cs b/src/Plugin/PluginMap.cs
old mode 100755
new mode 100644
diff --git a/src/Plugin/PluginSkeleton.cs b/src/Plugin/PluginSkeleton.cs
old mode 100755
new mode 100644
diff --git a/src/Plugin/RemoteLoggingServerPlugin.cs b/src/Plugin/RemoteLoggingServerPlugin.cs
old mode 100755
new mode 100644
index d24cc814..dfe24e23
--- a/src/Plugin/RemoteLoggingServerPlugin.cs
+++ b/src/Plugin/RemoteLoggingServerPlugin.cs
@@ -94,7 +94,7 @@ public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlug
///
///
/// This is the name under which the object is marshaled.
- ///
+ ///
///
///
public virtual string SinkUri
@@ -119,6 +119,9 @@ public virtual string SinkUri
/// This method is called when the plugin is attached to the repository.
///
///
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
override public void Attach(ILoggerRepository repository)
{
base.Attach(repository);
@@ -145,7 +148,10 @@ override public void Attach(ILoggerRepository repository)
/// sink is disconnected.
///
///
- override public void Shutdown()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ override public void Shutdown()
{
// Stops the sink from receiving messages
RemotingServices.Disconnect(m_sink);
@@ -247,7 +253,10 @@ public void LogEvents(LoggingEvent[] events)
/// therefore this implementation returns null.
///
///
- public override object InitializeLifetimeService()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecurityCritical]
+#endif
+ public override object InitializeLifetimeService()
{
return null;
}
diff --git a/src/Repository/ConfigurationChangedEventArgs.cs b/src/Repository/ConfigurationChangedEventArgs.cs
index 47bf36fb..77df7d41 100644
--- a/src/Repository/ConfigurationChangedEventArgs.cs
+++ b/src/Repository/ConfigurationChangedEventArgs.cs
@@ -1,30 +1,51 @@
-using System;
-using System.Collections;
-
-namespace log4net.Repository
-{
- ///
- ///
- ///
- public class ConfigurationChangedEventArgs : EventArgs
- {
- private readonly ICollection configurationMessages;
-
- ///
- ///
- ///
- ///
- public ConfigurationChangedEventArgs(ICollection configurationMessages)
- {
- this.configurationMessages = configurationMessages;
- }
-
- ///
- ///
- ///
- public ICollection ConfigurationMessages
- {
- get { return configurationMessages; }
- }
- }
-}
\ No newline at end of file
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+using System;
+using System.Collections;
+
+namespace log4net.Repository
+{
+ ///
+ ///
+ ///
+ public class ConfigurationChangedEventArgs : EventArgs
+ {
+ private readonly ICollection configurationMessages;
+
+ ///
+ ///
+ ///
+ ///
+ public ConfigurationChangedEventArgs(ICollection configurationMessages)
+ {
+ this.configurationMessages = configurationMessages;
+ }
+
+ ///
+ ///
+ ///
+ public ICollection ConfigurationMessages
+ {
+ get { return configurationMessages; }
+ }
+ }
+}
diff --git a/src/Repository/Hierarchy/DefaultLoggerFactory.cs b/src/Repository/Hierarchy/DefaultLoggerFactory.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/Hierarchy/Hierarchy.cs b/src/Repository/Hierarchy/Hierarchy.cs
old mode 100755
new mode 100644
index ff4a21db..444d98b1
--- a/src/Repository/Hierarchy/Hierarchy.cs
+++ b/src/Repository/Hierarchy/Hierarchy.cs
@@ -105,7 +105,7 @@ public Logger Logger
///
///
/// The structure of the logger hierarchy is maintained by the
- /// method. The hierarchy is such that children
+ /// method. The hierarchy is such that children
/// link to their parent but parents do not have any references to their
/// children. Moreover, loggers can be instantiated in any order, in
/// particular descendant before ancestor.
@@ -457,7 +457,7 @@ override public void ResetConfiguration()
/// This method should not normally be used to log.
/// The interface should be used
/// for routine logging. This interface can be obtained
- /// using the method.
+ /// using the method.
///
///
/// The logEvent is delivered to the appropriate logger and
@@ -568,7 +568,7 @@ void IBasicRepositoryConfigurator.Configure(params IAppender[] appenders)
///
///
/// This method provides the same functionality as the
- /// method implemented
+ /// method implemented
/// on this object, but it is protected and therefore can be called by subclasses.
///
///
@@ -612,7 +612,7 @@ void IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element)
///
///
/// This method provides the same functionality as the
- /// method implemented
+ /// method implemented
/// on this object, but it is protected and therefore can be called by subclasses.
///
///
@@ -866,7 +866,12 @@ private void UpdateParents(Logger log)
LogLog.Error(declaringType, "Unexpected object type ["+node.GetType()+"] in ht.", new LogException());
}
}
- }
+ }
+ if (i == 0) {
+ // logger name starts with a dot
+ // and we've hit the start
+ break;
+ }
}
// If we could not find any existing parents, then link with root.
diff --git a/src/Repository/Hierarchy/ILoggerFactory.cs b/src/Repository/Hierarchy/ILoggerFactory.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/Hierarchy/Logger.cs b/src/Repository/Hierarchy/Logger.cs
old mode 100755
new mode 100644
index 3b49b3fa..5c296530
--- a/src/Repository/Hierarchy/Logger.cs
+++ b/src/Repository/Hierarchy/Logger.cs
@@ -432,10 +432,12 @@ virtual public void Log(Type callerStackBoundaryDeclaringType, Level level, obje
{
log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex);
}
+#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0
catch
{
log4net.Util.LogLog.Error(declaringType, "Exception while logging");
}
+#endif
}
///
@@ -467,10 +469,12 @@ virtual public void Log(LoggingEvent logEvent)
{
log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex);
}
+#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0
catch
{
log4net.Util.LogLog.Error(declaringType, "Exception while logging");
}
+#endif
}
///
@@ -505,10 +509,12 @@ virtual public bool IsEnabledFor(Level level)
{
log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex);
}
+#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0
catch
{
log4net.Util.LogLog.Error(declaringType, "Exception while logging");
}
+#endif
return false;
}
@@ -593,6 +599,7 @@ virtual protected void CallAppenders(LoggingEvent loggingEvent)
//
if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0)
{
+ m_hierarchy.EmittedNoAppenderWarning = true;
LogLog.Debug(declaringType, "No appenders could be found for logger [" + Name + "] repository [" + Repository.Name + "]");
LogLog.Debug(declaringType, "Please initialize the log4net system properly.");
try
@@ -608,7 +615,6 @@ virtual protected void CallAppenders(LoggingEvent loggingEvent)
{
// Insufficient permissions to display info from the AppDomain
}
- m_hierarchy.EmittedNoAppenderWarning = true;
}
}
diff --git a/src/Repository/Hierarchy/LoggerKey.cs b/src/Repository/Hierarchy/LoggerKey.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/Hierarchy/ProvisionNode.cs b/src/Repository/Hierarchy/ProvisionNode.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/Hierarchy/RootLogger.cs b/src/Repository/Hierarchy/RootLogger.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs b/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs
old mode 100755
new mode 100644
index d4563a4b..cc17d126
--- a/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs
+++ b/src/Repository/Hierarchy/XmlHierarchyConfigurator.cs
@@ -345,7 +345,7 @@ protected IAppender ParseAppender(XmlElement appenderElement)
optionHandler.ActivateOptions();
}
- LogLog.Debug(declaringType, "reated Appender [" + appenderName + "]");
+ LogLog.Debug(declaringType, "Created Appender [" + appenderName + "]");
return appender;
}
catch (Exception ex)
@@ -634,7 +634,11 @@ protected void SetParameter(XmlElement element, object target)
try
{
// Expand environment variables in the string.
- propertyValue = OptionConverter.SubstituteVariables(propertyValue, Environment.GetEnvironmentVariables());
+ IDictionary environmentVariables = Environment.GetEnvironmentVariables();
+ if (HasCaseInsensitiveEnvironment) {
+ environmentVariables = CreateCaseInsensitiveWrapper(environmentVariables);
+ }
+ propertyValue = OptionConverter.SubstituteVariables(propertyValue, environmentVariables);
}
catch(System.Security.SecurityException)
{
@@ -1023,6 +1027,38 @@ protected object CreateObjectFromXml(XmlElement element, Type defaultTargetType,
#endregion Protected Instance Methods
+#if !NETCF
+ private bool HasCaseInsensitiveEnvironment
+ {
+ get
+ {
+#if NET_1_0 || NET_1_1 || CLI_1_0
+ // actually there is no guarantee, but we don't know better
+ return true;
+#elif MONO_1_0
+ // see above
+ return false;
+#else
+ PlatformID platform = Environment.OSVersion.Platform;
+ return platform != PlatformID.Unix && platform != PlatformID.MacOSX;
+#endif
+ }
+ }
+
+ private IDictionary CreateCaseInsensitiveWrapper(IDictionary dict)
+ {
+ if (dict == null)
+ {
+ return dict;
+ }
+ Hashtable hash = SystemInfo.CreateCaseInsensitiveHashtable();
+ foreach (DictionaryEntry entry in dict) {
+ hash[entry.Key] = entry.Value;
+ }
+ return hash;
+ }
+#endif
+
#region Private Constants
// String constants used while parsing the XML data
diff --git a/src/Repository/IBasicRepositoryConfigurator.cs b/src/Repository/IBasicRepositoryConfigurator.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/ILoggerRepository.cs b/src/Repository/ILoggerRepository.cs
old mode 100755
new mode 100644
index becbd051..30ef5b33
--- a/src/Repository/ILoggerRepository.cs
+++ b/src/Repository/ILoggerRepository.cs
@@ -219,7 +219,7 @@ public interface ILoggerRepository
/// lost.
///
///
- /// The method is careful to close nested
+ /// The 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.
@@ -254,7 +254,7 @@ public interface ILoggerRepository
/// This method should not normally be used to log.
/// The interface should be used
/// for routine logging. This interface can be obtained
- /// using the method.
+ /// using the method.
///
///
/// The logEvent is delivered to the appropriate logger and
diff --git a/src/Repository/IXmlRepositoryConfigurator.cs b/src/Repository/IXmlRepositoryConfigurator.cs
old mode 100755
new mode 100644
diff --git a/src/Repository/LoggerRepositorySkeleton.cs b/src/Repository/LoggerRepositorySkeleton.cs
old mode 100755
new mode 100644
index 0b3fa333..d5663315
--- a/src/Repository/LoggerRepositorySkeleton.cs
+++ b/src/Repository/LoggerRepositorySkeleton.cs
@@ -307,7 +307,7 @@ virtual public void ResetConfiguration()
/// This method should not normally be used to log.
/// The interface should be used
/// for routine logging. This interface can be obtained
- /// using the method.
+ /// using the method.
///
///
/// The logEvent is delivered to the appropriate logger and
diff --git a/src/ThreadContext.cs b/src/ThreadContext.cs
old mode 100755
new mode 100644
diff --git a/src/Util/AppenderAttachedImpl.cs b/src/Util/AppenderAttachedImpl.cs
old mode 100755
new mode 100644
diff --git a/src/Util/CompositeProperties.cs b/src/Util/CompositeProperties.cs
old mode 100755
new mode 100644
diff --git a/src/Util/ContextPropertiesBase.cs b/src/Util/ContextPropertiesBase.cs
old mode 100755
new mode 100644
diff --git a/src/Util/ConverterInfo.cs b/src/Util/ConverterInfo.cs
index f2919d59..b64edc9d 100644
--- a/src/Util/ConverterInfo.cs
+++ b/src/Util/ConverterInfo.cs
@@ -1,73 +1,94 @@
-using System;
-
-namespace log4net.Util
-{
- ///
- /// Wrapper class used to map converter names to converter types
- ///
- ///
- ///
- /// Pattern converter info class used during configuration by custom
- /// PatternString and PatternLayer converters.
- ///
- ///
- public sealed class ConverterInfo
- {
- private string m_name;
- private Type m_type;
- private readonly PropertiesDictionary properties = new PropertiesDictionary();
-
- ///
- /// default constructor
- ///
- public ConverterInfo()
- {
- }
-
- ///
- /// Gets or sets the name of the conversion pattern
- ///
- ///
- ///
- /// The name of the pattern in the format string
- ///
- ///
- public string Name
- {
- get { return m_name; }
- set { m_name = value; }
- }
-
- ///
- /// Gets or sets the type of the converter
- ///
- ///
- ///
- /// The value specified must extend the
- /// type.
- ///
- ///
- public Type Type
- {
- get { return m_type; }
- set { m_type = value; }
- }
-
- ///
- ///
- ///
- ///
- public void AddProperty(PropertyEntry entry)
- {
- properties[entry.Key] = entry.Value;
- }
-
- ///
- ///
- ///
- public PropertiesDictionary Properties
- {
- get { return properties; }
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+using System;
+
+namespace log4net.Util
+{
+ ///
+ /// Wrapper class used to map converter names to converter types
+ ///
+ ///
+ ///
+ /// Pattern converter info class used during configuration by custom
+ /// PatternString and PatternLayer converters.
+ ///
+ ///
+ public sealed class ConverterInfo
+ {
+ private string m_name;
+ private Type m_type;
+ private readonly PropertiesDictionary properties = new PropertiesDictionary();
+
+ ///
+ /// default constructor
+ ///
+ public ConverterInfo()
+ {
+ }
+
+ ///
+ /// Gets or sets the name of the conversion pattern
+ ///
+ ///
+ ///
+ /// The name of the pattern in the format string
+ ///
+ ///
+ public string Name
+ {
+ get { return m_name; }
+ set { m_name = value; }
+ }
+
+ ///
+ /// Gets or sets the type of the converter
+ ///
+ ///
+ ///
+ /// The value specified must extend the
+ /// type.
+ ///
+ ///
+ public Type Type
+ {
+ get { return m_type; }
+ set { m_type = value; }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void AddProperty(PropertyEntry entry)
+ {
+ properties[entry.Key] = entry.Value;
+ }
+
+ ///
+ ///
+ ///
+ public PropertiesDictionary Properties
+ {
+ get { return properties; }
+ }
+ }
+}
diff --git a/src/Util/CountingQuietTextWriter.cs b/src/Util/CountingQuietTextWriter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/CyclicBuffer.cs b/src/Util/CyclicBuffer.cs
old mode 100755
new mode 100644
diff --git a/src/Util/EmptyCollection.cs b/src/Util/EmptyCollection.cs
old mode 100755
new mode 100644
diff --git a/src/Util/EmptyDictionary.cs b/src/Util/EmptyDictionary.cs
old mode 100755
new mode 100644
diff --git a/src/Util/FormattingInfo.cs b/src/Util/FormattingInfo.cs
old mode 100755
new mode 100644
diff --git a/src/Util/GlobalContextProperties.cs b/src/Util/GlobalContextProperties.cs
old mode 100755
new mode 100644
diff --git a/src/Util/ILogExtensions.cs b/src/Util/ILogExtensions.cs
new file mode 100644
index 00000000..f8c0ebbf
--- /dev/null
+++ b/src/Util/ILogExtensions.cs
@@ -0,0 +1,1741 @@
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+#if NET_3_5 || NET_4_0 || MONO_3_5 || MONO_4_0
+
+using System;
+
+using log4net.Core;
+
+namespace log4net.Util
+{
+ ///
+ /// The static class ILogExtensions contains a set of widely used
+ /// methods that ease the interaction with the ILog interface implementations.
+ ///
+ ///
+ ///
+ /// This class contains methods for logging at different levels and checks the
+ /// properties for determining if those logging levels are enabled in the current
+ /// configuration.
+ ///
+ ///
+ /// Simple example of logging messages
+ ///
+ /// using log4net.Util;
+ ///
+ /// ILog log = LogManager.GetLogger("application-log");
+ ///
+ /// log.InfoExt("Application Start");
+ /// log.DebugExt("This is a debug message");
+ ///
+ ///
+ public static class ILogExtensions
+ {
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the Logger class.
+ ///
+ private readonly static Type declaringType = typeof(ILogExtensions);
+
+ #endregion //Private Static Fields
+
+ #region debug extensions
+
+ #region debug extensions that uses log message lambda expression
+
+ ///
+ /// Log a message object with the level.
+ ///
+ /// The logger on which the message is logged.
+ /// The lambda expression that gets the object to log.
+ ///
+ ///
+ /// This method first checks if this logger is INFO
+ /// enabled by reading the value property.
+ /// This check happens always and does not depend on the
+ /// implementation. If this logger is INFO enabled, then it converts
+ /// the message object (retrieved by invocation of the provided callback) to a
+ /// string by invoking the appropriate .
+ /// It then proceeds to call all the registered appenders in this logger
+ /// and also higher in the hierarchy depending on the value of
+ /// the additivity flag.
+ ///
+ /// WARNING Note that passing an
+ /// to this method will print the name of the
+ /// but no stack trace. To print a stack trace use the
+ /// form instead.
+ ///
+ ///
+ ///
+ ///
+ public static void DebugExt(this ILog logger, Func
///
- public static NativeError GetLastError()
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#elif !NETCF
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode=true)]
+#endif
+ public static NativeError GetLastError()
{
int number = Marshal.GetLastWin32Error();
return new NativeError(number, NativeError.GetErrorMessage(number));
@@ -152,7 +157,12 @@ public static NativeError GetError(int number)
/// using the native FormatMessage function.
///
///
- public static string GetErrorMessage(int messageId)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#elif !NETCF
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)]
+#endif
+ public static string GetErrorMessage(int messageId)
{
// Win32 constants
int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; // The function should allocates a buffer large enough to hold the formatted message
@@ -247,7 +257,7 @@ public override string ToString()
///
///
/// If the function fails, the return value is zero. To get extended error information,
- /// call .
+ /// call .
///
///
#if NETCF
diff --git a/src/Util/NullDictionaryEnumerator.cs b/src/Util/NullDictionaryEnumerator.cs
old mode 100755
new mode 100644
diff --git a/src/Util/NullEnumerator.cs b/src/Util/NullEnumerator.cs
old mode 100755
new mode 100644
diff --git a/src/Util/NullSecurityContext.cs b/src/Util/NullSecurityContext.cs
old mode 100755
new mode 100644
diff --git a/src/Util/OnlyOnceErrorHandler.cs b/src/Util/OnlyOnceErrorHandler.cs
old mode 100755
new mode 100644
index cc08d2d8..fb9d858b
--- a/src/Util/OnlyOnceErrorHandler.cs
+++ b/src/Util/OnlyOnceErrorHandler.cs
@@ -30,7 +30,7 @@ namespace log4net.Util
///
///
///
- /// The error message is processed using the LogLog sub-system.
+ /// The error message is processed using the LogLog sub-system by default.
///
///
/// This policy aims at protecting an otherwise working application
@@ -98,37 +98,50 @@ public void Reset()
/// The internal error code.
///
///
- /// Sends the error information to 's Error method.
+ /// Invokes if and only if this is the first error or the first error after has been called.
///
///
public void Error(string message, Exception e, ErrorCode errorCode)
{
if (m_firstTime)
{
- m_enabledDate = DateTime.Now;
- m_errorCode = errorCode;
- m_exception = e;
- m_message = message;
- m_firstTime = false;
-
- if (LogLog.InternalDebugging && !LogLog.QuietMode)
- {
- LogLog.Error(declaringType, "[" + m_prefix + "] ErrorCode: " + errorCode.ToString() + ". " + message, e);
- }
+ FirstError(message, e, errorCode);
}
}
- ///
+ ///
+ /// Log the very first error
+ ///
+ /// The error message.
+ /// The exception.
+ /// The internal error code.
+ ///
+ ///
+ /// Sends the error information to 's Error method.
+ ///
+ ///
+ public virtual void FirstError(string message, Exception e, ErrorCode errorCode) {
+ m_enabledDate = DateTime.Now;
+ m_errorCode = errorCode;
+ m_exception = e;
+ m_message = message;
+ m_firstTime = false;
+
+ if (LogLog.InternalDebugging && !LogLog.QuietMode) {
+ LogLog.Error(declaringType, "[" + m_prefix + "] ErrorCode: " + errorCode.ToString() + ". " + message, e);
+ }
+ }
+
+ ///
/// Log an Error
///
/// The error message.
/// The exception.
///
- ///
- /// Prints the message and the stack trace of the exception on the standard
- /// error output stream.
- ///
- ///
+ ///
+ /// Invokes if and only if this is the first error or the first error after has been called.
+ ///
+ ///
public void Error(string message, Exception e)
{
Error(message, e, ErrorCode.GenericFailure);
@@ -139,11 +152,10 @@ public void Error(string message, Exception e)
///
/// The error message.
///
- ///
- /// Print a the error message passed as parameter on the standard
- /// error output stream.
- ///
- ///
+ ///
+ /// Invokes if and only if this is the first error or the first error after has been called.
+ ///
+ ///
public void Error(string message)
{
Error(message, null, ErrorCode.GenericFailure);
diff --git a/src/Util/OptionConverter.cs b/src/Util/OptionConverter.cs
old mode 100755
new mode 100644
index d509e73f..616cf1bc
--- a/src/Util/OptionConverter.cs
+++ b/src/Util/OptionConverter.cs
@@ -492,7 +492,7 @@ public static object InstantiateByClassName(string className, Type superClass, o
}
///
- /// Performs variable substitution in string from the
+ /// Performs variable substitution in string from the
/// values of keys found in .
///
/// The string on which variable substitution is performed.
diff --git a/src/Util/PatternConverter.cs b/src/Util/PatternConverter.cs
old mode 100755
new mode 100644
index ba4c0188..7b333957
--- a/src/Util/PatternConverter.cs
+++ b/src/Util/PatternConverter.cs
@@ -174,33 +174,43 @@ virtual public void Format(TextWriter writer, object state)
}
else
{
- m_formatWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize);
-
- Convert(m_formatWriter, state);
-
- StringBuilder buf = m_formatWriter.GetStringBuilder();
- int len = buf.Length;
-
- if (len > m_max)
- {
- writer.Write(buf.ToString(len - m_max, m_max));
- }
- else if (len < m_min)
+ string msg = null;
+ int len;
+ lock (m_formatWriter)
+ {
+ m_formatWriter.Reset(c_renderBufferMaxCapacity, c_renderBufferSize);
+
+ Convert(m_formatWriter, state);
+
+ StringBuilder buf = m_formatWriter.GetStringBuilder();
+ len = buf.Length;
+ if (len > m_max)
+ {
+ msg = buf.ToString(len - m_max, m_max);
+ len = m_max;
+ }
+ else
+ {
+ msg = buf.ToString();
+ }
+ }
+
+ if (len < m_min)
{
if (m_leftAlign)
{
- writer.Write(buf.ToString());
+ writer.Write(msg);
SpacePad(writer, m_min - len);
}
else
{
SpacePad(writer, m_min - len);
- writer.Write(buf.ToString());
+ writer.Write(msg);
}
}
else
{
- writer.Write(buf.ToString());
+ writer.Write(msg);
}
}
}
diff --git a/src/Util/PatternParser.cs b/src/Util/PatternParser.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternString.cs b/src/Util/PatternString.cs
old mode 100755
new mode 100644
index 5a8a1dee..73f5a5fa
--- a/src/Util/PatternString.cs
+++ b/src/Util/PatternString.cs
@@ -73,7 +73,7 @@ namespace log4net.Util
///
///
/// The date format specifier admits the same syntax as the
- /// time pattern string of the .
+ /// time pattern string of the .
///
///
/// For better results it is recommended to use the log4net date
@@ -86,7 +86,7 @@ namespace log4net.Util
///
///
/// These dedicated date formatters perform significantly
- /// better than .
+ /// better than .
///
///
///
@@ -208,7 +208,7 @@ namespace log4net.Util
///
///
/// The date format specifier admits the same syntax as the
- /// time pattern string of the .
+ /// time pattern string of the .
///
///
/// For better results it is recommended to use the log4net date
@@ -221,7 +221,7 @@ namespace log4net.Util
///
///
/// These dedicated date formatters perform significantly
- /// better than .
+ /// better than .
///
///
///
@@ -236,8 +236,8 @@ namespace log4net.Util
///
///
/// Additional pattern converters may be registered with a specific
- /// instance using or
- /// .
+ /// instance using or
+ /// .
///
///
/// See the for details on the
@@ -462,7 +462,7 @@ public string Format()
///
///
/// This version of the method is used by the configurator.
- /// Programmatic users should use the alternative method.
+ /// Programmatic users should use the alternative method.
///
///
public void AddConverter(ConverterInfo converterInfo)
diff --git a/src/Util/PatternStringConverters/AppDomainPatternConverter.cs b/src/Util/PatternStringConverters/AppDomainPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/DatePatternConverter.cs b/src/Util/PatternStringConverters/DatePatternConverter.cs
old mode 100755
new mode 100644
index 8dec5d8b..88045dfa
--- a/src/Util/PatternStringConverters/DatePatternConverter.cs
+++ b/src/Util/PatternStringConverters/DatePatternConverter.cs
@@ -69,7 +69,7 @@ namespace log4net.Util.PatternStringConverters
///
/// Any other pattern string uses the formatter.
/// This formatter passes the pattern string to the
- /// method.
+ /// method.
/// For details on valid patterns see
/// DateTimeFormatInfo Class.
///
diff --git a/src/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs b/src/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs
index d23b8a14..a6dd2216 100644
--- a/src/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs
+++ b/src/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs
@@ -1,98 +1,98 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-#if !NETCF
-
-using System;
-using System.IO;
-
-namespace log4net.Util.PatternStringConverters
-{
- ///
- /// Write an folder path to the output
- ///
- ///
- ///
- /// Write an special path environment folder path to the output writer.
- /// The value of the determines
- /// the name of the variable to output.
- /// should be a value in the enumeration.
- ///
- ///
- /// Ron Grabowski
- internal sealed class EnvironmentFolderPathPatternConverter : PatternConverter
- {
- ///
- /// Write an special path environment folder path to the output
- ///
- /// the writer to write to
- /// null, state is not set
- ///
- ///
- /// Writes the special path environment folder path to the output .
- /// The name of the special path environment folder path to output must be set
- /// using the
- /// property.
- ///
- ///
- override protected void Convert(TextWriter writer, object state)
- {
- try
- {
- if (Option != null && Option.Length > 0)
- {
- Environment.SpecialFolder specialFolder =
- (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), Option, true);
-
- string envFolderPathValue = Environment.GetFolderPath(specialFolder);
- if (envFolderPathValue != null && envFolderPathValue.Length > 0)
- {
- writer.Write(envFolderPathValue);
- }
- }
- }
- 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.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx);
- }
- catch (Exception ex)
- {
- LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex);
- }
- }
-
- #region Private Static Fields
-
- ///
- /// The fully qualified type of the EnvironmentFolderPathPatternConverter class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(EnvironmentFolderPathPatternConverter);
-
- #endregion Private Static Fields
- }
-}
-
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+#if !NETCF
+
+using System;
+using System.IO;
+
+namespace log4net.Util.PatternStringConverters
+{
+ ///
+ /// Write an folder path to the output
+ ///
+ ///
+ ///
+ /// Write an special path environment folder path to the output writer.
+ /// The value of the determines
+ /// the name of the variable to output.
+ /// should be a value in the enumeration.
+ ///
+ ///
+ /// Ron Grabowski
+ internal sealed class EnvironmentFolderPathPatternConverter : PatternConverter
+ {
+ ///
+ /// Write an special path environment folder path to the output
+ ///
+ /// the writer to write to
+ /// null, state is not set
+ ///
+ ///
+ /// Writes the special path environment folder path to the output .
+ /// The name of the special path environment folder path to output must be set
+ /// using the
+ /// property.
+ ///
+ ///
+ override protected void Convert(TextWriter writer, object state)
+ {
+ try
+ {
+ if (Option != null && Option.Length > 0)
+ {
+ Environment.SpecialFolder specialFolder =
+ (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), Option, true);
+
+ string envFolderPathValue = Environment.GetFolderPath(specialFolder);
+ if (envFolderPathValue != null && envFolderPathValue.Length > 0)
+ {
+ writer.Write(envFolderPathValue);
+ }
+ }
+ }
+ 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.Debug(declaringType, "Security exception while trying to expand environment variables. Error Ignored. No Expansion.", secEx);
+ }
+ catch (Exception ex)
+ {
+ LogLog.Error(declaringType, "Error occurred while converting environment variable.", ex);
+ }
+ }
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the EnvironmentFolderPathPatternConverter class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(EnvironmentFolderPathPatternConverter);
+
+ #endregion Private Static Fields
+ }
+}
+
#endif // !NETCF
\ No newline at end of file
diff --git a/src/Util/PatternStringConverters/EnvironmentPatternConverter.cs b/src/Util/PatternStringConverters/EnvironmentPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/IdentityPatternConverter.cs b/src/Util/PatternStringConverters/IdentityPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/LiteralPatternConverter.cs b/src/Util/PatternStringConverters/LiteralPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/NewLinePatternConverter.cs b/src/Util/PatternStringConverters/NewLinePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs b/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs
old mode 100755
new mode 100644
index 29a33a68..e47ee9e0
--- a/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs
+++ b/src/Util/PatternStringConverters/ProcessIdPatternConverter.cs
@@ -46,7 +46,10 @@ internal sealed class ProcessIdPatternConverter : PatternConverter
/// Write the current process ID to the output .
///
///
- override protected void Convert(TextWriter writer, object state)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ override protected void Convert(TextWriter writer, object state)
{
#if (NETCF || SSCLI)
// On compact framework there is no System.Diagnostics.Process class
diff --git a/src/Util/PatternStringConverters/PropertyPatternConverter.cs b/src/Util/PatternStringConverters/PropertyPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/RandomStringPatternConverter.cs b/src/Util/PatternStringConverters/RandomStringPatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/UserNamePatternConverter.cs b/src/Util/PatternStringConverters/UserNamePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PatternStringConverters/UtcDatePatternConverter.cs b/src/Util/PatternStringConverters/UtcDatePatternConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PropertiesDictionary.cs b/src/Util/PropertiesDictionary.cs
old mode 100755
new mode 100644
diff --git a/src/Util/PropertyEntry.cs b/src/Util/PropertyEntry.cs
index 3ef83a1d..3357d989 100644
--- a/src/Util/PropertyEntry.cs
+++ b/src/Util/PropertyEntry.cs
@@ -1,59 +1,80 @@
-namespace log4net.Util
-{
- ///
- /// A class to hold the key and data for a property set in the config file
- ///
- ///
- ///
- /// A class to hold the key and data for a property set in the config file
- ///
- ///
- public class PropertyEntry
- {
- private string m_key = null;
- private object m_value = null;
-
- ///
- /// Property Key
- ///
- ///
- /// Property Key
- ///
- ///
- ///
- /// Property Key.
- ///
- ///
- public string Key
- {
- get { return m_key; }
- set { m_key = value; }
- }
-
- ///
- /// Property Value
- ///
- ///
- /// Property Value
- ///
- ///
- ///
- /// Property Value.
- ///
- ///
- public object Value
- {
- get { return m_value; }
- set { m_value = value; }
- }
-
- ///
- /// Override Object.ToString to return sensible debug info
- ///
- /// string info about this object
- public override string ToString()
- {
- return "PropertyEntry(Key=" + m_key + ", Value=" + m_value + ")";
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+namespace log4net.Util
+{
+ ///
+ /// A class to hold the key and data for a property set in the config file
+ ///
+ ///
+ ///
+ /// A class to hold the key and data for a property set in the config file
+ ///
+ ///
+ public class PropertyEntry
+ {
+ private string m_key = null;
+ private object m_value = null;
+
+ ///
+ /// Property Key
+ ///
+ ///
+ /// Property Key
+ ///
+ ///
+ ///
+ /// Property Key.
+ ///
+ ///
+ public string Key
+ {
+ get { return m_key; }
+ set { m_key = value; }
+ }
+
+ ///
+ /// Property Value
+ ///
+ ///
+ /// Property Value
+ ///
+ ///
+ ///
+ /// Property Value.
+ ///
+ ///
+ public object Value
+ {
+ get { return m_value; }
+ set { m_value = value; }
+ }
+
+ ///
+ /// Override Object.ToString to return sensible debug info
+ ///
+ /// string info about this object
+ public override string ToString()
+ {
+ return "PropertyEntry(Key=" + m_key + ", Value=" + m_value + ")";
+ }
+ }
+}
diff --git a/src/Util/ProtectCloseTextWriter.cs b/src/Util/ProtectCloseTextWriter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/QuietTextWriter.cs b/src/Util/QuietTextWriter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/ReadOnlyPropertiesDictionary.cs b/src/Util/ReadOnlyPropertiesDictionary.cs
old mode 100755
new mode 100644
index 407fd5c8..be7796a6
--- a/src/Util/ReadOnlyPropertiesDictionary.cs
+++ b/src/Util/ReadOnlyPropertiesDictionary.cs
@@ -52,7 +52,7 @@ public class ReadOnlyPropertiesDictionary : IDictionary
///
/// The Hashtable used to store the properties data
///
- private Hashtable m_hashtable = new Hashtable();
+ private readonly Hashtable m_hashtable = new Hashtable();
#endregion Private Instance Fields
@@ -203,10 +203,14 @@ protected Hashtable InnerHashtable
/// Serializes this object into the provided.
///
///
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecurityCritical]
+#else
[System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter=true)]
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+#endif
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
- foreach(DictionaryEntry entry in InnerHashtable)
+ foreach(DictionaryEntry entry in InnerHashtable.Clone() as IDictionary)
{
string entryKey = entry.Key as string;
object entryValue = entry.Value;
diff --git a/src/Util/ReaderWriterLock.cs b/src/Util/ReaderWriterLock.cs
old mode 100755
new mode 100644
index 94597c76..5ed53c53
--- a/src/Util/ReaderWriterLock.cs
+++ b/src/Util/ReaderWriterLock.cs
@@ -20,6 +20,9 @@
#if (!NETCF)
#define HAS_READERWRITERLOCK
#endif
+#if NET_4_0 || MONO_4_0
+#define HAS_READERWRITERLOCKSLIM
+#endif
using System;
@@ -58,8 +61,13 @@ public sealed class ReaderWriterLock
///
public ReaderWriterLock()
{
+
#if HAS_READERWRITERLOCK
+#if HAS_READERWRITERLOCKSLIM
+ m_lock = new System.Threading.ReaderWriterLockSlim();
+#else
m_lock = new System.Threading.ReaderWriterLock();
+#endif
#endif
}
@@ -79,7 +87,16 @@ public ReaderWriterLock()
public void AcquireReaderLock()
{
#if HAS_READERWRITERLOCK
+#if HAS_READERWRITERLOCKSLIM
+ // prevent ThreadAbort while updating state, see https://issues.apache.org/jira/browse/LOG4NET-443
+ try { }
+ finally
+ {
+ m_lock.EnterReadLock();
+ }
+#else
m_lock.AcquireReaderLock(-1);
+#endif
#else
System.Threading.Monitor.Enter(this);
#endif
@@ -97,7 +114,12 @@ public void AcquireReaderLock()
public void ReleaseReaderLock()
{
#if HAS_READERWRITERLOCK
+#if HAS_READERWRITERLOCKSLIM
+ m_lock.ExitReadLock();
+#else
m_lock.ReleaseReaderLock();
+
+#endif
#else
System.Threading.Monitor.Exit(this);
#endif
@@ -114,7 +136,16 @@ public void ReleaseReaderLock()
public void AcquireWriterLock()
{
#if HAS_READERWRITERLOCK
+#if HAS_READERWRITERLOCKSLIM
+ // prevent ThreadAbort while updating state, see https://issues.apache.org/jira/browse/LOG4NET-443
+ try { }
+ finally
+ {
+ m_lock.EnterWriteLock();
+ }
+#else
m_lock.AcquireWriterLock(-1);
+#endif
#else
System.Threading.Monitor.Enter(this);
#endif
@@ -132,7 +163,11 @@ public void AcquireWriterLock()
public void ReleaseWriterLock()
{
#if HAS_READERWRITERLOCK
+#if HAS_READERWRITERLOCKSLIM
+ m_lock.ExitWriteLock();
+#else
m_lock.ReleaseWriterLock();
+#endif
#else
System.Threading.Monitor.Exit(this);
#endif
@@ -143,9 +178,14 @@ public void ReleaseWriterLock()
#region Private Members
#if HAS_READERWRITERLOCK
+#if HAS_READERWRITERLOCKSLIM
+ private System.Threading.ReaderWriterLockSlim m_lock;
+#else
private System.Threading.ReaderWriterLock m_lock;
+#endif
+
#endif
#endregion
}
-}
+}
\ No newline at end of file
diff --git a/src/Util/ReusableStringWriter.cs b/src/Util/ReusableStringWriter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/SystemInfo.cs b/src/Util/SystemInfo.cs
old mode 100755
new mode 100644
index 87634cc2..8e044831
--- a/src/Util/SystemInfo.cs
+++ b/src/Util/SystemInfo.cs
@@ -225,7 +225,7 @@ public static int CurrentThreadId
{
#if NETCF_1_0
return System.Threading.Thread.CurrentThread.GetHashCode();
-#elif NET_2_0 || NETCF_2_0 || MONO_2_0
+#elif NET_2_0 || NETCF_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
return System.Threading.Thread.CurrentThread.ManagedThreadId;
#else
return AppDomain.GetCurrentThreadId();
@@ -263,13 +263,19 @@ public static string HostName
// Lookup the host name
s_hostName = System.Net.Dns.GetHostName();
}
- catch(System.Net.Sockets.SocketException)
+ catch (System.Net.Sockets.SocketException)
{
+ LogLog.Debug(declaringType, "Socket exception occurred while getting the dns hostname. Error Ignored.");
}
- catch(System.Security.SecurityException)
+ catch (System.Security.SecurityException)
{
// We may get a security exception looking up the hostname
// You must have Unrestricted DnsPermission to access resource
+ LogLog.Debug(declaringType, "Security exception occurred while getting the dns hostname. Error Ignored.");
+ }
+ catch (Exception ex)
+ {
+ LogLog.Debug(declaringType, "Some other exception occurred while getting the dns hostname. Error Ignored.", ex);
}
// Get the NETBIOS machine name of the current machine
@@ -295,6 +301,7 @@ public static string HostName
if (s_hostName == null || s_hostName.Length == 0)
{
s_hostName = s_notAvailableText;
+ LogLog.Debug(declaringType, "Could not determine the hostname. Error Ignored. Empty host name will be used");
}
}
return s_hostName;
@@ -450,12 +457,44 @@ public static string AssemblyLocationInfo(Assembly myAssembly)
{
try
{
- // This call requires FileIOPermission for access to the path
- // if we don't have permission then we just ignore it and
- // carry on.
- return myAssembly.Location;
+#if NET_4_0 || MONO_4_0
+ if (myAssembly.IsDynamic)
+ {
+ return "Dynamic Assembly";
+ }
+#else
+ if (myAssembly is System.Reflection.Emit.AssemblyBuilder)
+ {
+ return "Dynamic Assembly";
+ }
+ else if(myAssembly.GetType().FullName == "System.Reflection.Emit.InternalAssemblyBuilder")
+ {
+ return "Dynamic Assembly";
+ }
+#endif
+ else
+ {
+ // This call requires FileIOPermission for access to the path
+ // if we don't have permission then we just ignore it and
+ // carry on.
+ return myAssembly.Location;
+ }
+ }
+ catch (NotSupportedException)
+ {
+ // The location information may be unavailable for dynamic assemblies and a NotSupportedException
+ // is thrown in those cases. See: http://msdn.microsoft.com/de-de/library/system.reflection.assembly.location.aspx
+ return "Dynamic Assembly";
}
- catch(System.Security.SecurityException)
+ catch (TargetInvocationException ex)
+ {
+ return "Location Detect Failed (" + ex.Message + ")";
+ }
+ catch (ArgumentException ex)
+ {
+ return "Location Detect Failed (" + ex.Message + ")";
+ }
+ catch (System.Security.SecurityException)
{
return "Location Permission Denied";
}
@@ -566,7 +605,7 @@ public static string AssemblyFileName(Assembly myAssembly)
///
/// If the type name is fully qualified, i.e. if contains an assembly name in
/// the type name, the type will be loaded from the system using
- /// .
+ /// .
///
///
/// If the type name is not fully qualified, it will be loaded from the assembly
@@ -590,7 +629,7 @@ public static Type GetTypeFromString(Type relativeType, string typeName, bool th
///
/// If the type name is fully qualified, i.e. if contains an assembly name in
/// the type name, the type will be loaded from the system using
- /// .
+ /// .
///
///
/// If the type name is not fully qualified it will be loaded from the
@@ -615,7 +654,7 @@ public static Type GetTypeFromString(string typeName, bool throwOnError, bool ig
///
/// If the type name is fully qualified, i.e. if contains an assembly name in
/// the type name, the type will be loaded from the system using
- /// .
+ /// .
///
///
/// If the type name is not fully qualified it will be loaded from the specified
@@ -653,17 +692,29 @@ public static Type GetTypeFromString(Assembly relativeAssembly, string typeName,
if (loadedAssemblies != null)
{
+ Type fallback = null;
// Search the loaded assemblies for the type
foreach (Assembly assembly in loadedAssemblies)
{
- type = assembly.GetType(typeName, false, ignoreCase);
- if (type != null)
+ Type t = assembly.GetType(typeName, false, ignoreCase);
+ if (t != null)
{
// Found type in loaded assembly
LogLog.Debug(declaringType, "Loaded type ["+typeName+"] from assembly ["+assembly.FullName+"] by searching loaded assemblies.");
- return type;
+ if (assembly.GlobalAssemblyCache)
+ {
+ fallback = t;
+ }
+ else
+ {
+ return t;
+ }
}
}
+ if (fallback != null)
+ {
+ return fallback;
+ }
}
// Didn't find the type
@@ -835,7 +886,55 @@ public static bool TryParse(string s, out long val)
#endif
}
- ///
+ ///
+ /// Parse a string into an value
+ ///
+ /// the string to parse
+ /// out param where the parsed value is placed
+ /// true if the string was able to be parsed into an integer
+ ///
+ ///
+ /// Attempts to parse the string into an integer. If the string cannot
+ /// be parsed then this method returns false. The method does not throw an exception.
+ ///
+ ///
+ public static bool TryParse(string s, out short val)
+ {
+#if NETCF
+ val = 0;
+ try
+ {
+ val = short.Parse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture);
+ return true;
+ }
+ catch
+ {
+ }
+
+ return false;
+#else
+ // Initialise out param
+ val = 0;
+
+ try
+ {
+ double doubleVal;
+ if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal))
+ {
+ val = Convert.ToInt16(doubleVal);
+ return true;
+ }
+ }
+ catch
+ {
+ // Ignore exception, just return false
+ }
+
+ return false;
+#endif
+ }
+
+ ///
/// Lookup an application setting
///
/// the application settings key to lookup
@@ -928,7 +1027,7 @@ public static Hashtable CreateCaseInsensitiveHashtable()
{
#if NETCF_1_0
return new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
-#elif NETCF_2_0 || NET_2_0 || MONO_2_0
+#elif NETCF_2_0 || NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
return new Hashtable(StringComparer.OrdinalIgnoreCase);
#else
return System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();
diff --git a/src/Util/SystemStringFormat.cs b/src/Util/SystemStringFormat.cs
index 2df2f31b..4b57cc3e 100644
--- a/src/Util/SystemStringFormat.cs
+++ b/src/Util/SystemStringFormat.cs
@@ -1,231 +1,237 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.Text;
-using System.Xml;
-using System.Text.RegularExpressions;
-
-namespace log4net.Util
-{
- ///
- /// Utility class that represents a format string.
- ///
- ///
- ///
- /// Utility class that represents a format string.
- ///
- ///
- /// Nicko Cadell
- public sealed class SystemStringFormat
- {
- private readonly IFormatProvider m_provider;
- private readonly string m_format;
- private readonly object[] m_args;
-
- #region Constructor
-
- ///
- /// Initialise the
- ///
- /// An that supplies culture-specific formatting information.
- /// A containing zero or more format items.
- /// An array containing zero or more objects to format.
- public SystemStringFormat(IFormatProvider provider, string format, params object[] args)
- {
- m_provider = provider;
- m_format = format;
- m_args = args;
- }
-
- #endregion Constructor
-
- ///
- /// Format the string and arguments
- ///
- /// the formatted string
- public override string ToString()
- {
- return StringFormat(m_provider, m_format, m_args);
- }
-
- #region StringFormat
-
- ///
- /// Replaces the format item in a specified with the text equivalent
- /// of the value of a corresponding instance in a specified array.
- /// A specified parameter supplies culture-specific formatting information.
- ///
- /// An that supplies culture-specific formatting information.
- /// A containing zero or more format items.
- /// An array containing zero or more objects to format.
- ///
- /// A copy of format in which the format items have been replaced by the
- /// equivalent of the corresponding instances of in args.
- ///
- ///
- ///
- /// This method does not throw exceptions. If an exception thrown while formatting the result the
- /// exception and arguments are returned in the result string.
- ///
- ///
- private static string StringFormat(IFormatProvider provider, string format, params object[] args)
- {
- try
- {
- // The format is missing, log null value
- if (format == null)
- {
- return null;
- }
-
- // The args are missing - should not happen unless we are called explicitly with a null array
- if (args == null)
- {
- return format;
- }
-
- // Try to format the string
- return String.Format(provider, format, args);
- }
- catch(Exception ex)
- {
- log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]", ex);
- return StringFormatError(ex, format, args);
- }
- catch
- {
- log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]");
- return StringFormatError(null, format, args);
- }
- }
-
- ///
- /// Process an error during StringFormat
- ///
- private static string StringFormatError(Exception formatException, string format, object[] args)
- {
- try
- {
- StringBuilder buf = new StringBuilder("");
-
- if (formatException != null)
- {
- buf.Append("Exception during StringFormat: ").Append(formatException.Message);
- }
- else
- {
- buf.Append("Exception during StringFormat");
- }
- buf.Append(" ").Append(format).Append("");
- buf.Append("");
- RenderArray(args, buf);
- buf.Append("");
- buf.Append("");
-
- return buf.ToString();
- }
- catch(Exception ex)
- {
- log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex);
- return "Exception during StringFormat. See Internal Log.";
- }
- catch
- {
- log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling");
- return "Exception during StringFormat. See Internal Log.";
- }
- }
-
- ///
- /// Dump the contents of an array into a string builder
- ///
- private static void RenderArray(Array array, StringBuilder buffer)
- {
- if (array == null)
- {
- buffer.Append(SystemInfo.NullText);
- }
- else
- {
- if (array.Rank != 1)
- {
- buffer.Append(array.ToString());
- }
- else
- {
- buffer.Append("{");
- int len = array.Length;
-
- if (len > 0)
- {
- RenderObject(array.GetValue(0), buffer);
- for (int i = 1; i < len; i++)
- {
- buffer.Append(", ");
- RenderObject(array.GetValue(i), buffer);
- }
- }
- buffer.Append("}");
- }
- }
- }
-
- ///
- /// Dump an object to a string
- ///
- private static void RenderObject(Object obj, StringBuilder buffer)
- {
- if (obj == null)
- {
- buffer.Append(SystemInfo.NullText);
- }
- else
- {
- try
- {
- buffer.Append(obj);
- }
- catch(Exception ex)
- {
- buffer.Append("");
- }
- catch
- {
- buffer.Append("");
- }
- }
- }
-
- #endregion StringFormat
-
- #region Private Static Fields
-
- ///
- /// The fully qualified type of the SystemStringFormat class.
- ///
- ///
- /// Used by the internal logger to record the Type of the
- /// log message.
- ///
- private readonly static Type declaringType = typeof(SystemStringFormat);
-
- #endregion Private Static Fields
- }
-}
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using System.Text;
+using System.Xml;
+using System.Text.RegularExpressions;
+
+namespace log4net.Util
+{
+ ///
+ /// Utility class that represents a format string.
+ ///
+ ///
+ ///
+ /// Utility class that represents a format string.
+ ///
+ ///
+ /// Nicko Cadell
+ public sealed class SystemStringFormat
+ {
+ private readonly IFormatProvider m_provider;
+ private readonly string m_format;
+ private readonly object[] m_args;
+
+ #region Constructor
+
+ ///
+ /// Initialise the
+ ///
+ /// An that supplies culture-specific formatting information.
+ /// A containing zero or more format items.
+ /// An array containing zero or more objects to format.
+ public SystemStringFormat(IFormatProvider provider, string format, params object[] args)
+ {
+ m_provider = provider;
+ m_format = format;
+ m_args = args;
+ }
+
+ #endregion Constructor
+
+ ///
+ /// Format the string and arguments
+ ///
+ /// the formatted string
+ public override string ToString()
+ {
+ return StringFormat(m_provider, m_format, m_args);
+ }
+
+ #region StringFormat
+
+ ///
+ /// Replaces the format item in a specified with the text equivalent
+ /// of the value of a corresponding instance in a specified array.
+ /// A specified parameter supplies culture-specific formatting information.
+ ///
+ /// An that supplies culture-specific formatting information.
+ /// A containing zero or more format items.
+ /// An array containing zero or more objects to format.
+ ///
+ /// A copy of format in which the format items have been replaced by the
+ /// equivalent of the corresponding instances of in args.
+ ///
+ ///
+ ///
+ /// This method does not throw exceptions. If an exception thrown while formatting the result the
+ /// exception and arguments are returned in the result string.
+ ///
+ ///
+ private static string StringFormat(IFormatProvider provider, string format, params object[] args)
+ {
+ try
+ {
+ // The format is missing, log null value
+ if (format == null)
+ {
+ return null;
+ }
+
+ // The args are missing - should not happen unless we are called explicitly with a null array
+ if (args == null)
+ {
+ return format;
+ }
+
+ // Try to format the string
+ return String.Format(provider, format, args);
+ }
+ catch(Exception ex)
+ {
+ log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]", ex);
+ return StringFormatError(ex, format, args);
+ }
+#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0
+ catch
+ {
+ log4net.Util.LogLog.Warn(declaringType, "Exception while rendering format ["+format+"]");
+ return StringFormatError(null, format, args);
+ }
+#endif
+ }
+
+ ///
+ /// Process an error during StringFormat
+ ///
+ private static string StringFormatError(Exception formatException, string format, object[] args)
+ {
+ try
+ {
+ StringBuilder buf = new StringBuilder("");
+
+ if (formatException != null)
+ {
+ buf.Append("Exception during StringFormat: ").Append(formatException.Message);
+ }
+ else
+ {
+ buf.Append("Exception during StringFormat");
+ }
+ buf.Append(" ").Append(format).Append("");
+ buf.Append("");
+ RenderArray(args, buf);
+ buf.Append("");
+ buf.Append("");
+
+ return buf.ToString();
+ }
+ catch(Exception ex)
+ {
+ log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling", ex);
+ return "Exception during StringFormat. See Internal Log.";
+ }
+#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0
+ catch
+ {
+ log4net.Util.LogLog.Error(declaringType, "INTERNAL ERROR during StringFormat error handling");
+ return "Exception during StringFormat. See Internal Log.";
+ }
+#endif
+ }
+
+ ///
+ /// Dump the contents of an array into a string builder
+ ///
+ private static void RenderArray(Array array, StringBuilder buffer)
+ {
+ if (array == null)
+ {
+ buffer.Append(SystemInfo.NullText);
+ }
+ else
+ {
+ if (array.Rank != 1)
+ {
+ buffer.Append(array.ToString());
+ }
+ else
+ {
+ buffer.Append("{");
+ int len = array.Length;
+
+ if (len > 0)
+ {
+ RenderObject(array.GetValue(0), buffer);
+ for (int i = 1; i < len; i++)
+ {
+ buffer.Append(", ");
+ RenderObject(array.GetValue(i), buffer);
+ }
+ }
+ buffer.Append("}");
+ }
+ }
+ }
+
+ ///
+ /// Dump an object to a string
+ ///
+ private static void RenderObject(Object obj, StringBuilder buffer)
+ {
+ if (obj == null)
+ {
+ buffer.Append(SystemInfo.NullText);
+ }
+ else
+ {
+ try
+ {
+ buffer.Append(obj);
+ }
+ catch(Exception ex)
+ {
+ buffer.Append("");
+ }
+#if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0
+ catch
+ {
+ buffer.Append("");
+ }
+#endif
+ }
+ }
+
+ #endregion StringFormat
+
+ #region Private Static Fields
+
+ ///
+ /// The fully qualified type of the SystemStringFormat class.
+ ///
+ ///
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ ///
+ private readonly static Type declaringType = typeof(SystemStringFormat);
+
+ #endregion Private Static Fields
+ }
+}
diff --git a/src/Util/TextWriterAdapter.cs b/src/Util/TextWriterAdapter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/ThreadContextProperties.cs b/src/Util/ThreadContextProperties.cs
old mode 100755
new mode 100644
index a66155c9..17060852
--- a/src/Util/ThreadContextProperties.cs
+++ b/src/Util/ThreadContextProperties.cs
@@ -18,7 +18,9 @@
#endregion
using System;
+#if NETCF
using System.Collections;
+#endif
namespace log4net.Util
{
@@ -36,10 +38,18 @@ public sealed class ThreadContextProperties : ContextPropertiesBase
{
#region Private Instance Fields
+#if NETCF
///
/// The thread local data slot to use to store a PropertiesDictionary.
///
private readonly static LocalDataStoreSlot s_threadLocalSlot = System.Threading.Thread.AllocateDataSlot();
+#else
+ ///
+ /// Each thread will automatically have its instance.
+ ///
+ [ThreadStatic]
+ private static PropertiesDictionary _dictionary;
+#endif
#endregion Private Instance Fields
@@ -74,18 +84,20 @@ internal ThreadContextProperties()
///
override public object this[string key]
{
- get
- {
- PropertiesDictionary dictionary = GetProperties(false);
- if (dictionary != null)
+ get
+ {
+#if NETCF
+ PropertiesDictionary _dictionary = GetProperties(false);
+#endif
+ if (_dictionary != null)
{
- return dictionary[key];
+ return _dictionary[key];
}
return null;
}
- set
- {
- GetProperties(true)[key] = value;
+ set
+ {
+ GetProperties(true)[key] = value;
}
}
@@ -104,11 +116,32 @@ override public object this[string key]
///
public void Remove(string key)
{
- PropertiesDictionary dictionary = GetProperties(false);
- if (dictionary != null)
+#if NETCF
+ PropertiesDictionary _dictionary = GetProperties(false);
+#endif
+ if (_dictionary != null)
+ {
+ _dictionary.Remove(key);
+ }
+ }
+
+ ///
+ /// Get the keys stored in the properties.
+ ///
+ ///
+ /// Gets the keys stored in the properties.
+ ///
+ /// a set of the defined keys
+ public string[] GetKeys()
+ {
+#if NETCF
+ PropertiesDictionary _dictionary = GetProperties(false);
+#endif
+ if (_dictionary != null)
{
- dictionary.Remove(key);
+ return _dictionary.GetKeys();
}
+ return null;
}
///
@@ -121,10 +154,12 @@ public void Remove(string key)
///
public void Clear()
{
- PropertiesDictionary dictionary = GetProperties(false);
- if (dictionary != null)
+#if NETCF
+ PropertiesDictionary _dictionary = GetProperties(false);
+#endif
+ if (_dictionary != null)
{
- dictionary.Clear();
+ _dictionary.Clear();
}
}
@@ -135,7 +170,7 @@ public void Clear()
///
/// Get the PropertiesDictionary for this thread.
///
- /// create the dictionary if it does not exist, otherwise return null if is does not exist
+ /// create the dictionary if it does not exist, otherwise return null if does not exist
/// the properties for this thread
///
///
@@ -146,17 +181,20 @@ public void Clear()
///
internal PropertiesDictionary GetProperties(bool create)
{
- PropertiesDictionary properties = (PropertiesDictionary)System.Threading.Thread.GetData(s_threadLocalSlot);
- if (properties == null && create)
+#if NETCF
+ PropertiesDictionary _dictionary = (PropertiesDictionary)System.Threading.Thread.GetData(s_threadLocalSlot);
+#endif
+ if (_dictionary == null && create)
{
- properties = new PropertiesDictionary();
- System.Threading.Thread.SetData(s_threadLocalSlot, properties);
+ _dictionary = new PropertiesDictionary();
+#if NETCF
+ System.Threading.Thread.SetData(s_threadLocalSlot, _dictionary);
+#endif
}
- return properties;
+ return _dictionary;
}
#endregion Internal Instance Methods
}
}
-
diff --git a/src/Util/ThreadContextStack.cs b/src/Util/ThreadContextStack.cs
old mode 100755
new mode 100644
diff --git a/src/Util/ThreadContextStacks.cs b/src/Util/ThreadContextStacks.cs
old mode 100755
new mode 100644
diff --git a/src/Util/Transform.cs b/src/Util/Transform.cs
old mode 100755
new mode 100644
index 17919f9d..7e8f4086
--- a/src/Util/Transform.cs
+++ b/src/Util/Transform.cs
@@ -191,7 +191,10 @@ private static int CountSubstrings(string text, string substring)
private const string CDATA_END = "]]>";
private const string CDATA_UNESCAPABLE_TOKEN = "]]";
- private static Regex INVALIDCHARS=new Regex(@"[^\x09\x0A\x0D\x20-\xFF\u00FF-\u07FF\uE000-\uFFFD]",RegexOptions.Compiled);
+ ///
+ /// Characters illegal in XML 1.0
+ ///
+ private static Regex INVALIDCHARS=new Regex(@"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]",RegexOptions.Compiled);
#endregion Private Static Fields
}
}
diff --git a/src/Util/TypeConverters/BooleanConverter.cs b/src/Util/TypeConverters/BooleanConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/TypeConverters/ConversionNotSupportedException.cs b/src/Util/TypeConverters/ConversionNotSupportedException.cs
old mode 100755
new mode 100644
diff --git a/src/Util/TypeConverters/ConverterRegistry.cs b/src/Util/TypeConverters/ConverterRegistry.cs
old mode 100755
new mode 100644
index 6669bc8e..77271766
--- a/src/Util/TypeConverters/ConverterRegistry.cs
+++ b/src/Util/TypeConverters/ConverterRegistry.cs
@@ -33,8 +33,8 @@ namespace log4net.Util.TypeConverters
/// types.
///
///
- /// Use the and
- /// methods to register new converters.
+ /// Use the and
+ /// methods to register new converters.
/// The and methods
/// lookup appropriate converters to use.
///
diff --git a/src/Util/TypeConverters/EncodingConverter.cs b/src/Util/TypeConverters/EncodingConverter.cs
old mode 100755
new mode 100644
index d7f6a3a2..93c9eac9
--- a/src/Util/TypeConverters/EncodingConverter.cs
+++ b/src/Util/TypeConverters/EncodingConverter.cs
@@ -62,7 +62,7 @@ public bool CanConvertFrom(Type sourceType)
/// the encoding
///
///
- /// Uses the method to
+ /// Uses the method to
/// convert the argument to an .
///
///
diff --git a/src/Util/TypeConverters/IConvertFrom.cs b/src/Util/TypeConverters/IConvertFrom.cs
old mode 100755
new mode 100644
diff --git a/src/Util/TypeConverters/IConvertTo.cs b/src/Util/TypeConverters/IConvertTo.cs
old mode 100755
new mode 100644
diff --git a/src/Util/TypeConverters/IPAddressConverter.cs b/src/Util/TypeConverters/IPAddressConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/TypeConverters/PatternLayoutConverter.cs b/src/Util/TypeConverters/PatternLayoutConverter.cs
old mode 100755
new mode 100644
diff --git a/src/Util/TypeConverters/PatternStringConverter.cs b/src/Util/TypeConverters/PatternStringConverter.cs
old mode 100755
new mode 100644
index f5e13f85..2c79552f
--- a/src/Util/TypeConverters/PatternStringConverter.cs
+++ b/src/Util/TypeConverters/PatternStringConverter.cs
@@ -69,7 +69,7 @@ public bool CanConvertTo(Type targetType)
/// the converted object
///
///
- /// Uses the method to convert the
+ /// Uses the method to convert the
/// argument to a .
///
///
diff --git a/src/Util/TypeConverters/TypeConverter.cs b/src/Util/TypeConverters/TypeConverter.cs
old mode 100755
new mode 100644
index 48bc85aa..8fc8150c
--- a/src/Util/TypeConverters/TypeConverter.cs
+++ b/src/Util/TypeConverters/TypeConverter.cs
@@ -61,7 +61,7 @@ public bool CanConvertFrom(Type sourceType)
/// the Type
///
///
- /// Uses the method to convert the
+ /// Uses the method to convert the
/// argument to a .
/// Additional effort is made to locate partially specified types
/// by searching the loaded assemblies.
diff --git a/src/Util/TypeConverters/TypeConverterAttribute.cs b/src/Util/TypeConverters/TypeConverterAttribute.cs
old mode 100755
new mode 100644
diff --git a/src/Util/WindowsSecurityContext.cs b/src/Util/WindowsSecurityContext.cs
old mode 100755
new mode 100644
index 9e6e4510..0e902faf
--- a/src/Util/WindowsSecurityContext.cs
+++ b/src/Util/WindowsSecurityContext.cs
@@ -275,7 +275,11 @@ public override IDisposable Impersonate(object state)
/// token is used to initialize the WindowsIdentity.
///
///
- private static WindowsIdentity LogonUser(string userName, string domainName, string password)
+#if NET_4_0 || MONO_4_0
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, UnmanagedCode = true)]
+ private static WindowsIdentity LogonUser(string userName, string domainName, string password)
{
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml
index 4090576e..c52bf0de 100644
--- a/src/assembly/bin.xml
+++ b/src/assembly/bin.xml
@@ -33,7 +33,7 @@
KEYSLICENSENOTICE
- contribs/**
+ contribs/**examples/**src/assembly/**src/changes/**
@@ -41,10 +41,10 @@
src/ntdll/**src/performance/**src/site/**
- tests/README
- tests/*.xml
- tests/*.sample
- tests/*.bat
+ tests/README
+ tests/*.xml
+ tests/*.sample
+ tests/*.battests/input/**tests/resources/**tests/src/**
diff --git a/src/log4net.vs2003.csproj b/src/log4net.vs2003.csproj
deleted file mode 100644
index c8e0434f..00000000
--- a/src/log4net.vs2003.csproj
+++ /dev/null
@@ -1,1146 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/log4net.vs2003.sln b/src/log4net.vs2003.sln
deleted file mode 100644
index 85ca6657..00000000
--- a/src/log4net.vs2003.sln
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.vs2003", "log4net.vs2003.csproj", "{F6A02431-167E-4347-BC43-65532C31CDB7}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.Tests.vs2003", "..\tests\src\log4net.Tests.vs2003.csproj", "{4B68B77E-0C8B-4296-930D-6AC2787170B8}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfiguration) = preSolution
- Debug = Debug
- Release = Release
- EndGlobalSection
- GlobalSection(ProjectConfiguration) = postSolution
- {F6A02431-167E-4347-BC43-65532C31CDB7}.Debug.ActiveCfg = Debug|.NET
- {F6A02431-167E-4347-BC43-65532C31CDB7}.Debug.Build.0 = Debug|.NET
- {F6A02431-167E-4347-BC43-65532C31CDB7}.Release.ActiveCfg = Release|.NET
- {F6A02431-167E-4347-BC43-65532C31CDB7}.Release.Build.0 = Release|.NET
- {4B68B77E-0C8B-4296-930D-6AC2787170B8}.Debug.ActiveCfg = Debug|.NET
- {4B68B77E-0C8B-4296-930D-6AC2787170B8}.Debug.Build.0 = Debug|.NET
- {4B68B77E-0C8B-4296-930D-6AC2787170B8}.Release.ActiveCfg = Release|.NET
- {4B68B77E-0C8B-4296-930D-6AC2787170B8}.Release.Build.0 = Release|.NET
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- EndGlobalSection
- GlobalSection(ExtensibilityAddIns) = postSolution
- EndGlobalSection
-EndGlobal
diff --git a/src/log4net.vs2008.csproj b/src/log4net.vs2008.csproj
index edfd7d95..dfcff1f7 100644
--- a/src/log4net.vs2008.csproj
+++ b/src/log4net.vs2008.csproj
@@ -1,726 +1,769 @@
-
-
- Local
- 9.0.30729
- 2.0
- {181FE707-E161-4722-9F38-6AAAB6FAA106}
- Debug
- AnyCPU
-
-
-
-
- log4net
-
-
- JScript
- Grid
- IE50
- false
- Library
- log4net
-
-
-
-
-
-
- 2.0
-
-
- ..\build\bin\net\2.0\debug\
- false
- 285212672
- false
-
-
- TRACE;DEBUG;NET;NET_2_0
- log4net.xml
- true
- 4096
- false
- false
- false
- false
- 4
- full
- prompt
-
-
- ..\build\bin\net\1.0\release\
- false
- 285212672
- false
-
-
- TRACE;STRONG;NET;NET_1_0;
- log4net.xml
- false
- 4096
- true
- false
- false
- false
- 4
- none
- prompt
-
-
-
- System
-
-
-
- System.Data
-
-
- System.Web
-
-
- System.XML
-
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
- Code
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+ Local
+ 9.0.30729
+ 2.0
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}
+ Debug
+ AnyCPU
+
+
+
+
+ log4net
+
+
+ JScript
+ Grid
+ IE50
+ false
+ Library
+ log4net
+
+
+
+
+
+
+ 2.0
+
+
+ ..\build\bin\net\2.0\debug\
+ false
+ 285212672
+ false
+
+
+ TRACE;DEBUG;NET;NET_2_0
+ log4net.xml
+ true
+ 4096
+ false
+ false
+ false
+ false
+ 4
+ full
+ prompt
+
+
+ ..\build\bin\net\1.0\release\
+ false
+ 285212672
+ false
+
+
+ TRACE;STRONG;NET;NET_1_0;
+ log4net.xml
+ false
+ 4096
+ true
+ false
+ false
+ false
+ 4
+ none
+ prompt
+
+
+
+ System
+
+
+
+ System.Data
+
+
+ System.Web
+
+
+ System.XML
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
diff --git a/src/log4net.vs2008.sln b/src/log4net.vs2008.sln
index 11a6af3a..2bf603c5 100644
--- a/src/log4net.vs2008.sln
+++ b/src/log4net.vs2008.sln
@@ -1,25 +1,45 @@
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.vs2008", "log4net.vs2008.csproj", "{181FE707-E161-4722-9F38-6AAAB6FAA106}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.Tests.vs2008", "..\tests\src\log4net.Tests.vs2008.csproj", "{B0530F10-0238-49A9-93B0-8EF412E90BCF}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.Build.0 = Release|Any CPU
- {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.vs2008", "log4net.vs2008.csproj", "{181FE707-E161-4722-9F38-6AAAB6FAA106}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.Tests.vs2008", "..\tests\src\log4net.Tests.vs2008.csproj", "{B0530F10-0238-49A9-93B0-8EF412E90BCF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/log4net.vs2010.csproj b/src/log4net.vs2010.csproj
new file mode 100644
index 00000000..18430a53
--- /dev/null
+++ b/src/log4net.vs2010.csproj
@@ -0,0 +1,802 @@
+
+
+
+
+ Local
+ 9.0.30729
+ 2.0
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}
+ Debug
+ AnyCPU
+
+
+
+
+ log4net
+
+
+ JScript
+ Grid
+ IE50
+ false
+ Library
+ log4net
+
+
+
+
+
+
+ 3.5
+ v4.0
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+
+ ..\build\bin\net\4.0\debug\
+ false
+ 285212672
+ false
+
+
+ TRACE;DEBUG;NET;NET_2_0;NET_4_0
+ log4net.xml
+ true
+ 4096
+ false
+ false
+ false
+ false
+ 4
+ full
+ prompt
+ SecurityRules.ruleset
+
+
+ ..\build\bin\net\4.0\release\
+ false
+ 285212672
+ false
+
+
+ TRACE;STRONG;NET;NET_2_0;NET_4_0
+ log4net.xml
+ false
+ 4096
+ true
+ false
+ false
+ false
+ 4
+ none
+ prompt
+ AllRules.ruleset
+
+
+
+ System
+
+
+
+ System.Data
+
+
+ System.Web
+
+
+ System.XML
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/src/log4net.vs2010.sln b/src/log4net.vs2010.sln
new file mode 100644
index 00000000..db0afd90
--- /dev/null
+++ b/src/log4net.vs2010.sln
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.vs2010", "log4net.vs2010.csproj", "{181FE707-E161-4722-9F38-6AAAB6FAA106}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.Tests.vs2010", "..\tests\src\log4net.Tests.vs2010.csproj", "{B0530F10-0238-49A9-93B0-8EF412E90BCF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/log4net.vs2012.csproj b/src/log4net.vs2012.csproj
new file mode 100644
index 00000000..070534da
--- /dev/null
+++ b/src/log4net.vs2012.csproj
@@ -0,0 +1,802 @@
+
+
+
+
+ Local
+ 9.0.30729
+ 2.0
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}
+ Debug
+ AnyCPU
+
+
+
+
+ log4net
+
+
+ JScript
+ Grid
+ IE50
+ false
+ Library
+ log4net
+
+
+
+
+
+
+ 3.5
+ v4.5
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+
+ ..\build\bin\net\4.5\debug\
+ false
+ 285212672
+ false
+
+
+ TRACE;DEBUG;NET;NET_2_0;NET_4_0;NET_4_5
+ log4net.xml
+ true
+ 4096
+ false
+ false
+ false
+ false
+ 4
+ full
+ prompt
+ SecurityRules.ruleset
+
+
+ ..\build\bin\net\4.5\release\
+ false
+ 285212672
+ false
+
+
+ TRACE;STRONG;NET;NET_2_0;NET_4_0;NET_4_5
+ log4net.xml
+ false
+ 4096
+ true
+ false
+ false
+ false
+ 4
+ none
+ prompt
+ AllRules.ruleset
+
+
+
+ System
+
+
+
+ System.Data
+
+
+ System.Web
+
+
+ System.XML
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/src/log4net.vs2012.sln b/src/log4net.vs2012.sln
new file mode 100644
index 00000000..925b0049
--- /dev/null
+++ b/src/log4net.vs2012.sln
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.vs2012", "log4net.vs2012.csproj", "{181FE707-E161-4722-9F38-6AAAB6FAA106}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log4net.Tests.vs2012", "..\tests\src\log4net.Tests.vs2012.csproj", "{B0530F10-0238-49A9-93B0-8EF412E90BCF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {181FE707-E161-4722-9F38-6AAAB6FAA106}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0530F10-0238-49A9-93B0-8EF412E90BCF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/site/apt/download.apt b/src/site/apt/download.apt
deleted file mode 100644
index 277a4edd..00000000
--- a/src/site/apt/download.apt
+++ /dev/null
@@ -1,48 +0,0 @@
-~~ Licensed to the Apache Software Foundation (ASF) under one or more
-~~ contributor license agreements. See the NOTICE file distributed with
-~~ this work for additional information regarding copyright ownership.
-~~ The ASF licenses this file to You under the Apache License, Version 2.0
-~~ (the "License"); you may not use this file except in compliance with
-~~ the License. You may obtain a copy of the License at
-~~
-~~ http://www.apache.org/licenses/LICENSE-2.0
-~~
-~~ Unless required by applicable law or agreed to in writing, software
-~~ distributed under the License is distributed on an "AS IS" BASIS,
-~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-~~ See the License for the specific language governing permissions and
-~~ limitations under the License.
- ------
-Download Apache log4net 1.2.10
- ------
- ------
- ------
-
-Download Apache log4net 1.2.10
-
- log4net 1.2.10 is distributed under the {{{http://www.apache.org/licenses/LICENSE-2.0.html} Apache License, version 2.0}}.
-
- log4net has graduated from the Incubator project, however at the time the following releases were made,
- log4net was still undergoing incubation, therefore these releases are not officially endorsed by the ASF.
- Future releases of log4net will be officially endorsed by the ASF.
-
- The link in the Mirrors column should display a list of available mirrors with a
- default selection based on your inferred location. If you do not see that page,
- try a different browser. The checksum and signature are links to
- the originals on the main distribution server.
-
-*-------------------------+---------+----------+-----------+
-| | Mirrors | Checksum | Signature |
-*-------------------------+---------+----------+-----------+
-*-------------------------+---------+----------+-----------+
-| log4net 1.2.10 (zip) | {{{http://archive.apache.org/dist/incubator/log4net/1.2.10/incubating-log4net-1.2.10.zip} incubating-log4net-1.2.10.zip}} | {{{http://archive.apache.org/dist/incubator/log4net/1.2.10/incubating-log4net-1.2.10.zip.md5} incubating-log4net-1.2.10.zip.md5}} | {{{http://archive.apache.org/dist/incubator/log4net/1.2.10/incubating-log4net-1.2.10.zip.asc} incubating-log4net-1.2.10.zip.asc}}|
-| log4net 1.2.9-beta (zip) | {{{http://archive.apache.org/dist/incubator/log4net/1.2.9/incubating-log4net-1.2.9-beta.zip} incubating-log4net-1.2.9-beta.zip}} | {{{http://archive.apache.org/dist/incubator/log4net/1.2.9/incubating-log4net-1.2.9-beta.zip.md5} incubating-log4net-1.2.9-beta.zip.md5}} | {{{http://archive.apache.org/dist/incubator/log4net/1.2.9/incubating-log4net-1.2.9-beta.zip.asc} incubating-log4net-1.2.9-beta.zip.asc}}|
-*-------------------------+---------+----------+-----------+
-
- Please read {{{http://httpd.apache.org/dev/verification.html}Verifying Apache HTTP Server Releases}}
- for more information on why you should verify our releases.
-
-
-* Previous Releases
-
- Previous releases of log4net are available from the {{{http://sourceforge.net/project/showfiles.php?group_id=31983&release_id=171808}SourceForge Project Site}}.
diff --git a/src/site/apt/roadmap.apt b/src/site/apt/roadmap.apt
index c3602d5f..e3396ec4 100644
--- a/src/site/apt/roadmap.apt
+++ b/src/site/apt/roadmap.apt
@@ -13,15 +13,15 @@
~~ See the License for the specific language governing permissions and
~~ limitations under the License.
------
- log4net Roadmap
+ Apache log4net Roadmap
------
------
------
-log4net Roadmap
+Apache log4net™ Roadmap
- The log4net development roadmap is managed by our JIRA issue tracking system.
-
- For a list of upcoming fixes and in-progress tasks see:
-
- {{{http://issues.apache.org/jira/browse/LOG4NET?report=com.atlassian.jira.plugin.system.project:roadmap-panel}log4net Roadmap}}
+ The log4net development roadmap is managed by our JIRA issue tracking system.
+
+ For a list of upcoming fixes and in-progress tasks see:
+
+ {{{http://issues.apache.org/jira/browse/LOG4NET?report=com.atlassian.jira.plugin.system.project:roadmap-panel}Apache log4net Roadmap}}
diff --git a/src/site/resources/css/maven-base.css b/src/site/resources/css/maven-base.css
new file mode 100644
index 00000000..0167aa87
--- /dev/null
+++ b/src/site/resources/css/maven-base.css
@@ -0,0 +1,168 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+body {
+ margin: 0px;
+ padding: 0px;
+}
+img {
+ border:none;
+}
+table {
+ padding:0px;
+ width: 100%;
+ margin-left: -2px;
+ margin-right: -2px;
+}
+acronym {
+ cursor: help;
+ border-bottom: 1px dotted #feb;
+}
+table.bodyTable th, table.bodyTable td {
+ padding: 2px 4px 2px 4px;
+ vertical-align: top;
+}
+div.clear{
+ clear:both;
+ visibility: hidden;
+}
+div.clear hr{
+ display: none;
+}
+#bannerLeft, #bannerRight {
+ font-size: xx-large;
+ font-weight: bold;
+}
+#bannerLeft img, #bannerRight img {
+ margin: 0px;
+}
+.xleft, #bannerLeft img {
+ float:left;
+}
+.xright, #bannerRight {
+ float:right;
+}
+#banner {
+ padding: 0px;
+}
+#banner img {
+ border: none;
+}
+#breadcrumbs {
+ padding: 3px 10px 3px 10px;
+}
+#leftColumn {
+ width: 170px;
+ float:left;
+ overflow: auto;
+}
+#bodyColumn {
+ margin-right: 1.5em;
+ margin-left: 197px;
+}
+#legend {
+ padding: 8px 0 8px 0;
+}
+#navcolumn {
+ padding: 8px 4px 0 8px;
+}
+#navcolumn h5 {
+ margin: 0;
+ padding: 0;
+ font-size: small;
+}
+#navcolumn ul {
+ margin: 0;
+ padding: 0;
+ font-size: small;
+}
+#navcolumn li {
+ list-style-type: none;
+ background-image: none;
+ background-repeat: no-repeat;
+ background-position: 0 0.4em;
+ padding-left: 16px;
+ list-style-position: outside;
+ line-height: 1.2em;
+ font-size: smaller;
+}
+#navcolumn li.expanded {
+ background-image: url(../images/expanded.gif);
+}
+#navcolumn li.collapsed {
+ background-image: url(../images/collapsed.gif);
+}
+#poweredBy {
+ text-align: center;
+}
+#navcolumn img {
+ margin-top: 10px;
+ margin-bottom: 3px;
+}
+#poweredBy img {
+ display:block;
+ margin: 20px 0 20px 17px;
+}
+#search img {
+ margin: 0px;
+ display: block;
+}
+#search #q, #search #btnG {
+ border: 1px solid #999;
+ margin-bottom:10px;
+}
+#search form {
+ margin: 0px;
+}
+#lastPublished {
+ font-size: x-small;
+}
+.navSection {
+ margin-bottom: 2px;
+ padding: 8px;
+}
+.navSectionHead {
+ font-weight: bold;
+ font-size: x-small;
+}
+.section {
+ padding: 4px;
+}
+#footer {
+ padding: 3px 10px 3px 10px;
+ font-size: x-small;
+}
+#breadcrumbs {
+ font-size: x-small;
+ margin: 0pt;
+}
+.source {
+ padding: 12px;
+ margin: 1em 7px 1em 7px;
+}
+.source pre {
+ margin: 0px;
+ padding: 0px;
+}
+#navcolumn img.imageLink, .imageLink{
+ padding-left: 0px;
+ padding-bottom: 0px;
+ padding-top: 0px;
+ padding-right: 2px;
+ border: 0px;
+ margin: 0px;
+}
diff --git a/src/site/resources/css/site.css b/src/site/resources/css/site.css
index 8b137891..6005acea 100644
--- a/src/site/resources/css/site.css
+++ b/src/site/resources/css/site.css
@@ -1 +1,22 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
diff --git a/src/site/resources/download_log4net.cgi b/src/site/resources/download_log4net.cgi
new file mode 100755
index 00000000..4324f769
--- /dev/null
+++ b/src/site/resources/download_log4net.cgi
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Wrapper script around mirrors.cgi script
+# (we must change to that directory in order for python to pick up the
+# python includes correctly)
+cd /www/www.apache.org/dyn/mirrors
+/www/www.apache.org/dyn/mirrors/mirrors.cgi $*
diff --git a/src/site/resources/images/logos/maven-feather.png b/src/site/resources/images/logos/maven-feather.png
new file mode 100644
index 00000000..b5ada836
Binary files /dev/null and b/src/site/resources/images/logos/maven-feather.png differ
diff --git a/src/site/resources/images/ls-logo.jpg b/src/site/resources/images/ls-logo.jpg
old mode 100755
new mode 100644
index 611c5c36..35f2f473
Binary files a/src/site/resources/images/ls-logo.jpg and b/src/site/resources/images/ls-logo.jpg differ
diff --git a/src/site/site.vm b/src/site/site.vm
new file mode 100644
index 00000000..4b46bbf6
--- /dev/null
+++ b/src/site/site.vm
@@ -0,0 +1,542 @@
+
+
+#macro ( link $href $name $target $img $position $alt $border $width $height )
+ #set ( $linkTitle = ' title="' + $name + '"' )
+ #if( $target )
+ #set ( $linkTarget = ' target="' + $target + '"' )
+ #else
+ #set ( $linkTarget = "" )
+ #end
+ #if ( $href.toLowerCase().startsWith("http:/") || $href.toLowerCase().startsWith("https:/") ||
+ $href.toLowerCase().startsWith("ftp:/") || $href.toLowerCase().startsWith("mailto:/") ||
+ $href.toLowerCase().startsWith("file:/") || ($href.toLowerCase().indexOf("://") != -1) )
+ #set ( $linkClass = ' class="externalLink"' )
+ #else
+ #set ( $linkClass = "" )
+ #end
+ #if ( $img )
+ #if ( $position == "left" )
+ #image($img $alt $border $width $height)$name
+ #else
+ $name #image($img $alt $border $width $height)
+ #end
+ #else
+ $name
+ #end
+#end
+##
+#macro ( image $img $alt $border $width $height )
+ #if( $img )
+ #if ( ! ( $img.toLowerCase().startsWith("http:/") || $img.toLowerCase().startsWith("https:/") ||
+ $img.toLowerCase().startsWith("ftp:/") || $img.toLowerCase().startsWith("mailto:/") ||
+ $img.toLowerCase().startsWith("file:/") || ($img.toLowerCase().indexOf("://") != -1) ) )
+ #set ( $imgSrc = $PathTool.calculateLink( $img, $relativePath ) )
+ #set ( $imgSrc = $imgSrc.replaceAll( '\\', '/' ) )
+ #set ( $imgSrc = ' src="' + $imgSrc + '"' )
+ #else
+ #set ( $imgSrc = ' src="' + $img + '"' )
+ #end
+ #if( $alt )
+ #set ( $imgAlt = ' alt="' + $alt + '"' )
+ #else
+ #set ( $imgAlt = ' alt=""' )
+ #end
+ #if( $border )
+ #set ( $imgBorder = ' border="' + $border + '"' )
+ #else
+ #set ( $imgBorder = "" )
+ #end
+ #if( $width )
+ #set ( $imgWidth = ' width="' + $width + '"' )
+ #else
+ #set ( $imgWidth = "" )
+ #end
+ #if( $height )
+ #set ( $imgHeight = ' height="' + $height + '"' )
+ #else
+ #set ( $imgHeight = "" )
+ #end
+
+ #end
+#end
+#macro ( banner $banner $id )
+ #if ( $banner )
+ #if( $banner.href )
+ #set ( $hrf = $banner.href )
+ #if ( ! ( $hrf.toLowerCase().startsWith("http:/") || $hrf.toLowerCase().startsWith("https:/") ||
+ $hrf.toLowerCase().startsWith("ftp:/") || $hrf.toLowerCase().startsWith("mailto:/") ||
+ $hrf.toLowerCase().startsWith("file:/") || ($hrf.toLowerCase().indexOf("://") != -1) ) )
+ #set ( $hrf = $PathTool.calculateLink( $hrf, $relativePath ) )
+ #set ( $hrf = $hrf.replaceAll( '\\', '/' ) )
+ #if ( ( $hrf == '' ) )
+ #set ( $hrf = './' )
+ #end
+ #end
+
+ #else
+
- In order to build the Release builds of log4net a Strong
- Name key is required.
-
-
- Use the sn.exe tool in the
- .NET Framework SDK to generate a strong name key pair.
-
-
-sn -k log4net.snk
-
- The log4net.snk file should be placed in the root of the
- log4net distribution, in the same folder as the log4net.build
- file.
-
-
-
- NDoc 1.3 is used to build the log4net SDK documentation.
- NDoc is available from ndoc.sourceforge.net.
-
-
-
-
-
- The log4net HTML documentation is built using Velocity.
- The source are XML files in the xdocs/src directory.
- Building the documentation requires Java, Ant, and Velocity.
- Run ant from within the xdocs directory.
+ Sandcastle
+ Helpfile Builder is used to build the log4net SDK
+ documentation. Running it is currently not
+ integrated with the NAnt build process, you'll
+ have to open and run log4net.shfbproj
+ with SHFB manually.
diff --git a/src/site/xdoc/release/config-examples.xml b/src/site/xdoc/release/config-examples.xml
old mode 100755
new mode 100644
index c23f3c86..61895b5a
--- a/src/site/xdoc/release/config-examples.xml
+++ b/src/site/xdoc/release/config-examples.xml
@@ -25,10 +25,8 @@ limitations under the License.
-
+
-
-
This document presents example configurations for the built-in appenders.
@@ -653,6 +651,25 @@ CREATE TABLE Log (
]]>
+
+ This example shows how to configure the appender to use the "inter process" locking
+ model.
+
+
+
+
+
+
+
+
+
+ ]]>
+
+ Before you change the locking model so that
+ multiple process may log to the same file, please
+ read the FAQ.
+
+ The following example shows how to configure the ManagedColoredConsoleAppender
+ to log messages to the console. By default the messages are sent to the console
+ standard output stream. This example shows how to highlight error messages.
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+
+ This example shows how to colorize multiple levels.
+
+ The DynamicPatternLayout should be used whenever the header or footer should contain information that could change over time.
+ Compared to the static PatternLayout which does not re-evaluate on every invoke, the DynamicPatternLayout
+ does re-evaluate the pattern on every invoke. It does, for example, allow to include the current DateTime in the header and/or the footer which was not possible
+ with the static PatternLayout.
+
+
+ The following example shows how to configure the DynamicPatternLayout.
+
+
+
+
+
+ ]]>
+
diff --git a/src/site/xdoc/release/example-apps.xml b/src/site/xdoc/release/example-apps.xml
old mode 100755
new mode 100644
index 43ec2aa6..ca148885
--- a/src/site/xdoc/release/example-apps.xml
+++ b/src/site/xdoc/release/example-apps.xml
@@ -24,46 +24,13 @@ limitations under the License.
-
-
-
-
-
-
+
+
-
-
- The following examples are only available in the log4net release download, not
- on-line. To obtain the examples download one of the log4net releases.
+ The following examples are only available in the log4net source download, not
+ on-line. To obtain the examples download the log4net source release.
@@ -77,7 +44,7 @@ links[i].href = "#overview";
For example running nant in the
examples\net\1.0\Tutorials\ConsoleApp\cs directory
- will build the C# version of the .NET 1.0 ConsoleApp example.
+ will build the C# version of the Microsoft® .NET 1.0 ConsoleApp example.
nant can be run in any directory containing a
@@ -102,12 +69,12 @@ links[i].href = "#overview";
There are Visual Studio .NET 2002 project files for the .NET 1.0 framework.
- The solution files for C# and VB are in the examples\net\1.0
+ The solution files for C# and VB are in the examples\net\1.0
folder.
For the Managed C++ project there is a Visual Studio .NET 2003 project file
- in the examples\net\1.1 folder.
+ in the examples\net\1.1 folder.
diff --git a/src/site/xdoc/release/faq.xml b/src/site/xdoc/release/faq.xml
old mode 100755
new mode 100644
index 18d905b5..a67bcf23
--- a/src/site/xdoc/release/faq.xml
+++ b/src/site/xdoc/release/faq.xml
@@ -25,9 +25,9 @@ limitations under the License.
-
-
-
+
+
+
@@ -88,7 +88,7 @@ limitations under the License.
log4net runs on many different frameworks and each framework has its own requirements.
As a rule of thumb you will need an ECMA-335 compliant CLI runtime, for example,
- the Microsoft .NET runtime 1.0 (1.0.3705) or 1.1 (1.1.4322).
+ the Microsoft® .NET runtime 1.0 (1.0.3705) or 1.1 (1.1.4322).
Not all frameworks are created equal and some features have been excluded from
@@ -138,7 +138,7 @@ limitations under the License.
log4net supports multiple output appenders per logger.
- See the features overview document for more information on the features of log4net.
+ See the features overview document for more information on the features of log4net.
- log4net is a port of the popular log4j logging library.
+ log4net is a port of the popular Apache log4j™ logging library.
The initial port was done in June 2001, since then we have tried to remain in the
spirit of the original log4j. See the log4net history page for more details.
@@ -286,6 +278,82 @@ limitations under the License.
+ Starting with log4net 1.2.11 there are two
+ different binary distributions,
+ oldkey and newkey.
+
+
+
+ The oldkey distribution contains
+ assemblies signed with the same strong name key
+ that was used to sign the assemblies of log4net
+ 1.2.10 and earlier. This strong name key is only
+ available to log4net developers.
+
+
+
+ The newkey distribution contains
+ assemblies signed with the strong name key
+ available from log4net's
+ svn area or inside the source distribution.
+ Everybody can create assemblies that have the same
+ strong name.
+
+
+
+ For open source projects it is important that you
+ can create your own patched version of a product
+ and use it instead of the official release. This
+ is something that is now possible if the
+ newkey is used throughout.
+
+
+
+ The oldkey distribution is mostly
+ only for people who work with third-party
+ dependencies that require one of the earlier
+ releases of log4net and can't be recompiled to use
+ the new strong name. If you start a new project
+ or can recompile all your dependencies we strongly
+ recommend you use the newkey
+ assemblies.
+
+
+
+ If you are creating an assembly that is likely to
+ be combined with other assemblies that depend on
+ the old strong name, then it is better you use the
+ oldkey assemblies as well.
+
+
+
+ We currently plan to distribute the new-key
+ assembly under a different name while providing
+ old and newkey log4net.dll assemblies
+ holding type forwards to the new assembly. This
+ may create a cleaner migration path for projects
+ that have dependencies using both versions.
+ At the moment such projects will either need to
+ use the GAC or create sub-directories inside the
+ application directory and configure assembly
+ probing with a privatePath.
+
+
+
+ Note that the "new" strong name no longer provides
+ any kind of authenticity. If you want to be sure
+ you have the "real" Apache log4net, download the binary
+ release from one of the mirrors and verify the PGP
+ signature.
+
Note: the .NET Compact Framework 1.0 does not support System.Reflection.MethodBase.GetCurrentMethod().
+
+
+ Note: the two forms are only equivalent
+ if Foo is not a
+ generic class. For a generic class Foo<T> the variant
+ using typeof generates
+ a different logger for each different type
+ parameter T while the
+ variant using reflection generates the same
+ logger for all Ts.
+
- By default the FileAppender holds an exclusive write
- lock on the log file while it is logging. This prevents other processes from
- writing to the file. The FileAppender can be configured
- to use a different locking model, MinimalLock, that
- only acquires the write lock while a log is being written. This allows multiple
- processes to interleave writes to the same file, albeit with a loss in performance.
- See the FileAppender config examples
- for an example MinimalLock configuration.
-
-
- While the MinimalLock model may be used to interleave
- writes to a single file it may not be the optimal solution, especially when
- logging from multiple machines. Alternatively you may have one or more processes
- log to RemotingAppenders.
- Using the RemoteLoggingServerPlugin (or
- IRemoteLoggingSink) a process can receive all the events and
- log them to a single log file.
+
+ Before you even start trying any of the
+ alternatives provided, ask yourself whether you
+ really need to have multiple processes log to the
+ same file, then don't do it ;-).
+
+
+
+ FileAppender offers pluggable locking models for
+ this usecase but all existing implementations have
+ issues and drawbacks.
+
+
+
+ By default the FileAppender holds an
+ exclusive write lock on the log file while it
+ is logging. This prevents other processes from
+ writing to the file. This model is known to
+ break down with (at least on some versions of)
+ Mono on Linux and log files may get corrupted
+ as soon as another process tries to access the
+ log file.
+
+
+
+ MinimalLock only
+ acquires the write lock while a log is being
+ written. This allows multiple processes to
+ interleave writes to the same file, albeit with
+ a considerable loss in performance.
+
+
+ InterProcessLock
+ doesn't lock the file at all but synchronizes
+ using a system wide Mutex. This will only work
+ if all processes cooperate (and use the same
+ locking model). The acquisition and release of a
+ Mutex for every log entry to be written will
+ result in a loss of performance, but the Mutex
+ is preferable to the use of MinimalLock.
+
+
+ If you use RollingFileAppender things
+ become even worse as several process may try to
+ start rolling the log file concurrently. RollingFileAppender
+ completely ignores the locking model when
+ rolling files, rolling files is simply not
+ compatible with this scenario.
+
+
+ A better alternative is to have your processes
+ log to RemotingAppenders. Using
+ the RemoteLoggingServerPlugin
+ (or IRemoteLoggingSink) a
+ process can receive all the events and log
+ them to a single log file. One of the
+ examples shows how to use the RemoteLoggingServerPlugin.
+ To prevent silent failure of log4net as reported as LOG4NET-342,
+ log4net supports a way to evaluate if it was configured and also to evaluate messages generated on startup since 1.2.11. To
+ check if log4net was started and configured properly one can check the property
+ log4net.Repository.ILoggerRepository.Configured and enumerate the configuration messages as follows:
+
+ This problem has been reported by several people as issue
+ LOG4NET-178.
+ The issue seems to be caused by a broken LOG4NET configuration
+ or a timing problem caused by an application shutdown event that
+ floats in late after an application start event and thus LOG4NET
+ stops logging immediately after it has been started.
+
+
+ The first thing step to troubleshoot problems is enabling
+ the log4net internal debugging features as described
+ here
+ and fix all errors that pop up. If the problem still persists,
+ this comment
+ suggests to move the LOG4NET configuration out of the
+ web.config into a separate file
+ like log4net.config. Finally,
+ if both previous steps did not help and the problem still
+ occurs, you can try to work around the event timing problem
+ by invoking the configuration call from the class constructor as described in
+ this comment.
+
- See the support page for details.
+ First make sure it really is a bug and not a
+ usage error. When in doubt, ask on the log4net-user mailing
+ list first.
+
+
+ If you have identified a bug, please report it
+ via our Issue
+ Tracker. You may want to check it hasn't
+ been reported before by searching the existing
+ issues.
+
+ If you use attributes to configure log4net then
+ the order by which assemblies are loaded may
+ determine whether you attributes are used or
+ not. Assembly load order may be different in
+ DEBUG and RELEASE mode.
+
+
+
+ As stated in the
+ manual the attribute will only be read for
+ the first assembly that tries to use log4net.
+ So it is important that you obtain your
+ ILog instance as early as possible.
+
+
+
+ For a command line application "as early as
+ possible" probably is the class holding the
+ Main method, for a Web-Application
+ it would be your Global.asax class
+ and for a Windows Service it would be the class
+ deriving from ServiceBase.
+ You may have overlooked initialization code for
+ log4net in your application. log4net can be
+ initialized explicitly by calling one of the
+ configurators
+ (e.g. BasicConfigurator or
+ XmlConfigurator in the
+ log4net.Config namespace, or
+ implicitly by including the
+ [XmlConfiguratorAttribute] in the
+ assembly where log4net is first used.
+
+
+ See the
+ manual for more information. If you use
+ attributes to configure log4net then the order
+ by which assemblies are loaded may determine
+ whether you attributes are used or not.
+ Assembly load order may be different in DEBUG
+ and RELEASE mode. See also log4net doesn't log when built
+ in RELEASE mode.
+
+ Starting with .NET 4.5.1 ADO.NET has added
+ connection resiliency which is supposed to
+ re-establish the connection as part if the
+ framework. As a result log4net doesn't know the
+ connection is broken and will never attempt to
+ re-establish the connection.
+
+
+ Unfortunately re-connecting doesn't seem to be
+ working reliably. A workaround may be to add
+ ConnectRetryCount=0 to your
+ connection string.
+
+ No, the log4net project doesn't provide a Nuget
+ package of its own, but Jiří Činčura has kindly
+ created a Nuget package he develops at https://github.com/cincuranet/log4net-nuget.
+ Please report any issues with the packaging at
+ his github issue tracker.
+
- Note: Due to the .NET frameworks support for backward compatibility
- log4net will run on future versions of the runtimes listed above.
+
The "Client Profile" builds are stripped down
+ versions of the "normal" builds that don't contain any
+ ASP.NET releated code - which for example means the
+ %aspnet-* patterns and the
+ AspNetTraceAppender are not available.
+
+
+ *Not
+ supported by the binary release but can be built
+ from the source release.
@@ -132,6 +144,12 @@ limitations under the License.
the standard our stream or the standard error stream.
+
+
log4net.Appender.DebugAppender
+
+ Writes logging events to the .NET system.
+
+
log4net.Appender.EventLogAppender
@@ -197,6 +215,15 @@ limitations under the License.
Sends logging events to an email address.
+
+
log4net.Appender.SmtpPickupDirAppender
+
+ Sends logging events to an email
+ address but writes the emails to a
+ configurable directory rather than
+ sending them directly via SMTP.
+
+
log4net.Appender.TelnetAppender
@@ -218,7 +245,9 @@ limitations under the License.
-
+
A special log4net.Appender.ForwardingAppender can
+ be used to wrap another appender, for example to
+ attach additional filters.
@@ -273,7 +302,7 @@ limitations under the License.
- log4net is based on the highly successful log4j logging library,
+ log4net is based on the highly successful Apache log4j™ logging library,
in development since 1996. This popular and proven architecture has
so far been ported to 12 languages.
diff --git a/src/site/xdoc/release/framework-support.xml b/src/site/xdoc/release/framework-support.xml
old mode 100755
new mode 100644
index ce7d3c6a..3111a493
--- a/src/site/xdoc/release/framework-support.xml
+++ b/src/site/xdoc/release/framework-support.xml
@@ -25,10 +25,8 @@ limitations under the License.
-
+
-
-
log4net is built on a number of different frameworks. Each new version of the frameworks add
@@ -43,7 +41,7 @@ limitations under the License.
While the number of different builds available may seem confusing, you only need to select the
nearest build for your platform that is equal to or earlier than your chosen deployment framework.
- If you intend to deploy your application on the Microsoft .NET Framework 1.0 don't pick the
+ If you intend to deploy your application on the Microsoft® .NET Framework 1.0 don't pick the
log4net build that is built against the Microsoft .NET Framework 1.1 because the .NET framework
does not guarantee forward compatibility only backward compatibility.
@@ -54,11 +52,11 @@ limitations under the License.
intend to deploy you application on both the Microsoft .NET Frameworks and the Mono frameworks.
- log4net now builds on 6 frameworks:
+ log4net now builds on the following frameworks:
-
+
@@ -68,48 +66,72 @@ limitations under the License.
- For each of these frameworks a log4net assembly targeting the framework is supplied. Although it's
+ For most of these frameworks a log4net assembly targeting the framework is supplied. Although it's
perfectly possible to use the .NET Framework 1.0 version of log4net on the .NET Framework 1.1, having
an assembly that really targets a specific framework allows us to use features in that framework that
are not available in other frameworks or remove features from log4net that are not supported in a
specific framework.
+
+ There are no assemblies targeting the Compact
+ Framework 1.0/2.0 or Microsoft Shared Source CLI 1.0 in
+ the binary release, but they can be built from the
+ source release.
+
@@ -118,7 +140,7 @@ limitations under the License.
framework and the platform it runs on:
-
+
@@ -127,14 +149,28 @@ limitations under the License.
+
+
+
+
+
+
+
+
Appender
.NET Framework 1.0
.NET Framework 1.1
.NET Framework 2.0
+
.NET Framework 3.5
+
.NET Framework 4.0
+
.NET Framework 4.5
+
.NET Framework 3.5 Client Profile
+
.NET Framework 4.0 Client Profile
.NET CF 1.0
-
Mono 1.2
+
.NET CF 2.0
+
Mono
Shared Source CLI 1.0
CLI 1.0 Compatible
@@ -145,6 +181,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
x
@@ -157,12 +199,24 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
AspNetTraceAppender
x
x
x
+
x
+
x
+
x
+
+
+
x
@@ -177,12 +231,24 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
ColoredConsoleAppender
x
x
x
+
x
+
x
+
x
+
x
+
x
+
@@ -197,6 +263,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
DebugAppender
@@ -207,12 +279,24 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
EventLogAppender
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
@@ -227,6 +311,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
ForwardingAppender
@@ -237,17 +327,45 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
LocalSyslogAppender
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
x
+
+
ManagedColoredConsoleAppender
+
+
+
x
+
x
+
x
+
x
+
x
+
x
+
+
+
x
+
+
+
MemoryAppender
x
@@ -257,12 +375,24 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
NetSendAppender
x
x
x
+
x
+
x
+
x
+
x
+
x
+
@@ -274,6 +404,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
@@ -287,12 +423,24 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
RemotingAppender
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
x
@@ -307,12 +455,24 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
SmtpAppender
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
@@ -327,6 +487,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
TelnetAppender
@@ -337,6 +503,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
TraceAppender
@@ -347,6 +519,12 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
UdpAppender
@@ -357,33 +535,71 @@ limitations under the License.
x
x
x
+
x
+
x
+
x
+
x
+
x
+
x
-
+
+
+ none
+
+
+
+
+
+ none
+
+
+
+
none
-
+
none
-
+
none
+
+
+ none
+
+
+
+
+
+ As of log4net 1.2.11 this version is identical
+ to the .NET 3.5 version without support for
+ ASP.NET specific appenders and patterns.
+
+
+
+
+
+ As of log4net 1.2.11 this version is identical
+ to the .NET 4.0 version without support for
+ ASP.NET specific appenders and patterns.
+
+
+
-
-
Assembly attributes
The .NET Compact Framework 1.0 does not support retrieving assembly level
@@ -425,8 +641,6 @@ namespace TestApp
}
}
-
-
Notification events
The .NET Compact Framework 1.0 does not support notification events during the
@@ -440,8 +654,6 @@ namespace TestApp
method in order to prevent losing logging events.
See the code above for an example.
-
-
FileSystemWatcher
The .NET Compact Framework 1.0 does not support the
@@ -453,8 +665,6 @@ namespace TestApp
methods are not available. Watching changes to the log4net configuration
file is not supported on the .NET Compact Framework 1.0.
-
-
UserName
The .NET Compact Framework 1.0 does not support the
@@ -463,8 +673,6 @@ namespace TestApp
the LoggingEvent.UserName property will return the value
"NOT AVAILABLE".
-
-
Identity
The .NET Compact Framework 1.0 does not support the
@@ -473,23 +681,17 @@ namespace TestApp
the LoggingEvent.Identity property will return the value
"NOT AVAILABLE".
-
-
Environment variables
The .NET Compact Framework 1.0 does not support retrieving environment
variables, therefore it's not possible to substitute environment variables in
parameter values when using the .NET Compact Framework 1.0 version of log4net.
-
-
Serialization
The .NET Compact Framework 1.0 does not support serialization, therefore none of
the log4net classes in the .NET Compact Framework 1.0 version are serializable.
-
-
LoggingEvent.Domain
The .NET Compact Framework 1.0 does not support AppDomain functionality. The
@@ -498,16 +700,12 @@ namespace TestApp
PatternLayout. On the .NET Compact Framework 1.0 this
value is generated by taking the file name for the application's primary module.
-
-
-
There are 2 separate builds of log4net for mono; Mono 1.0, built using the C# compiler in a mode
@@ -525,12 +723,20 @@ namespace TestApp
none
+
+
+ none
+
+
+
+
+ none
+
+
-
-
FileSystemWatcher
SSCLI 1.0 does not support the
@@ -542,8 +748,6 @@ namespace TestApp
methods are not available. Watching changes to the log4net configuration
file is not supported on SSCLI 1.0.
-
-
UserName
SSCLI 1.0 does not support the
@@ -552,8 +756,6 @@ namespace TestApp
the LoggingEvent.UserName property will return the value
"NOT AVAILABLE".
-
-
Identity
SSCLI 1.0 does not support the
@@ -562,8 +764,6 @@ namespace TestApp
the LoggingEvent.Identity property will return the value
"NOT AVAILABLE".
-
-
diff --git a/src/site/xdoc/release/howto/chainsaw.xml b/src/site/xdoc/release/howto/chainsaw.xml
old mode 100755
new mode 100644
index 8ad6f17e..1bfef699
--- a/src/site/xdoc/release/howto/chainsaw.xml
+++ b/src/site/xdoc/release/howto/chainsaw.xml
@@ -27,10 +27,8 @@ limitations under the License.
-
-
- Apache log4j includes Chainsaw
+ Apache log4j™ includes Apache Chainsaw™
a graphical log viewer.
@@ -45,10 +43,15 @@ limitations under the License.
Save one or more of the sample xml config files to your local system and
load them when Chainsaw starts.
+
+
+ Please note also that it may be necessary to configure Chainsaw tabs as reported as
+ issue LOG4NET-259.
+
- log4net can be configured to log messages via UDP in such a way that Chainsaw
+ Apache log4net™ can be configured to log messages via UDP in such a way that Chainsaw
can receive and display them.
diff --git a/src/site/xdoc/release/howto/index.xml b/src/site/xdoc/release/howto/index.xml
old mode 100755
new mode 100644
index af86a6a5..43c72d94
--- a/src/site/xdoc/release/howto/index.xml
+++ b/src/site/xdoc/release/howto/index.xml
@@ -25,7 +25,7 @@ limitations under the License.
-
+
Below are presented, in no particular order, a series of documents
diff --git a/src/site/xdoc/release/manual/configuration.xml b/src/site/xdoc/release/manual/configuration.xml
old mode 100755
new mode 100644
index 7d9be6e3..8cdddd8b
--- a/src/site/xdoc/release/manual/configuration.xml
+++ b/src/site/xdoc/release/manual/configuration.xml
@@ -25,9 +25,7 @@ limitations under the License.
+ If you use attributes to
+ configure log4net, two settings of the
+ appSettings section of your
+ application's configuration file can be used to
+ override the values given in your assembly's
+ attributes.
+
+
+ The setting with the key "log4net.Config"
+ overrides the configuration file name (and is
+ considered to be relative to your application's
+ base directory), the setting with the key
+ "log4net.Config.Watch" determines whether the file
+ should be monitored for changes.
+
+ would configure your application to use a
+ configuration file "TestApp.exe.config" and not
+ monitor it for changes you can override this to
+ use the file "log4net.config" and monitor it
+ instead by adding
+
+
+
+
+]]>
+
+
+
+ to your application's configuration file.
+
+
+
Typically the log4net configuration is specified using a file. This file can
@@ -583,7 +623,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <log4net> element supports the following attributes:
-
+
@@ -622,7 +662,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <log4net> element supports the following child elements:
-
+
@@ -684,7 +724,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <appender> element supports the following attributes:
-
+
@@ -714,7 +754,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <appender> element supports the following child elements:
@@ -765,7 +805,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <filter> element supports the following attributes:
-
+
@@ -787,7 +827,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <filter> element supports the following child elements:
-
+
@@ -859,7 +899,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <layout> element supports the following attributes:
-
+
@@ -881,7 +921,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <layout> element supports the following child elements:
-
+
@@ -930,7 +970,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <root> element supports the following child elements:
-
+
@@ -979,7 +1019,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <logger> element supports the following attributes.
-
+
@@ -1008,7 +1048,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <logger> element supports the following child elements:
-
+
@@ -1054,7 +1094,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <renderer> element supports the following attributes.
-
+
@@ -1101,7 +1141,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <param> element supports the following attributes.
-
+
@@ -1139,7 +1179,7 @@ DEBUG [main] (Bar.cs:12) - Doing it again!
The <param> element supports the following child elements:
-
+
diff --git a/src/site/xdoc/release/manual/contexts.xml b/src/site/xdoc/release/manual/contexts.xml
old mode 100755
new mode 100644
index 8284ef0f..c1ae4b32
--- a/src/site/xdoc/release/manual/contexts.xml
+++ b/src/site/xdoc/release/manual/contexts.xml
@@ -25,9 +25,7 @@ limitations under the License.
-
-
-
+
Most real-world systems have to deal with multiple clients simultaneously. In a
typical multithreaded implementation of such a system, different threads will
@@ -53,7 +51,7 @@ limitations under the License.
-
+
Scope
Type
diff --git a/src/site/xdoc/release/manual/internals.xml b/src/site/xdoc/release/manual/internals.xml
old mode 100755
new mode 100644
index 650461d5..cba3e591
--- a/src/site/xdoc/release/manual/internals.xml
+++ b/src/site/xdoc/release/manual/internals.xml
@@ -25,9 +25,7 @@ limitations under the License.
-
-
-
+
One of the often-cited arguments against logging is its computational cost.
diff --git a/src/site/xdoc/release/manual/introduction.xml b/src/site/xdoc/release/manual/introduction.xml
old mode 100755
new mode 100644
index 891a822d..ac51bdfb
--- a/src/site/xdoc/release/manual/introduction.xml
+++ b/src/site/xdoc/release/manual/introduction.xml
@@ -25,16 +25,14 @@ limitations under the License.
-
-
-
+
This document is based on Short introduction to log4j by Ceki Gülcü.
- The log4net framework is based on log4j, see
- http://logging.apache.org/log4j for more information on log4j.
+ The log4net framework is based on Apache log4j™, see
+ http://logging.apache.org/log4j/ for more information on log4j.
The log4net framework, source code, binaries, documentation, examples and related
materials are published under the terms of the
Apache License, Version 2.0,
@@ -83,12 +81,20 @@ limitations under the License.
assembly targeting that framework is built:
-
Microsoft .NET Framework 1.0 (1.0.3705)
-
Microsoft .NET Framework 1.1 (1.1.4322)
+
Microsoft® .NET Framework 1.0
+
Microsoft .NET Framework 1.1
+
Microsoft .NET Framework 2.0
+
Microsoft .NET Framework 3.5
+
Microsoft .NET Framework 4.0
+
Microsoft .NET Framework 4.5
+
Microsoft .NET Framework 3.5 Client Profile
+
Microsoft .NET Framework 4.0 Client Profile
Microsoft .NET Compact Framework 1.0
Microsoft .NET Compact Framework 2.0
Mono 1.0
Mono 2.0
+
Mono 3.5
+
Mono 4.0
Microsoft Shared Source CLI 1.0
CLI 1.0 Compatible
@@ -290,7 +296,7 @@ namespace log4net
-
+
Logger name
@@ -332,7 +338,7 @@ namespace log4net
-
+
Logger name
@@ -369,7 +375,7 @@ namespace log4net
-
+
Logger name
@@ -418,7 +424,7 @@ namespace log4net
-
+
Logger name
@@ -563,7 +569,7 @@ ILog y = LogManager.GetLogger("wombat");]]>
The following appenders are defined in the log4net package:
-
+
Type
@@ -611,6 +617,12 @@ ILog y = LogManager.GetLogger("wombat");]]>
the standard our stream or the standard error stream.
+ Please note that ObjectRenderers are not used by the DebugFormat,
+ InfoFormat, WarnFormat,
+ ErrorFormat and FatalFormat methods.
+
diff --git a/src/site/xdoc/release/manual/plugins.xml b/src/site/xdoc/release/manual/plugins.xml
old mode 100755
new mode 100644
index 015f2bd6..7d395b9c
--- a/src/site/xdoc/release/manual/plugins.xml
+++ b/src/site/xdoc/release/manual/plugins.xml
@@ -25,9 +25,7 @@ limitations under the License.
-
-
-
+
Plugins are additional modular components that are attached to a logger repository.
diff --git a/src/site/xdoc/release/manual/repositories.xml b/src/site/xdoc/release/manual/repositories.xml
old mode 100755
new mode 100644
index 0a1e8382..9bd78408
--- a/src/site/xdoc/release/manual/repositories.xml
+++ b/src/site/xdoc/release/manual/repositories.xml
@@ -25,9 +25,7 @@ limitations under the License.
-
-
-
+
Logging repositories are considered advanced functionality. The default behavior
diff --git a/src/site/xdoc/release/release-notes.xml b/src/site/xdoc/release/release-notes.xml
old mode 100755
new mode 100644
index b8346208..45bddda4
--- a/src/site/xdoc/release/release-notes.xml
+++ b/src/site/xdoc/release/release-notes.xml
@@ -25,10 +25,384 @@ limitations under the License.
-
-
-
+
+
+
+
+
+
[LOG4NET-462] - ReadOnlyPropertiesDictionary not thread safe
+
[LOG4NET-394] - Lambda-based ILog-Extensions should catch errors
+
+
+
+
+
+
+
+
+
+ The binary distributions no longer contain assemblies
+ built for the Compact Framework 2.0 - you can build
+ those yourself using the source distribution.
+
+
+
+
+
[LOG4NET-148] - ThreadContext uses LocalDataStore to store ThreadSpecific data instead should be using [ThreadStatic] variables.
+
+
[LOG4NET-178] - Log4Net stops logging after appdomain recycle of ASP.NET2.0 application
+
+
[LOG4NET-202] - AdoNetAppenderParameter.Size Property is not optional
+
+
[LOG4NET-218] - Test StringFormatTest.TestFormatString fails
+
+
[LOG4NET-220] - multiple users overwrite existing log file when RollingFileAppender is rolling over date and minimal locking is used
+
+
[LOG4NET-228] - log4net.Util.HostName may throw System.Configuration.ConfigurationErrorsException in System.Net.Dns.GetHostName(). The exception should be ignored.
+
+
[LOG4NET-266] - AdoNetAppender does not work on a IIS 7 website using Windows authentication
+
+
[LOG4NET-277] - Registering a custom Object Renderer in configuration file
+
+
[LOG4NET-284] - In a multithreaded application, duplicate messages are output.
+
+
[LOG4NET-294] - Exception rendering object type [System.OutOfMemoryException]
+
+
[LOG4NET-317] - LogicalThreadContext sometimes doesn't follow CallContext's logical thread
+
+
[LOG4NET-322] - Conditional compilation symbols for .net4 Release
+
+
[LOG4NET-323] - AbsoluteTimeDateFormatter caches string representation of now too aggressively
+
+
[LOG4NET-331] - AdoNetAppender errors when writing Asp.net item when Request object is null
+
+
[LOG4NET-335] - Lost the ability to monitor changes to logger config files when you call ConfigureAndWatch multiple times with different Config File Names - worked fine on 1.2.10.0
+
[LOG4NET-342] - Add a way to prevent silent failure
+
+
+
+
+
+
+
+ log4net 1.2.11 is not only a bugfix release, it also
+ adds support for Microsoft® .NET 4.0 as well as the client profiles
+ of .NET 3.5 and .NET 4.0.
+
+
+
+ Starting with this release log4net uses a new strong
+ name key but we also provide a binary distribution using
+ the "old" strong name key of log4net 1.2.10 and earlier.
+ See the FAQ for details.
+
+
+
+ The binary distributions no longer contain assemblies
+ built for the Compact Framework 1.0 or the Shared Source
+ CLI - you can build those yourself using the source
+ distribution.
+
+
+
+
+ The signature of
+ ILoggerFactory.CreateLogger has changed.
+
+
+
+
+
+
[LOG4NET-76] - TextWriterAdapter is not thread safe
+
+
[LOG4NET-79] - SecurityException thrown in LogicalThreadContextProperties GetProperties
+
+
[LOG4NET-81] - LoggerRepositorySkeleton's OnConfigurationChanged method always raises its event with EventArgs.Empty instead of passing through its EventArgs parameter.
+
+
[LOG4NET-93] - Typos for node name in tutorial, excess quote, invalid XML
+
+
[LOG4NET-94] - Incorrect config file for ..\examples\net\1.0\Tutorials\ConsoleApp
+
+
[LOG4NET-95] - Level.CompareTo() may result a wrong Value -> sorting of Levels does not work
+
[LOG4NET-123] - EnvironmentPatternConverter does not expand User or System level environment variables under Windows
+
+
[LOG4NET-126] - Links on the log4net Examples page do not work, including the overview link explaining why the other links do not work
+
+
[LOG4NET-128] - Either documentation is incorrect or a bug in SmtpAppender
+
+
[LOG4NET-129] - EventLogAppender EventID parsing does not handle Active Properties properly
+
+
[LOG4NET-135] - Bad example code in documentation
+
+
[LOG4NET-137] - log4net.Filter.LevelMatchFilter does not work anymore
+
+
[LOG4NET-143] - Invalid Repository Config Uri composition from "log4net.Config" application setting
+
+
[LOG4NET-146] - System.NullReferenceException on FindAndRender object
+
+
[LOG4NET-158] - XMLConfigurator.ConfigureAndWatch() leaks resources if called multiple times
+
+
[LOG4NET-167] - ArrayOutOfBounds Exception in MemoryAppender.getEvents()
+
+
[LOG4NET-212] - Threading bug in the PatternConverter.cs
+
+
[LOG4NET-214] - EventLogAppender should also use config file to set EventId
+
+
[LOG4NET-215] - Exception on Convert for return %class{1} name
+
+
[LOG4NET-229] - Japanese characters get garbled with log4net.Layout.XmlLayoutSchemaLog4j
+
+
[LOG4NET-241] - Issue tracking page does not link to project
+
+
[LOG4NET-242] - Download page does not have link to KEYS file
+
+
[LOG4NET-243] - broken link on http://logging.apache.org/log4net/release/example-apps.html
+
+
[LOG4NET-244] - SmtpAppender.To Property has incorrect delimiter
+
+
[LOG4NET-257] - Visual Studio 2010 .NET 4.0 Application does not copy log4net lib to bin directory
+
+
[LOG4NET-265] - RemoteFileAppender Tests fail on Windows 7
+
+
[LOG4NET-274] - log4net doesn't log when running a .Net 4.0 Windows application built in Release mode
+
+
[LOG4NET-297] - AppenderSkeleton.RequiresLayout docs and implementation don't match
+
+
[LOG4NET-300] - FilterTest doesn't compile for .Net 2.0
+
+
[LOG4NET-301] - Unit tests fail on a clean checkout on .NET 2.0 using NAnt
+
+
[LOG4NET-310] - EventLogAppender's ActivateOptions throws SecurityException on Vista/Win2k3 and later when not run as administrator
+
+
[LOG4NET-311] - MinimalLock and AppendToFile=false don't work together in trunk's FileAppender
+
+
+
+
+
+
+
[LOG4NET-31] - Allow user to pass in additional parameters to <converter> node via some kind of <property> tag
+
+
[LOG4NET-38] - EventLogAppender: Add support for setting the Category on Event Log messages.
+
+
[LOG4NET-66] - PreserveFileExtension with StaticFileName
+
+
[LOG4NET-77] - A small improvement of log4net.Layout.Pattern.ExceptionPatternConverter - added 'Option' propery support
+
+
[LOG4NET-88] - support .NET 2.0 connectionStrings configuration section
+
+
[LOG4NET-96] - Expose the Message, Exception, and ErrorCode properties of OnlyOnceErrorHandler.
+
+
[LOG4NET-97] - Make Hierarchy's ILoggerFactory aware of the repository's LevelMap
+
+
[LOG4NET-98] - Update header comment in files to be compliant with new Apache header requirements: http://www.apache.org/legal/src-headers.html for 11/1/2006 deadline
+
+
[LOG4NET-100] - IPAddressConverter improvement for .NET 2 or .NET 3
+
+
[LOG4NET-106] - TraceAppender : Add switch to disable using logger name as trace category
+
+
[LOG4NET-112] - Add support to the UdpAppender for IP v6 remote addresses
+
+
[LOG4NET-131] - Add Cc and Bcc support to SmtpAppender
+
+
[LOG4NET-141] - Add CreateConnection method to AdoNetAppender to allow subclasses to have control of IDbConnection.
+
+
[LOG4NET-153] - Make it easier to configure multiple appenders in code using BasicConfigurator
+
+
[LOG4NET-157] - FAQ for getting the fully-qualified name of a class
+
+
[LOG4NET-164] - using a named mutex for file appenders
+
+
[LOG4NET-170] - Documentation improvement re: fixing and active properties
+
+
[LOG4NET-246] - Make it possible to choose whether or not to watch configuration files specified using the "log4net.Config" appsetting key
+
+
+
+
+
+
+
The various static Configure methods of the Configurator classes now return collections of configuration messages rather than void.
+
+
[LOG4NET-59] - add the ability to roll files based on universal time (UTC).
+
+
[LOG4NET-64] - add the ability to preserve the log file name extension when rolling the log file.
+
+
[LOG4NET-87] - Support ASP.Net related PatternConverters to allow items from the HttpContext.Current.Session, Cache, Request, etc. to be captured.
+
[LOG4NET-168] - New property ReplyTo address for the SmtpAppender required
+
+
[LOG4NET-176] - Buildable with VS 2008 and .NET FW 3.5
+
+
[LOG4NET-233] - Support .NET 4.0 including Client Profile
+
+
+
+
+
+
+
@@ -92,15 +466,11 @@ limitations under the License.
-
-
Renamed namespaces
Renamed namespace log4net.spi to log4net.Core.
Renamed namespace log4net.helpers to log4net.Util.
-
-
Renamed config classes and attributes
In the log4net.Config namespace the DOMConfigurator,
@@ -115,8 +485,6 @@ limitations under the License.
and AliasRepositoryAttribute types replace
DomainAttribute and AliasDomainAttribute.
-
-
Fixed pascal casing of type names
Renamed AdoNetAppender, AspNetTraceAppender,
@@ -125,28 +493,20 @@ limitations under the License.
Note that the config file type resolver is case insensitive so this is only a breaking change
for code that programmatically creates a type that has been renamed.
-
-
Layouts changed to stream their output to a TextWriter
Layouts have been changed to format their output to a TextWriter
rather than return a string. This increases performance and reduces temporary object creation.
-
-
C style string escapes no longer supported by config parser
The XML config parser no longer supports decoding C style escape sequences in strings.
Previously sequences like \n and \\
where decoded. Instead use the appropriate XML encodings as required.
-
-
-
-
New CLI build
A new log4net assembly is built that targets all CLI 1.0 compatible runtimes.
@@ -158,8 +518,6 @@ limitations under the License.
This build is only available in release configuration and can be found at
bin\cli\1.0\release.
-
-
Logging contexts
Logging contexts can be used to record contextual data that is relevant to the current
@@ -176,8 +534,6 @@ limitations under the License.
LogicalThreadContext, and LoggingEvent.
Context values specified in a narrower scope hide the matching value in a wider scope.
-
-
PatternLayout customization and long pattern names
The PatternLayout now supports long pattern names.
@@ -206,8 +562,6 @@ limitations under the License.
A new pattern based type, PatternString, can be used in
@@ -242,16 +596,12 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
The XmlConfigurator methods now support loading the
configuration data from a URI. Config can be loaded from any URI supported by the
System.Net.WebRequest class.
-
-
Support for No-Touch deployment
Log4net supports configuring No-Touch deployment applications using the
@@ -259,8 +609,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
or extension is specified then this is resolved relative to the deployment
URI.
-
-
Config file parser enhancements
The config file parser has been enhanced to support specifying the property subtype, or intermediate type,
@@ -272,8 +620,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
Implicit conversion will be attempted between the value string and the type specified,
and then again between the type and the target property type.
-
-
.NET string formatting syntax
Added .NET String.Format style formatting syntax methods to
@@ -282,16 +628,12 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
WarnFormat, ErrorFormat
and FatalFormat.
-
-
Customizable levels
Levels are defined by the repository LevelMap. The defined
levels, the relative ordering of levels and level display names can be configured on
a per-repository basis.
-
-
Per-appender security contexts
Appenders that interact with controlled platform resources, e.g. files, can be
@@ -301,8 +643,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
privileges of the appender. The WindowsSecurityContext
is used to specify alternative credentials on the Windows platform.
-
-
Added new appenders
AnsiColorTerminalAppender
@@ -340,15 +680,11 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
-
-
Added new LoggerMatchFilter filter
Added LoggerMatchFilter which matches a string against
the event's logger name.
-
-
Pluggable file locking models for the FileAppender
The FileAppender (and by extension the
@@ -361,23 +697,17 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
The RollingFileAppender now supports a new
rolling style, Once. In this mode the appender
will roll the file once per run.
-
-
SmtpAppender authentication
On the .NET 1.1 platform only, the SmtpAppender supports authenticating
against the mail server using either username and password or integrated NTLM authentication.
-
-
AdoNetAppender ReconnectOnError
Added new configuration property to AdoNetAppender.
@@ -385,32 +715,22 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
will force the appender to attempt to reconnect to the database if the connection
is lost.
-
-
UdpAppender hostname support
The UdpAppender config property RemoteAddress
can now be specified as a DNS hostname string. The hostname is resolved to an IP address.
-
-
-
-
FxCop compliance
Updates to bring the internal code in line with the current FxCop rules.
-
-
Separate NUnit tests
Moved the NUnit tests into a separate project, log4net.Tests.
-
-
Bug Fixes
RemotingAppender
@@ -436,15 +756,11 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
-
-
-
-
Changed assembly name to log4net
The build output is now log4net.dll
@@ -458,40 +774,30 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
by the assembly title. This includes the name of the framework
that the assembly was built on.
-
-
Combined Release and ReleaseStrong builds
The Release and ReleaseStrong builds have been consolidated into
a single build called Release. This Release build is strongly named.
-
-
New Appender: ColoredConsoleAppender
The ColoredConsoleAppender writes events to the
application's console. It can be configured to specify the text and background
colors for different level events.
-
-
New Appender: SmtpPickupDirAppender
The SmtpPickupDirAppender generates SMTP compliant
messages and writes them to a local directory. These files can then be read
by an SMTP agent (e.g. the IIS SMTP Agent) and delivered.
-
-
New Layout: XmlLayoutSchemaLog4j
This new layout formats the logging events as XML which complies with
- the log4j event dtd. This can be used to transfer log event from log4net
+ the Apache log4j™ event dtd. This can be used to transfer log event from log4net
to log4j. Currently the only appender that can communicate directly with
log4j is the UdpAppender.
-
-
New PatternLayout conversion characters
Added support for capturing the current thread principal name and the
@@ -509,15 +815,11 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
(Principal.Identity.Name).
-
-
Types specified in the config file are now loaded ignoring case
All types specified in the configuration files are now loaded
using a case insensitive method.
-
-
Fine grained fixing for buffered events
The LoggingEvent now supports fine grained
@@ -526,43 +828,31 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
property takes a combination of the FixFlags
enumeration values.
-
-
Code updated inline with FxCop 1.21
In line with the FxCop 1.21 guidelines:
Sealed utility classes. Added serialization security demand to GetObjectData.
Renamed parameters.
-
-
EventLogAppender 32K Limit
There is a limit of 32K characters in an EventLog message. Added a
check that only logs the first 32000 characters from the rendered
message.
-
-
-
-
Updated to support the Microsoft .NET Framework 1.1 Final
Updated to support the Microsoft .NET Framework 1.1 Final Beta (1.1.4322).
-
-
Features document
Added a new document that covers the main features of log4net.
- See the features
+ See the features
document for more information.
-
-
Hierarchy disabled until it is configured
The Hierarchy is now disabled until it has been configured.
@@ -582,34 +872,24 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
displayed on the console by default. This message will only be
displayed if internal debugging is enabled.
-
-
New examples in VisualBasic.NET, JScript and Managed C++
New examples in VisualBasic.NET, JScript and Managed C++.
TODO Link to document about examples.
-
-
Code and Documentation Updates
Code fixes. Documentation and manual updates.
See the ChangeLog for more information.
-
-
Added document with example appender configurations
log4net 1.2.0 beta 6 adds support for the the following frameworks:
@@ -646,24 +926,18 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support document for more information.
+ some of the builds. See the Framework Support document for more information.
-
-
New build system using NAnt
The new build system allows log4net to be built for all supported frameworks and
in all build configurations in one go.
-
-
New source code & distribution layout
The source code & distribution layout has been updated to support the new
build environment and multiple target frameworks.
-
-
Removed DomainAttribute.UseDefaultDomain property
Updated default behavior of DefaultRepositorySelector. Assemblies
@@ -673,8 +947,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
property then you should remove it, and if the default behavior is now
sufficient, you do not need to specify the DomainAttribute at all.
-
-
Updated configuration file parser
Updated config file parser to use the element name as the property to set. Also
@@ -703,16 +975,12 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
<threshold value="DEBUG"/>
</evaluator>
</appender>
-
-
Support for event ID
The EventLogAppender now supports setting the event ID in the
event log, this is taken from the EventID property from the per
event Properties map on the LoggingEvent.
-
-
Updated ADONetAppender
@@ -725,8 +993,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
Added ExceptionLayout to render the exception data
-
-
Support for front-end extension
This allows the logging API to be wrapped or adapted for specific purposes. Two
@@ -755,59 +1021,31 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
-
-
Added ForwardingAppender
Forwards events to multiple sub appenders after applying filter rules.
-
-
Added BufferingForwardingAppender
Forward events to sub appenders after buffering them.
-
-
Added ASPNetTraceAppender
Logs events to the ASP.NET trace system.
-
-
Added NetSendAppender
Delivers logging events using the Windows Messenger service.
-
-
Added UdpAppender
Sends logging events as connectionless UDP datagrams to a remote host or a
multicast group.
-
-
Removed obsolete methods
-
-
Lots of updates to improve our compliance with FxCop
-
-
Improved SDK documentation
-
-
-
-
Fixed Exception thrown when DOM Configurator called with a null XML
Element.
This occurred if the configuration file did not have a log4net section defined.
-
-
Made level lookup case insensitive
-
-
Prevented the Hierarchy's Threshold level from being set to a null reference
-
-
-
-
Added event specific properties to the logging event object
Appenders can add additional information to the events they are logging. The RemotingAppender
@@ -815,88 +1053,50 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
These properties can be accessed using the PatternLayout with the
%P{name} syntax.
-
-
Added a plugin framework
An IPlugin interface can be attached to any repository.
-
-
A new RemoteLoggingServerPlugin plugin acts as the server for the
RemotingAppender
-
-
Updated the core log4net framework to work in an environment with no
permissions
Specific appenders still require additional permissions to log correctly
-
-
Added support for domain aliasing using the AliasDomainAttribute
This allows a parent assembly to take control of the logging domain for child
assemblies.
-
-
Added events for repository creation, configuration change, configuration reset
and repository shutdown
-
-
Added LevelMap to the ILoggerRepository interface
The mapping from level name to level object is now repository specific,
therefore each repository can have independent mappings.
-
-
Moved hierarchy specific config file parser to new DOMHierarchyConfigurator class
This is controlled by the Hierarchy object and allows for better
encapsulation.
-
-
Added OnlyFixPartialEventData property to the buffered appenders
This setting causes slow settings to be ignored. This significantly improves the
performance of the buffered appenders.
-
-
XML entity references are supported in the XML config file.
-
-
Added support for expanding environment variables in <param> values
The environment variables must be specified as ${FOO} where FOO
is the name of the variable to expand.
-
-
Upgraded to use NUnit 2.0
-
-
File appenders can specify the encoding to use for the file
-
-
Added strong named configuration
-
-
-
-
Added log4net.Ext.Trace extension
This is a separate assembly that adds a trace level to log4net.
-
-
The default log file output directory is now the application base directory not
the current directory
-
-
Added MemoryAppender
Stores all the logging events in an in-memory buffer.
-
-
Moved the Hierarchy implementation into a separate namespace
The log4net.Repository.Hierarchy namespace now contains all the
code that is specific to the Hierarchy implementation.
-
-
Refactored the DOMConfigurator and BasicConfigurator
The Hierarchy specific data schema and implementation could be has
@@ -904,8 +1104,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
bootstrap code for these configurators remains in the log4net.Config
namespace.
-
-
Replaced the DOMConfiguratorAttribute UseExecutableDomain
property with UseDefaultDomain
@@ -913,34 +1111,18 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
allow the configuration of multiple assemblies to be accomplished more easily,
especially when developing web applications (ASP.NET).
-
-
A few good bug fixes!
-
-
-
-
Added ADONetAppender
Thanks to TechnologyOneCorp.com.
-
-
Added TraceLogAssembly extensibility example
-
-
Lots of bug fixes
-
-
-
-
Added 6 new examples
-
-
Split Category class into Logger and LogManager classes
The instance methods from Category have moved to the Logger
@@ -949,8 +1131,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
compatibility only. Changed interface ICategoryFactory to ILoggerFactory
and the implementation class DefaultCategoryFactory to DefaultLoggerFactory.
-
-
Replaced Priority class with Level class
The Priority class has been replaced by the Level class.
@@ -958,31 +1138,23 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
The Level class implements a static pool of Level objects.
The Level class is sealed and serializable.
-
-
Added ILoggerRepository interface implemented by Hierarchy
The Hierarchy class implements the ILoggerRepository interface.
This interface is used by the LogManager class and therefore
allows different implementations of ILoggerRepository to be used.
-
-
Enhanced NUnit tests
All the NUnit tests can be run using a single TestSuite: NUnitGUI
log4net.LogManager+AllTests,log4net.dll.
-
-
Added support for serializing LoggingEvents
The LoggingEvent class is serializable. All local state is
captured before serialization occurs. This now allows LoggingEvent
objects to be serialized between applications or machines.
-
-
Added RemotingAppender
Delivers LoggingEvents to a remote interface. This can be used to
@@ -990,8 +1162,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
remoting sink that receives the logging events, see examples\net\remoting\RemotingServer
for details.
-
-
Added support for rendering composite objects
The IObjectRenderer interface method DoRender now
@@ -999,8 +1169,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
appropriate renderer from the RendererMap to render any nested
objects.
-
-
Added support for rendering exceptions
The DefaultRenderer now has support for rendering exceptions to a
@@ -1008,8 +1176,6 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
used to render exceptions in the LoggingEvent. This allows the
rendering of specific exceptions to be enhanced by specific renderers.
-
-
Added ITriggeringEventEvaluator interface
This interface is used by SMTPAppender and RemotingAppender
@@ -1019,24 +1185,18 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
implemented by the LevelEvaluator class, which triggers above a
set level.
-
-
Added regex matching to the MDCFilter, NDCFilter and StringMatchFilter
The MDCFilter, NDCFilter and StringMatchFilter
can now be configured to use regex matches in addition to substring matches.
Set the RegexToMatch property to use this feature.
-
-
Added XMLLayout
emits an XML element for each LoggingEvent. This allows logging
events to be stored and manipulated as XML. The DTD for the XML emitted is in
the log4net-events.dtd
-
-
Added support for <logger> and <level> elements in the
DOMConfigurator
@@ -1046,15 +1206,11 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
elements to be used in place of the <category> and <priority>
elements. The old elements are still accepted for backward compatibility.
-
-
Added Threshold property to Hierarchy
Changed DisableXXX() methods on Hierarchy to a Threshold
property.
-
-
Added support for logging domains
The LogManager supports multiple logging domains. The LogManager
@@ -1069,15 +1225,11 @@ public class SpecialFolderPatternConverter : log4net.Util.PatternConverter
without conflicting with other modules in the process. The domain for the
assembly is configured using metadata attributes defined on the assembly.
-
-
DOMConfigurator can set params to arbitrary objects
Using a new <object> element, params can now be set to any
creatable object.
- Most of the guidelines for the log4net-user list also apply to the dev list.
- Please have a quick read through the guidelines, thanks.
-
-
-
- To prevent spam, we require you to be subscribed to the list before posting to it.
-
-
-
- This is the log4net developer list, it holds discussions relating to the
- development of log4net not the use of log4net. If you have a question that begins
- with the word "How" or you are unsure as the the appropriate list to post to then
- you probably want to start with the log4net-user list.
-
- Anyone can checkout source code from our anonymous SVN
- server. To do so, simply use the following command (if you are
- using a GUI SVN client, configure it appropriately).
-
- If you are not familiar with SVN, the Apache
- Source Code Repositories
- page has links to more information on SVN.
-
-
-
-
-
-
-
- Many bugs reported end up not being a bug in the log4net code,
- but are due to incorrect configuration, problems caused by installed applications,
- the operating system, etc.
-
-
- Before reporting a bug please make every effort to investigate and resolve the problem yourself.
- Just reporting a bug will not fix it. A good bug report includes a detailed
- description of the problem and a succinct test case which can reproduce the problem.
-
-
- Before reporting an issue please investigate the following information sources for
- a potential resolution.
-
- Before reporting a bug, you are advised to discuss it on the relevant mailing list first.
-
-
- Search the bug database to see if the bug
- you are seeing has already been reported. If it has been reported then you can vote for the issue.
-
-
-
-
- If after you have exhausted all other resources to resolve a problem you may want to file a bug report.
- Please make sure the problem is a bug in Logging and not a bug in your application.
-
-
- Please make sure you provide as much information as possible. Its very hard to fix a bug if the person
- looking into the problem can't reproduce it. Here is a listing of information which should be included:
-
-
-
Version - log4net version, or if from a nightly build, version and date of build.
-
Application Type - Assembly type, i.e. exe or dll, and how your code is launched, e.g. console application, windows application, ASP.NET project, COM+ hosted object, etc...
-
Framework - The .NET framework running the application, name (e.g. MS .NET, Mono, SSCLI) and version.
-
Platform - Computer operating system, version, and hardware platform in use.
-
Configuration - Attach configuration files if they would help track down the bug.
-
Log Files - Review your logs files, produced with internal log4net debug enabled. Submit any relevant sections of the log which help document the bug.
-
Stack Traces - Any stack traces generated by the bug, if any.
-
Example - Example configuration files or web applications which demonstrate the bug. When submitting an example which reproduces the bug, please try to make it as simple as possible.
-
Bug Fix Patch - A patch created using diff -u which fixes the bug. (If you have found a bug fix which can be applied to the code).
-
Description of the Bug - A description of the bug, include observed as well as expected behavior.
-
Miscellaneous - Any other information you feel will help track down the problem.
-
-
- Just reporting a bug will not fix it. A good bug report includes a detailed description of the
- problem and a succinct test case which can reproduce the problem. The very best sort of report
- includes an NUnit testcase which reproduces the issue, this means that we can fix it and that we can
- be sure that it stays fixed in future!
-
- Before starting to work on a patch it is probably a good idea to join the log4net-dev
- mailing list to check that equivalent or complementary work is not already underway.
-
-
- Currently the only supported way of submitting patches to log4net
- is via the JIRA issue tracking system.
-
-
- The preferred method of generating a patch is a unified context diff against
- the latest development version in SVN. To do this you should do the following:
-
-
-
-
- Get the latest version of the code from SVN, see the section above on
- Anonymous SVN Access for details on how to obtain the SVN version.
-
-
-
-
- Make your code changes to the log4net source. Please follow existing
- code styles where possible. If adding new API methods or classes then
- these should be appropriately documented with code comments.
- Contributions intended for inclusion in ASF products must be licensed
- to ASF under the terms of the
- Apache Software License.
-
-
-
-
- Generate a unified context diff for the files you have changed. Run the
- svn diff > patch-file command from the root of the log4net
- codebase to generate a diff file.
-
-
-
-
- If you have added new files these will not be included in the diff. You
- will need to attach these files separately.
-
-
-
-
- If you are not using SVN then you can still generate a unified context diff
- using the diff GNU tool with the -u command line options.
- The GNU tools are available for Windows as part
- of the Cygwin package.
-
-
- If you are unable to generate a diff please submit each file separately and place
- block comments around each code change to highlight the differences.
-
-
-
- In order to submit your patch please follow the following steps:
-
-
-
-
- Create a new issue for your patch. On the
- log4net issues home page
- select the Create New Issue from the menu bar. You will need to be logged
- into JIRA in order to create an issue.
-
-
-
-
- Select the issue type as appropriate.
-
-
-
-
- Prefix the summary with [PATCH]. Enter a description of the changes made,
- new features, or bug fixes in your patch.
-
-
-
-
- Once the issue has been created you can attach your patch file to the issue
- by selecting the Attach file to this issue operation from the left hand
- menu. When attaching your patch you must select the Grant license to ASF for
- inclusion in ASF works option. When attaching a patch please include in the
- description the baseline version of log4net you used to build your patch, if against
- an SVN version please include the version number and if from a tag or branch include
- the repository path.
-
-
-
-
- If you have other files to attach, e.g. you have added new files to log4net, then
- attach each file separately. Please include in the description the name of the file
- attached and the path it should live in the project.
-
-
-
-
- A notification will be sent to the log4net-dev list once you have created your issue,
- however it may also be worth mailing the log4net-dev list to encourage the project
- committers to apply your patch, or at least find out when they may do so.
-
- log4net has graduated from the Incubator project, however at the time
- the following releases were made, log4net was still undergoing incubation,
- therefore these releases are not officially endorsed by the ASF.
-
-
- Future releases of log4net will be officially endorsed by the ASF.
-
- The log4net project was started by Neoworks Limited
- in June 2001. It was created as an internal project within Neoworks to port the Apache
- log4j code base to the Microsoft .NET Framework. The code base was initially branched
- from a pre-alpha log4j 1.2.
-
-
-
- In July 2001 a Sourceforge project was started
- and log4net was published under the Apache Software License. The first public release of
- log4net was made in September 2001. A further 10 releases were made on the sourceforge
- site.
-
-
-
- In December 2003 the Apache Logging Services project was created.
- In February 2004 log4net was donated by Neoworks to the Apache Software Foundation
- to become a member of the Logging Services project.
-
-
-
- In February 2007 log4net graduated from the Apache Incubator project to become a
- fully fledged Apache project. Apache log4net is a subproject of the Logging Services project.
-
- log4net is a tool to help the programmer output log statements to a variety
- of output targets. log4net is a port of the excellent log4j framework to the
- .NET runtime. We have kept the framework similar in spirit to the original log4j
- while taking advantage of new features in the .NET runtime.
- For more information on log4net see the features document.
-
-
-
- log4net is part of the Apache Logging Services
- project. The Logging Services project is intended to provide cross-language logging
- services for purposes of application debugging and auditing.
-
- The log4net release builds are built using NAnt. Log4net can also be built
- using Visual Studio .NET 2002, 2003, or 2005.
-
-
- To build a release build of log4net you will need to create a strong
- name key file. See the Strong Name section below.
-
-
-
-
- Visual Studio .NET 2002, 2003 and 2005 are supported build platforms for log4net.
-
-
-
-
- The log4net distribution includes a solution and project file
- for Visual Studio .NET 2002. Open the log4net.sln
- from the src directory in the distribution.
-
-
- The log4net project requires only the following references:
-
-
-
System
-
System.Data
-
System.Web
-
System.XML
-
-
-
-
-
- Open the Visual Studio .NET 2002 solution file as above.
- Visual Studio will convert the solution and project files
- to Visual Studio .NET 2003 format.
-
-
- After converting the log4net project you must change the
- Conditional Compilation Constants specified for the
- log4net project. Open the project properties dialog and
- select the Configuration Properties/Build sheet.
- Replace the NET_1_0 constant with NET_1_1.
- Remember to do this for both Debug and Release configurations.
-
-
- The log4net project file is not suitable for building log4net
- for the .NET Compact Framework. To build for the Compact Framework
- you must create a new C# project for Smart Devices. Configure the
- project as a library project. Add all the C# files from the
- src directory in the distribution.
-
-
-
-
-
- Open the Visual Studio .NET 2002 solution file as above.
- Visual Studio will convert the solution and project files
- to Visual Studio .NET 2003 format.
-
-
- After converting the log4net project you must change the
- Conditional compilation symbols specified for the
- log4net project. Open the project properties page and
- select the Build sheet.
- Replace the NET_1_0 symbol with NET_2_0.
- Remember to do this for both Debug and Release configurations.
-
-
- In addition the log4net project requires the following new references:
-
-
-
System.Configuration
-
-
- The log4net project file is not suitable for building log4net
- for the .NET Compact Framework. To build for the Compact Framework
- you must create a new C# project for Smart Devices. Configure the
- project as a library project. Add all the C# files from the
- src directory in the distribution.
-
-
-
-
-
-
- The log4net distribution is built using the NAnt tool.
- A recent NAnt version 0.85 nightly build is required to build log4net, this is
- available from nant.sourceforge.net.
-
-
- To support building log4net for the SSCLI framework the NAnt configuration
- files need to be updated to specify the SSCLI framework directory.
-
-
- To build log4net from the command line, change directory to the root of the
- log4net distribution, ensure that the nant executable is in the
- PATH, and then run the following command:
-
-
-nant -buildfile:log4net.build compile-all
-
- This command will build log4net for all the supported frameworks
- that are available on the current machine. To list all the build
- targets that are available run the following command:
-
-
-nant -buildfile:log4net.build -projecthelp
-
- Under windows the build.cmd can be used
- to script the nant build. This can be called from a different
- directory and will locate the correct log4net.build file to use.
- For example:
-
-
-build.cmd compile-all
-
-
-
-
- In order to build the Release builds of log4net a Strong
- Name key is required.
-
-
- Use the sn.exe tool in the
- .NET Framework SDK to generate a strong name key pair.
-
-
-sn -k log4net.snk
-
- The log4net.snk file should be placed in the root of the
- log4net distribution, in the same folder as the log4net.build
- file.
-
-
-
-
-
- NDoc 1.3 is used to build the log4net SDK documentation.
- NDoc is available from ndoc.sourceforge.net.
-
-
-
-
-
- The log4net HTML documentation is built using Velocity.
- The source are XML files in the xdocs/src directory.
- Building the documentation requires Java, Ant, and Velocity.
- Run ant from within the xdocs directory.
-
- This document presents example configurations for the built-in appenders.
- These configurations are designed to work with the
- log4net.Config.DOMConfigurator and the
- log4net.Repository.Hierarchy.Hierarchy.
-
-
- These examples are by no means exhaustive configurations for the appenders.
- For a full list of the parameters that can be specified to each appender and
- more details on each options see the SDK documentation for the appender.
-
- The configuration of the AdoNetAppender depends on the
- provider selected for the target database. Here are some examples.
-
-
-
- The following example shows how to configure the AdoNetAppender
- to log messages to a SQL Server database. The events are written in batches of 100
- (BufferSize). The ConnectionType specifies the fully qualified type name
- for the System.Data.IDbConnection to use to connect to the
- database. The ConnectionString is database provider specific.
- The CommandText is either a prepared statement or a stored procedure, in this
- case it is a prepared statement. Each parameter to the prepared statement or stored procedure
- is specified with its name, database type and a layout that renders the value for the
- parameter.
-
- This example shows how to write events to a SQLite Database.
- This was tested against v0.21 of the
- SQLite .NET provider.
-
-
- SQLite doesn't have strongly-typed columns or field lengths but its
- recommended you still include this information for readability.
- The database table definition is:
-
- The following example shows how to configure the AspNetTraceAppender
- to log messages to the ASP.NET TraceContext. The messages are written to the
- System.Web.TraceContext.Write method if they are below
- level WARN. If they are WARN or above they are written to the
- System.Web.TraceContext.Warn method.
-
- The following example shows how to configure the BufferingForwardingAppender
- to buffer 100 messages before delivering them to the ConsoleAppender.
-
-
-
-
-
- ]]>
-
- This example shows how to deliver only significant events. A LevelEvaluator
- is specified with a threshold of WARN. This means that the events will only
- be delivered when a message with level of WARN or higher level is logged.
- Up to 512 (BufferSize) previous messages of any level will also be delivered to provide context
- information. Messages not sent will be discarded.
-
- The following example shows how to configure the ColoredConsoleAppender
- to log messages to the console. By default the messages are sent to the console
- standard output stream. This example shows how to highlight error messages.
-
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example shows how to colorize multiple levels.
-
- The following example shows how to configure the ConsoleAppender
- to log messages to the console. By default the messages are sent to the console
- standard output stream.
-
-
-
-
-
-
- ]]>
-
- This example shows how to direct the log messages to the console error stream.
-
- The following example shows how to configure the EventLogAppender to log
- to the Application event log on the local machine using the
- event Source of the AppDomain.FriendlyName.
-
-
-
-
-
-
- ]]>
-
- This example shows how to configure the EventLogAppender to
- use a specific event Source.
-
-
-
-
-
-
-
- ]]>
-
- For more information on how to setup the event log to allow the
- EventLogAppender to write to it, see the
- FAQ: Why doesn't the EventLogAppender work?.
-
- The following example shows how to configure the FileAppender
- to write messages to a file. The file specified is log-file.txt. The file will
- be appended to rather than overwritten each time the logging process starts.
-
-
-
-
-
-
-
-
- ]]>
-
- This example shows how to configure the file name to write to using
- an environment variable TMP. The encoding to use to write
- to the file is also specified.
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example shows how to configure the appender to use the minimal locking
- model that allows multiple processes to write to the same file.
-
- The following example shows how to configure the ForwardingAppender.
- The forwarding appender allows a set of constraints to be used to decorate an appender.
- In this example the ConsoleAppender is decorated with a Threshold of
- level WARN. This means that an event directed to the ConsoleAppender
- directly will be logged regardless of its level, but an event directed to the ForwardingAppender
- will only be passed on to the ConsoleAppender if its level is WARN
- or higher. This appender is used only in special circumstances.
-
- The following example shows how to configure the NetSendAppender
- to deliver messages to a specific user's screen. As this appender is typically only
- used for important notifications a Threshold of level Error
- is specified. This example delivers the messages to the user nicko on the
- machine SQUARE. However things are not always straight forward using the Windows
- Messenger Service, one possible outcome using this configuration is that the Server
- will broadcast looking for a WINS server which it will then ask to deliver the message
- to the Recipient, the WINS server will deliver it to the first terminal that the
- user logged in from.
-
- The following example shows how to configure the RemotingAppender
- to deliver logging events to a specified Sink (in this example
- the sink is tcp://localhost:8085/LoggingSink).
- In this example the events are delivered in blocks of 95 events because
- of the BufferSize. No events are discarded. The OnlyFixPartialEventData
- option allows the appender to ignore certain logging event properties that
- can be very slow to generate (e.g. the calling location information).
-
-
-
-
-
-
-
- ]]>
-
- This example configures the RemotingAppender to
- deliver the events only when an event with level ERROR
- or above is logged. When the events are delivered, up to 200 (BufferSize)
- previous events (regardless of level) will be delivered to provide context.
- Events not delivered will be discarded.
-
- The RollingFileAppender builds on the
- FileAppender and has the same options
- as that appender.
-
-
- The following example shows how to configure the RollingFileAppender
- to write to the file log.txt. The file written to will always be called log.txt
- because the StaticLogFileName param is specified. The file will be rolled based on
- a size constraint (RollingStyle). Up to 10 (MaxSizeRollBackups)
- old files of 100 KB each (MaximumFileSize) will be kept. These rolled files will be
- named: log.txt.1, log.txt.2, log.txt.3, etc...
-
-
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example show how to configure the RollingFileAppender
- to roll log files on a date period. This example will roll the log file every minute!
- To change the rolling period adjust the DatePattern value.
- For example, a date pattern of "yyyyMMdd" will roll every day.
- See System.Globalization.DateTimeFormatInfo for a list of available patterns.
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example show how to configure the RollingFileAppender
- to roll log files on a date period and within a date period on file size. For each day
- only the last 10 files of 1MB will be kept.
-
-
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example show how to configure the RollingFileAppender
- to roll log files once per program execution. The appendToFile
- property is set to false to prevent the appender from overwriting
- the existing files. The maxSizeRollBackups is set to negative
- 1 to allow an infinite number of backup files. The file size does have to be limited but
- here it is set to 50 Gigabytes which, if a log file exceeds this size limit during a single
- run then it will also be rolled.
-
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- A more basic approach to once per application rolling is to use a FileAppender
- with appendToFile set to false or set the
- RollingFileAppender's rollingStyle property to false.
-
- The following example shows how to configure the SmtpAppender
- to deliver log events via SMTP email. The To, From, Subject and
- SmtpHost are required parameters.
- This example shows how to deliver only significant events. A LevelEvaluator
- is specified with a threshold of WARN. This means that an email
- will be sent for each WARN or higher level message that is logged.
- Each email will also contain up to 512 (BufferSize) previous messages of any level to
- provide context. Messages not sent will be discarded.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example shows how to configure the SmtpAppender
- to deliver all messages in emails with 512 (BufferSize) messages per
- email.
-
-
-
-
-
-
-
-
-
-
-
-
- ]]>
-
- This example shows a more verbose formatting layout for the mail messages.
-
- The SmtpPickupDirAppender is configured similarly
- to the SmtpAppender. The only difference is that rather
- than specify a SmtpHost parameter a PickupDir must be specified.
-
-
- The PickupDir parameter is a path that must exist and the code executing the
- appender must have permission to create new files and write to them in this directory.
- The path is relative to the application's base directory (AppDomain.BaseDirectory).
-
-
- The following example shows how to configure the SmtpPickupDirAppender
- to deliver log events via SMTP email. The To, From, Subject and
- PickupDir are required parameters.
- This example shows how to deliver only significant events. A LevelEvaluator
- is specified with a threshold of WARN. This means that an email
- will be sent for each WARN or higher level message that is logged.
- Each email will also contain up to 512 (BufferSize) previous messages of any level to
- provide context. Messages not sent will be discarded.
-
- The following example shows how to configure the TraceAppender
- to log messages to the System.Diagnostics.Trace system.
- This is the tracing system supplied with the .net base class libraries.
- See the MSDN documentation for the System.Diagnostics.Trace
- class for more details on how to configure the trace system.
-
- The following examples are only available in the log4net release download, not
- on-line. To obtain the examples download one of the log4net releases.
-
-
-
-
-
-
-
- A single example can be build by running nant from
- the example directory.
-
-
- For example running nant in the
- examples\net\1.0\Tutorials\ConsoleApp\cs directory
- will build the C# version of the .NET 1.0 ConsoleApp example.
-
-
- nant can be run in any directory containing a
- nant.build file. The typical behavior of the build file
- is to build all projects under the current directory.
-
-
- For example running nant in the
- examples\net\1.1 directory
- will build all the examples for the .NET 1.1 platform.
-
-
-
-
-
- To build all the examples either run nant in the
- examples directory or you can specify the
- compile-examples target to the main log4net nant build.
-
-
-
-
-
- There are Visual Studio .NET 2002 project files for the .NET 1.0 framework.
- The solution files for C# and VB are in the examples\net\1.0
- folder.
-
-
- For the Managed C++ project there is a Visual Studio .NET 2003 project file
- in the examples\net\1.1 folder.
-
-
-
-
-
-
-
-
- ConsoleApp shows how to write a simple console application that initializes
- logging and logs various events.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute ConsoleApp.exe from the build output directory.
-
-
-
-
-
- ConsoleApp shows how to write a simple ASP.NET web application that initializes
- logging and logs various events.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example you need to have an ASP.NET container application to
- host the web application, for example IIS. In IIS create a new virtual
- directory pointing to the WebApp src directory. Configure IIS to recognize
- this virtual directory as an application. Open up a web browser, navigate to
- the virtual directory and to the WebForm1.aspx page within it.
-
-
-
-
-
- The RemotingClient application is a simple console application that configures
- log4net with the RemotingAppender. This appender will attempt to deliver the
- logging events to a remoting listener. This example should be run in conjunction
- with the RemotingServer.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute RemotingClient.exe from the build output directory.
-
-
-
-
-
- The RemotingServer application is a simple console application that listens for
- logging events from a remote RemotingAppender and then logs them through the
- local log4net instance. This example should be run in conjunction
- with the RemotingClient.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute RemotingServer.exe from the build output directory.
- While this process is running execute the RemotingClient.exe program on
- the same machine. The logging events from the client are transferred to the server.
-
-
-
-
-
- The SimpleModule is a class library that is intended to be used as part of
- the SimpleApp example,
- This class library uses the log4net.Config.Repository
- attribute to create a separate configuration space from other assemblies.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- This library is intended to be used as part of the SimpleApp example.
-
-
-
-
-
- The SharedModule is a class library that is intended to be used as part of
- the SimpleApp example,
- This class library uses log4net but does not attempt to configure logging.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- This library is intended to be used as part of the SimpleApp example.
-
-
-
-
-
- The SimpleApp example uses the SimpleModule and SharedModule to demonstrate
- the ways in which multiple assemblies within the same process may be
- separately configured.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute SimpleApp.exe from the build output directory.
-
-
-
-
-
- The EventIDLogApp example demonstrates using the log4net.Ext.EventID extension.
- The extension needs to be built separately from the
- extensions\net\1.0\log4net.Ext.EventID directory.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute EventIDLogApp.exe from the build output directory.
-
-
-
-
-
- The TraceLogApp example demonstrates using the log4net.Ext.Trace extension.
- The extension needs to be built separately from the
- extensions\net\1.0\log4net.Ext.Trace directory.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute TraceLogApp.exe from the build output directory.
-
-
-
-
-
- This project includes the following example appenders.
-
-
-
- AsyncAppender
-
-
- FastDbAppender
-
-
- FireEventAppender
-
-
- MessageBoxAppender
-
-
- MessageObjectExpanderAppender
-
-
- MsmqAppender
-
-
- PatternFileAppender
-
-
- SimpleSmtpAppender
-
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute SampleAppendersApp.exe from the build output directory.
-
-
-
-
-
- This project includes the following example layouts.
-
-
-
- ForwardingLayout
-
-
- LineWrappingLayout
-
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- To run this example execute SampleLayoutsApp.exe from the build output directory.
-
-
-
-
-
- The NotLogging example benchmarks the performance of log4net logging statements in
- user code in various scenarios including when logging is disabled.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- The WmiAppender sample shows an example appender that fires events through
- Windows Management Instrumentation.
-
-
- This example is available for the following platforms and languages. If a version
- is not available for your chosen platform and language combination then select the
- nearest platform for the appropriate language.
-
- log4net is a tool to help the programmer output log statements to a variety of
- output targets.
-
-
- In case of problems with an application, it is helpful to enable logging so
- that the problem can be located. With log4net it is possible to enable logging at
- runtime without modifying the application binary. The log4net package is designed
- so that log statements can remain in production code without incurring a
- high performance cost. It follows that the speed of logging (or rather not
- logging) is crucial.
-
-
- At the same time, log output can be so voluminous that it quickly becomes
- overwhelming. One of the distinctive features of log4net (and common to all of
- the log4x libraries) is the notion of hierarchical
- loggers. Using these loggers it is possible to selectively control
- which log statements are output at arbitrary granularity.
-
-
- log4net is designed with two distinct goals in mind: speed and flexibility. There
- is a tight balance between these two requirements.
-
- No. log4net is not reliable. It is a best-effort and fail-stop logging system.
-
-
- By fail-stop, we mean that log4net will not throw unexpected exceptions at
- run-time potentially causing your application to crash. If for any reason, log4net
- throws an uncaught exception (except for ArgumentException and
- ArgumentNullException which may be thrown), please send an email
- to the
- log4net-user@logging.apache.org mailing list. Uncaught exceptions
- are handled as serious bugs requiring immediate attention.
-
-
- Moreover, log4net will not revert to System.Console.Out
- or System.Console.Error when its designated
- output stream is not opened, is not writable or becomes full. This avoids
- corrupting an otherwise working program by flooding the user's terminal because
- logging fails. However, log4net will output a single message to
- System.Console.Error and System.Diagnostics.Trace
- indicating that logging can not be performed.
-
- log4net runs on many different frameworks and each framework has its own requirements.
- As a rule of thumb you will need an ECMA-335 compliant CLI runtime, for example,
- the Microsoft .NET runtime 1.0 (1.0.3705) or 1.1 (1.1.4322).
-
-
- Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support
- document for more information.
-
- The log output can be customized in many ways. Moreover, one can completely
- override the output format by implementing one's own ILayout
-
-
- Here is an example output using PatternLayout with the conversion
- pattern %timestamp [%thread] %-5level %logger{2} %ndc - %message%newline
-
-
-
- The first field is the number of milliseconds elapsed since the start of the
- program. The second field is the thread outputting the log statement. The third
- field is the level of the log statement. The fourth field is the rightmost
- two components of the name of the logger making the log request. The fifth field (just
- before the '-') is the nested diagnostic context (NDC). Note the
- nested diagnostic context may be empty as in the first two statements. The text
- after the '-' is the message of the statement.
-
- The logger concept lies at the heart of log4net's configuration. Loggers are organized into a
- hierarchy and give the programmer run-time control on which logging statements
- are printed or not.
-
-
- Loggers are assigned levels through the configuration of log4net. A log statement is
- routed through to the appender depending on its level and its logger.
-
- Contrary to the GNU Public License (GPL) the Apache Software License does not
- make any claims over your extensions. By extensions, we mean totally new code
- that invokes existing log4net code. You are free to do whatever you wish with
- your proprietary log4net extensions. In particular, you may choose to
- never release your extensions to the wider public. For details see the
- Apache License, Version 2.0.
-
-
- We are very careful not to unnecessarily change the log4net client API so that newer log4net
- releases are backward compatible with previous versions. We are a lot less
- scrupulous with the internal log4net API. Thus, if your extension is designed to
- work with the internals of a specific log4net version, then when the next release
- of log4net comes out, you will probably need to adapt your proprietary extensions to the
- new release. Thus, you will be forced to spend precious resources in order to
- keep up with log4net changes. This is commonly referred to as the "stupid-tax".
- By donating the code and making it part of the standard distribution, you save
- yourself the unnecessary maintenance work.
-
-
- If your extensions are useful then someone will eventually write an extension
- providing the same or very similar functionality. Your development effort will
- be wasted.
-
-
- Unless the proprietary log4net extension is business critical, there is little
- reason for not donating your extensions back to the project.
-
- log4net is a port of the popular log4j logging library.
- The initial port was done in June 2001, since then we have tried to remain in the
- spirit of the original log4j. See the log4net history page for more details.
-
- Logging behavior can be set using configuration files which are parsed at runtime.
- Using configuration files the programmer can define loggers and set their
- levels.
-
-
- Configuration files are specified in XML. See log4net.Config.XmlConfigurator
- for more details.
-
-
- See the various log4net.Layout and log4net.Appender
- components for specific configuration options.
-
- Setting the Threshold on the Hierarchy to Level OFF will disable all
- logging from that Hierarchy. This can be done in the log4net configuration file
- by setting the "threshold" attribute on the log4net configuration element to "OFF".
- For example:
-
- log4net uses public properties to configure components such as
- Appenders, Layouts, Loggers etc.
-
-
- Thus, any writable public property in on the appender corresponds to a
- configurable option. For example, in RollingFileAppender the
- public int MaxSizeRollBackups { set; } property corresponds to
- the MaxSizeRollBackups option.
-
-
- Layouts options are also defined by their writable properties. Same goes for most
- other log4net components.
-
- Yes it is. Setting the Threshold option of any appender extending
- AppenderSkeleton, (most log4net appenders extend
- AppenderSkeleton) will filter out all log events
- with a lower level than the value of the threshold option.
-
-
- For example, setting the threshold of an appender to DEBUG will also allow INFO,
- WARN, ERROR and FATAL messages to log along with DEBUG messages. (DEBUG is the
- lowest level). This is usually acceptable as there is little use for DEBUG
- messages without the surrounding INFO, WARN, ERROR and FATAL messages.
- Similarly, setting the threshold of an appender to ERROR will filter out DEBUG,
- INFO and WARN messages but not ERROR or FATAL messages.
-
-
- This policy usually best encapsulates what the user actually wants to do, as
- opposed to her mind-projected solution.
-
-
- If you must filter events by exact level match, then you can attach a
- LevelMatchFilter to any appender to filter out logging
- events by exact level match.
-
- Yes. When specifying the type in the configuration file you can give the assembly
- qualified name of the type. For example:
-
- ]]>
-
- The .NET runtime will try to locate the assembly called MyAssembly.
- How .NET locates assemblies is beyond the scope of this FAQ.
-
-
- When loading an assembly from the GAC the fully qualified assembly name,
- including the version, culture and public key must be specified. This is
- in the standard syntax supported by System.Type.GetType.
- See the next FAQ on how to get the version and public key for an assembly.
-
- The fully qualified name for an assembly includes the version, culture and
- public key. The public key is derived from the strong name used to identify
- the publisher. When referencing an assembly from the GAC the fully qualified
- name must be used. To get the version, culture and public key you can use a
- tool like the excellent .NET Reflector from Lutz Roeder available from
- http://www.aisto.com/roeder/dotnet.
-
- Newlines in the config file need to be escaped using an XML numeric character reference.
- The sequence that represents a CR LF is . The following example adds
- a header and footer to the output each followed by a newline.
-
- Log4net supports a pattern syntax for setting string properties similar to the
- PatternLayout used to format the output messages.
- This pattern syntax can be used by specifying type="log4net.Util.PatternString"
- on the string property in the config file. This tells the config parser to pass the
- value to the PatternString type before converting the result
- to a string. For details on the patterns supported see the
- PatternString SDK Reference.
-
-
- The following example sets the file name for a FileAppender to include the
- current process id by specifying the %processid pattern in the
- File property.
-
- You can name logging loggers by locality. It turns out that
- instantiating a logger in each class, with the logger name equal to the
- fully-qualified name of the class, is a useful and straightforward approach of
- defining loggers. This approach has many benefits:
-
-
-
- It is very simple to implement.
-
- It is very simple to explain to new developers.
-
- It automatically mirrors your application's own modular design.
-
- It can be further refined at will.
-
- Printing the logger automatically gives information on the locality of the
- log statement.
-
-
- However, this is not the only way for naming loggers. A common alternative
- is to name loggers by functional areas. For example, the
- "database" logger, "remoting" logger, "security" logger, or the "XML"
- logger.
-
-
- You may choose to name loggers by functionality and subcategorize by
- locality, as in "DATABASE.MyApp.MyClass" or
- "DATABASE.MyApp.MyModule.MyOtherClass".
-
-
- You are totally free in choosing the names of your loggers. The
- log4net package merely allows you to manage your names in a hierarchy. However,
- it is your responsibility to define this hierarchy.
-
-
- Note: by naming loggers by locality one tends to name things by
- functionality, since in most cases the locality relates closely to
- functionality.
-
- You can easily retrieve the fully-qualified name of a class in a static block
- for class X, with the statement typeof(X).Name.
- Note that X is the class name and span an instance.
- However because the LogManager.GetLogger method is overloaded
- to take an instance of Type as well as string
- usually only the type of the class is required.
-
-
- Here is the suggested usage template:
-
-
-
- An equivalent and more portable solution, though slightly longer, is to use the declaring type
- of the static constructor.
-
-
-
- Note: the .NET Compact Framework 1.0 does not support System.Reflection.MethodBase.GetCurrentMethod().
-
- incurs the cost of constructing the message parameter, that is converting both
- integer i and entry[i] to
- a string, and concatenating intermediate strings. This, regardless of whether
- the message will be logged or not.
-
-
- If you are worried about speed, then write
-
-
-
- This way you will not incur the cost of parameter construction if debugging is
- disabled for logger log. On the other hand, if the logger is
- debug enabled, you will incur the cost of evaluating whether the logger is
- enabled or not, twice: once in IsDebugEnabled and once in Debug.
- This is an insignificant overhead since evaluating a logger takes less than
- 1% of the time it takes to actually log a statement.
-
- So you don't think that the previous FAQ is really the fastest way
- of not logging? Well there is a faster way but it does have some
- drawbacks. Starting from:
-
-
-
- It is possible to further eliminate the calls to IsDebugEnabled
- so that the call is only made once per logger. If you are using one logger
- for each class then you can store the enabled state for the logger in a static
- variable in the class and then test against this variable:
-
-
-
- So why exactly is this faster? Well to start with the IsDebugEnabled
- is not called for each log statement, it is called once per logger. Furthermore as the
- isDebugEnabled variable is private static readonly
- the JIT compiler can at run-time optimize out the if test altogether.
- This means that at runtime the JIT compiler won't even compile the logging statements into native code, i.e.
- all the logging just disappears.
-
-
- So what is the downside to using this? Well one of the clever features of log4net is that
- you can change the logging configuration while your program is running. If you need to
- investigate an issue in your application, you don't have to stop the application, setup the
- logging and restart the application, you can change the logging configuration and the
- log4net will reload it (see XmlConfigurator.ConfigureAndWatch APIs for more
- information). However if the JIT has compiled out all of the logging statements
- then they are gone and you can't get them back by reloading the configuration file. Effectively
- this means that the logging configuration can only be set when the application loads and
- it cannot be changed at runtime. It is up to you to decide if you need ultimate speed or need
- to be able to reload the logging configuration while the application is running.
-
- Many developers are confronted with the problem of distinguishing the log
- output originating from the same class but different client requests. They come
- up with ingenious mechanisms to fan out the log output to different files. In
- most cases, this is not the right approach.
-
-
- It is simpler to use a context property or stack (ThreadContext).
- Typically, one would ThreadContext.Properties["ID"] = "XXX"
- client specific information, such as the client's hostname, ID or any other
- distinguishing information when starting to handle the client's request.
- Thereafter, log output will automatically include the context data
- so that you can distinguish logs from different client requests even if they
- are output to the same file.
-
-
- See the ThreadContext and the PatternLayout classes for more
- information.
-
- By default the FileAppender holds an exclusive write
- lock on the log file while it is logging. This prevents other processes from
- writing to the file. The FileAppender can be configured
- to use a different locking model, MinimalLock, that
- only acquires the write lock while a log is being written. This allows multiple
- processes to interleave writes to the same file, albeit with a loss in performance.
- See the FileAppender config examples
- for an example MinimalLock configuration.
-
-
- While the MinimalLock model may be used to interleave
- writes to a single file it may not be the optimal solution, especially when
- logging from multiple machines. Alternatively you may have one or more processes
- log to RemotingAppenders.
- Using the RemoteLoggingServerPlugin (or
- IRemoteLoggingSink) a process can receive all the events and
- log them to a single log file.
-
- The timestamp is created when the logging event is created. That is so say,
- when the Debug, Info,
- Warn, Error
- or Fatal method is invoked. This is unaffected by the time at
- which they may arrive at a remote server. Since the timestamps are
- transmitted in UTC format by the RemotingAppender,
- they all appear in the same time zone as
- the host creating the logfile. Since the clocks of various machines may not be
- synchronized, this may account for time interval inconsistencies between events
- generated on different hosts.
-
- The simple answer is as soon as possible. The long answer is more complex.
-
-
- If you are configuring log4net programmatically, i.e. by calling the
- XmlConfigurator.Configure method then you should do so
- before you begin logging and it is reasonable to do this very soon after application
- start.
-
-
- If you are configuring log4net by specifying assembly level attributes on
- your assembly then the configuration will be loaded once the first call to
- the LogManager.GetLogger is made. It is necessary
- that the first call to LogManager.GetLogger made
- during the process (or AppDomain) is made from the assembly that has the
- configuration attributes. Log4net will look only once and only on the first
- calling assembly for the configuration attributes.
-
- Yes. You can implement the log4net.Layout.ILayout
- interface to create you own customized log format, or you can extend the
- LayoutSkeleton class which provides a default
- implementation of the ILayout interface.
- Appenders can be parameterized to use the layout of your choice.
-
- Yes. You can implement the log4net.Appender.IAppender
- interface to create you own customized appender. We recommend that you extend the
- log4net.Appender.AppenderSkeleton class rather than
- starting from scratch. You should implement your custom code in a assembly
- separate from the log4net assembly. To get started it is worth looking at the
- source of the log4net.Appender.TraceAppender as an
- example of the minimum amount of code required to get an appender working.
-
-
- To configure log4net to use your custom appender you need to specify the
- assembly qualified name of the appender type in the config file. For
- example:
-
- ]]>
-
- The .NET runtime will try to locate the assembly called MyAssembly.
- How .NET locates assemblies is beyond the scope of this FAQ.
-
- There are 2 different ways to enable internal debugging in log4net.
- These are listed below. The preferred method is to specify
- the log4net.Internal.Debug option in the application's
- config file.
-
-
-
-
- Internal debugging can also be enabled by setting a value in the application's
- configuration file (not the log4net configuration file, unless the log4net config
- data is embedded in the application's config file). The log4net.Internal.Debug
- application setting must be set to the value true.
- For example:
-
- This setting is read immediately on startup an will cause all internal
- debugging messages to be emitted.
-
-
-
-
- To enable log4net's internal debug programmatically you need
- to set the log4net.Util.LogLog.InternalDebugging
- property to true. Obviously the sooner this
- is set the more debug will be produced.
-
-
-
-
- Internal debugging messages are written to the console and to the
- System.Diagnostics.Trace
- system. If the application does not have a console the messages logged
- there will be lost. Note that an application can redirect the console
- stream by setting the System.Console.Out. The
- Trace system will by default send the message to an attached debugger
- (where the messages will appear in the output window). If the process
- does not have a debugger attached then the messages are sent to the
- system debugger. A utility like DebugView from
- http://www.sysinternals.com
- may be used to capture these messages.
-
-
- As log4net internal debug messages are written to the System.Diagnostics.Trace
- system it is possible to redirect those messages to a local file. You can define
- a trace listener by adding the following to your application's .config file:
-
- If you are not getting events delivered to the event log this usually indicates
- a permissions problem. Basically if the event log does not exist the EventLogAppender
- tries to create it, but you need local administrator permissions to create event logs
- (just to write into the right bit of the registry). You don't need administrator
- permissions to log to an existing event log, but it must exist. If you are using the
- event log from a web application or service using the event log can be a little tricky.
-
-
- A web application will run as the user account ASPNET. This account deliberately has
- few permissions to reduce the chances of someone hacking into the web server. While the
- account has permission to write to the event log it does not have permission to create
- event sources (registry create and write access), which are needed to write to the event log.
-
-
- There are a couple of solutions:
-
-
-
-
- Make the ASPNET user a member of the Administrators group. This will work because the
- user will then have the required permissions. This is not recommended
- for production use.
-
-
-
-
- As the event source only needs to be created once for the machine, create an installer
- and configure it to create the event source.
- The installer will need to be run as Administrator (don't they all). See
- System.Diagnostics.EventLogInstaller in the Microsoft .NET
- Framework SDK for an example of how to create a simple event log installer.
-
- The web application runs as a special user account on the web server
- called ASPNET. This account has restricted permissions to protect the
- web server from attacks. By default this account may not have permission
- to write to the file system. Make sure that the ASPNET account has
- permission to create and write to files in the directory chosen for
- logging.
-
- A windows service runs as a user account specified in the services
- control panel. This account may have restricted permissions, make
- sure that the account has permission to create and write to files
- in the directory chosen for logging.
-
-
- A windows service is launched by windows. The current directory in
- a service is set to the windows system directory (e.g.
- C:\Windows\System32). If you are loading
- the configuration file from the current directory then be aware
- that this path will not be the location of your assemblies.
- The best way to get the path to your assemblies is to use
- AppDomain.BaseDirectory.
- Note that the log4net internals never use the current directory.
-
- If you need to use ODBC to connect to your database then please note that the
- ADO.NET ODBC drivers are not included in the standard .NET framework redistributable.
- You can download the drivers from microsoft download at:
- ODBC .NET Data Provider.
-
- log4net is a tool to help the programmer output log statements to a
- variety of output targets. In case of problems with an application,
- it is helpful to enable logging so that the problem can be located.
- With log4net it is possible to enable logging at runtime without
- modifying the application binary. The log4net package is designed so
- that log statements can remain in shipped code without incurring a
- high performance cost. It follows that the speed of logging (or
- rather not logging) is crucial.
-
-
- At the same time, log output can be so voluminous that it quickly becomes
- overwhelming. One of the distinctive features of log4net is the notion of
- hierarchical loggers. Using these loggers it is possible to selectively
- control which log statements are output at arbitrary granularity.
-
-
- log4net is designed with two distinct goals in mind: speed and flexibility
-
-
-
-
-
-
Support for multiple frameworks
-
Output to multiple logging targets
-
Hierarchical logging architecture
-
XML Configuration
-
Dynamic Configuration
-
Logging Context
-
Proven architecture
-
Modular and extensible design
-
High performance with flexibility
-
-
-
-
-
- log4net runs on all ECMA CLI 1.0 compatible runtimes.
- log4net has specific builds for the following frameworks:
-
-
-
Microsoft .NET Framework 1.0 (1.0.3705)
-
Microsoft .NET Framework 1.1 (1.1.4322)
-
Microsoft .NET Framework 2.0 (2.0.50727)
-
Microsoft .NET Compact Framework 1.0
-
-
Mono 1.0
-
Mono 2.0
-
Microsoft Shared Source CLI 1.0
-
CLI 1.0 Compatible
-
-
- Note: Due to the .NET frameworks support for backward compatibility
- log4net will run on future versions of the runtimes listed above.
-
-
-
-
-
- log4net ships with the following appenders (not on all frameworks):
-
-
-
-
-
- Type
-
- Description
-
-
-
log4net.Appender.AdoNetAppender
-
- Writes logging events to a database using either prepared statements or stored
- procedures.
-
-
-
-
log4net.Appender.AnsiColorTerminalAppender
-
- Writes color highlighted logging events to a an ANSI terminal window.
-
-
-
-
log4net.Appender.AspNetTraceAppender
-
- Writes logging events to the ASP trace context. These can then be rendered at
- the end of the ASP page or on the ASP trace page.
-
-
-
-
log4net.Appender.ColoredConsoleAppender
-
- Writes color highlighted logging events to the application's Windows Console.
-
-
-
-
log4net.Appender.ConsoleAppender
-
- Writes logging events to the application's Console. The events may go to either
- the standard our stream or the standard error stream.
-
-
-
-
log4net.Appender.EventLogAppender
-
- Writes logging events to the Windows Event Log.
-
-
-
-
log4net.Appender.FileAppender
-
- Writes logging events to a file in the file system.
-
-
-
-
log4net.Appender.LocalSyslogAppender
-
- Writes logging events to the local syslog service (UNIX only).
-
-
-
-
log4net.Appender.MemoryAppender
-
- Stores logging events in an in memory buffer.
-
-
-
-
log4net.Appender.NetSendAppender
-
- Writes logging events to the Windows Messenger service. These messages are
- displayed in a dialog on a users terminal.
-
-
-
-
log4net.Appender.OutputDebugStringAppender
-
- Writes logging events to the debugger. If the application has no
- debugger, the system debugger displays the string. If the application has no
- debugger and the system debugger is not active, the message is ignored.
-
-
-
-
log4net.Appender.RemoteSyslogAppender
-
- Writes logging events to a remote syslog service using UDP networking.
-
-
-
-
log4net.Appender.RemotingAppender
-
- Writes logging events to a remoting sink using .NET remoting.
-
-
-
-
log4net.Appender.RollingFileAppender
-
- Writes logging events to a file in the file system. The RollingFileAppender can
- be configured to log to multiple files based upon date or file size
- constraints.
-
-
-
-
log4net.Appender.SmtpAppender
-
- Sends logging events to an email address.
-
-
-
-
log4net.Appender.TelnetAppender
-
- Clients connect via Telnet to receive logging events.
-
-
-
-
log4net.Appender.TraceAppender
-
- Writes logging events to the .NET trace system.
-
-
-
-
log4net.Appender.UdpAppender
-
- Sends logging events as connectionless UDP datagrams to a remote host or a
- multicast group using a UdpClient.
-
-
-
-
-
-
-
-
-
- Hierarchical logging is an ideal fit with component based development.
- Each component has its own of logger. When individually tested, the
- properties of these loggers may be set as the developer requires.
- When combined with other components, the loggers inherit the properties
- determined by the integrator of the components. One can selectively elevate
- logging priorities on one component without affecting the other components.
- This is useful when you need a detailed trace from just a single component
- without crowding the trace file with messages from other components. All
- this can be done through configuration files; no code changes are required.
-
-
-
-
-
- log4net is configured using an XML configuration file. The configuration
- information can be embedded within other XML configuration files
- (such as the application's .config file) or in a separate file. The
- configuration is easily readable and updateable while retaining the
- flexibility to express all configurations.
-
-
- Alternatively log4net can be configured programmatically.
-
-
-
-
-
- log4net can monitor its configuration file for changes and dynamically
- apply changes made by the configurator. The logging levels, appenders,
- layouts, and just about everything else can be adjusted at runtime.
- In many cases it is possible to diagnose application issues without
- terminating the process in question. This can a very valuable tool in
- investigating issues with deployed applications.
-
-
-
-
-
- log4net can be used to collect logging context data in a way that is transparent
- to the developer at the point of logging. The GlobalContext and the
- ThreadContext allow the application to store contextual data that is
- attached to logging messages. For instance, in a web service,
- once the caller is authenticated the username of the caller could be
- stored in a ThreadContext property. This property would then be automatically
- logged as part of each subsequent logging message made from the same thread.
-
-
-
-
-
- log4net is based on the highly successful log4j logging library,
- in development since 1996. This popular and proven architecture has
- so far been ported to 12 languages.
-
- log4net is built on a number of different frameworks. Each new version of the frameworks add
- new features. To take advantage of these new features we must build log4net using the
- appropriate framework. We also maintain builds compatible with older versions of the frameworks.
-
-
- It is important to remember that the .NET frameworks support backward compatibility, that is
- a new version of the framework will run binary assemblies that were targeted to previous versions
- of the framework.
-
-
- While the number of different builds available may seem confusing, you only need to select the
- nearest build for your platform that is equal to or earlier than your chosen deployment framework.
- If you intend to deploy your application on the Microsoft .NET Framework 1.0 don't pick the
- log4net build that is built against the Microsoft .NET Framework 1.1 because the .NET framework
- does not guarantee forward compatibility only backward compatibility.
-
-
- The lowest common denominator build is the CLI 1.0 Compatible build. This build is compatible with
- the ECMA/ISO CLI 1.0 standard APIs and will run on all frameworks that support the standard. (Note
- that the Microsoft .NET Compact Framework does not support this standard). Use this build if you
- intend to deploy you application on both the Microsoft .NET Frameworks and the Mono frameworks.
-
- For each of these frameworks a log4net assembly targeting the framework is supplied. Although it's
- perfectly possible to use the .NET Framework 1.0 version of log4net on the .NET Framework 1.1, having
- an assembly that really targets a specific framework allows us to use features in that framework that
- are not available in other frameworks or remove features from log4net that are not supported in a
- specific framework.
-
-
-
-
-
- The appenders available to each framework depend on the functionality of the
- framework and the platform it runs on:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Appender
-
.NET Framework 1.0
-
.NET Framework 1.1
-
.NET Framework 2.0
-
.NET CF 1.0
-
Mono 1.2
-
Shared Source CLI 1.0
-
CLI 1.0 Compatible
-
-
-
AdoNetAppender
-
x
-
x
-
x
-
x
-
x
-
-
x
-
-
-
AnsiColorTerminalAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
AspNetTraceAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
BufferingForwardingAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
ColoredConsoleAppender
-
x
-
x
-
x
-
-
-
-
-
-
-
ConsoleAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
DebugAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
EventLogAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
FileAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
ForwardingAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
LocalSyslogAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
MemoryAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
NetSendAppender
-
x
-
x
-
x
-
-
-
-
-
-
-
OutputDebugStringAppender
-
x
-
x
-
x
-
x
-
-
-
-
-
-
RemoteSyslogAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
RemotingAppender
-
x
-
x
-
x
-
-
x
-
x
-
x
-
-
-
RollingFileAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
SmtpAppender
-
x
-
x
-
x
-
-
x
-
-
x
-
-
-
SmtpPickupDirAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
TelnetAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
TraceAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
UdpAppender
-
x
-
x
-
x
-
x
-
x
-
x
-
x
-
-
-
-
-
-
-
-
- none
-
-
-
-
-
- none
-
-
-
-
-
- none
-
-
-
-
-
-
-
Assembly attributes
-
- The .NET Compact Framework 1.0 does not support retrieving assembly level
- attributes, therefore all log4net configuration attributes were removed from
- the .NET Compact Framework 1.0 version of log4net.
-
-
- For Smart-device applications, the log4net system can be configured by passing
- the location of the log4net configuration file to the
- log4net.Config.XmlConfigurator.Configure(FileInfo)
- method in the entry point of the application.
-
-
For example:
-
-
-namespace TestApp
-{
- using System.IO;
-
- public class EntryPoint
- {
- /// <summary>
- /// Application entry point.
- /// </summary>
- public static void Main()
- {
- // Uncomment the next line to enable log4net internal debugging
- // log4net.Util.LogLog.InternalDebugging = true;
-
- // This will instruct log4net to look for a configuration file
- // called config.log4net in the root directory of the device
- log4net.Config.XmlConfigurator.Configure(new FileInfo(@"\config.log4net"));
-
- ...
-
- // This will shutdown the log4net system
- log4net.LogManager.Shutdown();
- }
- }
-}
-
-
-
-
Notification events
-
- The .NET Compact Framework 1.0 does not support notification events during the
- application shutdown, therefore log4net cannot automatically hook the
- application shutdown notification.
-
-
- Applications will need to programmatically shutdown the log4net system during
- the application's shutdown using the
- log4net.LogManager.Shutdown()
- method in order to prevent losing logging events.
- See the code above for an example.
-
-
-
-
FileSystemWatcher
-
- The .NET Compact Framework 1.0 does not support the
- System.IO.FileSystemWatcher
- class. As a result, the
- XmlConfiguratorAttribute.Watch
- property and the
- XmlConfigurator.ConfigureAndWatch
- methods are not available. Watching changes to the log4net configuration
- file is not supported on the .NET Compact Framework 1.0.
-
-
-
-
UserName
-
- The .NET Compact Framework 1.0 does not support the
- System.Security.Principal.WindowsIdentity class.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.UserName property will return the value
- "NOT AVAILABLE".
-
-
-
-
Identity
-
- The .NET Compact Framework 1.0 does not support the
- System.Security.Principal.IPrincipal interface.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.Identity property will return the value
- "NOT AVAILABLE".
-
-
-
-
Environment variables
-
- The .NET Compact Framework 1.0 does not support retrieving environment
- variables, therefore it's not possible to substitute environment variables in
- parameter values when using the .NET Compact Framework 1.0 version of log4net.
-
-
-
-
Serialization
-
- The .NET Compact Framework 1.0 does not support serialization, therefore none of
- the log4net classes in the .NET Compact Framework 1.0 version are serializable.
-
-
-
-
LoggingEvent.Domain
-
- The .NET Compact Framework 1.0 does not support AppDomain functionality. The
- friendly name for the current AppDomain is stored in the LoggingEvent.Domain
- property and is accessed using the %a pattern of the
- PatternLayout. On the .NET Compact Framework 1.0 this
- value is generated by taking the file name for the application's primary module.
-
-
-
-
-
-
-
- There are 2 separate builds of log4net for mono; Mono 1.0, built using the C# compiler in a mode
- which is compatible with the CLI 1.0 language specification, and; Mono 2.0, built using the .NET
- 2.0 extensions to the C# language.
-
-
-
-
- none
-
-
-
-
- none
-
-
-
-
-
-
-
-
-
FileSystemWatcher
-
- SSCLI 1.0 does not support the
- System.IO.FileSystemWatcher
- class. As a result, the
- XmlConfiguratorAttribute.Watch
- property and the
- XmlConfigurator.ConfigureAndWatch
- methods are not available. Watching changes to the log4net configuration
- file is not supported on SSCLI 1.0.
-
-
-
-
UserName
-
- SSCLI 1.0 does not support the
- System.Security.Principal.WindowsIdentity class.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.UserName property will return the value
- "NOT AVAILABLE".
-
-
-
-
Identity
-
- SSCLI 1.0 does not support the
- System.Security.Principal.IPrincipal interface.
- This is used to capture the current thread's user identity. Therefore
- the LoggingEvent.Identity property will return the value
- "NOT AVAILABLE".
-
-
-
-
-
-
-
- This build of log4net is designed to run on any ECMA CLI 1.0 compatible runtime.
- The assembly does not support any platform specific features. The build includes
- the common subset of functionality found in the .NET 1.0 and Mono 1.0 builds.
- The output assembly is built using the Microsoft .NET 1.0 compiler and library.
-
-
- The log4net CLI 1.0 assembly is runtime compatible with the following frameworks:
-
-
-
Microsoft .NET Framework 1.0 (and higher)
-
Mono 1.0 (and higher)
-
-
- Only a Release build is generated for this configuration because the assembly
- debugging information has not been standardized.
-
- Apache log4j includes Chainsaw
- a graphical log viewer.
-
-
- Chainsaw can either receive and display log events in realtime over
- the network, or it can load a previously created log file.
-
-
-
- Before Chainsaw can display data, one or more receivers must be setup.
- This is usually done by specifying an xml config file when the program
- first starts up.
- Save one or more of the sample xml config files to your local system and
- load them when Chainsaw starts.
-
-
-
-
- log4net can be configured to log messages via UDP in such a way that Chainsaw
- can receive and display them.
-
-
-
-
- Configure log4net to use a UdpAppender with the following config snippet:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
- Chainsaw should be configured to start a UDPReceiver using the
- following configuration document:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
- Chainsaw can also load an XML log file if it is formatted according
- to the log4j schema. Use the following log4net config to output
- to file using the log4j schema:
-
-
-
-
-
-
-
-
-]]>
-
-
- To load the file into Chainsaw drag the file into the Chainsaw
- app and drop it on the tab labeled Drag & Drop log files here.
-
- Inserting log requests into the application code requires a fair amount of
- planning and effort. Observation shows that approximately 4 percent of code is
- dedicated to logging. Consequently, even moderately sized applications will
- have thousands of logging statements embedded within their code. Given their
- number, it becomes imperative to manage these log statements without the need
- to modify them manually.
-
-
- The log4net environment is fully configurable programmatically. However, it is
- far more flexible to configure log4net using configuration files. Currently,
- configuration files are written in XML.
-
-
- Let us give a taste of how this is done with the help of an imaginary
- application
- MyApp
- that uses log4net.
-
-
-using Com.Foo;
-
-// Import log4net classes.
-using log4net;
-using log4net.Config;
-
-public class MyApp
-{
- // Define a static logger variable so that it references the
- // Logger instance named "MyApp".
- private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
-
- static void Main(string[] args)
- {
- // Set up a simple configuration that logs on the console.
- BasicConfigurator.Configure();
-
- log.Info("Entering application.");
- Bar bar = new Bar();
- bar.DoIt();
- log.Info("Exiting application.");
- }
-}
-
- MyApp
- begins by importing log4net related classes. It then defines a static logger
- variable with the name
- MyApp
- which happens to be the fully qualified name of the class.
-
-
- MyApp
- uses the following
- Bar
- class:
-
-
-// Import log4net classes.
-using log4net;
-
-namespace Com.Foo
-{
- public class Bar
- {
- private static readonly ILog log = LogManager.GetLogger(typeof(Bar));
-
- public void DoIt()
- {
- log.Debug("Did it again!");
- }
- }
-}
-
- The invocation of the
- BasicConfigurator.Configure()
- method creates a rather simple log4net setup. This method is hardwired to add
- to the root logger a
- ConsoleAppender. The output will be formatted using a
- PatternLayout
- set to the pattern
- "%-4timestamp [%thread] %-5level %logger %ndc - %message%newline".
-
-
- Note that by default, the root logger is assigned to
- Level.DEBUG.
-
-
- The output of MyApp is:
-
-
-
- As a side note, let me mention that in log4net child loggers link only to their
- existing ancestors. In particular, the logger named
- Com.Foo.Bar
- is linked directly to the
- root
- logger, thereby circumventing the unused
- Com
- or
- Com.Foo
- loggers. This significantly increases performance and reduces log4net's memory
- footprint.
-
-
- The
- MyApp
- class configures log4net by invoking
- BasicConfigurator.Configure()
- method. Other classes only need to import the
- log4net
- namespace, retrieve the loggers they wish to use, and log away.
-
-
- The previous example always outputs the same log information. Fortunately, it
- is easy to modify
- MyApp
- so that the log output can be controlled at run-time. Here is a slightly
- modified version.
-
- This version of
- MyApp
- instructs the
- XmlConfigurator
- to parse a configuration file and set up logging accordingly. The path to the
- configuration file is specified on the command line.
-
-
- Here is a sample configuration file that results in exactly same output as the
- previous
- BasicConfigurator
- based example.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-]]>
-
- Suppose we are no longer interested in seeing the output of any component
- belonging to the
- Com.Foo
- package. The following configuration file shows one possible way of achieving
- this.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-]]>
-
- The output of
- MyApp
- configured with this file is shown below.
-
-
-2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application.
-2000-09-07 14:07:41,529 [main] INFO MyApp - Exiting application.
-
- As the logger
- Com.Foo.Bar
- does not have an assigned level, it inherits its level from
- Com.Foo, which was set to WARN in the configuration
- file. The log statement from the
- Bar.DoIt
- method has the level DEBUG, lower than the logger level WARN. Consequently,
- DoIt()
- method's log request is suppressed.
-
-
- Here is another configuration file that uses multiple appenders.
-
- Calling the enhanced MyApp with the this configuration file will output the
- following on the console.
-
-
-
- In addition, as the root logger has been allocated a second appender, output
- will also be directed to the
- example.log
- file. This file will be rolled over when it reaches 100KB. When roll-over
- occurs, the old version of
- example.log
- is automatically moved to
- example.log.1.
-
-
- Note that to obtain these different logging behaviors we did not need to
- recompile code. We could just as easily have logged to an email address,
- redirected all
- Com.Foo
- output to an NT Event logger, or forwarded logging events to a remote log4net
- server, which would log according to local server policy.
-
-
- For more examples of configuring appenders using the XmlConfigurator
- see the Example Appender Configuration
- document.
-
-
-
-
- The log4net configuration can be configured using assembly-level attributes rather than
- specified programmatically.
-
-
-
- XmlConfiguratorAttribute
-
- The log4net.Config.XmlConfiguratorAttribute Allows the
- XmlConfigurator to be configured using the following properties:
-
-
-
- ConfigFile
-
- If specified, this is the filename of the configuration file to use with the
- XmlConfigurator. This file path is relative to the
- application base directory (AppDomain.CurrentDomain.BaseDirectory).
-
-
- This property cannot be used in conjunction with the
- ConfigFileExtension property.
-
-
-
- ConfigFileExtension
-
- If specified, this is the extension for the configuration file. The assembly
- file name is used as the base name with the this extension appended. For example
- if the assembly is loaded from the a file TestApp.exe
- and the ConfigFileExtension property is set to
- log4net then the configuration file name is
- TestApp.exe.log4net. This is equivalent to setting the
- ConfigFile property to TestApp.exe.log4net.
-
-
- The path to the configuration file is build by using the application base
- directory (AppDomain.CurrentDomain.BaseDirectory),
- the assembly file name and the configuration file extension.
-
-
- This property cannot be used in conjunction with the
- ConfigFile property.
-
-
-
- Watch
-
- If this flag is specified and set to true
- then the framework will watch the configuration file and will reload the config
- each time the file is modified.
-
-
-
-
- If neither of the ConfigFile or ConfigFileExtension
- properties are specified, the application configuration file (e.g. TestApp.exe.config)
- will be used as the log4net configuration file.
-
-
- Example usage:
-
-
-// Configure log4net using the .config file
-[assembly: log4net.Config.XmlConfigurator(Watch=true)]
-// This will cause log4net to look for a configuration file
-// called TestApp.exe.config in the application base
-// directory (i.e. the directory containing TestApp.exe)
-// The config file will be watched for changes.
-
-
-// Configure log4net using the .log4net file
-[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
-// This will cause log4net to look for a configuration file
-// called TestApp.exe.log4net in the application base
-// directory (i.e. the directory containing TestApp.exe)
-// The config file will be watched for changes.
-
-
- This attribute may only be used once per assembly.
-
-
-
-
- Using attributes can be a clearer method for defining where the application's
- configuration will be loaded from. However it is worth noting that attributes
- are purely passive. They are information only. Therefore if you use configuration
- attributes you must invoke log4net to allow it to read the attributes. A simple
- call to LogManager.GetLogger will cause the attributes
- on the calling assembly to be read and processed. Therefore it is imperative
- to make a logging call as early as possible during the application start-up, and
- certainly before any external assemblies have been loaded and invoked.
-
-
-
-
-
- Typically the log4net configuration is specified using a file. This file can
- be read in one of two ways:
-
-
-
Using the .NET System.Configuration API
-
Reading the file contents directly
-
-
-
-
- The System.Configuration API is only available if the
- configuration data is in the application's config file; the file named
- MyApp.exe.config or Web.config. Because the System.Configuration
- API does not support reloading of the config file the configuration settings
- cannot be watched using the log4net.Config.XmlConfigurator.ConfigureAndWatch
- methods. The main advantage of using the System.Configuration
- APIs to read the configuration data is that it requires less permissions than accessing
- the configuration file directly.
-
-
- The only way to configure an application using the System.Configuration
- APIs is to call the log4net.Config.XmlConfigurator.Configure() method or
- the log4net.Config.XmlConfigurator.Configure(ILoggerRepository) method.
-
-
- In order to embed the configuration data in the .config file the section name must be
- identified to the .NET config file parser using a configSections element.
- The section must specify the log4net.Config.Log4NetConfigurationSectionHandler
- that will be used to parse the config section. This type must be fully assembly qualified
- because it is being loaded by the .NET config file parser not by log4net. The correct
- assembly name for the log4net assembly must be specified.
- The following is a simple example configuration file that specifies the correct
- section handler to use for the log4net section.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-]]>
-
- In the above example the log4net assembly is specified.
- This assembly must be located where the .NET runtime can find it. For example it could
- be located in the same directory as the application. If the log4net assembly is stored in
- the GAC then the fully qualified assembly name must be specified including the culture,
- version and public key.
-
-
- When using the .config file to specify the configuration the section name and
- XML element name must be log4net.
-
-
-
-
-
- The XmlConfigurator can directly read any XML file and use it to configure log4net.
- This includes the application's .config file; the file named MyApp.exe.config
- or Web.config. The only reason not to read the configuration file directly is if the
- application does not have sufficient permissions to read the file, then the configuration
- must be loaded using the .NET configuration APIs (see above).
-
-
- The file to read the configuration from can be specified using any of
- the log4net.Config.XmlConfigurator methods that
- accept a System.IO.FileInfo object. Because the
- file system can be monitored for file change notifications the
- ConfigureAndWatch methods can be used to monitor
- the configuration file for modifications and automatically reconfigure log4net.
-
-
- Additionally the log4net.Config.XmlConfiguratorAttribute
- can be used to specify the file to read the configuration from.
-
-
- The configuration is read from the log4net element
- in the file. Only one log4net element can be specified
- in the file but it may be located anywhere in the XML hierarchy. For example it
- may be the root element:
-
-
-
-
-
-
-
-
-
-
-
-
-]]>
-
- Or it may be nested within other elements:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-]]>
-
- The above example shows how the configuration data can be embedded
- inside a .config file even though the file is being read directly
- by log4net. An important note is that the .NET config file parser
- will throw an exception if it finds an element that has not been
- registered using the configSections element.
- Therefore in the above example the log4net
- section name is registered, but the type specified to handle the
- section is System.Configuration.IgnoreSectionHandler.
- This is a built-in class that indicates that another method for reading
- the config section will be employed.
-
-
-
-
-
-
-
- log4net includes a configuration reader that parses an XML DOM, the
- log4net.Config.XmlConfigurator. This section defines the
- syntax accepted by the configurator.
-
-
- This is an example of a valid XML configuration. The root element
- must be <log4net>. Note that this does not mean
- that this element cannot be embedded in another XML document. See the section above
- on Configuration Files for more information
- on how to embed the XmlConfigurator XML in a configuration file.
-
-
-
-
-
-
-
-
-
-
-
-]]>
-
- The <log4net> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
debug
-
- Optional attribute. Value must be either true or false.
- The default value is false. Set this attribute to true
- to enable internal log4net debugging for this configuration.
-
-
-
-
update
-
- Optional attribute. Value must be either Merge or Overwrite.
- The default value is Merge. Set this attribute to Overwrite
- to reset the configuration of the repository being configured before applying this configuration.
-
-
-
-
threshold
-
- Optional attribute. Value must be the name of a level registered on the repository.
- The default value is ALL. Set this attribute to limit the messages
- that are logged across the whole repository, regardless of the logger that the message is logged to.
-
-
-
-
-
- The <log4net> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender
-
- Zero or more elements allowed. Defines an appender.
-
-
-
-
logger
-
- Zero or more elements allowed. Defines the configuration of a logger.
-
-
-
-
renderer
-
- Zero or more elements allowed. Defines an object renderer.
-
-
-
-
root
-
- Optional element, maximum of one allowed. Defines the configuration of the root logger.
-
-
-
-
param
-
- Zero or more elements allowed. Repository specific parameters
-
-
-
-
-
-
-
- Appenders may only be defined as child elements of the <log4net>
- element. Each appender must be uniquely named. The implementing type for the appender must be specified.
-
-
- This example shows an appender of type log4net.Appender.ConsoleAppender being
- defined. The appender will be known as ConsoleAppender.
-
-
-
-
-
-]]>
-
-
- The <appender> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
name
-
- Required attribute. Value must be a string name for this appender. The name must be unique
- among all the appenders defined in this configuration file. This name is used by the
- <appender-ref> element of a Logger to reference an appender.
-
-
-
-
type
-
- Required attribute. Value must be the type name for this appender. If the appender is
- not defined in the log4net assembly this type name must be fully assembly qualified.
-
-
-
-
-
- The <appender> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender-ref
-
- Zero or more elements allowed. Allows the appender to reference other appenders.
- Not supported by all appenders.
-
-
-
-
filter
-
- Zero or more elements allowed. Defines the filters used by this appender.
-
-
-
-
layout
-
- Optional element, maximum of one allowed. Defines the layout used by this appender.
-
-
-
-
param
-
- Zero or more elements allowed. Appender specific parameters.
-
- Filters elements may only be defined as children of <appender> elements.
-
-
- The <filter> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
type
-
- Required attribute. Value must be the type name for this filter. If the filter is
- not defined in the log4net assembly this type name must be fully assembly qualified.
-
-
-
-
-
- The <filter> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
param
-
- Zero or more elements allowed. Filter specific parameters.
-
-
-
-
-
-
- Filters form a chain that the event has to pass through. Any filter along the way can accept the event
- and stop processing, deny the event and stop processing, or allow the event on to the next filter.
- If the event gets to the end of the filter chain without being denied it is implicitly accepted and will be logged.
-
-
-
-
-]]>
-
- This filter will deny events that have a level that is lower than INFO
- or higher than FATAL.
- All events between INFO and FATAL will be logged.
-
-
- If we want to only allow messages through that have a specific substring (e.g. 'database')
- then we need to specify the following filters:
-
-
-
-
-]]>
-
- The first filter will look for the substring 'database' in the message text of the event.
- If the text is found the filter will accept the message and filter processing will stop,
- the message will be logged. If the substring is not found the event will be passed to
- the next filter to process. If there is no next filter the event would be implicitly
- accepted and would be logged. But because we don't want the non matching events to be
- logged we need to use a log4net.Filter.DenyAllFilter
- that will just deny all events that reach it. This filter is only useful at the end of the filter chain.
-
-
- If we want to allow events that have either 'database' or 'ldap' in the message text we can use the following filters:
-
-
-
-
-
-
-
-]]>
-
-
-
-
- Layout elements may only be defined as children of <appender> elements.
-
-
- The <layout> element supports the following attributes:
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
type
-
- Required attribute. Value must be the type name for this layout. If the layout is
- not defined in the log4net assembly this type name must be fully assembly qualified.
-
-
-
-
-
- The <layout> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
param
-
- Zero or more elements allowed. Layout specific parameters.
-
-
-
-
-
- This example shows how to configure a layout that uses the log4net.Layout.PatternLayout.
-
-
-
-]]>
-
-
-
-
-
-
- Only one root logger element may only be defined and it must be a child of <log4net> element.
- The root logger is the root of the logger hierarchy. All loggers ultimately inherit from this logger.
-
-
- An example root logger:
-
-
-
-
-]]>
-
-
- The <root> element supports no attributes.
-
-
- The <root> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender-ref
-
- Zero or more elements allowed. Allows the logger to reference appenders by name.
-
-
-
-
level
-
- Optional element, maximum of one allowed. Defines the logging level for this logger.
- This logger will only accept event that are at this level or above.
-
-
-
-
param
-
- Zero or more elements allowed. Logger specific parameters.
-
-
-
-
-
-
-
-
- Logger elements may only be defined as children of the <log4net> element.
-
-
- An example logger:
-
-
-
-
-]]>
-
-
- The <logger> element supports the following attributes.
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
name
-
- Required attribute. Value must be the name of the logger.
-
-
-
-
additivity
-
- Optional attribute. Value may be either true or false.
- The default value is true. Set this attribute to false
- to prevent this logger from inheriting the appenders defined on parent loggers.
-
-
-
-
-
- The <logger> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
appender-ref
-
- Zero or more elements allowed. Allows the logger to reference appenders by name.
-
-
-
-
level
-
- Optional element, maximum of one allowed. Defines the logging level for this logger.
- This logger will only accept event that are at this level or above.
-
-
-
-
param
-
- Zero or more elements allowed. Logger specific parameters.
-
-
-
-
-
-
-
-
- Renderer elements may only be defined as children of the <log4net> element.
-
-
- An example renderer:
-
- ]]>
-
-
- The <renderer> element supports the following attributes.
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
renderingClass
-
- Required attribute. Value must be the type name for this renderer. If the type is
- not defined in the log4net assembly this type name must be fully assembly qualified.
- This is the type of the object that will take responsibility for rendering the
- renderedClass.
-
-
-
-
renderedClass
-
- Required attribute. Value must be the type name for the target type for this renderer. If the type is
- not defined in the log4net assembly this type name must be fully assembly qualified.
- This is the name of the type that this renderer will render.
-
-
-
-
-
- The <renderer> element supports no child elements.
-
-
-
-
-
- Parameter elements may be children of many elements. See the specific elements above for details.
-
-
- An example param:
-
- ]]>
-
-
- The <param> element supports the following attributes.
-
-
-
-
-
-
-
-
-
Attribute
-
Description
-
-
-
name
-
- Required attribute. Value must be the name of the parameter to set on the parent object.
-
-
-
-
value
-
- Optional attribute. One of value or type attributes must be specified.
- The value of this attribute is a string that can be converted to the value of the
- parameter.
-
-
-
-
type
-
- Optional attribute. One of value or type attributes must be specified.
- The value of this attribute is a type name to create and set as the value of the
- parameter. If the type is not defined in the log4net assembly this type name must
- be fully assembly qualified.
-
-
-
-
-
- The <param> element supports the following child elements:
-
-
-
-
-
-
-
-
-
Element
-
Description
-
-
-
param
-
- Zero or more elements allowed. Parameter specific parameters.
-
-
-
-
-
- An example param that uses nested param elements:
-
-
-
-]]>
-
-
-
- Configuration parameters map directly to writable properties on an object.
- The properties available depend on the actual type of the object being
- configured. The log4net SDK documentation contains the API reference for
- all the components included in the log4net assembly.
-
-
- For 3rd party components please see their relevant API reference for
- details of the properties available.
-
-
-
-
-
- All parameters may alternately be specified using the parameter name as the element name
- rather than using the param element and name attribute.
-
- Most real-world systems have to deal with multiple clients simultaneously. In a
- typical multithreaded implementation of such a system, different threads will
- handle different clients. Logging is especially well suited to trace and debug
- complex distributed applications. An approach to differentiate the
- logging output of one client from another is to instantiate a new separate
- logger for each client. However this promotes the proliferation of loggers and
- increases the management overhead of logging.
-
-
- A lighter technique is to uniquely stamp each log request initiated from the
- same client interaction.
-
-
- Log4net supports different types of contextual logging and contexts with different scopes.
-
-
-
-
- Contextual data can be set in different scopes. These contexts have progressively narrower visibility.
- In the logging event itself the values from all of the contexts are combined together such that
- values specified in a lower scoped context hide values from a higher context.
-
-
-
-
-
-
Scope
-
Type
-
Description
-
-
-
Global
-
log4net.GlobalContext
-
- The global context is shared by all threads in the current AppDomain.
- This context is thread safe for use by multiple threads concurrently.
-
-
-
-
Thread
-
log4net.ThreadContext
-
- The thread context is visible only to the current managed thread.
-
-
-
-
Logical Thread
-
log4net.ThreadLogicalContext
-
- The logical thread context is visible to a logical thread. Logical
- threads can jump from one managed thread to another. For more details
- see the .NET API System.Runtime.Remoting.Messaging.CallContext.
-
-
-
-
Event
-
log4net.Core.LoggingEvent
-
- Each event captures the current contextual state at the time the event
- is generated. Contextual data can be set on the event itself. This context
- is only visible to the code generating the event itself.
-
-
-
-
-
-
-
-
- The log4net contexts store properties, i.e. name value pairs. The name is a string
- the value is any object. A property can be set as follows:
-
-
-
- If properties with the same name are set in more than one context scope then
- the value in the narrowest scope (lower down in the list above) will hide the
- other values.
-
-
- The property values are stored as objects within the LoggingEvent.
- The PatternLayout supports rendering the value of a named
- property using the %property{name} syntax. The value is
- converted to a string by passing it to the log4net.ObjectRenderer.RendererMap
- which will locate any custom renderer for the value type. The default behavior for
- custom types is to call the object's ToString() method.
-
-
-
-
- An active property value is one who's value changes over time.
-
-
- For example, imagine a custom type that implemented the
- ToString() method to return the
- number of bytes allocated by the runtime garbage collector.
-
-
-
- An instance of this type can be added to the log4net.GlobalContext
- during application startup:
-
-
-
- Once this property is set in the context all subsequent logging events will have a property
- called GCAllocatedBytes. The value of the property will be an instance of the
- GCAllocatedBytesHelper type. When this value is rendered to a
- string by calling the ToString method the current number of bytes
- allocated by the garbage collector will be returned and included in the output.
-
-
- Note that the ToStringmethod will not be
- called until the LoggingEventis rendered, as
- explained in the Fixingsection. An active property
- is not eligible to be fixed unless it implements
- IFixingRequired.
-
-
-
-
-
-
- Some properties, e.g. the current thread property, or any
- active properties, are not realised
- until their containing LoggingEventis rendered. If the
- LoggingEventis been sent to a buffering appender (such as
- AdoNetAppender) then this rendering will not happen
- unless the
- BufferingAppenderSkeleton's
- Fix propertyhas been set. In addition, an active property is not eligible to be fixed unless it implements
- IFixingRequired.
-
-
-
-
-
- Sometimes simple key value pairs are not the most convenient way of capturing contextual
- information. A stack of information is a very convenient way of storing data especially
- as our applications tend to be stack based.
-
-
- The ThreadContext and LogicalThreadContext
- also support storing contextual data in a stack. The stack is stored in context property,
- therefore stacks have names and more than one stack can exist in the same context. A property
- value set in a narrower context would override a stack with the same property name set in a
- wider scoped context.
-
-
- The stack supports Push and Pop methods.
- As more contextual data is pushed onto the stack the stack grows. When the stack is rendered
- all the data pushed onto the stack is output with the most recent data to the right hand
- end of the string.
-
-
- As the stack is just an object stored in the context properties it is also rendered
- using the same PatternLayout syntax: %property{name}.
- Where name is the name of the stack.
-
-
- Calls the the stack's Push and Pop
- methods must be matched up so that each push has a corresponding pop. The
- Push method also returns an IDisposable
- object that will perform the required pop operation when it is disposed. This allows
- the C# using syntax to be used to automate the stack management.
-
-
-
- The INFO level log has a stack stored in its NDC property. The top item in the
- stack is the string context.
- The using syntax ensures that the value context is popped off the stack
- at the end of the block.
-
-
- The using
- syntax is recommended because it removes some work load from the developer and
- reduces errors in matching up the Push and Pop calls, especially when exceptions
- can occur.
-
-
-
-
-
- The NDC (Nested Diagnostic Context) exists for compatibility
- with older versions of log4net. This helper class implements a stack which is stored
- in the thread context property named NDC.
-
-
-
-
-
- The MDC (MappedDiagnostic Context) exists for compatibility
- with older versions of log4net. This helper class implements a properties map which is
- mapped directly through to the thread context properties.
-
-
-
-
- To illustrate this point, let us take the example of a web service delivering
- content to numerous clients. The web service can build the NDC at the very
- beginning of the request before executing other code. The contextual
- information can be the client's host name and other information inherent to the
- request, typically information contained in cookies. Hence, even if the web
- service is serving multiple clients simultaneously, the logs initiated by the
- same code, i.e. belonging to the same logger, can still be distinguished
- because each client request will have a different NDC stack. Contrast this with
- the complexity of passing a freshly instantiated logger to all code exercised
- during the client's request.
-
-
- Nevertheless, some sophisticated applications, such as virtual hosting web
- servers, must log differently depending on the virtual host context and also
- depending on the software component issuing the request. Log4net supports
- multiple logger repositories. This would allow each virtual host to possess its own copy
- of the logger hierarchy. Configuring multiple logger hierarchies is beyond the
- scope of this document.
-
- One of the often-cited arguments against logging is its computational cost.
- This is a legitimate concern as even moderately sized applications can generate
- thousands of log requests. Much effort was spent measuring and tweaking logging
- performance. Log4net claims to be fast and flexible: speed first, flexibility
- second.
-
-
- The user should be aware of the following performance issues.
-
-
-
- Logging performance when logging is turned off.
-
- When logging is turned off entirely or just for a set of levels, the cost of a
- log request consists of a method invocation plus an integer comparison.
-
-
- However, The method invocation involves the "hidden" cost of parameter
- construction.
-
-
- For example, for some logger
- log, writing,
-
-
-log.Debug("Entry number: " + i + " is " + entry[i].ToString());
-
- incurs the cost of constructing the message parameter, i.e. converting both
- integer
- i
- and
- entry[i]
- to strings, and concatenating intermediate strings, regardless of whether the
- message will be logged or not. This cost of parameter construction can be quite
- high and it depends on the number and type of the parameters involved.
-
-
- To avoid the parameter construction cost write:
-
-
-if(log.IsDebugEnabled)
-{
- log.Debug("Entry number: " + i + " is " + entry[i].ToString());
-}
-
- This will not incur the cost of parameter construction if debugging is
- disabled. On the other hand, if the logger is debug-enabled, it will incur
- twice the cost of evaluating whether the logger is enabled or not: once in
- IsDebugEnabled
- and once in
- Debug. This is an insignificant overhead because
- evaluating a logger takes about 1% of the time it takes to actually log.
-
-
- Certain users resort to pre-processing or compile-time techniques to compile
- out all log statements. This leads to perfect performance efficiency with
- respect to logging. However, since the resulting application binary does not
- contain any log statements, logging cannot be turned on for that binary. In
- many people's opinion this is a disproportionate price to pay in exchange for a
- small performance gain.
-
-
-
- The performance of deciding whether to log or not to log when logging is
- turned on.
-
- This is essentially the performance of walking the logger hierarchy. When
- logging is turned on, log4net still needs to compare the level of the log
- request with the level of the request logger. However, loggers may not have an
- assigned level; they can inherit them from the logger hierarchy. Thus, before
- inheriting a level, the logger may need to search its ancestors.
-
-
- There has been a serious effort to make this hierarchy walk to be as fast as
- possible. For example, child loggers link only to their existing ancestors. In
- the
- BasicConfigurator
- example shown earlier, the logger named
- Com.Foo.Bar
- is linked directly to the root logger, thereby circumventing the nonexistent
- Com
- or
- Com.Foo
- loggers. This significantly improves the speed of the walk, especially in
- "sparse" hierarchies.
-
-
- The typical cost of walking the hierarchy is typically 3 times slower than when
- logging is turned off entirely.
-
-
-
- Actually outputting log messages
-
- This is the cost of formatting the log output and sending it to its target
- destination. Here again, a serious effort was made to make layouts (formatters)
- perform as quickly as possible. The same is true for appenders.
-
-
-
-
- Although log4net has many features, its first design goal was speed. Some
- log4net components have been rewritten many times to improve performance.
- Nevertheless, contributors frequently come up with new optimizations. You
- should be pleased to know that when configured with the
- SimpleLayout
- performance tests have shown log4net to log within an order of magnitude of
- System.Console.WriteLine.
-
-
-
-
-
- The following is the series of steps and checks that a messages goes through while being logged.
- For the purposes of this example we will document an INFO level
- message being logged on logger ConsoleApp.LoggingExample. This logger is configured
- to use the log4net.Appender.ConsoleAppender. The repository used
- in this example is a log4net.Repository.Hierarchy object.
-
-
-
-
- The user logs a message using the ILog.Info method on the logger
- obtained using a call to log4net.LogManager.GetLogger("ConsoleApp.LoggingExample").
- For example: log4net.LogManager.GetLogger("ConsoleApp.LoggingExample").Info("Application Start");
- The ILog interface is actually an extension to log4net that provides level
- specific logging methods (i.e. Debug, Info, Warn, Error, and Fatal).
-
-
-
-
- The message is then logged through to the ILogger.Log method on the
- appropriate log4net.Repository.Hierarchy.Logger object. The
- ILogger.Log method takes the Level to
- log at as a parameter and therefore works for all levels.
-
-
-
-
- The repository threshold level is compared to the message level to determine if the message
- can be logged. If the message level is below the threshold level the message is not logged.
- In this case the repository is a log4net.Repository.Hierarchy object.
-
-
-
-
- The Logger level is compared to the message level to determine if the
- message can be logged. Note that the Logger level is inherited from a
- parent Logger if not specified explicitly for this Logger.
- If the message level is below the Logger level the message is not logged.
-
-
-
-
- A LoggingEvent instance is created to encapsulate the message being logged.
-
-
-
-
- The list of appenders for the Logger is built. This includes appenders
- attached to parent Loggers except where excluded by the
- Logger.Additivity property.
-
-
-
-
- The LoggingEvent object is passed to the
- IAppender.DoAppend method for each appender.
-
-
-
-
- For Each Appender that the LoggingEvent is delivered to the following
- actions take place:
-
-
-
-
- The appender threshold level is compared to the message level to determine if the message
- can be logged. If the message level is below the threshold level the message is not logged.
-
-
-
-
- If the appender has a filter chain the LoggingEvent is passed down the
- filter chain which can decide if the message can be logged or not.
-
-
-
-
- Next an appender specific check is performed. Usually this check will verify that all the
- required properties are set for the appender (e.g. a Layout is set if required).
-
-
-
-
- The LoggingEvent is passed to the appender specific
- Append method. What happens now is specific to the appender.
-
-
-
-
- The following actions take place in the ConsoleAppender.Append method:
-
-
-
-
- The ConsoleAppender uses a Layout to
- format the message as a string for display.
-
-
-
-
- The Layout uses the LoggingEvent.RenderedMessage
- property to get the string for the message object. This uses the registered
- IObjectRenderer for the type of the message object.
-
-
-
-
- The message text is displayed on the console using the Console.WriteLine method.
-
- This document is based on Short introduction to log4j by Ceki Gülcü.
-
-
- The log4net framework is based on log4j, see
- http://logging.apache.org/log4j for more information on log4j.
- The log4net framework, source code, binaries, documentation, examples and related
- materials are published under the terms of the
- Apache License, Version 2.0,
- a copy of which has been included with this distribution in the LICENSE.txt file.
-
-
- This document is an introduction to the log4net API, its unique features and
- design rationale. Log4net is an open source project based on the work of many
- authors. It allows the developer to control which log statements are output
- with arbitrary granularity. It is fully configurable at runtime using external
- configuration files.
-
-
- Almost every large application includes its own logging or tracing API.
- Inserting log statements into code is a low-tech method for debugging it. It
- may also be the only way because debuggers are not always available or
- applicable. This is usually the case for multithreaded applications and
- distributed applications at large.
-
-
- Once an application has been deployed it may not be possible to utilize
- development and debugging tools. An administrator can use effective logging
- systems to diagnose and fix many configuration issues.
-
-
- Experience indicates that logging is an important component of the development
- cycle. It offers several advantages. It provides precise context about the
- execution of the application. Once inserted into the code, the generation of
- logging output requires no human intervention. Moreover, log output can be
- saved in persistent medium to be studied at a later time. In addition to its
- use in the development cycle, a sufficiently rich logging package can also be
- viewed as an auditing tool.
-
-
- Logging does have its drawbacks. It can slow down an application. If too
- verbose, it can cause scrolling blindness. To alleviate these concerns, log4net
- is designed to be reliable, fast and extensible. Since logging is rarely the
- main focus of an application, the log4net API strives to be simple to
- understand and to use.
-
-
-
-
-
- Log4net is available for several frameworks. For each supported framework an
- assembly targeting that framework is built:
-
-
-
Microsoft .NET Framework 1.0 (1.0.3705)
-
Microsoft .NET Framework 1.1 (1.1.4322)
-
Microsoft .NET Framework 2.0 (2.0.50727)
-
Microsoft .NET Compact Framework 1.0
-
Microsoft .NET Compact Framework 2.0
-
Mono 1.0
-
Mono 2.0
-
Microsoft Shared Source CLI 1.0
-
CLI 1.0 Compatible
-
-
- Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support
- document for more information.
-
-
-
-
-
- Log4net has three main components: loggers, appenders and layouts.
- These three types of components work together to enable developers to log
- messages according to message type and level, and to control at runtime how
- these messages are formatted and where they are reported. These components are
- helped by filters that control the actions of the appender and
- object renderers that turn objects into strings.
-
-
-
-
- The first and foremost advantage of any logging API over plain
- System.Console.WriteLine
- resides in its ability to disable certain log statements while allowing others
- to print unhindered. This capability assumes that the logging space, that is,
- the space of all possible logging statements, is categorized according to some
- developer-chosen criteria.
-
-
- Loggers are named entities. Logger names are case-sensitive and they follow the
- following hierarchical naming rule:
-
-
-
Named Hierarchy
-
-
- A logger is said to be an ancestor of another logger if its name
- followed by a dot is a prefix of the descendant logger name. A logger is
- said to be a parent of a child logger if there are no ancestors
- between itself and the descendant logger.
-
-
- The hierarchy works very much in the same way as the namespace and class
- hierarchy in .NET. This is very convenient as we shall soon see.
-
-
-
-
- For example, the logger named
- "Foo.Bar"
- is a parent of the logger named
- "Foo.Bar.Baz". Similarly,
- "System"
- is a parent of
- "System.Text"
- and an ancestor of
- "System.Text.StringBuilder". This naming scheme
- should be familiar to most developers.
-
-
- The root logger resides at the top of the logger hierarchy. It is exceptional
- in three ways:
-
-
-
- It always exists
-
- It cannot be retrieved by name
-
- It always has an assigned level
-
-
- Loggers are retrieved using the static method from the
- log4net.LogManager
- class. The
- GetLogger
- methods take the name of the desired logger as a parameter. They are listed
- below:
-
-
-
- The
- GetLogger
- methods that takes a
- Type
- parameter uses the fully qualified type name as the name of the logger to
- retrieve.
-
-
- These
- GetLogger
- methods return an
- ILog
- interface. That is the representation of the Logger passed back to the
- developer. The
- ILog
- interface is defined below:
-
-
-
- Loggers may be assigned levels. Levels are instances of the
- log4net.Core.Level
- class. The following levels are defined in order of increasing priority:
-
-
-
- ALL
-
-
- DEBUG
-
-
- INFO
-
-
- WARN
-
-
- ERROR
-
-
- FATAL
-
-
- OFF
-
-
-
- If a given logger is not assigned a level, then it inherits one from its
- closest ancestor with an assigned level. More formally:
-
-
-
Level Inheritance
-
-
- The inherited level for a given logger X, is equal to the first
- non-null level in the logger hierarchy, starting at X and proceeding
- upwards in the hierarchy towards the root logger.
-
-
-
-
- To ensure that all loggers can eventually inherit a level, the root logger
- always has an assigned level. The default value for the root logger is
- DEBUG.
-
-
- Below are four tables with various assigned level values and the resulting
- inherited levels according to the above rule.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
none
-
Proot
-
-
-
X.Y
-
none
-
Proot
-
-
-
X.Y.Z
-
none
-
Proot
-
-
-
-
- In Example 1 above, only the root logger is assigned a level. This level
- value,
- Proot, is inherited by the other loggers
- X,
- X.Y
- and
- X.Y.Z.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
Px
-
Px
-
-
-
X.Y
-
Pxy
-
Pxy
-
-
-
X.Y.Z
-
Pxyz
-
Pxyz
-
-
-
-
- In Example 2 above, all loggers have an assigned level value. There is
- no need for level inheritance.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
Px
-
Px
-
-
-
X.Y
-
none
-
Px
-
-
-
X.Y.Z
-
Pxyz
-
Pxyz
-
-
-
-
- In Example 3 above, the loggers
- root,
- X
- and
- X.Y.Z
- are assigned the levels
- Proot,
- Px
- and
- Pxyz
- respectively. The logger
- X.Y
- inherits its level value from its parent
- X.
-
-
-
-
-
-
- Logger name
-
- Assigned level
-
- Inherited level
-
-
-
root
-
Proot
-
Proot
-
-
-
X
-
Px
-
Px
-
-
-
X.Y
-
none
-
Px
-
-
-
X.Y.Z
-
none
-
Px
-
-
-
-
- In Example 4 above, the loggers root and
- X
- and are assigned the levels
- Proot
- and
- Px
- respectively. The loggers
- X.Y
- and
- X.Y.Z
- inherits their level value from their nearest parent
- X
- having an assigned level.
-
-
- Logging requests are made by invoking one of the printing methods of a logger
- instance (through the log4net.ILog). These printing methods are
- Debug,
- Info,
- Warn,
- Error, and
- Fatal.
-
-
- By definition, the printing method determines the level of a logging request.
- For example, if
- log
- is a logger instance, then the statement
- log.Info("..")
- is a logging request of level INFO.
-
-
- A logging request is said to be enabled if its level is higher than or
- equal to the level of its logger. Otherwise, the request is said to be disabled.
- A logger without an assigned level will inherit one from the hierarchy. This
- rule is summarized below.
-
-
-
Basic Selection Rule
-
-
- A log request of level L in a logger with (either assigned or inherited,
- whichever is appropriate) level K, is enabled if L >= K.
-
-
-
-
- This rule is at the heart of log4net. It assumes that levels are ordered. For
- the standard levels, we have
- DEBUG < INFO < WARN < ERROR < FATAL.
-
-
- Calling the
- log4net.LogManager.GetLogger
- method with the same name will always return a reference to the exact same
- logger object.
-
-
- For example, in:
-
-
-
- x
- and
- y
- refer to exactly the same logger object.
-
-
- Thus, it is possible to configure a logger and then to retrieve the same
- instance somewhere else in the code without passing around references. In
- fundamental contradiction to biological parenthood, where parents always
- precede their children, log4net loggers can be created and configured in any
- order. In particular, a "parent" logger will find and link to its descendants
- even if it is instantiated after them.
-
-
- Configuration of the log4net environment is typically done at application
- initialization. The preferred way is by reading a configuration file. This
- approach will be discussed shortly.
-
-
- Log4net makes it easy to name loggers by software component. This can be
- accomplished by statically instantiating a logger in each class, with the
- logger name equal to the fully qualified name of the class. This is a useful
- and straightforward method of defining loggers. As the log output bears the
- name of the generating logger, this naming strategy makes it easy to identify
- the origin of a log message. However, this is only one possible, albeit common,
- strategy for naming loggers. Log4net does not restrict the possible set of
- loggers. The developer is free to name the loggers as desired.
-
-
- Nevertheless, naming loggers after the class where they are located seems to be
- the best strategy known so far. It is simple an obvious to the developers where
- each log message came from. Most importantly it leverages the design of the
- application to produce the design of the logger hierarchy. Hopefully some
- thought has gone into the design of the application.
-
-
-
-
-
- The ability to selectively enable or disable logging requests based on their
- logger is only part of the picture. Log4net allows logging requests to print to
- multiple destinations. In log4net speak, an output destination is called an appender.
- Appenders must implement the log4net.Appenders.IAppender
- interface.
-
-
- The following appenders are defined in the log4net package:
-
- Writes logging events to the application's Console. The events may go to either
- the standard our stream or the standard error stream. The events may have configurable
- text and background colors defined for each level.
-
- Writes logging events to the debugger. If the application has no
- debugger, the system debugger displays the string. If the application has no
- debugger and the system debugger is not active, the message is ignored.
-
- Writes logging events to a file in the file system. The RollingFileAppender can
- be configured to log to multiple files based upon date or file size
- constraints.
-
- Sends logging events as connectionless UDP datagrams to a remote host or a
- multicast group using a UdpClient.
-
-
-
-
-
- More than one appender can be attached to a logger.
-
-
-
- Each enabled logging request for a given logger will be forwarded to all
- the appenders in that logger as well as the appenders higher in the hierarchy.
-
- In other words, appenders are inherited additively from the logger hierarchy.
- For example, if a console appender is added to the root logger, then all
- enabled logging requests will at least print on the console. If in addition a
- file appender is added to a logger, say X, then enabled logging requests
- for X and X's children will print on a file and on the
- console. It is possible to override this default behavior so that appender
- accumulation is no longer additive by setting the additivity flag on the logger
- to
- false.
-
-
- The rules governing appender additivity are summarized below.
-
-
-
Appender Additivity
-
-
- The output of a log statement of logger X will go to all the appenders
- in X and its ancestors. This is the meaning of the term "appender
- additivity".
-
-
- However, if an ancestor of logger X, say Y, has the additivity
- flag set to
- false, then X's output will be directed to all
- the appenders in X and it's ancestors up to and including Y but
- not the appenders in any of the ancestors of Y.
-
-
- Loggers have their additivity flag set to
- true
- by default.
-
-
-
-
- The table below shows an example:
-
-
-
-
-
- Logger Name
-
- Added Appenders
-
- Additivity Flag
-
- Output Targets
-
- Comment
-
-
-
root
-
A1
-
not applicable
-
A1
-
There is no default appender attached to root.
-
-
-
x
-
A-x1, A-x2
-
true
-
A1, A-x1, A-x2
-
Appenders of "x" and root.
-
-
-
x.y
-
none
-
true
-
A1, A-x1, A-x2
-
Appenders of "x" and root.
-
-
-
x.y.z
-
A-xyz1
-
true
-
A1, A-x1, A-x2, A-xyz1
-
Appenders in "x.y.z", "x" and root.
-
-
-
security
-
A-sec
-
false
-
A-sec
-
No appender accumulation since the additivity flag is set to
- false.
-
-
-
security.access
-
none
-
true
-
A-sec
-
Only appenders of "security" because the additivity flag in "security" is set
- to
- false.
-
-
-
-
-
-
-
- Appenders can filter the events that are delivered to them. The filters can be
- specified in the configuration to allow fine control of the events that are
- logged through different appenders.
-
-
- The simplest form of control is to specify a
- Threshold
- on the appender. This works by logging only the events that have a level that
- is greater than or equal to the threshold.
-
-
- More complex and custom event filtering can be done using the filter chain
- defined on each appender. Filters must implement the
- log4net.Filter.IFilter interface.
-
-
- The following filters are defined in the log4net package:
-
- The filters can be configured to either accept or reject the event based upon
- the match.
-
-
-
-
-
- More often than not, users wish to customize not only the output destination
- but also the output format. This is accomplished by associating a layout
- with an appender. The layout is responsible for formatting the logging request
- according to the user's wishes, whereas an appender takes care of sending the
- formatted output to its destination. The
- PatternLayout, part of the standard log4net
- distribution, lets the user specify the output format according to conversion
- patterns similar to the C language
- printf
- function.
-
-
- For example, the PatternLayout with the conversion pattern
- "%timestamp [%thread] %-5level %logger - %message%newline"
- will output something akin to:
-
-
-
- The first field is the number of milliseconds elapsed since the start of the
- program. The second field is the thread making the log request. The third field
- is the level of the log statement. The fourth field is the name of the logger
- associated with the log request. The text after the '-' is the message of the
- statement.
-
-
- The following layouts are included in the log4net package:
-
- Formats the logging event as an XML element that
- complies with the log4j event dtd.
-
-
-
-
-
-
-
-
- Just as importantly, log4net will render the content of the log message
- according to user specified criteria. For example, if you frequently need to
- log
- Oranges, an object type used in your current project,
- then you can register an
- OrangeRenderer
- that will be invoked whenever an orange needs to be logged.
-
-
- Object rendering follows the class hierarchy. For example, assuming oranges are
- fruits, if you register an
- FruitRenderer, all fruits including oranges will be
- rendered by the
- FruitRenderer, unless of course you registered an
- orange specific
- OrangeRenderer.
-
-
- Object renderers have to implement the
- log4net.ObjectRenderer.IObjectRenderer
- interface.
-
- Plugins are additional modular components that are attached to a logger repository.
-
-
- Plugins are stored in the PluginMap of an
- ILoggerRepository.
- Plugins are attached to the repository by using the PluginMap.Add
- method.
-
-
- The following plugins are included in the log4net package:
-
-
-
-
-
- Type
-
- Description
-
-
-
log4net.Plugin.RemoteLoggingServerPlugin
-
- Creates a remote logging sink that can receive logging events from a
- RemotingAppender.
-
-
-
-
-
-
-
RemoteLoggingServerPlugin
-
- Creates a remote logging sink that can receive logging events from a
- RemotingAppender.
-
-
- Creates a remoting logging sink. A single
- parameter must be passed to the constructor that specifies the sink URI. This is a
- name used to identify the logging sink object published via remoting and must be
- agreed with the client before communication can take place.
-
-
- Example usage:
-
-
-
-
-
-
-
- Plugins can be configured using the following assembly-level attributes:
-
-
-
-
PluginAttribute
-
- Specifies a plugin type to create and attach to the default repository. This attribute
- does not allow plugins to be parameterized. The plugin class must have a public default constructor.
-
-
- This attribute may be used as many times as necessary to attach plugins to the repository.
-
- Logging repositories are considered advanced functionality. The default behavior
- should be sufficient for most users.
-
-
- Log4net supports logging repositories. A repository is uniquely named.
- Each repository is a (ILoggerRepository).
- Multiple assemblies can link to the same repository.
-
-
- By default there is a single logging repository per process (more precisely per AppDomain). This extends
- across all assemblies loaded into the process and allows them to all share a
- single configuration. The configuration of the repository only needs to be done once,
- typically in the entry point to the application, either programmatically or using
- a configuration attribute.
-
-
- Named logging repositories can be created using the LogManager.CreateRepository
- method. The repository for can be retrieved using the
- LogManager.GetRepository method.
- A repository created in this way will need to be configured programmatically.
-
-
-
-
- An assembly may choose to utilize a named logging repository rather than the default repository.
- This completely separates the logging for the assembly from the rest of the application.
- This can be very useful to component developers that wish to use log4net for their
- components but do not want to require that all the applications that use their
- component are aware of log4net. It also means that their debugging configuration is
- separated from the applications configuration. The assembly should specify the
- RepositoryAttribute to set its logging repository.
-
-
- The log4net logging repositories can be configured using the following assembly-level
- attributes:
-
-
-
- AliasRepositoryAttribute
-
- Specifies a named repository to use as this assembly's repository.
-
-
- An assembly's logger repository is defined by its
- RepositoryAttribute, however this can be overridden by an
- assembly loaded before the target assembly.
-
-
- An assembly can alias another assembly's repository by specifying
- this attribute with the name of the target repository.
-
-
- This attribute may be used as many times as necessary to alias all the required
- repositories.
-
-
-
- RepositoryAttribute
-
- Specifies the logging repository for the assembly.
-
-
- Assemblies are mapped to logging repositories. This attribute controls the configuration of the repository. The
- Name property specifies the name of the repository
- for this assembly. The RepositoryType
- property specifies the type of the repository object to create for the assembly.
- If this attribute is not specified and a Name
- is not specified then the assembly will be part of the default shared logging
- repository.
-
-
- This attribute may only be used once per assembly.
-
[LOG4NET-72] - Performance of ILog.xxxFormat methods
-
[LOG4NET-74] - Change MemoryAppender member variables to protected
-
-
-
-
-
-
-
-
-
-
-
Renamed namespaces
-
- Renamed namespace log4net.spi to log4net.Core.
- Renamed namespace log4net.helpers to log4net.Util.
-
-
-
-
Renamed config classes and attributes
-
- In the log4net.Config namespace the DOMConfigurator,
- DOMConfiguratorAttribute, DomainAttribute,
- and AliasDomainAttribute have been marked as obsolete. These types are
- still available and functional in this release.
-
-
- The XmlConfigurator and XmlConfiguratorAttribute
- types replace DOMConfigurator and
- DOMConfiguratorAttribute. The RepositoryAttribute
- and AliasRepositoryAttribute types replace
- DomainAttribute and AliasDomainAttribute.
-
-
-
-
Fixed pascal casing of type names
-
- Renamed AdoNetAppender, AspNetTraceAppender,
- SmtpAppender, Iso8601DateFormatter,
- MdcFilter, and NdcFilter.
- Note that the config file type resolver is case insensitive so this is only a breaking change
- for code that programmatically creates a type that has been renamed.
-
-
-
-
Layouts changed to stream their output to a TextWriter
-
- Layouts have been changed to format their output to a TextWriter
- rather than return a string. This increases performance and reduces temporary object creation.
-
-
-
-
C style string escapes no longer supported by config parser
-
- The XML config parser no longer supports decoding C style escape sequences in strings.
- Previously sequences like \n and \\
- where decoded. Instead use the appropriate XML encodings as required.
-
-
-
-
-
-
-
-
-
New CLI build
-
- A new log4net assembly is built that targets all CLI 1.0 compatible runtimes.
- This build is essentially a common subset of the Mono 1.0 and .NET 1.0 builds.
- It is built using the MS .NET 1.0 compiler and libraries but does not use any
- platform specific APIs.
-
-
- This build is only available in release configuration and can be found at
- bin\cli\1.0\release.
-
-
-
-
Logging contexts
-
- Logging contexts can be used to record contextual data that is relevant to the current
- process. Logging contexts are both an extension of the concepts embodied in the
- MDC and NDC and a replacement for
- them. The MDC and NDC have been
- reimplemented to use the ThreadContext as storage.
-
-
- The logging contexts provide a single unified view that cuts across different
- scopes within an application.
- The contexts are layered in the following order of narrowing scope:
- GlobalContext, ThreadContext,
- LogicalThreadContext, and LoggingEvent.
- Context values specified in a narrower scope hide the matching value in a wider scope.
-
-
-
-
PatternLayout customization and long pattern names
-
- The PatternLayout now supports long pattern names.
- These pattern names are significantly more readable than the single character patterns.
-
-
- The PatternLayout now supports custom patterns. New patterns
- can be defined in the config file:
-
- The above config defines a custom pattern called myConverter
- which is bound to the TestApp.MyPatternConverter, TestApp
- type. This type must extend the log4net.Util.PatternConverter
- base class. The custom pattern can then be used in the pattern string.
-
- A new pattern based type, PatternString, can be used in
- the config file to set string properties using a pattern syntax. For example the
- File property of the FileAppender could be set as follows:
-
- The XmlConfigurator methods now support loading the
- configuration data from a URI. Config can be loaded from any URI supported by the
- System.Net.WebRequest class.
-
-
-
-
Support for No-Touch deployment
-
- Log4net supports configuring No-Touch deployment applications using the
- XmlConfiguratorAttribute. If a relative config file
- or extension is specified then this is resolved relative to the deployment
- URI.
-
-
-
-
Config file parser enhancements
-
- The config file parser has been enhanced to support specifying the property subtype, or intermediate type,
- directly on the property element, for example:
-
- Implicit conversion will be attempted between the value string and the type specified,
- and then again between the type and the target property type.
-
-
-
-
.NET string formatting syntax
-
- Added .NET String.Format style formatting syntax methods to
- the ILog interface. The new methods are:
- DebugFormat, InfoFormat,
- WarnFormat, ErrorFormat
- and FatalFormat.
-
-
-
-
Customizable levels
-
- Levels are defined by the repository LevelMap. The defined
- levels, the relative ordering of levels and level display names can be configured on
- a per-repository basis.
-
-
-
-
Per-appender security contexts
-
- Appenders that interact with controlled platform resources, e.g. files, can be
- configured to use a separate security context when accessing these resources.
- The calling thread may not have appropriate privileges to access the resource a
- custom SecurityContext can be used to elevate the
- privileges of the appender. The WindowsSecurityContext
- is used to specify alternative credentials on the Windows platform.
-
-
-
-
Added new appenders
-
-
AnsiColorTerminalAppender
-
-
- The AnsiColorTerminalAppender writes events to
- the application's ANSI terminal window. It can be configured to specify
- the text and background colors for different level events. Note that Console
- applications running on Windows do not have an ANSI terminal window and
- should use the ColoredConsoleAppender instead.
-
-
-
LocalSyslogAppender
-
-
- Logs events to a local syslog service. This appender uses the POSIX libc syslog
- library functions. If these functions are not available on the local system then
- this appender will not work!
-
-
-
RemoteSyslogAppender
-
-
- The RemoteSyslogAppender uses the BSD syslog protocol to
- log to a syslog daemon. The syslogd listens for for messages on UDP port 514.
-
-
-
TelnetAppender
-
-
- The TelnetAppender accepts socket connections and streams
- logging messages back to the client. The output is provided in a telnet-friendly way
- so that a log can be monitored over a TCP/IP socket.
- This allows simple remote monitoring of application logging.
-
-
-
-
-
-
Added new LoggerMatchFilter filter
-
- Added LoggerMatchFilter which matches a string against
- the event's logger name.
-
-
-
-
Pluggable file locking models for the FileAppender
-
- The FileAppender (and by extension the
- RollingFileAppender) now support pluggable file
- locking models. The default model, ExclusiveLock,
- maintains the current exclusive file locking behavior. An alternative
- model, MinimalLock, can be used to support writing to
- a single output file from multiple processes.
-
- The RollingFileAppender now supports a new
- rolling style, Once. In this mode the appender
- will roll the file once per run.
-
-
-
-
SmtpAppender authentication
-
- On the .NET 1.1 platform only, the SmtpAppender supports authenticating
- against the mail server using either username and password or integrated NTLM authentication.
-
-
-
-
AdoNetAppender ReconnectOnError
-
- Added new configuration property to AdoNetAppender.
- Setting ReconnectOnError to true
- will force the appender to attempt to reconnect to the database if the connection
- is lost.
-
-
-
-
UdpAppender hostname support
-
- The UdpAppender config property RemoteAddress
- can now be specified as a DNS hostname string. The hostname is resolved to an IP address.
-
-
-
-
-
-
-
-
-
FxCop compliance
-
- Updates to bring the internal code in line with the current FxCop rules.
-
-
-
-
Separate NUnit tests
-
- Moved the NUnit tests into a separate project, log4net.Tests.
-
-
-
-
Bug Fixes
-
-
RemotingAppender
-
-
- Sends events from a ThreadPool thread
- rather than the calling thread to prevent transfer,
- and potential loss, of the CallContext.
-
-
-
RollingFileAppender
-
-
- Fixed date rolling period detection for non UTC timezones.
-
-
-
ColoredConsoleAppender
-
-
- Updated to support writing more than 30,000 chars in a single message.
- Fixed background color overspill if the console window needs to
- scroll the contents.
-
-
-
-
-
-
-
-
-
-
-
-
-
Changed assembly name to log4net
-
- The build output is now log4net.dll
- for all frameworks. This is a breaking change.
-
-
- To resolve cross platform and cross version issues we have
- changed the log4net assembly to use a common name for all
- frameworks. The assembly friendly name is now log4net.
- The builds for each framework can now be differentiated
- by the assembly title. This includes the name of the framework
- that the assembly was built on.
-
-
-
-
Combined Release and ReleaseStrong builds
-
- The Release and ReleaseStrong builds have been consolidated into
- a single build called Release. This Release build is strongly named.
-
-
-
-
New Appender: ColoredConsoleAppender
-
- The ColoredConsoleAppender writes events to the
- application's console. It can be configured to specify the text and background
- colors for different level events.
-
-
-
-
New Appender: SmtpPickupDirAppender
-
- The SmtpPickupDirAppender generates SMTP compliant
- messages and writes them to a local directory. These files can then be read
- by an SMTP agent (e.g. the IIS SMTP Agent) and delivered.
-
-
-
-
New Layout: XmlLayoutSchemaLog4j
-
- This new layout formats the logging events as XML which complies with
- the log4j event dtd. This can be used to transfer log event from log4net
- to log4j. Currently the only appender that can communicate directly with
- log4j is the UdpAppender.
-
-
-
-
New PatternLayout conversion characters
-
- Added support for capturing the current thread principal name and the
- app domain friendly name for each logging event.
-
-
-
%a
-
- Used to output the friendly name of the AppDomain where the
- logging event was generated.
-
-
%u
-
- Used to output the user name for the currently active user
- (Principal.Identity.Name).
-
-
-
-
-
Types specified in the config file are now loaded ignoring case
-
- All types specified in the configuration files are now loaded
- using a case insensitive method.
-
-
-
-
Fine grained fixing for buffered events
-
- The LoggingEvent now supports fine grained
- fixing of data that needs to be accessed outside the append context,
- e.g. when an event is buffered. The new Fix
- property takes a combination of the FixFlags
- enumeration values.
-
-
-
-
Code updated inline with FxCop 1.21
-
- In line with the FxCop 1.21 guidelines:
- Sealed utility classes. Added serialization security demand to GetObjectData.
- Renamed parameters.
-
-
-
-
EventLogAppender 32K Limit
-
- There is a limit of 32K characters in an EventLog message. Added a
- check that only logs the first 32000 characters from the rendered
- message.
-
-
-
-
-
-
-
-
-
Updated to support the Microsoft .NET Framework 1.1 Final
-
- Updated to support the Microsoft .NET Framework 1.1 Final Beta (1.1.4322).
-
-
-
-
Features document
-
- Added a new document that covers the main features of log4net.
- See the features
- document for more information.
-
-
-
-
Hierarchy disabled until it is configured
-
- The Hierarchy is now disabled until it has been configured.
- All messages logged to the Hierarchy before it has been
- configured will be ignored without an error message being
- written to the console.
-
-
- If you are configuring log4net programmatically (i.e. not using
- one of the built-in configurators) you must set the
- ILoggerRepository.Configured property
- to true once you have configured
- the repository.
-
-
- The no appenders defined for a logger message will no longer be
- displayed on the console by default. This message will only be
- displayed if internal debugging is enabled.
-
-
-
-
New examples in VisualBasic.NET, JScript and Managed C++
-
- New examples in VisualBasic.NET, JScript and Managed C++.
- TODO Link to document about examples.
-
-
-
-
Code and Documentation Updates
-
- Code fixes. Documentation and manual updates.
- See the ChangeLog for more information.
-
-
-
-
Added document with example appender configurations
- Not all frameworks are created equal and some features have been excluded from
- some of the builds. See the Framework Support document for more information.
-
-
-
-
New build system using NAnt
-
- The new build system allows log4net to be built for all supported frameworks and
- in all build configurations in one go.
-
-
-
-
New source code & distribution layout
-
- The source code & distribution layout has been updated to support the new
- build environment and multiple target frameworks.
-
-
-
-
Removed DomainAttribute.UseDefaultDomain property
-
- Updated default behavior of DefaultRepositorySelector. Assemblies
- are now by default placed into the default domain. To specify another domain,
- the DomainAttribute must be used. This is the opposite behavior
- to what was previously available. If you were previously specifying the DomainAttribute.UseDefaultDomain
- property then you should remove it, and if the default behavior is now
- sufficient, you do not need to specify the DomainAttribute at all.
-
-
-
-
Updated configuration file parser
-
- Updated config file parser to use the element name as the property to set. Also
- removed <object> tag, the type attribute can now be
- specified on the property element directly.
-
- The EventLogAppender now supports setting the event ID in the
- event log, this is taken from the EventID property from the per
- event Properties map on the LoggingEvent.
-
-
-
-
Updated ADONetAppender
-
-
-
- Added support for prepared statements and stored procedures
-
- Added RawTimeStampLayoutto correctly convert the timestamps into
- database date time format
-
- Added ExceptionLayout to render the exception data
-
-
-
-
-
Support for front-end extension
-
- This allows the logging API to be wrapped or adapted for specific purposes. Two
- extension samples are included in the distribution:
-
-
-
-
-
-
-
-
-
- Extension
-
- Description
-
-
-
log4net.Ext.Trace
-
Adds trace logging methods
-
-
-
log4net.Ext.EventID
-
Adds additional eventId parameter to all methods
-
-
-
-
-
-
-
Added ForwardingAppender
-
Forwards events to multiple sub appenders after applying filter rules.
-
-
-
Added BufferingForwardingAppender
-
Forward events to sub appenders after buffering them.
-
-
-
Added ASPNetTraceAppender
-
Logs events to the ASP.NET trace system.
-
-
-
Added NetSendAppender
-
Delivers logging events using the Windows Messenger service.
-
-
-
Added UdpAppender
-
Sends logging events as connectionless UDP datagrams to a remote host or a
- multicast group.
-
-
-
Removed obsolete methods
-
-
-
Lots of updates to improve our compliance with FxCop
-
-
-
Improved SDK documentation
-
-
-
-
-
-
-
-
Fixed Exception thrown when DOM Configurator called with a null XML
- Element.
-
This occurred if the configuration file did not have a log4net section defined.
-
-
-
Made level lookup case insensitive
-
-
-
Prevented the Hierarchy's Threshold level from being set to a null reference
-
-
-
-
-
-
-
-
Added event specific properties to the logging event object
-
- Appenders can add additional information to the events they are logging. The RemotingAppender
- and the SMTPAppender both add a 'hostname' property to the events.
- These properties can be accessed using the PatternLayout with the
- %P{name} syntax.
-
-
-
-
Added a plugin framework
-
An IPlugin interface can be attached to any repository.
-
-
-
A new RemoteLoggingServerPlugin plugin acts as the server for the
- RemotingAppender
-
-
-
Updated the core log4net framework to work in an environment with no
- permissions
-
Specific appenders still require additional permissions to log correctly
-
-
-
Added support for domain aliasing using the AliasDomainAttribute
-
This allows a parent assembly to take control of the logging domain for child
- assemblies.
-
-
-
Added events for repository creation, configuration change, configuration reset
- and repository shutdown
-
-
-
Added LevelMap to the ILoggerRepository interface
-
The mapping from level name to level object is now repository specific,
- therefore each repository can have independent mappings.
-
-
-
Moved hierarchy specific config file parser to new DOMHierarchyConfigurator class
-
This is controlled by the Hierarchy object and allows for better
- encapsulation.
-
-
-
Added OnlyFixPartialEventData property to the buffered appenders
-
This setting causes slow settings to be ignored. This significantly improves the
- performance of the buffered appenders.
-
-
-
XML entity references are supported in the XML config file.
-
-
-
Added support for expanding environment variables in <param> values
-
- The environment variables must be specified as ${FOO} where FOO
- is the name of the variable to expand.
-
-
-
-
Upgraded to use NUnit 2.0
-
-
-
File appenders can specify the encoding to use for the file
-
-
-
Added strong named configuration
-
-
-
-
-
-
-
-
Added log4net.Ext.Trace extension
-
This is a separate assembly that adds a trace level to log4net.
-
-
-
The default log file output directory is now the application base directory not
- the current directory
-
-
-
Added MemoryAppender
-
Stores all the logging events in an in-memory buffer.
-
-
-
Moved the Hierarchy implementation into a separate namespace
-
- The log4net.Repository.Hierarchy namespace now contains all the
- code that is specific to the Hierarchy implementation.
-
-
-
-
Refactored the DOMConfigurator and BasicConfigurator
-
- The Hierarchy specific data schema and implementation could be has
- now been moved to the log4net.Repository.Hierarchy namespace. The
- bootstrap code for these configurators remains in the log4net.Config
- namespace.
-
-
-
-
Replaced the DOMConfiguratorAttribute UseExecutableDomain
- property with UseDefaultDomain
-
- This change to the implementation of the DOMConfiguratorAttribute should
- allow the configuration of multiple assemblies to be accomplished more easily,
- especially when developing web applications (ASP.NET).
-
-
-
-
A few good bug fixes!
-
-
-
-
-
-
-
-
Added ADONetAppender
-
Thanks to TechnologyOneCorp.com.
-
-
-
Added TraceLogAssembly extensibility example
-
-
-
Lots of bug fixes
-
-
-
-
-
-
-
-
Added 6 new examples
-
-
-
Split Category class into Logger and LogManager classes
-
- The instance methods from Category have moved to the Logger
- class. The static methods from Category have moved to the LogManager
- class. The Category class still exists but for backward
- compatibility only. Changed interface ICategoryFactory to ILoggerFactory
- and the implementation class DefaultCategoryFactory to DefaultLoggerFactory.
-
-
-
-
Replaced Priority class with Level class
-
- The Priority class has been replaced by the Level class.
- The Priority class still exists for backward compatibility only.
- The Level class implements a static pool of Level objects.
- The Level class is sealed and serializable.
-
-
-
-
Added ILoggerRepository interface implemented by Hierarchy
-
- The Hierarchy class implements the ILoggerRepository interface.
- This interface is used by the LogManager class and therefore
- allows different implementations of ILoggerRepository to be used.
-
-
-
-
Enhanced NUnit tests
-
- All the NUnit tests can be run using a single TestSuite: NUnitGUI
- log4net.LogManager+AllTests,log4net.dll.
-
-
-
-
Added support for serializing LoggingEvents
-
- The LoggingEvent class is serializable. All local state is
- captured before serialization occurs. This now allows LoggingEvent
- objects to be serialized between applications or machines.
-
-
-
-
Added RemotingAppender
-
- Delivers LoggingEvents to a remote interface. This can be used to
- collect distributed logging into a single log file. There is an example
- remoting sink that receives the logging events, see examples\net\remoting\RemotingServer
- for details.
-
-
-
-
Added support for rendering composite objects
-
- The IObjectRenderer interface method DoRender now
- takes a RendererMap argument. This allows the renderer to use the
- appropriate renderer from the RendererMap to render any nested
- objects.
-
-
-
-
Added support for rendering exceptions
-
- The DefaultRenderer now has support for rendering exceptions to a
- string. This includes nested exceptions. The RendererMap is now
- used to render exceptions in the LoggingEvent. This allows the
- rendering of specific exceptions to be enhanced by specific renderers.
-
-
-
-
Added ITriggeringEventEvaluator interface
-
- This interface is used by SMTPAppender and RemotingAppender
- to determine if a LoggingEvent meets a set of user defined
- criteria. These appenders use the interface to determine whether or not to
- deliver the current buffer of events to their listener. The interface is
- implemented by the LevelEvaluator class, which triggers above a
- set level.
-
-
-
-
Added regex matching to the MDCFilter, NDCFilter and StringMatchFilter
-
- The MDCFilter, NDCFilter and StringMatchFilter
- can now be configured to use regex matches in addition to substring matches.
- Set the RegexToMatch property to use this feature.
-
-
-
-
Added XMLLayout
-
- emits an XML element for each LoggingEvent. This allows logging
- events to be stored and manipulated as XML. The DTD for the XML emitted is in
- the log4net-events.dtd
-
-
-
-
Added support for <logger> and <level> elements in the
- DOMConfigurator
-
- As the Category and Priority classes have been
- replaced by the Logger and Level classes. The DOMConfigurator
- has been updated to allow the <logger> and <level>
- elements to be used in place of the <category> and <priority>
- elements. The old elements are still accepted for backward compatibility.
-
-
-
-
Added Threshold property to Hierarchy
-
- Changed DisableXXX() methods on Hierarchy to a Threshold
- property.
-
-
-
-
Added support for logging domains
-
- The LogManager supports multiple logging domains. The LogManager
- uses an instance of the IRepositorySelector class to map from
- domains to ILoggerRepository instances. The default implementation
- is to have a separate ILoggerRepository for each domain. When a
- call is made to the static methods on LogManager the domain can be
- specified (as a string) or the domain can be inferred automatically from the
- calling assembly. The default behavior is for each assembly loaded into the
- process to have its own domain and ILoggerRepository. These can
- each be configured separately. This allows standalone assemblies to use log4net
- without conflicting with other modules in the process. The domain for the
- assembly is configured using metadata attributes defined on the assembly.
-
-
-
-
DOMConfigurator can set params to arbitrary objects
-
- Using a new <object> element, params can now be set to any
- creatable object.
-
- log4net user support is provided via a mailing list. Discussion on log4net is held on the
- log4net-user mailing list. Please search the archives before posting because it
- is likely that your question has been answered before.
-
-
-
-
- You can browse the mailing list archives at the following locations:
-
- Before posting please read the following guidelines:
-
-
-
-
-
- Ask smart questions
- Every volunteer project obtains its strength from the people involved
- in it. You are welcome to join any of our mailing lists. You can
- choose to lurk, or actively participate; it's up to you. The level of
- community responsiveness to specific questions is generally directly
- proportional to the amount of effort you spend formulating your
- question. Eric Raymond and Rick Moen have even written an essay entitled
- "Asking Smart Questions"
- precisely on this topic.
-
-
-
-
-
- Keep your email short and to the point
- If your email is more than about a page of text, chances are that it
- won't get read by very many people. It is much better to try to pack a
- lot of informative information (see above about asking smart questions)
- into as small of an email as possible. If you are replying to a previous
- email, it is a good idea to only quote the parts that you are replying
- to and to remove the unnecessary bits. This makes it easier for people
- to follow a thread as well as making the email archives easier to search
- and read.
-
-
-
-
-
- Do your best to ensure that you are not sending HTML or "Stylelized" email to the list
- If you are using Outlook or Outlook Express or Eudora, chances are that
- you are sending HTML email by default. There is usually a setting that
- will allow you to send "Plain Text" email. If you are using Microsoft
- products to send email, there are several bugs in the software that
- prevent you from turning off the sending of HTML email. Please read this
- page as well.
-
-
-
-
-
- Watch where you are sending email
- Our mailing lists have set the Reply-To to go back to the
- list. That means that when you Reply to a message, it will go to the list
- and not to the original author directly. The reason is because it helps
- facilitate discussion on the list for everyone to benefit from. Be careful
- of this as sometimes you may intend to reply to a message directly to someone
- instead of the entire list.
-
-
- The appropriate contents of the Reply-To header is an age-old debate that
- should not be brought up on the mailing lists. You can examine opposing points of view
- condemning
- our convention and condoning
- it. Bringing this topic up for debate again on a mailing list will add nothing new
- and is considered off-topic.
-
-
-
-
-
- Do not cross post messages
- In other words, pick a mailing list and send your messages to that mailing
- list only. Do not send your messages to multiple mailing lists. The reason is
- that people may be subscribed to one list and not to the other. Therefore,
- some people will only see part of the conversation.
-
-
-
-
-
- Where relevant please try to include the following information in your postings.
-
-
-
-
-
- Specify the version of log4net you are using.
-
-
-
-
-
- Specify what your assembly type is, i.e. exe or dll, and how your code is launched,
- e.g. console application, windows application, ASP.NET project, COM+ hosted object, etc...
-
-
-
-
-
- Specify which runtime platform (e.g. MS .NET, Mono, SSCLI) you are using and which version.
-
-
-
-
-
- If you are having configuration issues then include logging configuration files if any, plus source code.
-
-
-
-
-
- If possible please reproduce your issue with the
- internal log4net debugging
- enabled. Include this debug output in your post, it is usually the first thing we ask for in diagnosing issues.
-
-
-
-
-
- If you think you have found a bug then a short example reproducing the problem is very much appreciated.
-
-
-
-
-
- To prevent spam, we require you to be subscribed to the list before posting to it.
-