nicko 2005/02/07 12:46:01
Added: xdocs/src/release faq.xml
Removed: xdocs/src/release/manual faq.xml
Log:
Moved FAQ doc out of manual folder
Revision Changes Path
1.1 logging-log4net/xdocs/src/release/faq.xml
Index: faq.xml
===================================================================
<?xml version="1.0" ?>
<!--
Copyright 2004-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.
-->
<document>
<properties>
<author email="nicko at apache dot org">Nicko Cadell</author>
<title>log4net Manual - Frequently Asked Questions</title>
</properties>
<meta name="keywords" content="log4net frequently asked questions,
log4net faq, log4net" />
<body>
<section name="log4net Manual - Frequently Asked Questions">
<sectionMenu name="Contents" />
<section name="Information">
<section name="What is log4net?">
<p>
log4net is a tool to help the
programmer output log statements to a variety of
output targets.
</p>
<p>
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 <i>production</i> code without incurring a
high performance cost. It
follows that the speed of logging (or rather not
logging) is crucial.
</p>
<p>
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 <i>hierarchical
loggers</i>. Using these
loggers it is possible to selectively control
which log statements are output
at arbitrary granularity.
</p>
<p>
log4net is designed with two
distinct goals in mind: speed and flexibility. There
is a tight balance between
these two requirements.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Is log4net a reliable logging
system?">
<p>
No. log4net is not reliable. It
is a best-effort and <em>fail-stop</em> logging system.
</p>
<p>
By fail-stop, we mean that
log4net will not throw unexpected exceptions at
run-time potentially causing
your application to crash. <b>If for any reason, log4net
throws an uncaught
exception</b> (except for <span class="code">ArgumentException</span> and
<span
class="code">ArgumentNullException</span> which may be thrown), <b>please send
an email
to the <a
href="mailto:[email protected]">
[email protected]</a> mailing list</b>. Uncaught exceptions
are handled as serious bugs
requiring immediate attention.
</p>
<p>
Moreover, log4net will not
revert to <span class="code">System.Console.Out</span>
or <span
class="code">System.Console.Error</span> 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
<span
class="code">System.Console.Error</span> and
<span>System.Diagnostics.Trace</span>
indicating that logging can not
be performed.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What are the prerequisites for
log4net?">
<p>
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).
</p>
<p>
Not all frameworks are created
equal and some features have been excluded from
some of the builds. See the <a
href="../framework-support.html">Framework Support</a>
document for more information.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Is there example code for using
log4net?">
<p>
There is a directory containing
examples in <span class="code">log4net\examples</span>.
The examples are broken down by
framework.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What are the features of
log4net?">
<ul>
<li>
log4net is optimized
for speed.</li>
<li>
log4net is based on a
named logger hierarchy.</li>
<li>
log4net is fail-stop
but not reliable.</li>
<li>
log4net is
thread-safe.</li>
<li>
log4net is not
restricted to a predefined set of facilities.</li>
<li>
Logging behavior can be
set at runtime using a configuration file.
Configuration files are
in XML format.</li>
<li>
log4net is designed to
handle exceptions from the start.</li>
<li>
log4net can direct its
output to many sinks including: a file, the console, the NT EventLog or even
e-mail.</li>
<li>
log4net categorizes
logging into levels: DEBUG, INFO, WARN, ERROR and FATAL.</li>
<li>
The format of the log
output can be easily changed by implementing a new layout class.</li>
<li>
The target of the log
output as well as the writing strategy can be altered by
writing a new appender
class.</li>
<li>
log4net supports
multiple output appenders per logger.</li>
</ul>
<p>
See the <a
href="../features.html">features</a> overview document for more information on
the features of log4net.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Is log4net thread-safe?">
<p>
Yes, log4net is thread-safe.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What does log output look like?">
<p>
The log output can be
customized in many ways. Moreover, one can completely
override the output format by
implementing one's own <span class="code">ILayout</span>
</p>
<p>
Here is an example output using
<span class="code">PatternLayout</span> with the conversion
pattern <span
class="code">%timestamp [%thread] %-5level %logger{2} %ndc -
%message%newline</span>
</p>
<source language="text"><![CDATA[
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.]]></source>
<p>
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
<em>nested diagnostic context</em> (<span class="code">NDC</span>). Note the
nested diagnostic context may
be empty as in the first two statements. The text
after the '-' is the message of
the statement.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What are Loggers?">
<p>
The logger concept lies at the
heart of log4net's configuration. Loggers are organized into a
hierarchy and give the
programmer <em>run-time</em> control on which logging statements
are printed or not.
</p>
<p>
Loggers are assigned levels
through the configuration of log4net. A log statement is
routed through to the appender
depending on its level <em>and</em> its logger.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Why should I donate my
extensions to log4net back to the project?">
<p>
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. <em>You are free to do whatever you wish with
your proprietary log4net
extensions.</em> In particular, you may choose to
never release your extensions
to the wider public. For details see the
<a
href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version
2.0</a>.
</p>
<p>
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.
</p>
<p>
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.
</p>
<p>
Unless the proprietary log4net
extension is business critical, there is little
reason for not donating your
extensions back to the project.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What should I keep in mind when
contributing code?">
<ol>
<li>
Stick to the existing
indentation style even if you hate it.
<p>
Alternating
between indentation styles makes it hard to understand the source
code. Make it
hard on yourself but easier on others.
</p>
</li>
<li>
<b>Thoroughly test your
code.</b>
<p>
There is
nothing more irritating than finding the bugs in debugging (i.e. logging) code.
</p>
</li>
<li>
Keep it simple, small
and fast.
<p>
It's all about
the application not about logging.
</p>
</li>
<li>
Did I mention sticking
with the indentation style?</li>
</ol>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="How fast do bugs in log4net get
fixed?">
<p>
As fast as they get reported ;-)
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What is the history of log4net?">
<p>
log4net is a port of the
popular <a href="http://logging.apache.org/log4j/">log4j</a> 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 <a href="../../history.html">history</a> page for more details.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Where can I find the latest
distribution of log4net?">
<p>
The log4net <a
href="http://logging.apache.org/log4net/">home page</a> is a good place to
start.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
</section>
<section name="Configuration">
<section name="How can I change log behavior at
runtime?">
<p>
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.
</p>
<p>
Configuration files are
specified in XML. See <span class="code">log4net.Config.XmlConfigurator</span>
for more details.
</p>
<p>
See the various <span
class="code">log4net.Layout</span> and <span
class="code">log4net.Appender</span>
components for specific
configuration options.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="How do I completely disable all
logging at runtime?">
<p>
Setting the <span
class="code">Threshold</span> 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:
</p>
<source language="xml"><![CDATA[
<log4net threshold="OFF" />]]></source>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What are the configurable
options for an appender?">
<p>
log4net uses public properties
to configure components such as
Appenders, Layouts, Loggers etc.
</p>
<p>
Thus, any writable public
property in on the appender corresponds to a
configurable option. For
example, in <span class="code">RollingFileAppender</span> the
<span class="code">public int
MaxSizeRollBackups { set; }</span> property corresponds to
the <span
class="code">MaxSizeRollBackups</span> option.
</p>
<p>
Layouts options are also
defined by their writable properties. Same goes for most
other log4net components.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Is it possible to direct log
output to different appenders by level?">
<p>
Yes it is. Setting the <span
class="code">Threshold</span> option of any appender extending
<span
class="code">AppenderSkeleton</span>, (most log4net appenders extend
<span
class="code">AppenderSkeleton</span>) will filter out all log events
with a <em>lower</em> level
than the value of the threshold option.
</p>
<p>
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.
</p>
<p>
This policy usually best
encapsulates what the user actually wants to do, as
opposed to her mind-projected
solution.
</p>
<p>
If you must filter events by
exact level match, then you can attach a
<span
class="code">LevelMatchFilter</span> to any appender to filter out logging
events by exact level match.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Is there a way to get log4net to
automatically reload a configuration file if it changes?">
<p>
Yes. The <span
class="code">XmlConfigurator</span> supports automatic
reloading through the <span
class="code">ConfigureAndWatch</span> APIs. See the API
documentation for more details.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Can I load an appender from
another assembly?">
<p>
Yes. When specifying the type
in the configuration file you can give the assembly
qualified name of the type. For
example:
</p>
<source language="xml"><![CDATA[
<appender name="..." type="MyNamespace.MyAppender, MyAssembly">]]></source>
<p>
The .NET runtime will try to
locate the assembly called <i>MyAssembly</i>.
How .NET locates assemblies is
beyond the scope of this FAQ.
</p>
<p>
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 <span class="code">System.Type.GetType</span>.
See the next FAQ on how to get
the version and public key for an assembly.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="How do I get the Public Key for
an assembly?">
<p>
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
<a
href="http://www.aisto.com/roeder/dotnet">http://www.aisto.com/roeder/dotnet</a>.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
</section>
<section name="Implementing Logging">
<section name="Are there any suggested ways for
naming loggers?">
<p>
Yes, there are.
</p>
<p>
You can name logging loggers by
<strong>locality</strong>. 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:
</p>
<ul>
<li>
It is very simple to
implement.</li>
<li>
It is very simple to
explain to new developers.</li>
<li>
It automatically
mirrors your application's own modular design.</li>
<li>
It can be further
refined at will.</li>
<li>
Printing the logger
automatically gives information on the locality of the
log statement.</li>
</ul>
<p>
However, this is not the only
way for naming loggers. A common alternative
is to name loggers by
<strong>functional areas</strong>. For example, the
"database" logger, "remoting"
logger, "security" logger, or the "XML"
logger.
</p>
<p>
You may choose to name loggers
by functionality and subcategorize by
locality, as in
"DATABASE.MyApp.MyClass" or
"DATABASE.MyApp.MyModule.MyOtherClass".
</p>
<p>
<em>You are totally free in
choosing the names of your loggers.</em> The
log4net package merely allows
you to manage your names in a hierarchy. However,
it is your responsibility to
define this hierarchy.
</p>
<p>
<b>Note:</b> by naming loggers
by locality one tends to name things by
functionality, since in most
cases the locality relates closely to
functionality.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="How do I get the fully-qualified
name of a class in a static block?">
<p>
You can easily retrieve the
fully-qualified name of a class in a static block
for class <span
class="code">X</span>, with the statement <span
class="code">typeof(X).Name</span>.
Note that <span
class="code">X</span> is the class name and span an instance.
However because the <span
class="code">LogManager.GetLogger</span> method is overloaded
to take an instance of <span
class="code">Type</span> as well as <span class="code">string</span>
usually only the type of the
class is required.
</p>
<p>
Here is the suggested usage
template:
</p>
<source language="C#"><![CDATA[
public class Foo
{
private static readonly ILog log = LogManager.GetLogger(typeof(Foo));
... other code
}]]></source>
<p>
An equivalent and more portable
solution, though slightly longer, is to use the declaring type
of the static constructor.
</p>
<source language="C#"><![CDATA[
public class Foo
{
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
... other code
}]]></source>
<p>
<b>Note:</b> the .NET Compact
Framework 1.0 does not support <span
class="code">System.Reflection.MethodBase.GetCurrentMethod()</span>.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What is the fastest way of (not)
logging?">
<p>
For some logger <span
class="code">log</span>, writing,
</p>
<source language="C#"><![CDATA[
log.Debug("Entry number: " + i + " is " + entry[i]);]]></source>
<p>
incurs the cost of constructing
the message parameter, that is converting both
integer <span
class="code">i</span> and <span class="code">entry[i]</span> to
a string, and concatenating
intermediate strings. This, regardless of whether
the message will be logged or
not.
</p>
<p>
If you are worried about speed,
then write
</p>
<source language="C#"><![CDATA[
if(log.IsDebugEnabled)
{
log.Debug("Entry number: " + i + " is " + entry[i]);
}]]></source>
<p>
This way you will not incur the
cost of parameter construction if debugging is
disabled for logger <span
class="code">log</span>. 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
<span class="code">IsDebugEnabled</span> and once in <span
class="code">Debug</span>.
This is an insignificant
overhead since evaluating a logger takes less than
1% of the time it takes to
actually log a statement.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="What is REALLY the FASTEST way
of (not) logging?">
<p>
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:
</p>
<source language="C#"><![CDATA[
if(log.IsDebugEnabled)
{
log.Debug("Entry number: " + i + " is " + entry[i]);
}]]></source>
<p>
It is possible to further
eliminate the calls to <span class="code">IsDebugEnabled</span>
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:
</p>
<source language="C#"><![CDATA[
public class FastLogger
{
private static readonly ILog log =
LogManager.GetLogger(typeof(FastLogger));
private static readonly bool isDebugEnabled = log.IsDebugEnabled;
public void MyMethod()
{
if(isDebugEnabled)
{
log.Debug("Entry number: " + i + " is " + entry[i]);
}
}
}]]></source>
<p>
So why exactly is this faster?
Well to start with the <span class="code">IsDebugEnabled</span>
is not called for each log
statement, it is called once per logger. Furthermore as the
<span
class="code">isDebugEnabled</span> variable is <span class="code">private
static readonly</span>
the JIT compiler can at
<em>run-time</em> optimize out the <span class="code">if</span> 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.
</p>
<p>
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
<span class="code">XmlConfigurator.ConfigureAndWatch</span> 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.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Can the outputs of multiple
client request go to different log files?">
<p>
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.
</p>
<p>
It is simpler to use a nested
diagnostic context (<span class="code">NDC</span>).
Typically, one would <span
class="code">NDC.Push()</span>
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 nested diagnostic context
so that you can distinguish
logs from different client requests even if they
are output to the same file.
</p>
<p>
See the <span
class="code">NDC</span> and the <span class="code">PatternLayout</span> classes
for more
information.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Logger instances seem to be
create only. Why isn't there a method to remove logger instances?">
<p>
It is quite nontrivial to
define the semantics of a "removed" logger which is
still referenced by the user.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="How do I get multiple process to
log to the same file?">
<p>
The <span
class="code">FileAppender</span> holds a write lock on the log
file while it is logging. This
prevents other processes from writing to the
file, therefore it is not
possible to have multiple processes log directly
to the same log file, even if
they are on the same machine.
</p>
<p>
You may have each process log
to a <span class="code">RemotingAppender</span>.
The receiving <span
class="code">RemoteLoggingServerPlugin</span> (or
<span
class="code">IRemoteLoggingSink</span>) can receive all the events and
send them to a single log file.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="If I have many processes across
multiple hosts (possibly across multiple time zones) logging to the same file
using the method above, what happens to timestamps?">
<p>
The timestamp is created when
the logging event is created. That is so say,
when the <span
class="code">Debug</span>, <span class="code">Info</span>,
<span class="code">Warn</span>,
<span class="code">Error</span>
or <span
class="code">Fatal</span> method is invoked. This is unaffected by the time at
which they may arrive at a
remote server. Since the timestamps are
stored in UTC format inside the
event, 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.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="When should I log my first
message?">
<p>
The simple answer is as soon as
possible. The long answer is more complex.
</p>
<p>
If you are configuring log4net
programmatically, i.e. by calling the
<span
class="code">XmlConfigurator.Configure</span> method then you should do so
before you begin logging and it
is reasonable to do this very soon after application
start.
</p>
<p>
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 <span
class="code">LogManager.GetLogger</span> is made. It is necessary
that the first call to <span
class="code">LogManager.GetLogger</span> 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.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
</section>
<section name="Customization">
<section name="Can the log output format be
customized?">
<p>
Yes. You can implement the
<span class="code">log4net.Layout.ILayout</span>
interface to create you own
customized log format, or you can extend the
<span
class="code">LayoutSkeleton</span> class which provides a default
implementation of the <span
class="code">ILayout</span> interface.
Appenders can be parameterized
to use the layout of your choice.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Can I write a custom appender?">
<p>
Yes. You can implement the
<span class="code">log4net.Appender.IAppender</span>
interface to create you own
customized appender. We recommend that you extend the
<span
class="code">log4net.Appender.AppenderSkeleton</span> 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 <span
class="code">log4net.Appender.TraceAppender</span> as an
example of the minimum amount
of code required to get an appender working.
</p>
<p>
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:
</p>
<source language="xml"><![CDATA[
<appender name="..." type="MyNamespace.MyAppender, MyAssembly">]]></source>
<p>
The .NET runtime will try to
locate the assembly called <i>MyAssembly</i>.
How .NET locates assemblies is
beyond the scope of this FAQ.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
</section>
<section name="Troubleshooting">
<section id="internalDebug" name="How do I
enable log4net internal debugging?">
<p>
There are several different
ways to enable internal debugging in log4net.
These different methods are
listed below. The preferred method is to specify
the <span
class="code">log4net.Internal.Debug</span> option in the application's
config file.
</p>
<ul>
<li>
<p>
To enable
log4net's internal debug programmatically you need
to set the
<span class="code">log4net.helpers.LogLog.InternalDebugging</span>
property to
<span class="code">true</span>. Obviously the sooner this
is set the more
debug will be produced.
</p>
</li>
<li>
<p>
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 <span
class="code">log4net.Internal.Debug</span>
application
setting must be set to the value <span class="code">true</span>.
For example:
</p>
<source
language="xml"><![CDATA[
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
</configuration>]]></source>
<p>
This setting is
read immediately on startup an will cause all internal
debugging
messages to be emitted.
</p>
</li>
<li>
<p>
To enable
internal debugging from a configuration file, the
<span
class="code">debug</span> attribute on the log4net
configuration
element can be set to the value <span class="code">true</span>.
For example:
</p>
<source
language="xml"><![CDATA[
<log4net debug="true">
... configuration ...
</log4net>]]></source>
<p>
Using this
method does require that your configuration file is located
and loaded,
otherwise the attribute will not be read. If you need to
debug the
process of locating the configuration file then use one of the other
methods for
enabling debugging.
</p>
</li>
</ul>
<p>
Internal debugging messages are
written to the console and to the
<span
class="code">System.Diagnostics.Trace</span>
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 <span
class="code">System.Console.Out</span>. 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
<a
href="http://www.sysinternals.com">http://www.sysinternals.com</a>
may be used to capture these
messages.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section id="trouble-EventLog" name="Why
doesn't the EventLogAppender work?">
<p>
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.
</p>
<p>
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.
</p>
<p>
There are a couple of solutions:
</p>
<ol>
<li>
<p>
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.
</p>
</li>
<li>
<p>
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
<span
class="code">System.Diagnostics.EventLogInstaller</span> in the Microsoft .NET
Framework SDK
for an example of how to create a simple event log installer.
</p>
</li>
</ol>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Why can't I log to a
FileAppender from a web application?">
<p>
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.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="Why doesn't the logging in my
service work?">
<p>
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.
</p>
<p>
A windows service is launched
by windows. The current directory in
a service is set to the windows
system directory (e.g.
<span
class="code">C:\Windows\System32</span>). 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
<span
class="code">AppDomain.BaseDirectory</span>.
Note that the log4net internals
never use the current directory.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="I am having trouble using the
AdoNetAppender to connect to my database?">
<p>
For details on the different
ways in which ADO.NET can connect to a database see:
<a
href="http://msdn.microsoft.com/library/en-us/cpguide/html/cpconadonetconnections.asp">Connecting
to a Data Source Using ADO.NET</a>.
</p>
<p>
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:
<a
href="http://www.microsoft.com/downloads/details.aspx?FamilyID=6ccd8427-1017-4f33-a062-d165078e32b1">ODBC
.NET Data Provider</a>.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
<section name="How do I report bugs?">
<p>
See the <a
href="../../support.html">support</a> page for details.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
</section>
<section name="Miscellaneous">
<section name="How do I make log4net appear in
the Visual Studio Add References dialog?">
<p>
There is a good discussion of
this topic on Robert GcLaws blog:
<a
href="http://weblogs.asp.net/rmclaws/archive/2003/11/15/37743.aspx">Building a
Better Server Control Experience, Part 2</a>.
</p>
</section>
<p><a href="#top">Back to Top</a></p>
</section>
</section>
</body>
</document>