| <!DOCTYPE html> |
| <!-- |
| | Generated by Apache Maven Doxia Site Renderer 1.9.1 from src/site/asciidoc/manual/json-template-layout.adoc.vm at 2021-03-07 |
| | Rendered using Apache Maven Fluido Skin 1.8 |
| --> |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <meta name="generator" content="Apache Maven Doxia Site Renderer 1.9.1" /> |
| <title>Log4j – </title> |
| <link rel="stylesheet" href="../css/apache-maven-fluido-1.8.min.css" /> |
| <link rel="stylesheet" href="../css/site.css" /> |
| <link rel="stylesheet" href="../css/print.css" media="print" /> |
| <script src="../js/apache-maven-fluido-1.8.min.js"></script> |
| </head> |
| <body class="topBarDisabled"> |
| <div class="container-fluid"> |
| <header> |
| <div id="banner"> |
| <div class="pull-left"><a href="http://logging.apache.org" id="bannerLeft"><img src="../images/ls-logo.jpg" alt=""/></a></div> |
| <div class="pull-right"><a href="http://logging.apache.org/log4j/2.x" id="bannerRight"><img src="../images/logo.png" alt=""/></a></div> |
| <div class="clear"><hr/></div> |
| </div> |
| |
| <div id="breadcrumbs"> |
| <ul class="breadcrumb"> |
| <li id="publishDate">Last Published: 2021-03-07<span class="divider">|</span> |
| </li> |
| <li id="projectVersion">Version: 2.14.1</li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://github.com/apache/logging-log4j2" class="externalLink" title="GitHub">GitHub</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://analysis.apache.org/dashboard/index/org.apache.logging.log4j:log4j" class="externalLink" title="Sonar">Sonar</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="../../../" title="Logging Services">Logging Services</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://www.apache.org/" class="externalLink" title="Apache">Apache</a></li> |
| <li class="pull-right"><a href="https://cwiki.apache.org/confluence/display/LOGGING/Log4j" class="externalLink" title="Logging Wiki">Logging Wiki</a></li> |
| </ul> |
| </div> |
| </header> |
| <div class="row-fluid"> |
| <header id="leftColumn" class="span2"> |
| <nav class="well sidebar-nav"> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/home.png" alt="Apache Log4j™ 2" border="0"/> Apache Log4j™ 2</li> |
| <li><a href="../index.html" title="About"><span class="none"></span>About</a></li> |
| <li><a href="../download.html" title="Download"><span class="none"></span>Download</a></li> |
| <li><a href="../javadoc.html" title="Javadoc"><span class="icon-chevron-right"></span>Javadoc</a></li> |
| <li><a href="../maven-artifacts.html" title="Maven, Ivy, Gradle Artifacts"><span class="icon-chevron-right"></span>Maven, Ivy, Gradle Artifacts</a></li> |
| <li><a href="../runtime-dependencies.html" title="Runtime Dependencies"><span class="none"></span>Runtime Dependencies</a></li> |
| <li><a href="../changelog.html" title="Changelog"><span class="none"></span>Changelog</a></li> |
| <li><a href="../faq.html" title="FAQ"><span class="none"></span>FAQ</a></li> |
| <li><a href="../performance.html" title="Performance"><span class="icon-chevron-right"></span>Performance</a></li> |
| <li><a href="../articles.html" title="Articles and Tutorials"><span class="none"></span>Articles and Tutorials</a></li> |
| <li><a href="../security.html" title="Security"><span class="none"></span>Security</a></li> |
| <li><a href="../support.html" title="Support"><span class="none"></span>Support</a></li> |
| <li><a href="../thanks.html" title="Thanks"><span class="none"></span>Thanks</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/pencil.png" alt="For Contributors" border="0"/> For Contributors</li> |
| <li><a href="../build.html" title="Building Log4j from Source"><span class="none"></span>Building Log4j from Source</a></li> |
| <li><a href="../guidelines.html" title="Guidelines"><span class="none"></span>Guidelines</a></li> |
| <li><a href="../javastyle.html" title="Style Guide"><span class="none"></span>Style Guide</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/book.png" alt="Manual" border="0"/> Manual</li> |
| <li><a href="../manual/index.html" title="Introduction"><span class="none"></span>Introduction</a></li> |
| <li><a href="../manual/architecture.html" title="Architecture"><span class="none"></span>Architecture</a></li> |
| <li><a href="../manual/compatibility.html" title="Log4j 1.x Compatibility"><span class="none"></span>Log4j 1.x Compatibility</a></li> |
| <li><a href="../manual/migration.html" title="Log4j 1.x Migration"><span class="none"></span>Log4j 1.x Migration</a></li> |
| <li><a href="../manual/api.html" title="Java API"><span class="icon-chevron-right"></span>Java API</a></li> |
| <li><a href="../manual/scala-api.html" title="Scala API"><span class="none"></span>Scala API</a></li> |
| <li><a href="../manual/configuration.html" title="Configuration"><span class="icon-chevron-right"></span>Configuration</a></li> |
| <li><a href="../manual/usage.html" title="Usage"><span class="icon-chevron-right"></span>Usage</a></li> |
| <li><a href="../manual/webapp.html" title="Web Applications and JSPs"><span class="icon-chevron-right"></span>Web Applications and JSPs</a></li> |
| <li><a href="../manual/lookups.html" title="Lookups"><span class="icon-chevron-right"></span>Lookups</a></li> |
| <li><a href="../manual/appenders.html" title="Appenders"><span class="icon-chevron-right"></span>Appenders</a></li> |
| <li><a href="../manual/layouts.html" title="Layouts"><span class="icon-chevron-down"></span>Layouts</a> |
| <ul class="nav nav-list"> |
| <li><a href="../manual/layouts.html#CSVLayouts" title="CSV"><span class="none"></span>CSV</a></li> |
| <li><a href="../manual/layouts.html#GELFLayout" title="GELF"><span class="none"></span>GELF</a></li> |
| <li><a href="../manual/layouts.html#HTMLLayout" title="HTML"><span class="none"></span>HTML</a></li> |
| <li><a href="../manual/layouts.html#JSONLayout" title="JSON"><span class="none"></span>JSON</a></li> |
| <li class="active"><a href="#"><span class="none"></span>JSON Template</a></li> |
| <li><a href="../manual/layouts.html#PatternLayout" title="Pattern"><span class="none"></span>Pattern</a></li> |
| <li><a href="../manual/layouts.html#RFC5424Layout" title="RFC-5424"><span class="none"></span>RFC-5424</a></li> |
| <li><a href="../manual/layouts.html#SerializedLayout" title="Serialized"><span class="none"></span>Serialized</a></li> |
| <li><a href="../manual/layouts.html#SyslogLayout" title="Syslog"><span class="none"></span>Syslog</a></li> |
| <li><a href="../manual/layouts.html#XMLLayout" title="XML"><span class="none"></span>XML</a></li> |
| <li><a href="../manual/layouts.html#YamlLayout" title="YAML"><span class="none"></span>YAML</a></li> |
| <li><a href="../manual/layouts.html#LocationInformation" title="Location Information"><span class="none"></span>Location Information</a></li> |
| </ul></li> |
| <li><a href="../manual/filters.html" title="Filters"><span class="icon-chevron-right"></span>Filters</a></li> |
| <li><a href="../manual/async.html" title="Async Loggers"><span class="icon-chevron-right"></span>Async Loggers</a></li> |
| <li><a href="../manual/garbagefree.html" title="Garbage-free Logging"><span class="icon-chevron-right"></span>Garbage-free Logging</a></li> |
| <li><a href="../manual/jmx.html" title="JMX"><span class="none"></span>JMX</a></li> |
| <li><a href="../manual/logsep.html" title="Logging Separation"><span class="none"></span>Logging Separation</a></li> |
| <li><a href="../manual/extending.html" title="Extending Log4j"><span class="icon-chevron-right"></span>Extending Log4j</a></li> |
| <li><a href="../manual/plugins.html" title="Plugins"><span class="icon-chevron-right"></span>Plugins</a></li> |
| <li><a href="../manual/customconfig.html" title="Programmatic Log4j Configuration"><span class="icon-chevron-right"></span>Programmatic Log4j Configuration</a></li> |
| <li><a href="../manual/customloglevels.html" title="Custom Log Levels"><span class="icon-chevron-right"></span>Custom Log Levels</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/tag.png" alt="Related Projects" border="0"/> Related Projects</li> |
| <li><a href="http://logging.apache.org/log4j/scala/index.html" class="externalLink" title="Log4j-Scala"><span class="none"></span>Log4j-Scala</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/link.png" alt="Legacy Sites" border="0"/> Legacy Sites</li> |
| <li><a href="http://logging.apache.org/log4j/1.2/" class="externalLink" title="Log4j 1.2 - End of Life"><span class="none"></span>Log4j 1.2 - End of Life</a></li> |
| <li><a href="http://logging.apache.org/log4j/log4j-2.3/" class="externalLink" title="Log4j 2.3 - Java 6"><span class="none"></span>Log4j 2.3 - Java 6</a></li> |
| <li><a href="http://logging.apache.org/log4j/log4j-2.12.1" class="externalLink" title="Log4j 2.12.1 - Java 7"><span class="none"></span>Log4j 2.12.1 - Java 7</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/cog.png" alt="Components" border="0"/> Components</li> |
| <li><a href="../log4j-api/index.html" title="API"><span class="none"></span>API</a></li> |
| <li><a href="../log4j-core/index.html" title="Implementation"><span class="none"></span>Implementation</a></li> |
| <li><a href="../log4j-jcl/index.html" title="Commons Logging Bridge"><span class="none"></span>Commons Logging Bridge</a></li> |
| <li><a href="../log4j-1.2-api/index.html" title="Log4j 1.2 API"><span class="none"></span>Log4j 1.2 API</a></li> |
| <li><a href="../log4j-slf4j-impl/index.html" title="SLF4J Binding"><span class="none"></span>SLF4J Binding</a></li> |
| <li><a href="../log4j-jul/index.html" title="JUL Adapter"><span class="none"></span>JUL Adapter</a></li> |
| <li><a href="../log4j-jpl/index.html" title="JDK Platform Logger"><span class="none"></span>JDK Platform Logger</a></li> |
| <li><a href="../log4j-to-slf4j/index.html" title="Log4j 2 to SLF4J Adapter"><span class="none"></span>Log4j 2 to SLF4J Adapter</a></li> |
| <li><a href="../log4j-flume-ng/index.html" title="Apache Flume Appender"><span class="none"></span>Apache Flume Appender</a></li> |
| <li><a href="../log4j-taglib/index.html" title="Log4j Tag Library"><span class="none"></span>Log4j Tag Library</a></li> |
| <li><a href="../log4j-jmx-gui/index.html" title="Log4j JMX GUI"><span class="none"></span>Log4j JMX GUI</a></li> |
| <li><a href="../log4j-web/index.html" title="Log4j Web Application Support"><span class="none"></span>Log4j Web Application Support</a></li> |
| <li><a href="../log4j-appserver/index.html" title="Log4j Application Server Integration"><span class="none"></span>Log4j Application Server Integration</a></li> |
| <li><a href="../log4j-couchdb/index.html" title="Log4j CouchDB appender"><span class="none"></span>Log4j CouchDB appender</a></li> |
| <li><a href="../log4j-mongodb3/index.html" title="Log4j MongoDB3 appender"><span class="none"></span>Log4j MongoDB3 appender</a></li> |
| <li><a href="../log4j-mongodb4/index.html" title="Log4j MongoDB4 appender"><span class="none"></span>Log4j MongoDB4 appender</a></li> |
| <li><a href="../log4j-cassandra/index.html" title="Log4j Cassandra appender"><span class="none"></span>Log4j Cassandra appender</a></li> |
| <li><a href="../log4j-iostreams/index.html" title="Log4j IO Streams"><span class="none"></span>Log4j IO Streams</a></li> |
| <li><a href="../log4j-liquibase/index.html" title="Log4j Liquibase Binding"><span class="none"></span>Log4j Liquibase Binding</a></li> |
| <li><a href="../log4j-docker/index.html" title="Log4j Docker Support"><span class="none"></span>Log4j Docker Support</a></li> |
| <li><a href="../log4j-spring-cloud-config/log4j-spring-cloud-config-client/index.html" title="Log4j Spring Cloud Config Client"><span class="none"></span>Log4j Spring Cloud Config Client</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/info.png" alt="Project Information" border="0"/> Project Information</li> |
| <li><a href="../dependency-convergence.html" title="Dependency Convergence"><span class="none"></span>Dependency Convergence</a></li> |
| <li><a href="../dependency-management.html" title="Dependency Management"><span class="none"></span>Dependency Management</a></li> |
| <li><a href="../team-list.html" title="Project Team"><span class="none"></span>Project Team</a></li> |
| <li><a href="../mail-lists.html" title="Mailing Lists"><span class="none"></span>Mailing Lists</a></li> |
| <li><a href="../issue-tracking.html" title="Issue Tracking"><span class="none"></span>Issue Tracking</a></li> |
| <li><a href="../license.html" title="Project License"><span class="none"></span>Project License</a></li> |
| <li><a href="../source-repository.html" title="Source Repository"><span class="none"></span>Source Repository</a></li> |
| <li><a href="../project-summary.html" title="Project Summary"><span class="none"></span>Project Summary</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/layers.png" alt="Project Reports" border="0"/> Project Reports</li> |
| <li><a href="../changes-report.html" title="Changes Report"><span class="none"></span>Changes Report</a></li> |
| <li><a href="../jira-report.html" title="JIRA Report"><span class="none"></span>JIRA Report</a></li> |
| <li><a href="../rat-report.html" title="RAT Report"><span class="none"></span>RAT Report</a></li> |
| </ul> |
| </nav> |
| <div class="well sidebar-nav"> |
| <hr /> |
| <div id="poweredBy"> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" /></a> |
| </div> |
| </div> |
| </header> |
| <main id="bodyColumn" class="span10" > |
| <h1>JSON Template Layout</h1> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p><code>JsonTemplateLayout</code> is a customizable, efficient, and garbage-free JSON |
| emitting layout. It encodes <code>LogEvent</code>s according to the structure described |
| by the JSON template provided. In a nutshell, it shines with its</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Customizable JSON structure (see <code>eventTemplate[Uri]</code> and |
| <code>stackTraceElementTemplate[Uri]</code> parameters)</p> |
| </li> |
| <li> |
| <p>Customizable timestamp formatting (see <code>timestamp</code> parameter)</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="usage">Usage</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Adding <code>log4j-layout-template-json</code> artifact to your list of dependencies is |
| enough to enable access to <code>JsonTemplateLayout</code> in your Log4j configuration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.apache.logging.log4j</groupId> |
| <artifactId>log4j-layout-template-json</artifactId> |
| <version>2.14.1</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For instance, given the following JSON template modelling |
| <a href="https://github.com/logstash/log4j-jsonevent-layout">the official Logstash |
| <code>JSONEventLayoutV1</code></a> (accessible via <code>classpath:LogstashJsonEventLayoutV1.json</code>)</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "mdc": { |
| "$resolver": "mdc" |
| }, |
| "exception": { |
| "exception_class": { |
| "$resolver": "exception", |
| "field": "className" |
| }, |
| "exception_message": { |
| "$resolver": "exception", |
| "field": "message" |
| }, |
| "stacktrace": { |
| "$resolver": "exception", |
| "field": "stackTrace", |
| "stackTrace": { |
| "stringified": true |
| } |
| } |
| }, |
| "line_number": { |
| "$resolver": "source", |
| "field": "lineNumber" |
| }, |
| "class": { |
| "$resolver": "source", |
| "field": "className" |
| }, |
| "@version": 1, |
| "source_host": "${hostName}", |
| "message": { |
| "$resolver": "message", |
| "stringified": true |
| }, |
| "thread_name": { |
| "$resolver": "thread", |
| "field": "name" |
| }, |
| "@timestamp": { |
| "$resolver": "timestamp" |
| }, |
| "level": { |
| "$resolver": "level", |
| "field": "name" |
| }, |
| "file": { |
| "$resolver": "source", |
| "field": "fileName" |
| }, |
| "method": { |
| "$resolver": "source", |
| "field": "methodName" |
| }, |
| "logger_name": { |
| "$resolver": "logger", |
| "field": "name" |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>in combination with the below <code>log4j2.xml</code> configuration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"/></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>or with the below <code>log4j2.properties</code> configuration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-ini" data-lang="ini">appender.console.json.type = JsonTemplateLayout |
| appender.console.json.eventTemplateUri = classpath:LogstashJsonEventLayoutV1.json</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><code>JsonTemplateLayout</code> emits JSON strings as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "exception": { |
| "exception_class": "java.lang.RuntimeException", |
| "exception_message": "test", |
| "stacktrace": "java.lang.RuntimeException: test\n\tat org.apache.logging.log4j.JsonTemplateLayoutDemo.main(JsonTemplateLayoutDemo.java:11)\n" |
| }, |
| "line_number": 12, |
| "class": "org.apache.logging.log4j.JsonTemplateLayoutDemo", |
| "@version": 1, |
| "source_host": "varlik", |
| "message": "Hello, error!", |
| "thread_name": "main", |
| "@timestamp": "2017-05-25T19:56:23.370+02:00", |
| "level": "ERROR", |
| "file": "JsonTemplateLayoutDemo.java", |
| "method": "main", |
| "logger_name": "org.apache.logging.log4j.JsonTemplateLayoutDemo" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="layout-config">Layout Configuration</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p><code>JsonTemplateLayout</code> is configured with the following parameters:</p> |
| </div> |
| <table class="tableblock frame-all grid-all spread"> |
| <caption class="title">Table 1. <code>JsonTemplateLayout</code> parameters</caption> |
| <colgroup> |
| <col style="width: 16.6666%;"/> |
| <col style="width: 16.6666%;"/> |
| <col style="width: 66.6668%;"/> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>Parameter Name</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>Type</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>charset</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>Charset</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>Charset</code> used for <code>String</code> encoding</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>locationInfoEnabled</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">toggles access to the <code>LogEvent</code> source; file name, line number, etc. |
| (defaults to <code>false</code> set by <code>log4j.layout.jsonTemplate.locationInfoEnabled</code> |
| property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>stackTraceEnabled</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">toggles access to the stack traces (defaults to <code>true</code> set by |
| <code>log4j.layout.jsonTemplate.stackTraceEnabled</code> property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>eventTemplate</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">inline JSON template for rendering <code>LogEvent</code>s (has priority over |
| <code>eventTemplateUri</code>, defaults to <code>null</code> set by |
| <code>log4j.layout.jsonTemplate.eventTemplate</code> property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>eventTemplateUri</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">URI pointing to the JSON template for rendering <code>LogEvent</code>s (defaults to |
| <code>classpath:EcsLayout.json</code> set by <code>log4j.layout.jsonTemplate.eventTemplateUri</code> |
| property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>eventTemplateRootObjectKey</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">if given, puts the event template into a JSON object composed of a single |
| member with the given key (defaults to <code>null</code> set by |
| <code>log4j.layout.jsonTemplate.eventTemplateRootObjectKey</code> |
| property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>eventTemplateAdditionalFields</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>EventTemplateAdditionalField[]</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">additional key-value pairs appended to the root of the event template</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>stackTraceElementTemplate</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">inline JSON template for rendering <code>StackTraceElement</code>s (has priority over |
| <code>stackTraceElementTemplateUri</code>, defaults to <code>null</code> set by |
| <code>log4j.layout.jsonTemplate.stackTraceElementTemplate</code> property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>stackTraceElementTemplateUri</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JSON template for rendering <code>StackTraceElement</code>s (defaults to |
| <code>classpath:StackTraceElementLayout.json</code> set by |
| <code>log4j.layout.jsonTemplate.stackTraceElementTemplateUri</code> property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>eventDelimiter</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">delimiter used for separating emitted <code>LogEvent</code>s (defaults to |
| <code>System.lineSeparator()</code> set by <code>log4j.layout.jsonTemplate.eventDelimiter</code> |
| property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>nullEventDelimiterEnabled</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">append <code>\0</code> (<code>null</code>) character to the end of every emitted <code>eventDelimiter</code> |
| (defaults to <code>false</code> set by |
| <code>log4j.layout.jsonTemplate.nullEventDelimiterEnabled</code> property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>maxStringLength</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>int</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">truncate string values longer than the specified limit (defaults to 16384 set |
| by <code>log4j.layout.jsonTemplate.maxStringLength</code> property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>truncatedStringSuffix</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">suffix to append to strings truncated due to exceeding <code>maxStringLength</code> |
| (defaults to <code>…</code> set by <code>log4j.layout.jsonTemplate.truncatedStringSuffix</code> |
| property)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>recyclerFactory</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>RecyclerFactory</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">recycling strategy that can either be <code>dummy</code>, <code>threadLocal</code>, or <code>queue</code> |
| (set by <code>log4j.layout.jsonTemplate.recyclerFactory</code> property)</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect2"> |
| <h3 id="additional-event-template-fields">Additonal event template fields</h3> |
| <div class="paragraph"> |
| <p>Additional event template fields are a convenient short-cut to add custom fields |
| to a template or override the existing ones. Following configuration overrides |
| the <code>host</code> field of the <code>GelfLayout.json</code> template and adds two new custom |
| fields:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="title">XML configuration with additional fields</div> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><JsonTemplateLayout eventTemplateUri="classpath:GelfLayout.json"> |
| <EventTemplateAdditionalField key="host" value="www.apache.org"/> |
| <EventTemplateAdditionalField key="_serviceName" value="auth-service"/> |
| <EventTemplateAdditionalField key="_containerId" value="6ede3f0ca7d9"/> |
| </JsonTemplateLayout></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The default <code>format</code> for the added new fields are <code>String</code>. |
| One can also provide JSON-formatted additional fields:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="title">XML-formatted configuration with JSON-formatted additional fields</div> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><JsonTemplateLayout eventTemplateUri="classpath:GelfLayout.json"> |
| <EventTemplateAdditionalField |
| key="marker" |
| format="JSON" |
| value='{"$resolver": "marker", "field": "name"}'/> |
| <EventTemplateAdditionalField |
| key="aNumber" |
| format="JSON" |
| value="1"/> |
| <EventTemplateAdditionalField |
| key="aList" |
| format="JSON" |
| value='[1, 2, "three"]'/> |
| </JsonTemplateLayout></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Additional event template fields can very well be introduced using properties-, |
| YAML-, and JSON-formatted configurations:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="title">Properties-formatted configuration with JSON-formatted additional fields</div> |
| <div class="content"> |
| <pre class="highlight"><code class="language-properties" data-lang="properties">appender.console.layout.type = JsonTemplateLayout |
| appender.console.layout.eventTemplateUri = classpath:GelfLayout.json |
| appender.console.layout.eventTemplateAdditionalField[0].type = EventTemplateAdditionalField |
| appender.console.layout.eventTemplateAdditionalField[0].key = marker |
| appender.console.layout.eventTemplateAdditionalField[0].value = {"$resolver": "marker", "field": "name"} |
| appender.console.layout.eventTemplateAdditionalField[0].format = JSON |
| appender.console.layout.eventTemplateAdditionalField[1].type = EventTemplateAdditionalField |
| appender.console.layout.eventTemplateAdditionalField[1].key = aNumber |
| appender.console.layout.eventTemplateAdditionalField[1].value = 1 |
| appender.console.layout.eventTemplateAdditionalField[1].format = JSON |
| appender.console.layout.eventTemplateAdditionalField[2].type = EventTemplateAdditionalField |
| appender.console.layout.eventTemplateAdditionalField[2].key = aList |
| appender.console.layout.eventTemplateAdditionalField[2].value = [1, 2, "three"] |
| appender.console.layout.eventTemplateAdditionalField[2].format = JSON</code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="title">YAML-formatted configuration with JSON-formatted additional fields</div> |
| <div class="content"> |
| <pre class="highlight"><code class="language-yaml" data-lang="yaml">JsonTemplateLayout: |
| eventTemplateAdditionalField: |
| - key: "marker" |
| value: '{"$resolver": "marker", "field": "name"}' |
| format: "JSON" |
| - key: "aNumber" |
| value: "1" |
| format: "JSON" |
| - key: "aList" |
| value: '[1, 2, "three"]' |
| format: "JSON"</code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="title">JSON-formatted configuration with JSON-formatted additional fields</div> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "JsonTemplateLayout": { |
| "eventTemplateAdditionalField": [ |
| { |
| "key": "marker", |
| "value": "{\"$resolver\": \"marker\", \"field\": \"name\"}", |
| "format": "JSON" |
| }, |
| { |
| "key": "aNumber", |
| "value": "1", |
| "format": "JSON" |
| }, |
| { |
| "key": "aList", |
| "value": "[1, 2, \"three\"]", |
| "format": "JSON" |
| } |
| ] |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="recycling-strategy">Recycling strategy</h3> |
| <div class="paragraph"> |
| <p><code>RecyclerFactory</code> plays a crucial role for determining the memory footprint of |
| the layout. Template resolvers employ it to create recyclers for objects that |
| they can reuse. The function of each <code>RecyclerFactory</code> and when one should |
| prefer one over another is explained below:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>dummy</code> performs no recycling, hence each recycling attempt will result in a |
| new instance. This will obviously create a load on the garbage-collector. It |
| is a good choice for applications with low and medium log rate.</p> |
| </li> |
| <li> |
| <p><code>threadLocal</code> performs the best, since every instance is stored in |
| <code>ThreadLocal</code>s and accessed without any synchronization cost. Though this |
| might not be a desirable option for applications running with hundreds of |
| threads or more, e.g., a web servlet.</p> |
| </li> |
| <li> |
| <p><code>queue</code> is the best of both worlds. It allows recycling of objects up to a |
| certain number (<code>capacity</code>). When this limit is exceeded due to excessive |
| concurrent load (e.g., <code>capacity</code> is 50 but there are 51 threads concurrently |
| trying to log), it starts allocating. <code>queue</code> is a good strategy where |
| <code>threadLocal</code> is not desirable.</p> |
| <div class="paragraph"> |
| <p><code>queue</code> also accepts optional <code>supplier</code> (of type <code>java.util.Queue</code>, defaults to |
| <code>org.jctools.queues.MpmcArrayQueue.new</code> if JCTools is in the classpath; |
| otherwise <code>java.util.concurrent.ArrayBlockingQueue.new</code>) and <code>capacity</code> (of |
| type <code>int</code>, defaults to <code>max(8,2*cpuCount+1)</code>) parameters:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>queue:supplier=org.jctools.queues.MpmcArrayQueue.new |
| queue:capacity=10 |
| queue:supplier=java.util.concurrent.ArrayBlockingQueue.new,capacity=50</code></pre> |
| </div> |
| </div> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The default <code>RecyclerFactory</code> is <code>threadLocal</code>, if |
| <code>log4j2.enable.threadlocals=true</code>; otherwise, <code>queue</code>.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="template-config">Template Configuration</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Templates are configured by means of the following <code>JsonTemplateLayout</code> |
| parameters:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>eventTemplate[Uri]</code> (for serializing <code>LogEvent</code>s)</p> |
| </li> |
| <li> |
| <p><code>stackTraceElementTemplate[Uri]</code> (for serializing <code>StackStraceElement</code>s)</p> |
| </li> |
| <li> |
| <p><code>eventTemplateAdditionalFields</code> (for extending the used event template)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect2"> |
| <h3 id="event-templates">Event Templates</h3> |
| <div class="paragraph"> |
| <p><code>eventTemplate[Uri]</code> describes the JSON structure <code>JsonTemplateLayout</code> uses to |
| serialize <code>LogEvent</code>s. The default configuration (accessible by |
| <code>log4j.layout.jsonTemplate.eventTemplate[Uri]</code> property) is set to |
| <code>classpath:EcsLayout.json</code> provided by the <code>log4j-layout-template-json</code> |
| artifact:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "@timestamp": { |
| "$resolver": "timestamp", |
| "pattern": { |
| "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", |
| "timeZone": "UTC" |
| } |
| }, |
| "log.level": { |
| "$resolver": "level", |
| "field": "name" |
| }, |
| "message": { |
| "$resolver": "message", |
| "stringified": true |
| }, |
| "process.thread.name": { |
| "$resolver": "thread", |
| "field": "name" |
| }, |
| "log.logger": { |
| "$resolver": "logger", |
| "field": "name" |
| }, |
| "labels": { |
| "$resolver": "mdc", |
| "flatten": true, |
| "stringified": true |
| }, |
| "tags": { |
| "$resolver": "ndc" |
| }, |
| "error.type": { |
| "$resolver": "exception", |
| "field": "className" |
| }, |
| "error.message": { |
| "$resolver": "exception", |
| "field": "message" |
| }, |
| "error.stack_trace": { |
| "$resolver": "exception", |
| "field": "stackTrace", |
| "stackTrace": { |
| "stringified": true |
| } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><code>log4j-layout-template-json</code> artifact contains the following predefined event |
| templates:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-template-json/src/main/resources/EcsLayout.json"><code>EcsLayout.json</code></a> |
| described by <a href="https://www.elastic.co/guide/en/ecs/current/ecs-reference.html">the Elastic Common Schema (ECS) specification</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-template-json/src/main/resources/LogstashJsonEventLayoutV1.json"><code>LogstashJsonEventLayoutV1.json</code></a> |
| described in <a href="https://github.com/logstash/log4j-jsonevent-layout">Logstash |
| <code>json_event</code> pattern for log4j</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-template-json/src/main/resources/GelfLayout.json"><code>GelfLayout.json</code></a> |
| described by <a href="https://docs.graylog.org/en/3.1/pages/gelf.html#gelf-payload-specification">the |
| Graylog Extended Log Format (GELF) payload specification</a> with additional |
| <code>_thread</code> and <code>_logger</code> fields. (Here it is advised to override the obligatory |
| <code>host</code> field with a user provided constant via <code>eventTemplateAdditionalFields</code> |
| to avoid <code>hostName</code> property lookup at runtime, which incurs an extra cost.)</p> |
| </li> |
| <li> |
| <p><a href="https://github.com/apache/logging-log4j2/tree/master/log4j-layout-template-json/src/main/resources/JsonLayout.json"><code>JsonLayout.json</code></a> |
| providing the exact JSON structure generated by <a href="layouts.html#JSONLayout"><code>JsonLayout</code></a> |
| with the exception of <code>thrown</code> field. (<code>JsonLayout</code> serializes the <code>Throwable</code> |
| as is via Jackson <code>ObjectMapper</code>, whereas <code>JsonLayout.json</code> template of |
| <code>JsonTemplateLayout</code> employs the <code>StackTraceElementLayout.json</code> template |
| for stack traces to generate a document-store-friendly flat structure.)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="event-template-resolvers">Event Template Resolvers</h4> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-endOfBatch"><code>endOfBatch</code></h5> |
| <div class="paragraph"> |
| <p>Resolves <code>logEvent.isEndOfBatch()</code> boolean flag:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "endOfBatch" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-exception"><code>exception</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = field , [ stringified ] , [ stackTrace ] |
| field = "field" -> ( "className" \| "message" \| "stackTrace" ) |
| |
| stackTrace = "stackTrace" -> stringified |
| stringified = "stringified" -> ( boolean \| truncation ) |
| truncation = "truncation" -> ( |
| [ suffix ] |
| , [ pointMatcherStrings ] |
| , [ pointMatcherRegexes ] |
| ) |
| suffix = "suffix" -> string |
| pointMatcherStrings = "pointMatcherStrings" -> string[] |
| pointMatcherRegexes = "pointMatcherRegexes" -> string[]</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves fields of the <code>Throwable</code> returned by <code>logEvent.getThrown()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>stringified</code> is set to <code>false</code> by default. <code>stringified</code> at the root level is |
| <strong>deprecated</strong> in favor of <code>stackTrace.stringified</code>, which has precedence if both |
| are provided.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>pointMatcherStrings</code> and <code>pointMatcherRegexes</code> enable the truncation of |
| stringified stack traces after the given matching point. If both parameters are |
| provided, <code>pointMatcherStrings</code> will be checked first.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a stringified stack trace truncation takes place, it will be indicated with |
| <code>suffix</code>, which by default is set to the configured <code>truncatedStringSuffix</code> in |
| the layout, unless explicitly provided.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that this resolver is toggled by |
| <code>log4j.layout.jsonTemplate.stackTraceEnabled</code> property.</p> |
| </div> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <div class="title">Warning</div> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Since <code>Throwable#getStackTrace()</code> clones the original <code>StackTraceElement[]</code>, |
| access to (and hence rendering of) stack traces are not garbage-free.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each <code>pointMatcherRegexes</code> item triggers a <code>Pattern#matcher()</code> call, which is |
| not garbage-free either.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve <code>logEvent.getThrown().getClass().getCanonicalName()</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "exception", |
| "field": "className" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the stack trace into a list of <code>StackTraceElement</code> objects:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "exception", |
| "field": "stackTrace" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the stack trace into a string field:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "exception", |
| "field": "stackTrace", |
| "stackTrace": { |
| "stringified": true |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the stack trace into a string field such that the content will be |
| truncated by the given point matcher:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "exception", |
| "field": "stackTrace", |
| "stackTrace": { |
| "stringified": { |
| "truncation": { |
| "suffix": ">", |
| "pointMatcherStrings": ["at javax.servlet.http.HttpServlet.service"] |
| } |
| } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-exceptionRootCause"><code>exceptionRootCause</code></h5> |
| <div class="paragraph"> |
| <p>Resolves the fields of the innermost <code>Throwable</code> returned by |
| <code>logEvent.getThrown()</code>. Its syntax and garbage-footprint are identical to the |
| <a href="#event-template-exception"><code>exception</code></a> resolver.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-level"><code>level</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = field , [ severity ] |
| field = "field" -> ( "name" | "severity" ) |
| severity = severity-field |
| severity-field = "field" -> ( "keyword" | "code" )</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves the fields of the <code>logEvent.getLevel()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the level name:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "level", |
| "field": "name" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the <a href="https://en.wikipedia.org/wiki/Syslog#Severity_levels">Syslog severity</a> |
| keyword:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "level", |
| "field": "severity", |
| "severity": { |
| "field": "keyword" |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the <a href="https://en.wikipedia.org/wiki/Syslog#Severity_levels">Syslog severity</a> |
| code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "level", |
| "field": "severity", |
| "severity": { |
| "field": "code" |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-logger"><code>logger</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = "field" -> ( "name" | "fqcn" )</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves <code>logEvent.getLoggerFqcn()</code> and <code>logEvent.getLoggerName()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the logger name:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "logger", |
| "field": "name" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the logger’s fully qualified class name:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "logger", |
| "field": "fqcn" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-main"><code>main</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = ( index | key ) |
| index = "index" -> number |
| key = "key" -> string</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Performs <a href="lookups.html#AppMainArgsLookup">Main Argument Lookup</a> for the |
| given <code>index</code> or <code>key</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the 1st <code>main()</code> method argument:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "main", |
| "index": 0 |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the argument coming right after <code>--userId</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "main", |
| "key": "--userId" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-map"><code>map</code></h5> |
| <div class="paragraph"> |
| <p>Resolves <code>MapMessage</code>s. See <a href="#map-resolver-template">Map Resolver Template</a> |
| for details.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-mdc"><code>mdc</code></h5> |
| <div class="paragraph"> |
| <p>Resolves Mapped Diagnostic Context (MDC), aka. Thread Context Data. See |
| <a href="#map-resolver-template">Map Resolver Template</a> for details.</p> |
| </div> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <div class="title">Warning</div> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p><code>log4j2.garbagefreeThreadContextMap</code> flag needs to be turned on to iterate |
| the map without allocations.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-message"><code>message</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = [ stringified ] , [ fallbackKey ] |
| stringified = "stringified" -> boolean |
| fallbackKey = "fallbackKey" -> string</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves <code>logEvent.getMessage()</code>.</p> |
| </div> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <div class="title">Warning</div> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>For simple string messages, the resolution is performed without allocations. |
| For <code>ObjectMessage</code>s and <code>MultiformatMessage</code>s, it depends.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the message into a string:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "message", |
| "stringified": true |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the message such that if it is an <code>ObjectMessage</code> or a |
| <code>MultiformatMessage</code> with JSON support, its type (string, list, object, etc.) |
| will be retained:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "message" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Given the above configuration, a <code>SimpleMessage</code> will generate a <code>"sample log |
| message"</code>, whereas a <code>MapMessage</code> will generate a <code>{"action": "login", |
| "sessionId": "87asd97a"}</code>. Certain indexed log storage systems (e.g., |
| <a href="https://www.elastic.co/elasticsearch/">Elasticsearch</a>) will not allow both values |
| to coexist due to type mismatch: one is a <code>string</code> while the other is an <code>object</code>. |
| Here one can use a <code>fallbackKey</code> to work around the problem:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "message", |
| "fallbackKey": "formattedMessage" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Using this configuration, a <code>SimpleMessage</code> will generate a |
| <code>{"formattedMessage": "sample log message"}</code> and a <code>MapMessage</code> will generate a |
| <code>{"action": "login", "sessionId": "87asd97a"}</code>. Note that both emitted JSONs are |
| of type <code>object</code> and have no type-conflicting fields.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-messageParameter"><code>messageParameter</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = [ stringified ] , [ index ] |
| stringified = "stringified" -> boolean |
| index = "index" -> number</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves <code>logEvent.getMessage().getParameters()</code>.</p> |
| </div> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <div class="title">Warning</div> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Regarding garbage footprint, <code>stringified</code> flag translates to |
| <code>String.valueOf(value)</code>, hence mind not-<code>String</code>-typed values. Further, |
| <code>logEvent.getMessage()</code> is expected to implement <code>ParameterVisitable</code> interface, |
| which is the case if <code>log4j2.enableThreadLocals</code> property set to true.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the message parameters into an array:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "messageParameter" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the string representation of all message parameters into an array:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "messageParameter", |
| "stringified": true |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the first message parameter:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "messageParameter", |
| "index": 0 |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the string representation of the first message parameter:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "messageParameter", |
| "index": 0, |
| "stringified": true |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-ndc"><code>ndc</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = [ pattern ] |
| pattern = "pattern" -> string</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves the Nested Diagnostic Context (NDC), aka. Thread Context Stack, |
| <code>String[]</code> returned by <code>logEvent.getContextStack()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve all NDC values into a list:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "ndc" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve all NDC values matching with the <code>pattern</code> regex:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "ndc", |
| "pattern": "user(Role|Rank):\\w+" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-pattern"><code>pattern</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = pattern , [ stackTraceEnabled ] |
| pattern = "pattern" -> string |
| stackTraceEnabled = "stackTraceEnabled" -> boolean</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolver delegating to <a href="layouts.html#PatternLayout"><code>PatternLayout</code></a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The default value of <code>stackTraceEnabled</code> is inherited from the parent |
| <code>JsonTemplateLayout</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the string produced by <code>%p %c{1.} [%t] %X{userId} %X %m%ex</code> pattern:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "pattern", |
| "pattern": "%p %c{1.} [%t] %X{userId} %X %m%ex" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-source"><code>source</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = "field" -> ( |
| "className" | |
| "fileName" | |
| "methodName" | |
| "lineNumber" )</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves the fields of the <code>StackTraceElement</code> returned by |
| <code>logEvent.getSource()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that this resolver is toggled by |
| <code>log4j.layout.jsonTemplate.locationInfoEnabled</code> property.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the line number:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "source", |
| "field": "lineNumber" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-thread"><code>thread</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = "field" -> ( "name" | "id" | "priority" )</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves <code>logEvent.getThreadId()</code>, <code>logEvent.getThreadName()</code>, |
| <code>logEvent.getThreadPriority()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the thread name:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "thread", |
| "field": "name" |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="event-template-resolver-timestamp"><code>timestamp</code></h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = [ patternConfig | epochConfig ] |
| |
| patternConfig = "pattern" -> ( [ format ] , [ timeZone ] , [ locale ] ) |
| format = "format" -> string |
| timeZone = "timeZone" -> string |
| locale = "locale" -> ( |
| language | |
| ( language , "_" , country ) | |
| ( language , "_" , country , "_" , variant ) |
| ) |
| |
| epochConfig = "epoch" -> ( unit , [ rounded ] ) |
| unit = "unit" -> ( |
| "nanos" | |
| "millis" | |
| "secs" | |
| "millis.nanos" | |
| "secs.nanos" | |
| ) |
| rounded = "rounded" -> boolean</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolves <code>logEvent.getInstant()</code> in various forms.</p> |
| </div> |
| <table class="tableblock frame-all grid-all spread"> |
| <caption class="title">Table 2. <code>timestamp</code> template resolver examples</caption> |
| <colgroup> |
| <col style="width: 71.4285%;"/> |
| <col style="width: 28.5715%;"/> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Configuration</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>Output</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp" |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>2020-02-07T13:38:47.098+02:00</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "pattern": { |
| "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", |
| "timeZone": "UTC", |
| "locale": "en_US" |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>2020-02-07T13:38:47.098Z</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "secs" |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>1581082727.982123456</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "secs", |
| "rounded": true |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>1581082727</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "secs.nanos" |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>982123456</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "millis" |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>1581082727982.123456</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "millis", |
| "rounded": true |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>1581082727982</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "millis.nanos" |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>123456</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><div><div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "timestamp", |
| "epoch": { |
| "unit": "nanos" |
| } |
| }</code></pre> |
| </div> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>1581082727982123456</code></p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="map-resolver-template">Map Resolver Template</h4> |
| <div class="paragraph"> |
| <p><code>ReadOnlyStringMap</code> is Log4j’s <code>Map<String, Object></code> equivalent with |
| garbage-free accessors and heavily employed throughout the code base. It is the |
| data structure backing both Mapped Diagnostic Context (MDC), aka. Thread Context |
| Data and <code>MapMessage</code> implementations. Hence template resolvers for both of |
| these are provided by a single backend: <code>ReadOnlyStringMapResolver</code>. Put another |
| way, both <code>mdc</code> and <code>map</code> resolvers support identical configuration, behaviour, |
| and garbage footprint, which are detailed below.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = singleAccess | multiAccess |
| |
| singleAccess = key , [ stringified ] |
| key = "key" -> string |
| stringified = "stringified" -> boolean |
| |
| multiAccess = [ pattern ] , [ flatten ] , [ stringified ] |
| pattern = "pattern" -> string |
| flatten = "flatten" -> ( boolean | flattenConfig ) |
| flattenConfig = [ flattenPrefix ] |
| flattenPrefix = "prefix" -> string</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><code>singleAccess</code> resolves a single field, whilst <code>multiAccess</code> resolves a |
| multitude of fields. If <code>flatten</code> is provided, <code>multiAccess</code> merges the fields |
| with the parent, otherwise creates a new JSON object containing the values.</p> |
| </div> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <div class="title">Warning</div> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Regarding garbage footprint, <code>stringified</code> flag translates to |
| <code>String.valueOf(value)</code>, hence mind not-<code>String</code>-typed values.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p><code>"$resolver"</code> is left out in the following examples, since it is to be |
| defined by the actual resolver, e.g., <code>map</code>, <code>mdc</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the value of the field keyed with <code>userRole</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "…", |
| "key": "userRole" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve the string representation of the <code>userRank</code> field value:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "…", |
| "key": "userRank", |
| "stringified": true |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve all fields into an object:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "…" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Resolve all fields into an object such that values are converted to string:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "…", |
| "stringified": true |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Merge all fields whose keys are matching with the <code>user(Role|Rank)</code> regex into |
| the parent:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "…", |
| "flatten": true, |
| "pattern": "user(Role|Rank)" |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>After converting the corresponding field values to string, merge all fields to |
| parent such that keys are prefixed with <code>_</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "$resolver": "…", |
| "stringified": true, |
| "flatten": { |
| "prefix": "_" |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="stack-trace-element-templates">Stack Trace Element Templates</h3> |
| <div class="paragraph"> |
| <p><code>stackTraceElement[Uri]</code> describes the JSON structure <code>JsonTemplateLayout</code> uses |
| to format <code>StackTraceElement</code>s. The default configuration (accessible by |
| <code>log4j.layout.jsonTemplate.stackTraceElementTemplate[Uri]</code> property) is set to |
| <code>classpath:StackTraceElementLayout.json</code> provided by the |
| <code>log4j-layout-template-json</code> artifact:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-json" data-lang="json">{ |
| "class": { |
| "$resolver": "stackTraceElement", |
| "field": "className" |
| }, |
| "method": { |
| "$resolver": "stackTraceElement", |
| "field": "methodName" |
| }, |
| "file": { |
| "$resolver": "stackTraceElement", |
| "field": "fileName" |
| }, |
| "line": { |
| "$resolver": "stackTraceElement", |
| "field": "lineNumber" |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The allowed template configuration syntax is as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code>config = "field" -> ( |
| "className" | |
| "fileName" | |
| "methodName" | |
| "lineNumber" )</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>All above accesses to <code>StackTraceElement</code> is garbage-free.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="features">Features</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Below is a feature comparison matrix between <code>JsonTemplateLayout</code> and |
| alternatives.</p> |
| </div> |
| <table class="tableblock frame-all grid-all spread"> |
| <caption class="title">Table 3. Feature comparison matrix</caption> |
| <colgroup> |
| <col style="width: 42.8571%;"/> |
| <col style="width: 14.2857%;"/> |
| <col style="width: 14.2857%;"/> |
| <col style="width: 14.2857%;"/> |
| <col style="width: 14.2858%;"/> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Feature</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>JsonTemplateLayout</code></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="layouts.html#JSONLayout"><code>JsonLayout</code></a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="layouts.html#GELFLayout"><code>GelfLayout</code></a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/elastic/java-ecs-logging/tree/master/log4j2-ecs-layout"><code>EcsLayout</code></a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Java version</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Dependencies</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">None</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Jackson</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">None</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">None</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Schema customization?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Timestamp customization?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">(Almost) garbage-free?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Custom typed <code>Message</code> serialization?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">?<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnote_1" title="View footnote.">1</a>]</sup></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Custom typed <code>MDC</code> value serialization?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Rendering stack traces as array?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Stack trace truncation?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JSON pretty print?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Additional string fields?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Additional JSON fields?</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✓</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">✕</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="faq">F.A.Q.</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="faq-lookups">Are lookups supported in templates?</h3> |
| <div class="paragraph"> |
| <p>Yes, <a href="lookups.html">lookups</a> (e.g., <code>${java:version}</code>, |
| <code>${env:USER}</code>, <code>${date:MM-dd-yyyy}</code>) are supported in string |
| literals of templates. Though note that they are not garbage-free.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="are_recursive_collections_supported">Are recursive collections supported?</h3> |
| <div class="paragraph"> |
| <p>No. Consider a <code>Message</code> containing a recursive value as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Object[] recursiveCollection = new Object[1]; |
| recursiveCollection[0] = recursiveCollection;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>While the exact exception might vary, you will most like get a |
| <code>StackOverflowError</code> while trying to render <code>recursiveCollection</code> into a |
| <code>String</code>. Note that this is also the default behaviour for other Java standard |
| library methods, e.g., <code>Arrays.toString()</code>. Hence mind self references while |
| logging.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="faq-garbage-free">Is <code>JsonTemplateLayout</code> garbage-free?</h3> |
| <div class="paragraph"> |
| <p>Yes, if the garbage-free layout behaviour toggling properties |
| <code>log4j2.enableDirectEncoders</code> and <code>log4j2.garbagefreeThreadContextMap</code> are |
| enabled. Take into account the following caveats:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The configured <a href="#recycling-strategy">recycling strategy</a> might not be |
| garbage-free.</p> |
| </li> |
| <li> |
| <p>Since <code>Throwable#getStackTrace()</code> clones the original <code>StackTraceElement[]</code>, |
| access to (and hence rendering of) stack traces are not garbage-free.</p> |
| </li> |
| <li> |
| <p>Serialization of <code>MapMessage</code>s and <code>ObjectMessage</code>s are mostly |
| garbage-free except for certain types (e.g., <code>BigDecimal</code>, <code>BigInteger</code>, |
| <code>Collection</code>s with the exception of <code>List</code>).</p> |
| </li> |
| <li> |
| <p><a href="lookups.html">Lookups</a> (that is, <code>${…​}</code> variables) are not garbage-free.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Don’t forget to checkout <a href="#event-template-resolvers">the notes on garbage footprint of resolvers</a> |
| you employ in templates.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div id="footnotes"> |
| <hr/> |
| <div class="footnote" id="_footnote_1"> |
| <a href="#_footnoteref_1">1</a>. Only for <code>ObjectMessage</code>s and if Jackson is in the classpath. |
| </div> |
| </div> |
| </main> |
| </div> |
| </div> |
| <hr/> |
| <footer> |
| <div class="container-fluid"> |
| <div class="row-fluid"> |
| <p align="center">Copyright © 1999-2021 <a class="external" href="http://www.apache.org">The Apache Software Foundation</a>. All Rights Reserved.<br> |
| Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the Apache Logging project logo are trademarks of The Apache Software Foundation.</p> |
| </div> |
| </div> |
| </footer> |
| </body> |
| </html> |