Skip to content

Commit 0929509

Browse files
committed
added first parts of introduction
1 parent b8a46b7 commit 0929509

File tree

3 files changed

+321
-1
lines changed

3 files changed

+321
-1
lines changed

src/site/antora/modules/ROOT/nav.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* xref:download.adoc[]
1919
* xref:development.adoc[]
2020
* xref:manual/index.adoc[]
21+
** xref:manual/introduction.adoc[]
2122
** xref:manual/appenders.adoc[]
2223
** xref:manual/configuration.adoc[]
2324
*** xref:manual/configuration/examples.adoc[]
@@ -43,8 +44,8 @@
4344
** xref:manual/filters.adoc[]
4445
** xref:manual/layouts.adoc[]
4546
** xref:manual/installation.adoc[]
47+
** xref:manual/supported-frameworks.adoc[]
4648
* xref:features.adoc[]
47-
* xref:supported-frameworks.adoc[]
4849
* xref:release-notes.adoc[]
4950
* xref:release-review.adoc[]
5051
* {logging-services-url}/support.html[Support]
Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
////
2+
Licensed to the Apache Software Foundation (ASF) under one or more
3+
contributor license agreements. See the NOTICE file distributed with
4+
this work for additional information regarding copyright ownership.
5+
The ASF licenses this file to You under the Apache License, Version 2.0
6+
(the "License"); you may not use this file except in compliance with
7+
the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
////
17+
18+
= Introduction
19+
20+
[#overview]
21+
== Overview
22+
23+
This document introduces the log4net API, its unique features, and the rationale behind its design.
24+
log4net enables developers to control logging output with fine-grained precision.
25+
It is fully configurable at runtime through external configuration files.
26+
27+
Almost every large application includes some form of logging or tracing system.
28+
Adding log statements is a straightforward and effective method for debugging.
29+
Sometimes it's the only available method, especially in multithreaded or distributed applications.
30+
Traditional debuggers may be limited or unavailable in such environments.
31+
32+
After deployment, logging often becomes the only way to understand application behavior.
33+
Effective logging systems allow administrators to diagnose and resolve issues.
34+
35+
Experience shows that logging is a critical part of the development process.
36+
It provides detailed context about the application's execution.
37+
It operates automatically once integrated into the codebase.
38+
Log output can also be stored persistently for later analysis.
39+
Beyond development, a powerful logging system can also serve as an auditing mechanism.
40+
41+
Logging has trade-offs.
42+
It can reduce performance.
43+
It can produce overwhelming amounts of output.
44+
log4net is designed to minimize these downsides.
45+
It is fast, reliable, and extensible.
46+
The log4net API emphasizes simplicity and ease of use.
47+
48+
[#frameworks]
49+
== Frameworks
50+
51+
log4net is available for several frameworks.
52+
For each supported framework, an assembly targeting that framework is built:
53+
54+
* .NET Standard 2.0 via .NET 8.0
55+
* Microsoft .NET Framework 4.6.2
56+
57+
Not all frameworks are created equal, and some features have been excluded from certain builds.
58+
For more information, see the xref:./supported-frameworks.adoc[] document.
59+
60+
[#main-components]
61+
== Main Components
62+
63+
log4net has three main components:
64+
65+
* loggers - capture and categorize log messages.
66+
67+
* appenders - define where and how log messages are output
68+
69+
* layouts - control the format of log messages.
70+
71+
These components work together to enable developers to log messages according to message type and level.
72+
They also allow controlling at runtime how these messages are formatted and where they are reported.
73+
74+
These components are assisted by filters that control the actions of the appender.
75+
Object renderers are used to turn objects into strings.
76+
77+
[#logger-hierarchy]
78+
== Logger hierarchy
79+
80+
Loggers are named entities, with case-sensitive names that follow a hierarchical structure.
81+
The main advantage of logging APIs over `System.Console.WriteLine` is the ability to disable certain log statements while allowing others to print.
82+
83+
Loggers can have parent-child relationships based on their names.
84+
For example, a logger named `Animals.Carnivora` is the parent of `Animals.Carnivora.Dog`, and `System` is the parent of `System.Text` and ancestor of `System.Text.StringBuilder`.
85+
This hierarchy is similar to .NET's namespace and class structure.
86+
87+
The root logger sits at the top of the hierarchy:
88+
89+
* It always exists
90+
* It cannot be retrieved by name
91+
* It always has an assigned level
92+
93+
Loggers are retrieved using the static `GetLogger` method from the `log4net.LogManager` class.
94+
It can take either a string for the logger name or a `Type` for the desired class.
95+
96+
[source,csharp]
97+
----
98+
namespace log4net
99+
{
100+
public class LogManager
101+
{
102+
public static ILog GetLogger(string name);
103+
public static ILog GetLogger(Type type);
104+
}
105+
}
106+
----
107+
108+
The `GetLogger` method that takes a `Type` parameter uses the fully qualified type name as the name of the logger to retrieve.
109+
110+
These `GetLogger` methods return an `ILog` interface, which is the representation of the logger passed back to the developer.
111+
112+
The `ILog` interface is defined as follows:
113+
114+
[source,csharp]
115+
----
116+
namespace log4net
117+
{
118+
public interface ILog
119+
{
120+
/* Test if a level is enabled for logging */
121+
bool IsDebugEnabled { get; }
122+
bool IsInfoEnabled { get; }
123+
bool IsWarnEnabled { get; }
124+
bool IsErrorEnabled { get; }
125+
bool IsFatalEnabled { get; }
126+
127+
/* Log a message object */
128+
void Debug(object message);
129+
void Info(object message);
130+
void Warn(object message);
131+
void Error(object message);
132+
void Fatal(object message);
133+
134+
/* Log a message object and exception */
135+
void Debug(object message, Exception t);
136+
void Info(object message, Exception t);
137+
void Warn(object message, Exception t);
138+
void Error(object message, Exception t);
139+
void Fatal(object message, Exception t);
140+
141+
/* Log a message string using the System.String.Format syntax */
142+
void DebugFormat(string format, params object[] args);
143+
void InfoFormat(string format, params object[] args);
144+
void WarnFormat(string format, params object[] args);
145+
void ErrorFormat(string format, params object[] args);
146+
void FatalFormat(string format, params object[] args);
147+
148+
/* Log a message string using the System.String.Format syntax and provide a culture / format provider */
149+
void DebugFormat(IFormatProvider provider, string format, params object[] args);
150+
void InfoFormat(IFormatProvider provider, string format, params object[] args);
151+
void WarnFormat(IFormatProvider provider, string format, params object[] args);
152+
void ErrorFormat(IFormatProvider provider, string format, params object[] args);
153+
void FatalFormat(IFormatProvider provider, string format, params object[] args);
154+
}
155+
}
156+
----
157+
158+
[#logger-levels]
159+
== Logger Levels
160+
161+
Loggers may be assigned levels.
162+
Levels are instances of the `log4net.Core.Level` class.
163+
The following levels are defined in order of increasing priority:
164+
165+
* ALL
166+
* DEBUG
167+
* INFO
168+
* WARN
169+
* ERROR
170+
* FATAL
171+
* OFF
172+
173+
If a given logger is not assigned a level, it inherits one from its closest ancestor with an assigned level.
174+
175+
More formally:
176+
177+
[#level-inheritance]
178+
=== Level Inheritance
179+
180+
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.
181+
182+
To ensure that all loggers can eventually inherit a level, the root logger always has an assigned level.
183+
The default value for the root logger is `DEBUG`.
184+
185+
Below are four examples showing various assigned level values and the resulting inherited levels according to the inheritance rule.
186+
187+
[#example1]
188+
==== Example 1: Root Logger Assigned Level
189+
190+
[cols="1,1,1"]
191+
|===
192+
| Logger name | Assigned level | Inherited level
193+
| root | DEBUG | DEBUG
194+
| X | none | DEBUG
195+
| X.Y | none | DEBUG
196+
| X.Y.Z | none | DEBUG
197+
|===
198+
199+
In this example, the root logger is assigned the level `DEBUG`, so all child loggers inherit this level.
200+
201+
[#example2]
202+
==== Example 2: All Loggers Have Assigned Levels
203+
204+
[cols="1,1,1"]
205+
|===
206+
| Logger name | Assigned level | Inherited level
207+
| root | DEBUG | DEBUG
208+
| X | INFO | INFO
209+
| X.Y | WARN | WARN
210+
| X.Y.Z | ERROR | ERROR
211+
|===
212+
213+
Here, each logger has its own assigned level, so no inheritance is needed.
214+
215+
[#example3]
216+
==== Example 3: Some Loggers Inherit Level
217+
218+
[cols="1,1,1"]
219+
|===
220+
| Logger name | Assigned level | Inherited level
221+
| root | DEBUG | DEBUG
222+
| X | INFO | INFO
223+
| X.Y | none | INFO
224+
| X.Y.Z | ERROR | ERROR
225+
|===
226+
227+
In this example, the `X.Y` logger inherits the `INFO` level from its parent `X` logger. The `X.Y.Z` logger has its own assigned level, `ERROR`.
228+
229+
[#example4]
230+
==== Example 4: Some Loggers Inherit from Parent
231+
232+
[cols="1,1,1"]
233+
|===
234+
| Logger name | Assigned level | Inherited level
235+
| root | DEBUG | DEBUG
236+
| X | INFO | INFO
237+
| X.Y | none | INFO
238+
| X.Y.Z | none | INFO
239+
|===
240+
241+
Here, the `X.Y` and `X.Y.Z` loggers inherit the level `INFO` from their parent `X` logger.
242+
243+
[#example-summary]
244+
==== Summary
245+
246+
The idea is that loggers inherit the level of their closest ancestor logger if no level is explicitly assigned. This ensures that you don’t need to manually assign levels to each logger, and the level can propagate upwards in the hierarchy.
247+
248+
[#logging-requests]
249+
=== Logging Requests
250+
251+
Logging requests are made by invoking one of the printing methods of a logger instance (through the log4net.ILog).
252+
253+
The available printing methods are:
254+
255+
* Debug
256+
* Info
257+
* Warn
258+
* Error
259+
* Fatal
260+
261+
By definition, the printing method determines the level of a logging request. For example:
262+
263+
[source,csharp]
264+
----
265+
log.Info("...");
266+
----
267+
268+
This statement represents a logging request with level `INFO`.
269+
270+
A logging request is considered "enabled" if its level is higher than or equal to the level of the logger. Otherwise, the request is "disabled."
271+
272+
If a logger does not have an assigned level, it will inherit one from its closest ancestor in the logger hierarchy.
273+
274+
[#basic-selection-rule]
275+
==== Basic Selection Rule
276+
277+
A log request of level `L` in a logger with (either assigned or inherited, whichever is appropriate) level `K` is enabled if `L >= K`.
278+
279+
This rule is at the heart of log4net. It assumes that levels are ordered. For the standard levels, we have:
280+
281+
* DEBUG < INFO < WARN < ERROR < FATAL
282+
283+
Calling the `log4net.LogManager.GetLogger` method with the same name will always return a reference to the exact same logger object.
284+
285+
For example:
286+
287+
[source,csharp]
288+
----
289+
ILog x = LogManager.GetLogger("wombat");
290+
ILog y = LogManager.GetLogger("wombat");
291+
----
292+
293+
In this case, `x` and `y` refer to exactly the same logger object.
294+
295+
Thus, it is possible to configure a logger and then to retrieve the same instance somewhere else in the code without passing around references.
296+
297+
In fundamental contradiction to biological parenthood, where parents always precede their children, log4net loggers can be created and configured in any order.
298+
299+
In particular, a "parent" logger will find and link to its descendants even if it is instantiated after them.
300+
301+
Configuration of the log4net environment is typically done at application initialization.
302+
The preferred way is by reading a configuration file.
303+
This approach will be discussed shortly.
304+
305+
Log4net makes it easy to name loggers by software component.
306+
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.
307+
308+
This is a useful and straightforward method of defining loggers.
309+
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.
310+
311+
However, this is only one possible, albeit common, strategy for naming loggers.
312+
Log4net does not restrict the possible set of loggers.
313+
The developer is free to name the loggers as desired.
314+
315+
Nevertheless, naming loggers after the class where they are located seems to be the best strategy known so far.
316+
It is simple and obvious to the developers where each log message came from.
317+
318+
Most importantly, it leverages the design of the application to produce the design of the logger hierarchy.
319+
Hopefully, some thought has gone into the design of the application.
File renamed without changes.

0 commit comments

Comments
 (0)