////
    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.
////

= Layouts

An xref:manual/configuration/appenders.adoc[appender] uses a *layout* to encode a LogEvent into a form that meets the needs of whatever will be consuming the log event.
This page will try to answer following questions:

* <<concerns,What are some common concerns shared by all predefined layouts?>>
* <<predefined-layouts,Which layouts does log4net provide?>>

[#concerns]
== Common Concerns

This section outlines some common concerns shared by most predefined layouts in log4net that users should be aware of.

[#structured-logging]
=== Structured Logging

In modern production environments, logs are typically not read from local files by engineers.
Instead, they are sent to log ingestion systems like Elasticsearch, Google Cloud Logging, or similar platforms for observability, metrics, and monitoring purposes.

To support this, logs must be encoded in a machine-readable format — a practice known as *structured logging*.

log4net provides support for structured logging through specialized layouts.
For production use cases, we recommend using either:

* `XmlLayout` — for structured XML output.
* `JsonLayout` — via the external project https://gitlab.com/gdziadkiewicz/log4net.Ext.Json/-/blob/develop/log4net.Ext.Json/Layout/SerializedLayout.cs[log4net.Ext.Json].

These layouts help ensure your logs are compatible with log aggregation and analysis tools.

[#predefined-layouts]
== Predefined Layouts

log4net includes a set of predefined layouts designed to support a variety of common logging scenarios.

[#patternlayout]
=== PatternLayout

`PatternLayout` is a customizable, efficient, and human-readable layout that generates log messages based on a user-defined pattern.
It works similarly to `String.Format()` but provides specialized directives for injecting properties from a `LoggingEvent`.

[IMPORTANT]
====
`PatternLayout` is *not* intended for structured logging.
In production, prefer `XmlLayout` or `JsonLayout` for generating machine-readable logs (e.g., XML or JSON) that can be consumed by log ingestion systems such as Elasticsearch or Google Cloud Logging.
====

A conversion pattern is composed of literal text and conversion specifiers (format control expressions).
For example, the following pattern:

[source,charp]
----
logger.Debug("Woof!");
logger.Warn("Meow!");
----

will yield the output

[source,text]
----
2024-12-21 14:07:41,517 [main] DEBUG Animals.Carnivora.Dog - Woof!
2024-12-21 14:07:41,517 [main] WARN  Animals.Carnivora.Dog - Meow!
----

[#dynamic-pattern-layout]
=== DyamicPatternLayout

The `DynamicPatternLayout` should be used whenever the header or footer needs to include information that may change over time.

Unlike the static `PatternLayout`, which renders headers and footers only once, the `DynamicPatternLayout` re-evaluates its pattern every time it is invoked.
This makes it possible, for example, to include the current date and time in the header or footer—something not possible with the static layout.

The following example shows how to configure the `DynamicPatternLayout`:

[source,xml]
----
<layout type="log4net.Layout.DynamicPatternLayout">
  <header value="Log started at %date%newline" />
  <footer value="Log ended at %date%newline" />
  <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
----

[#layout-list]
=== List of Layouts

[cols="Type,Description"]
|===
|Type |Description

|`log4net.Layout.DynamicPatternLayout`
|Formats the logging event using a pattern string that is re-evaluated on every log event, allowing dynamic values like timestamps in headers or footers.

|`log4net.Layout.ExceptionLayout`
|Outputs only the exception text from the logging event.

|`log4net.Layout.PatternLayout`
|Formats the logging event using a flexible pattern string with various conversion specifiers.

|`log4net.Layout.RawTimeStampLayout`
|Outputs the raw timestamp (as a `DateTime`) from the logging event.

|`log4net.Layout.RawUtcTimeStampLayout`
|Outputs the raw timestamp in UTC from the logging event.

|`log4net.Layout.SimpleLayout`
|Provides a very simple format: `[level] - [message]`.

|`log4net.Layout.XmlLayout`
|Formats the logging event as a basic XML element.

|`log4net.Layout.XmlLayoutSchemaLog4j`
|Formats the logging event as XML compliant with the log4j event DTD.

|===