You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2022/03/14 12:27:13 UTC

[logging-log4j2] branch LOG4J2-3393 updated (6d22a08 -> 227d598)

This is an automated email from the ASF dual-hosted git repository.

vy pushed a change to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


 discard 6d22a08  LOG4J2-3393 Make TextEncoderHelper.encodeText() fallbacks JIT-friendly.
 discard bcfee78  LOG4J2-3393 JTL benchmark updates.
 discard 510606e  LOG4J2-3393 Inline context acquisition in JsonTemplateLayout.
 discard e7d4004  LOG4J2-3393 Remove redundant branching in JsonTemplateLayout.
 discard 37edca9  LOG4J2-3393 Avoid StringBuilderEncoder thread-local allocation in JsonTemplateLayout.
 discard e9cada3  LOG4J2-3393 Replace lambdas with classes to ease performance troubleshooting.
 discard 8a85c03  LOG4J2-3393 Use a single LogEvent in JMH benchmarks.
 discard dd25a31  LOG4J2-3393 Bump JMH from 1.21 to 1.34.
 discard 8d55e01  LOG4J2-2368 Test JsonTemplateLayout's ThreadLocalRecycler against nested logging.
 discard 2e85b9d  LOG4J2-3393 Fix StringBuilder sizing code typo in JsonWriter#trimStringBuilder().
 discard d81f97e  LOG4J2-3393 Improve "blackhole" behavior in ByteBuffer consumption.
 discard 6873b39  LOG4J2-3393 Go wild and embed ECS Layout for troubleshooting!
 discard acd0d0f  LOG4J2-3393 Create JTL benchmark main() for easy testing.
 discard b3a979a  LOG4J2-3393 Refactor JTL TemplateResolvers into smaller components.
     add 5a459dd  LOG4J2-3341 - Support specifying the level and appender references on the Logger as on property
     add 8b6df44  LOG4J2-3356 JPMS-export all JsonTemplateLayout packages.
     add c43f563  LOG4J2-2240 - Add unit tests
     add 4c6ef35  Bump maven-jxr-plugin from 2.5 to 3.1.1 (#752)
     add e8dab8c  LOG4J2-3297 - Limit loading of configuration via a url to https by default
     add 5f37d17  LOG4J2-3297 - Limit loading of configuration via a url to https by default
     add 2451c3e  Trim MaxBackupIndex if last char is blank. (#755)
     add 92c73ed  Trim input to Integer.parseInt() in DefaultRolloverStrategy. (#755)
     add 72bf5bd  Fix NPE in DefaultRolloverStrategy. (#755)
     add 3bd53c1  LOG4J2-3297 - Limit loading of configuration via a url to https by default
     add 746e59a  Bump maven-site-plugin from 3.8.2 to 3.11.0 (#757)
     add b89b898  LOG4J2-3193 - Add unit test to validate loading via the system property works
     add b763df3  LOG4J2-3405 - Document that the Spring Boot Lookup requires the log4j-spring-boot dependency.
     add 3913f59  LOG4J2-3393 Fix StringBuilder sizing code typo in JsonWriter#trimStringBuilder().
     add 5410ff5  LOG4J2-2368 Test JsonTemplateLayout's ThreadLocalRecycler against nested logging.
     add d865bfa  Bump HdrHistogram from 2.1.9 to 2.1.12 (#759)
     add cf2bf80  Bump log4j2-ecs-layout from 1.0.1 to 1.3.2 (#760)
     add 9ffa643  [LOG4J2-3404] Create default layouts using the available Configuration (#756)
     add 77f0450  LOG4J2-3404 changelog
     add d87a307  Issues with multiple Log4j 1.x filters (#753)
     add 92cdf40  Log4j 1.2 bridge issues with filters #753.
     add b652d23  Use System.arraycopy.
     add b0ea2ad  Merge catch clauses.
     add c4bbd7a  Remove unused method.
     add a8a659b  Allow for whitespace in property files.
     add 9ccf1fd  Remove useless parentheses.
     add 3d933aa  Format.
     add 02e2cfc  Allow for whitespace in configuration files.
     add 6bd9e06  Javadoc.
     add 5e052c9  LOG4J2-3334 - Create test to try to verify the problem
     add f161a66  Format nit.
     add 5bedb72  Format nits.
     add 74577ba  Replace array hack with AtomicReference.
     add e03665f  Remove unused imports.
     add 8a23f92  Bump de.flapdoodle.embed.mongo from 3.2.8 to 3.3.1 (#746)
     add b713368  Merge branch 'release-2.x' of https://gitbox.apache.org/repos/asf/logging-log4j2 into release-2.x
     add 2604351  Comment empty block.
     add 7cb2c9a  Format nits.
     add 900e80f  Javadoc and add toString().
     add a5b2574  Javadoc.
     add ae4cba2  Internal refactoring.
     add 087a6fc  Fill basic support in DOMConfigurator except for DOM-based APIs.
     add 51e02a3  Log4j 1.2 bridge implements most of DOMConfigurator.
     add 47c640b  Ignore config internal class from revapi, BC OK, only SC changed anyway.
     add 7254541  Internal refactoring.
     add ffc74e3  Bump json-unit from 2.28.0 to 2.32.0 (#765)
     add 8e89ecd  LOG4J2-3304 - Fix issue that the initialize status of LogManager is not set when factoryClassName is present and instantiate successfully (#676)
     add ef178a2  LOG4J2-3304 - Create test that verifies this fix
     add d6c8ab0  LOG4J2-3304 - Mark LogManager as initialized when a LoggerFactory is specified
     add e0a53b0  Bump kubernetes-client from 4.6.1 to 5.12.1 (#766)
     add c33646f  Trim whitespace before parsing a String into an Integer.
     add 6b9d180  Log4j 1.2 bridge internal refactoring adds getBooleanValueAttribute().
     add 51da8e2  [LOG4J2-3410] Log4j 1.2 bridge throws a ClassCastException when logging a Map with non-String keys.
     add 14fa165  LOG4J2-3407 Check for non-existent appender when parsing properties (#761)
     add 77656c6  Changes for release
     add 362fe76  [LOG4J2-3407] Log4j 1.2 bridge Check for non-existent appender when parsing properties #761.
     add 00810b5  Adds Log4j 1.x global threshold (#764)
     add 7b465eb  Log4j 1.2 bridge supports global threshold #764.
     add 0c9c050  Add missing dependencies
     add 1aa682e  Email addresses must be valid
     add 24ff45d  Fix checkstyle rules broken due to upgrade of checkstyle version
     add cecd3db  Bump org.mongodb:mongodb-driver-sync from 4.4.1 to 4.5.0.
     add 45a56bc  Bump de.flapdoodle.embed:de.flapdoodle.embed.mongo from 3.3.1 to 3.4.1.
     add 1e746ca  Bump org.eclipse.persistence:org.eclipse.persistence.jpa from 2.7.9 to 2.7.10.
     add f4f5dfe  Clean up SQL test fixtures.
     add d4852d7  Bump org.junit-pioneer:junit-pioneer from 1.5.0 to 1.6.1.
     add 19ed75f  Bump org.apache.activemq:activemq-broker from 5.16.3 to 5.16.4.
     add e416542  [LOG4J2-3391] Add optional additional fields to NoSQLAppender.
     add a61d2f0  Bump org.jacoco:jacoco-maven-plugin from 0.8.6 to 0.8.7.
     add 97dfa67  Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.3.1 to 3.3.2.
     add 032af32  Get site build to finish
     add df06a79  Run "site" goal for dependabot PRs in CI
     add 820a671  Some of the necessary revapi changes
     add fcf567b  More revapi changes
     add af63102  See if we can get the CI build working
     add 8c40d62  Prepare for release
     add eedc3cd  [maven-release-plugin] prepare release log4j-2.17.2-rc1
     add bf21070  [maven-release-plugin] prepare for next development iteration
     add af5d3b5  [LOG4J-3413] Fixes resolution of non-Log4j properties
     add 35f9db7  Merge pull request #774 from ppkarwasz/jira3413
     add ee93748  Add changelog entry for LOG4J2-3413
     add 9f75dea  Javadoc.
     add 7673943  Javadoc.
     add e652dc3  [LOG4J2-3423] JAR file containing Log4j configuration isn't closed.
     add 980d550  Fix spelling.
     add cb51ea0  Better docs.
     add d9e2c8f  Format tweaks.
     add ba48b1d  [LOG4J2-3423] JAR file containing Log4j configuration isn't closed.
     add d1d52e5  Match POM version.
     add dc1742c  [LOG4J2-3425] Syslog appender lacks the SocketOptions setting.
     add 1305bad  Add the missing space
     add ab2a9bf  LOG4J2-3423 - Get lastModified of the file
     add b03d760  Provide a uniform Log4j 1.x message factory
     add 613eea5  Remove the revapi plugin
     add 12977a9  Merge pull request #785 from carterkozak/ckozak/no-revapi
     add 3ae603d  Improves behavior of failing Log4j 1.x builders
     add cc2c896  Improves validation of Log4j 2.x components
     add 4492c26  LOG4J2-3424: Correctly handle property attribute values
     add 31697cf  Update change list
     add 922a150  Add disabled but failing tests from Log4j 1 as TODOs.
     add 2e49ade  Update test fixture for JPA and H2 to follow the only IDENTUTY syntax that will be allowed in H2 2.x. Actually updating to H2 2.x fails and might require an update the Eclipse JPA provider.
     add 11c6e65  [LOG4J2-3428] Update 3rd party dependencies for 2.17.3
     add f8f11e2  Add comment.
     add ba16485  [LOG4J2-3426] Refactors wrapping code
     add e5c7457  [LOG4J-3426] Update changelog
     add 7594b07  [LOG4J2-3427] Add a ServiceLoader tool
     add a536df6  Adds OSGI support through 'osgi-resource-locator'
     add 04ee8fb  [LOG4J2-3427] Updates changes
     add 48ab5e9  [LOG4J2-3418] Fix Log4j2CloudConfigLoggingSystem registration
     add 54565f0  Update changes
     add de4e5dd  [LOG4J2-3423] Refactoring of URLConnection code
     add 50b00d8  [LOG4J2-3428] Update 3rd party dependencies for 2.17.3
     add a73f103  Tests that configuring and reconfiguring STOCK and CUSTOM appenders properly pick up different settings.
     add 8d8a954  Delete inadvertent file previously committed.
     add 67ba1fe  [LOG4J2-3040] Avoid ClassCastException in JeroMqManager with custom LoggerContextFactory (#791)
     add 9d3f836  [LOG4J2-3040] Avoid ClassCastException in JeroMqManager with custom LoggerContextFactory #791
     add 2aa831e  [LOG4J2-3428] Update 3rd party dependencies for 2.17.3.
     add e291887  Fix minor typo (#792)
     add 168b5c1  Fix minor typo #792.
     add 1a364cc  [LOG4J2-3419] Adds support for custom Log4j 1.x levels (#789)
     add 1f17804  Update changelog
     add a4edd2f  Bump slf4jVersion from 1.7.35 to 1.7.36 (#776)
     add 7b9c413  Fix code typo in customconfig.xml (#781)
     add 3a146ee  Catch all FileAppenderTest asynchronous errors
     add 4e571f3  FileAppenderTest: increase thread pool termination timeout
     add 10460ec  Switches Cassandra to random port
     new a0a310f  LOG4J2-3393 Refactor JTL TemplateResolvers into smaller components.
     new cdade74  LOG4J2-3393 Create JTL benchmark main() for easy testing.
     new c4cac94  LOG4J2-3393 Go wild and embed ECS Layout for troubleshooting!
     new a604623  LOG4J2-3393 Improve "blackhole" behavior in ByteBuffer consumption.
     new 35e0c20  LOG4J2-3393 Bump JMH from 1.21 to 1.34.
     new 7136e8c  LOG4J2-3393 Use a single LogEvent in JMH benchmarks.
     new 3f6a9af  LOG4J2-3393 Replace lambdas with classes to ease performance troubleshooting.
     new 264ae84  LOG4J2-3393 Avoid StringBuilderEncoder thread-local allocation in JsonTemplateLayout.
     new 970e80e  LOG4J2-3393 Remove redundant branching in JsonTemplateLayout.
     new c907fcd  LOG4J2-3393 Inline context acquisition in JsonTemplateLayout.
     new 8a48540  LOG4J2-3393 JTL benchmark updates.
     new 81905f9  LOG4J2-3393 Make TextEncoderHelper.encodeText() fallbacks JIT-friendly.
     new 6a19108  LOG4J2-3393 Make JsonWriter garbage-free for StringMaps.
     new 69608b9  LOG4J2-3393 Clean-up wrong BiConsumer usages.
     new 6e6bd23  LOG4J2-3393 Fix revapi issues.
     new 227d598  LOG4J2-3393 Optimize MessageResolver for CharSequence.

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (6d22a08)
            \
             N -- N -- N   refs/heads/LOG4J2-3393 (227d598)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 16 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .github/workflows/build.yml                        |   28 +-
 RELEASE-NOTES.md                                   |  205 ++-
 checkstyle.xml                                     |   36 +-
 log4j-1.2-api/pom.xml                              |   13 +-
 log4j-1.2-api/revapi.json                          |   18 +
 .../java/org/apache/log4j/AppenderSkeleton.java    |    5 +-
 .../src/main/java/org/apache/log4j/Category.java   |   63 +-
 .../src/main/java/org/apache/log4j/Hierarchy.java  |    3 +-
 .../src/main/java/org/apache/log4j/Level.java      |   26 +-
 .../src/main/java/org/apache/log4j/Priority.java   |    9 +
 .../org/apache/log4j/PropertyConfigurator.java     |   12 +-
 .../java/org/apache/log4j/RollingFileAppender.java |    8 +-
 .../main/java/org/apache/log4j/WriterAppender.java |   10 +-
 .../org/apache/log4j/bridge/AppenderAdapter.java   |   42 +-
 .../org/apache/log4j/bridge/AppenderWrapper.java   |   32 +-
 .../org/apache/log4j/bridge/FilterAdapter.java     |   52 +-
 .../org/apache/log4j/bridge/FilterWrapper.java     |   21 +
 .../org/apache/log4j/bridge/LayoutAdapter.java     |   30 +-
 .../org/apache/log4j/bridge/LayoutWrapper.java     |   37 +-
 .../org/apache/log4j/bridge/LogEventAdapter.java   |   29 +-
 .../org/apache/log4j/bridge/LogEventWrapper.java   |    8 +-
 .../apache/log4j/bridge/RewritePolicyWrapper.java  |    2 +-
 .../org/apache/log4j/builders/AbstractBuilder.java |   46 +-
 .../java/org/apache/log4j/builders/Builder.java    |    6 +-
 .../org/apache/log4j/builders/BuilderManager.java  |  168 +-
 .../{appender/AppenderBuilder.java => Parser.java} |   31 +-
 .../log4j/builders/appender/AppenderBuilder.java   |    8 +-
 .../builders/appender/AsyncAppenderBuilder.java    |   28 +-
 .../builders/appender/ConsoleAppenderBuilder.java  |   27 +-
 .../appender/DailyRollingFileAppenderBuilder.java  |   13 +-
 .../builders/appender/FileAppenderBuilder.java     |   13 +-
 .../builders/appender/NullAppenderBuilder.java     |    4 +-
 .../builders/appender/RewriteAppenderBuilder.java  |   17 +-
 .../appender/RollingFileAppenderBuilder.java       |   13 +-
 .../builders/appender/SocketAppenderBuilder.java   |   27 +-
 .../builders/appender/SyslogAppenderBuilder.java   |   14 +-
 .../builders/filter/DenyAllFilterBuilder.java      |    4 +-
 .../log4j/builders/filter/FilterBuilder.java       |   13 +-
 .../builders/filter/LevelMatchFilterBuilder.java   |   13 +-
 .../builders/filter/LevelRangeFilterBuilder.java   |   15 +-
 .../builders/filter/StringMatchFilterBuilder.java  |   21 +-
 .../log4j/builders/layout/HtmlLayoutBuilder.java   |   10 +-
 .../log4j/builders/layout/LayoutBuilder.java       |   12 +-
 .../builders/layout/PatternLayoutBuilder.java      |   18 +-
 .../log4j/builders/layout/SimpleLayoutBuilder.java |    4 +-
 .../log4j/builders/layout/TTCCLayoutBuilder.java   |   14 +-
 .../log4j/builders/layout/XmlLayoutBuilder.java    |   13 +-
 .../builders/rewrite/RewritePolicyBuilder.java     |   12 +-
 .../apache/log4j/config/Log4j1Configuration.java   |    7 +
 .../log4j/config/Log4j1ConfigurationParser.java    |   28 +-
 .../log4j/config/PropertiesConfiguration.java      |   44 +-
 .../org/apache/log4j/config/PropertySetter.java    |    2 +-
 .../org/apache/log4j/helpers/OptionConverter.java  |  245 ++-
 .../org/apache/log4j/helpers/PatternParser.java    |  939 ++++++------
 .../java/org/apache/log4j/helpers/QuietWriter.java |    6 +-
 .../org/apache/log4j/helpers/UtilLoggingLevel.java |    2 +-
 .../org/apache/log4j/or/jms/MessageRenderer.java   |    8 +-
 .../log4j/pattern/Log4j1NdcPatternConverter.java   |    4 +-
 .../org/apache/log4j/rewrite/MapRewritePolicy.java |    6 +-
 .../log4j/rewrite/PropertyRewritePolicy.java       |   10 +-
 .../org/apache/log4j/spi/AppenderAttachable.java   |    4 +-
 .../src/main/java/org/apache/log4j/spi/Filter.java |   12 -
 .../java/org/apache/log4j/spi/LocationInfo.java    |    8 +-
 .../java/org/apache/log4j/xml/DOMConfigurator.java |  113 +-
 .../log4j/xml/UnrecognizedElementHandler.java      |    3 +-
 .../java/org/apache/log4j/xml/XMLWatchdog.java}    |   28 +-
 .../org/apache/log4j/xml/XmlConfiguration.java     |  129 +-
 .../test/java/org/apache/log4j/CategoryTest.java   |   49 +-
 ...omNoopAppender.java => CustomFileAppender.java} |   33 +-
 .../java/org/apache/log4j/CustomNoopAppender.java  |   34 +-
 .../src/test/java/org/apache/log4j/LevelTest.java  |    5 +-
 .../test/java/org/apache/log4j/ListAppender.java   |    4 +-
 .../test/java/org/apache/log4j/LogWithMDCTest.java |    9 +-
 .../java/org/apache/log4j/LogWithRouteTest.java    |   10 +-
 .../java/org/apache/log4j/LoggerJira3410Test.java  |   82 +
 .../src/test/java/org/apache/log4j/LoggerTest.java |    9 +-
 .../test/java/org/apache/log4j/LoggingTest.java    |    5 +-
 .../test/java/org/apache/log4j/PriorityTest.java   |    6 +-
 .../apache/log4j/bridge/LogEventWrapperTest.java   |    6 +-
 .../apache/log4j/builders/BuilderManagerTest.java  |   53 +
 .../log4j/builders/Log4j2ListAppenderBuilder.java  |   89 ++
 .../config/AbstractLog4j1ConfigurationTest.java    |  153 +-
 .../config/Log4j1ConfigurationFactoryTest.java     |   39 +
 .../config/PropertiesConfigurationFactoryTest.java |    2 +-
 .../log4j/config/PropertiesConfigurationTest.java  |   60 +-
 .../config/PropertiesReconfigurationTest.java      |  213 ++-
 .../StartsWithFilter.java}                         |   77 +-
 .../org/apache/log4j/config/TestConfigurator.java  |    2 +-
 .../apache/log4j/config/XmlConfigurationTest.java  |   12 +
 .../TestCase1.java}                                |   58 +-
 .../org/apache/log4j/defaultInit/TestCase2.java    |   59 +
 .../org/apache/log4j/defaultInit/TestCase3.java    |   53 +
 .../org/apache/log4j/defaultInit/TestCase4.java    |   60 +
 .../org/apache/log4j/helpers/DateLayoutTest.java   |   11 +-
 .../log4j/helpers/OptionConverterLevelTest.java    |  123 ++
 .../apache/log4j/helpers/UtilLoggingLevelTest.java |   36 +-
 .../pattern/Log4j1NdcPatternConverterTest.java     |    4 +-
 .../AbsoluteDateAndTimeFilter.java}                |   33 +-
 .../AbsoluteTimeFilter.java}                       |   32 +-
 .../java/org/apache/log4j/util/ControlFilter.java  |   47 +
 .../log4j/util/EnhancedJunitTestRunnerFilter.java  |   58 +
 .../EnhancedLineNumberFilter.java}                 |   39 +-
 .../UtilLoggingLevelTest.java => util/Filter.java} |   32 +-
 .../ISO8601Filter.java}                            |   32 +-
 .../apache/log4j/util/JunitTestRunnerFilter.java   |   54 +
 .../LineNumberFilter.java}                         |   35 +-
 .../RelativeTimeFilter.java}                       |   33 +-
 .../apache/log4j/util/SerializationTestHelper.java |  112 +-
 .../org/apache/log4j/util/SunReflectFilter.java    |   43 +
 .../java/org/apache/log4j/util/Transformer.java    |   59 +
 .../UnexpectedFormatException.java}                |   28 +-
 .../XMLLineAttributeFilter.java}                   |   35 +-
 .../XMLTimestampFilter.java}                       |   32 +-
 .../java/org/apache/log4j/xml/DOMTestCase.java     |  473 ++++++
 ...g4j1-file.properties => LOG4J2-3407.properties} |   15 +-
 .../config-1.2/log4j-global-threshold.properties   |   17 +-
 .../log4j-global-threshold.xml}                    |   34 +-
 .../log4j-untrimmed.properties}                    |   27 +-
 .../resources/log4j-multipleFilters.properties     |   69 +
 .../src/test/resources/log4j-multipleFilters.xml   |   92 ++
 .../log4j1-1.2.17/input/xml/DOMTestCase1.xml       |    4 +-
 ...erties => log4j1-appenders-custom-1.properties} |   17 +-
 ...erties => log4j1-appenders-custom-2.properties} |   17 +-
 ...j1-file.properties => log4j1-file-1.properties} |    3 +
 ...j1-file.properties => log4j1-file-2.properties} |    8 +-
 log4j-api-java9/pom.xml                            |    2 +-
 log4j-api/pom.xml                                  |   11 +-
 log4j-api/revapi.json                              |   24 +-
 .../java/org/apache/logging/log4j/LogManager.java  |    2 +-
 .../logging/log4j/message/StructuredDataId.java    |    2 +-
 .../apache/logging/log4j/util/PropertiesUtil.java  |   28 +-
 .../apache/logging/log4j/util/PropertySource.java  |   27 +-
 .../logging/log4j/util/ServiceLoaderUtil.java      |  137 ++
 .../logging/log4j/util/SortedArrayStringMap.java   |    5 +-
 .../org/apache/logging/log4j/util/Strings.java     |    2 +-
 .../java/org/apache/logging/log4j/util/Unbox.java  |    2 +-
 .../logging/log4j/util/PropertiesUtilTest.java     |   28 +
 .../log4j/util/PropertySourceTokenizerTest.java    |    4 +
 .../logging/log4j/util/ServiceLoaderUtilTest.java  |  127 ++
 .../log4j/util/SortedArrayStringMapTest.java       |   10 +
 .../org/apache/logging/log4j/util/StringsTest.java |   10 +
 .../logging/log4j/util/test/BetterService.java     |    8 +-
 .../apache/logging/log4j/util/test/Service.java    |    8 +-
 .../apache/logging/log4j/util/test/Service1.java   |    8 +-
 .../apache/logging/log4j/util/test/Service2.java   |    8 +-
 .../src/test/resources/Jira3413Test.properties     |   24 +-
 ...rg.apache.logging.log4j.util.test.BetterService |    5 +-
 .../org.apache.logging.log4j.util.test.Service     |   20 +-
 log4j-appserver/pom.xml                            |    2 +-
 log4j-bom/pom.xml                                  |    4 +-
 log4j-cassandra/pom.xml                            |    2 +-
 log4j-cassandra/revapi.json                        |   13 +
 .../logging/log4j/cassandra/CassandraRule.java     |   15 +-
 .../src/test/resources/CassandraAppenderTest.xml   |    2 +-
 log4j-core-its/pom.xml                             |    2 +-
 log4j-core-java9/pom.xml                           |    2 +-
 log4j-core/pom.xml                                 |    2 +-
 log4j-core/revapi.json                             |  105 +-
 .../log4j/core/appender/AbstractAppender.java      |   14 +-
 .../log4j/core/appender/AbstractManager.java       |    7 +
 .../log4j/core/appender/ConsoleAppender.java       |   19 +-
 .../logging/log4j/core/appender/FileAppender.java  |    3 +
 .../logging/log4j/core/appender/FileManager.java   |    2 +
 .../core/appender/HttpURLConnectionManager.java    |   10 +-
 .../log4j/core/appender/OutputStreamAppender.java  |    6 +-
 .../log4j/core/appender/RollingFileAppender.java   |   17 +-
 .../logging/log4j/core/appender/SmtpAppender.java  |    7 +-
 .../log4j/core/appender/SyslogAppender.java        |    2 +-
 .../log4j/core/appender/WriterAppender.java        |   12 +-
 .../core/appender/mom/jeromq/JeroMqManager.java    |    2 +-
 .../core/appender/mom/kafka/KafkaManager.java      |    3 +-
 .../appender/rolling/AbstractRolloverStrategy.java |    3 +-
 .../appender/rolling/DefaultRolloverStrategy.java  |    7 +-
 .../rolling/DirectWriteRolloverStrategy.java       |    2 +-
 .../log4j/core/async/AsyncLoggerConfig.java        |   41 +-
 .../logging/log4j/core/async/DisruptorUtil.java    |    2 +-
 .../core/async/ThreadNameCachingStrategy.java      |    3 +-
 .../log4j/core/config/AbstractConfiguration.java   |   12 +-
 .../log4j/core/config/ConfigurationFactory.java    |   60 +-
 .../log4j/core/config/ConfigurationSource.java     |   43 +-
 .../logging/log4j/core/config/HttpWatcher.java     |    2 +
 .../logging/log4j/core/config/LoggerConfig.java    |  315 +++-
 .../apache/logging/log4j/core/config/Property.java |   34 +-
 .../builder/impl/DefaultConfigurationBuilder.java  |    3 +-
 .../config/composite/DefaultMergeStrategy.java     |    5 +-
 .../log4j/core/config/json/JsonConfiguration.java  |   10 +-
 .../core/config/plugins/util/PluginBuilder.java    |   40 +-
 .../core/config/plugins/util/ResolverUtil.java     |    2 +
 .../constraints/{Required.java => NotBlank.java}   |   19 +-
 .../plugins/validation/constraints/Required.java   |    5 +-
 ...quiredValidator.java => NotBlankValidator.java} |   29 +-
 .../validation/validators/RequiredValidator.java   |    2 +-
 .../properties/PropertiesConfigurationBuilder.java |   57 +-
 .../log4j/core/config/xml/XmlConfiguration.java    |    4 +-
 .../logging/log4j/core/filter/CompositeFilter.java |    9 +-
 .../log4j/core/impl/ThrowableFormatOptions.java    |    3 +-
 .../Log4jStackTraceElementDeserializer.java        |    4 +-
 .../logging/log4j/core/layout/AbstractLayout.java  |    2 +-
 .../log4j/core/layout/AbstractStringLayout.java    |   20 +-
 .../logging/log4j/core/layout/LoggerFields.java    |    3 +-
 .../logging/log4j/core/layout/PatternLayout.java   |    8 +-
 .../log4j/core/net/Rfc1349TrafficClass.java        |   32 +-
 .../logging/log4j/core/net/SocketOptions.java      |  146 +-
 .../log4j/core/net/UrlConnectionFactory.java       |   47 +-
 .../log4j/core/pattern/LevelPatternConverter.java  |    3 +-
 .../log4j/core/pattern/NameAbbreviator.java        |    3 +-
 .../logging/log4j/core/pattern/PatternParser.java  |   10 +-
 .../log4j/core/pattern/RepeatPatternConverter.java |    3 +-
 .../apache/logging/log4j/core/tools/Generate.java  |    4 +-
 .../log4j/core/tools/picocli/CommandLine.java      |   14 +-
 .../logging/log4j/core/util/AbstractWatcher.java   |    2 +-
 .../core/util/BasicAuthorizationProvider.java      |    4 +-
 .../apache/logging/log4j/core/util/Builder.java    |   15 +
 .../logging/log4j/core/util/CronExpression.java    |    8 +-
 .../apache/logging/log4j/core/util/Integers.java   |    5 +-
 .../logging/log4j/core/util/OptionConverter.java   |    4 +-
 .../log4j/core/util/datetime/FastDateParser.java   |    4 +-
 ...rTest.java => AbstractAppenderBuilderTest.java} |   69 +-
 .../core/appender/FileAppenderBuilderTest.java     |   60 +-
 .../log4j/core/appender/FileAppenderTest.java      |   92 +-
 .../rolling/RollingAppenderDeleteScriptTest.java   |    3 +-
 .../log4j/core/async/perftest/PerfTestDriver.java  |    7 +-
 .../core/async/perftest/ResponseTimeTest.java      |    3 +-
 .../core/config/ConfigurationPropertyTest.java     |   52 +
 .../log4j/core/config/ConfigurationSourceTest.java |   49 +-
 .../core/config/ConfiguratorSetLevelTest.java      |   61 +
 .../logging/log4j/core/config/PropertyTest.java    |   54 +
 .../core/config/ReconfigurationFailureTest.java    |   80 +
 .../properties/PropertiesConfigurationTest.java    |   17 +
 .../log4j/core/filter/CompositeFilterTest.java     |   49 +
 .../core/layout/AbstractStringLayoutTest.java      |   26 +-
 .../log4j/core/layout/Rfc5424LayoutTest.java       |   12 +-
 .../log4j/core/net/UrlConnectionFactoryTest.java   |  217 +++
 .../core/net/ssl/TlsSyslogInputStreamReader.java   |    4 +-
 .../pattern/ThrowablePatternConverterTest.java     |    9 +-
 .../log4j/core/selector/TestClassLoader.java       |    8 +-
 .../logging/log4j/core/util/NetUtilsTest.java      |   28 +-
 .../logging/log4j/core/util/WatchHttpTest.java     |    2 +
 .../src/test/resources/InvalidConfig.xml           |   30 +-
 .../src/test/resources/InvalidXML.xml              |   26 +-
 .../resources/LoggerLevelAppenderTest.properties   |    2 +
 ... => LoggerLevelSysPropsAppenderTest.properties} |    8 +-
 .../RootLoggerLevelAppenderTest.properties         |    3 +-
 .../src/test/resources/configPropertyTest.xml      |    9 +
 log4j-core/src/test/resources/jarfile.jar          |  Bin 0 -> 1122 bytes
 .../src/test/resources/jarfile/config/console.xml  |   28 +
 .../src/test/resources/log4j-set-level.xml         |   28 +-
 log4j-couchdb/pom.xml                              |    2 +-
 log4j-couchdb/revapi.json                          |   15 +
 log4j-distribution/pom.xml                         |   28 +-
 log4j-docker/pom.xml                               |    2 +-
 log4j-docker/revapi.json                           |   15 +
 log4j-flume-ng/pom.xml                             |    2 +-
 log4j-flume-ng/revapi.json                         |   27 +
 .../log4j/flume/appender/FlumeAppenderTest.java    |    5 +-
 .../appender/FlumePersistentAppenderTest.java      |    7 +-
 log4j-iostreams/pom.xml                            |    2 +-
 log4j-iostreams/revapi.json                        |   19 +
 log4j-jakarta-web/pom.xml                          |    2 +-
 log4j-jakarta-web/revapi.json                      |   30 +-
 .../log4j/web/appender/ServletAppender.java        |    8 +-
 log4j-jcl/pom.xml                                  |    2 +-
 log4j-jcl/revapi.json                              |   15 +
 log4j-jdbc-dbcp2/pom.xml                           |    2 +-
 log4j-jdbc-dbcp2/revapi.json                       |   15 +
 log4j-jmx-gui/pom.xml                              |    2 +-
 log4j-jmx-gui/revapi.json                          |   38 +
 log4j-jpa/pom.xml                                  |    2 +-
 log4j-jpa/revapi.json                              |   21 +
 .../jpa/converter/InstantAttributeConverter.java   |    9 +-
 .../StackTraceElementAttributeConverter.java       |    3 +-
 .../core/appender/db/jpa/JpaH2AppenderTest.java    |    9 +-
 .../appender/db/jpa/JpaHsqldbAppenderTest.java     |    9 +-
 log4j-jpl/pom.xml                                  |    2 +-
 log4j-jul/pom.xml                                  |    2 +-
 log4j-jul/revapi.json                              |   19 +
 log4j-kubernetes/pom.xml                           |    2 +-
 log4j-kubernetes/revapi.json                       |   15 +
 log4j-layout-template-json/pom.xml                 |    4 +-
 log4j-layout-template-json/revapi.json             | 1616 +++++++++++---------
 .../template/json/resolver/MessageResolver.java    |    5 +-
 .../template/json/resolver/PatternResolver.java    |    2 +-
 .../layout/template/json/util/JsonWriter.java      |   28 +-
 .../template/json/util/RecyclerFactories.java      |   11 +-
 .../layout/template/json/util/JsonReaderTest.java  |    9 +-
 .../layout/template/json/util/JsonWriterTest.java  |    2 +-
 log4j-liquibase/pom.xml                            |    2 +-
 log4j-mongodb3/pom.xml                             |    2 +-
 log4j-mongodb3/revapi.json                         |   12 +
 .../logging/log4j/mongodb3/MongoDb3TestRule.java   |    5 +-
 log4j-mongodb4/pom.xml                             |    2 +-
 log4j-mongodb4/revapi.json                         |   12 +
 .../logging/log4j/mongodb4/MongoDb4TestRule.java   |    5 +-
 log4j-osgi/pom.xml                                 |    6 +-
 .../log4j/osgi/tests/AbstractLoadBundleTest.java   |   44 +
 log4j-perf/pom.xml                                 |    2 +-
 log4j-samples/log4j-samples-configuration/pom.xml  |    2 +-
 log4j-samples/log4j-samples-flume-common/pom.xml   |    2 +-
 .../log4j/samples/app/LoggingController.java       |    3 +-
 log4j-samples/log4j-samples-flume-embedded/pom.xml |    2 +-
 log4j-samples/log4j-samples-flume-remote/pom.xml   |    2 +-
 .../log4j-samples-loggerProperties/pom.xml         |    2 +-
 log4j-samples/pom.xml                              |    2 +-
 log4j-slf4j-impl/pom.xml                           |    2 +-
 log4j-slf4j18-impl/pom.xml                         |    2 +-
 log4j-spring-boot/pom.xml                          |   22 +-
 .../boot/Log4j2CloudConfigLoggingSystem.java       |   28 +-
 .../logging/log4j/spring/boot/SpringLookup.java    |    9 +-
 .../spring.factories}                              |    2 +-
 .../boot/Log4j2CloudConfigLoggingSystemTest.java   |   28 +-
 .../spring/boot/Log4j2SpringBootInitTest.java      |   62 +
 .../src/test/resources/application.yml             |    5 +
 .../src/test/resources/log4j2-springProfile.xml    |    3 +-
 .../log4j-spring-cloud-config-client/pom.xml       |    2 +-
 .../pom.xml                                        |    2 +-
 .../pom.xml                                        |    4 +-
 .../log4j-spring-cloud-config-samples/pom.xml      |    2 +-
 log4j-spring-cloud-config/pom.xml                  |    2 +-
 log4j-taglib/pom.xml                               |    2 +-
 log4j-taglib/revapi.json                           |   20 +-
 log4j-to-jul/pom.xml                               |    3 +-
 log4j-to-jul/revapi.json                           |   12 +
 log4j-to-slf4j/pom.xml                             |    2 +-
 log4j-web/pom.xml                                  |    2 +-
 log4j-web/revapi.json                              |   30 +-
 .../log4j/web/appender/ServletAppender.java        |    8 +-
 pom.xml                                            |  183 +--
 src/changes/announcement.vm                        |   16 +-
 src/changes/changes.xml                            |  105 +-
 src/site/markdown/index.md.vm                      |   28 +-
 src/site/xdoc/manual/appenders.xml                 |   42 +-
 src/site/xdoc/manual/configuration.xml.vm          |  108 +-
 src/site/xdoc/manual/customconfig.xml              |    2 +-
 src/site/xdoc/manual/lookups.xml                   |    3 +-
 334 files changed, 8081 insertions(+), 3306 deletions(-)
 create mode 100644 log4j-1.2-api/revapi.json
 copy log4j-1.2-api/src/main/java/org/apache/log4j/builders/{appender/AppenderBuilder.java => Parser.java} (62%)
 copy log4j-1.2-api/src/{test/java/org/apache/log4j/CustomNoopAppender.java => main/java/org/apache/log4j/xml/XMLWatchdog.java} (61%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{CustomNoopAppender.java => CustomFileAppender.java} (60%)
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/LoggerJira3410Test.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/builders/BuilderManagerTest.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/builders/Log4j2ListAppenderBuilder.java
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{CustomNoopAppender.java => config/StartsWithFilter.java} (64%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => defaultInit/TestCase1.java} (51%)
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/defaultInit/TestCase2.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/defaultInit/TestCase3.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/defaultInit/TestCase4.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/helpers/OptionConverterLevelTest.java
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/AbsoluteDateAndTimeFilter.java} (61%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/AbsoluteTimeFilter.java} (61%)
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/util/ControlFilter.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/util/EnhancedJunitTestRunnerFilter.java
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/EnhancedLineNumberFilter.java} (54%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/Filter.java} (56%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/ISO8601Filter.java} (61%)
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/util/JunitTestRunnerFilter.java
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/LineNumberFilter.java} (61%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/RelativeTimeFilter.java} (61%)
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/util/SunReflectFilter.java
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/util/Transformer.java
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/UnexpectedFormatException.java} (61%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/XMLLineAttributeFilter.java} (60%)
 copy log4j-1.2-api/src/test/java/org/apache/log4j/{helpers/UtilLoggingLevelTest.java => util/XMLTimestampFilter.java} (61%)
 create mode 100644 log4j-1.2-api/src/test/java/org/apache/log4j/xml/DOMTestCase.java
 copy log4j-1.2-api/src/test/resources/{log4j1-file.properties => LOG4J2-3407.properties} (69%)
 copy log4j-core/src/test/resources/RootLoggerLevelAppenderTest.properties => log4j-1.2-api/src/test/resources/config-1.2/log4j-global-threshold.properties (55%)
 copy log4j-1.2-api/src/test/resources/{log4j1-1.2.17/input/xml/DOMTestCase1.xml => config-1.2/log4j-global-threshold.xml} (52%)
 copy log4j-1.2-api/src/test/resources/{log4j1-file.properties => config-1.2/log4j-untrimmed.properties} (50%)
 create mode 100644 log4j-1.2-api/src/test/resources/log4j-multipleFilters.properties
 create mode 100644 log4j-1.2-api/src/test/resources/log4j-multipleFilters.xml
 copy log4j-1.2-api/src/test/resources/{log4j1-file.properties => log4j1-appenders-custom-1.properties} (81%)
 copy log4j-1.2-api/src/test/resources/{log4j1-file.properties => log4j1-appenders-custom-2.properties} (81%)
 copy log4j-1.2-api/src/test/resources/{log4j1-file.properties => log4j1-file-1.properties} (99%)
 rename log4j-1.2-api/src/test/resources/{log4j1-file.properties => log4j1-file-2.properties} (89%)
 create mode 100644 log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
 create mode 100644 log4j-api/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
 copy log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java => log4j-api/src/test/java/org/apache/logging/log4j/util/test/BetterService.java (86%)
 copy log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java => log4j-api/src/test/java/org/apache/logging/log4j/util/test/Service.java (86%)
 copy log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java => log4j-api/src/test/java/org/apache/logging/log4j/util/test/Service1.java (86%)
 copy log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java => log4j-api/src/test/java/org/apache/logging/log4j/util/test/Service2.java (86%)
 copy log4j-core/src/test/resources/LoggerLevelAppenderTest.properties => log4j-api/src/test/resources/Jira3413Test.properties (64%)
 copy log4j-spring-boot/src/main/resources/log4j2.system.properties => log4j-api/src/test/resources/META-INF/services/org.apache.logging.log4j.util.test.BetterService (86%)
 copy log4j-core/src/test/resources/LoggerLevelAppenderTest.properties => log4j-api/src/test/resources/META-INF/services/org.apache.logging.log4j.util.test.Service (73%)
 copy log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/validation/constraints/{Required.java => NotBlank.java} (76%)
 copy log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/validation/validators/{RequiredValidator.java => NotBlankValidator.java} (66%)
 copy log4j-core/src/test/java/org/apache/logging/log4j/core/appender/{FileAppenderBuilderTest.java => AbstractAppenderBuilderTest.java} (53%)
 create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfigurationPropertyTest.java
 create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfiguratorSetLevelTest.java
 create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/config/ReconfigurationFailureTest.java
 create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/filter/CompositeFilterTest.java
 create mode 100644 log4j-core/src/test/java/org/apache/logging/log4j/core/net/UrlConnectionFactoryTest.java
 copy log4j-spring-boot/src/test/resources/log4j2-springProfile.xml => log4j-core/src/test/resources/InvalidConfig.xml (62%)
 copy log4j-spring-boot/src/test/resources/log4j2-springProfile.xml => log4j-core/src/test/resources/InvalidXML.xml (64%)
 copy log4j-core/src/test/resources/{LoggerLevelAppenderTest.properties => LoggerLevelSysPropsAppenderTest.properties} (80%)
 create mode 100644 log4j-core/src/test/resources/jarfile.jar
 create mode 100644 log4j-core/src/test/resources/jarfile/config/console.xml
 copy log4j-spring-boot/src/test/resources/log4j2-springProfile.xml => log4j-core/src/test/resources/log4j-set-level.xml (66%)
 create mode 100644 log4j-couchdb/revapi.json
 create mode 100644 log4j-docker/revapi.json
 create mode 100644 log4j-flume-ng/revapi.json
 create mode 100644 log4j-iostreams/revapi.json
 create mode 100644 log4j-jcl/revapi.json
 create mode 100644 log4j-jdbc-dbcp2/revapi.json
 create mode 100644 log4j-jmx-gui/revapi.json
 create mode 100644 log4j-jul/revapi.json
 create mode 100644 log4j-kubernetes/revapi.json
 create mode 100644 log4j-mongodb3/revapi.json
 create mode 100644 log4j-mongodb4/revapi.json
 rename log4j-spring-boot/src/main/resources/{log4j2.system.properties => META-INF/spring.factories} (85%)
 create mode 100644 log4j-spring-boot/src/test/java/org/apache/logging/log4j/spring/boot/Log4j2SpringBootInitTest.java
 create mode 100644 log4j-spring-boot/src/test/resources/application.yml
 create mode 100644 log4j-to-jul/revapi.json

[logging-log4j2] 07/16: LOG4J2-3393 Replace lambdas with classes to ease performance troubleshooting.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 3f6a9af70bcab0d4e80c90a0cbcd2a6becac9791
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Sat Feb 19 19:52:11 2022 +0100

    LOG4J2-3393 Replace lambdas with classes to ease performance troubleshooting.
---
 .../template/json/resolver/TemplateResolvers.java  | 166 ++++++++++++++++-----
 1 file changed, 128 insertions(+), 38 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java
index 450b874..125d5c4 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java
@@ -51,30 +51,44 @@ public final class TemplateResolvers {
     }
 
     private static final TemplateResolver<?> EMPTY_ARRAY_RESOLVER =
-            new UnresolvableTemplateResolver() {
-                @Override
-                public void resolve(final Object value, final JsonWriter jsonWriter) {
-                    jsonWriter.writeArrayStart();
-                    jsonWriter.writeArrayEnd();
-                }
-            };
+            new EmptyArrayResolver();
+
+    private static final class EmptyArrayResolver
+            extends UnresolvableTemplateResolver {
+
+        @Override
+        public void resolve(final Object value, final JsonWriter jsonWriter) {
+            jsonWriter.writeArrayStart();
+            jsonWriter.writeArrayEnd();
+        }
+
+    }
 
     private static final TemplateResolver<?> EMPTY_OBJECT_RESOLVER =
-            new UnresolvableTemplateResolver() {
-                @Override
-                public void resolve(final Object value, final JsonWriter jsonWriter) {
-                    jsonWriter.writeObjectStart();
-                    jsonWriter.writeObjectEnd();
-                }
-            };
+            new EmptyObjectResolver();
 
-    private static final TemplateResolver<?> NULL_RESOLVER =
-            new UnresolvableTemplateResolver() {
-                @Override
-                public void resolve(final Object value, final JsonWriter jsonWriter) {
-                    jsonWriter.writeNull();
-                }
-            };
+    private static final class EmptyObjectResolver
+            extends UnresolvableTemplateResolver {
+
+        @Override
+        public void resolve(final Object value, final JsonWriter jsonWriter) {
+            jsonWriter.writeObjectStart();
+            jsonWriter.writeObjectEnd();
+        }
+
+    }
+
+    private static final TemplateResolver<?> NULL_RESOLVER = new NullResolver();
+
+    private static final class NullResolver
+            extends UnresolvableTemplateResolver {
+
+        @Override
+        public void resolve(final Object value, final JsonWriter jsonWriter) {
+            jsonWriter.writeNull();
+        }
+
+    }
 
     public static <V, C extends TemplateResolverContext<V, C>> TemplateResolver<V> ofTemplate(
             final C context,
@@ -146,7 +160,7 @@ public final class TemplateResolvers {
             final C context,
             final List<Object> list) {
 
-        // Create resolver for each children.
+        // Create resolver for each child.
         final List<TemplateResolver<V>> itemResolvers = list
                 .stream()
                 .map(item -> {
@@ -168,7 +182,20 @@ public final class TemplateResolvers {
         }
 
         // Create a parent resolver collecting each child resolver execution.
-        return (final V value, final JsonWriter jsonWriter) -> {
+        return new ArrayResolver<>(itemResolvers);
+
+    }
+
+    private static final class ArrayResolver<V> implements TemplateResolver<V> {
+
+        private final List<TemplateResolver<V>> itemResolvers;
+
+        private ArrayResolver(final List<TemplateResolver<V>> itemResolvers) {
+            this.itemResolvers = itemResolvers;
+        }
+
+        @Override
+        public void resolve(final V value, final JsonWriter jsonWriter) {
             jsonWriter.writeArrayStart();
             for (int itemResolverIndex = 0;
                  itemResolverIndex < itemResolvers.size();
@@ -176,11 +203,12 @@ public final class TemplateResolvers {
                 if (itemResolverIndex > 0) {
                     jsonWriter.writeSeparator();
                 }
-                final TemplateResolver<V> itemResolver = itemResolvers.get(itemResolverIndex);
+                final TemplateResolver<V> itemResolver =
+                        itemResolvers.get(itemResolverIndex);
                 itemResolver.resolve(value, jsonWriter);
             }
             jsonWriter.writeArrayEnd();
-        };
+        }
 
     }
 
@@ -440,18 +468,14 @@ public final class TemplateResolvers {
                             contextJsonWriter.use(() ->
                                     contextJsonWriter.writeString(replacedText));
                     // Create a resolver dedicated to the escaped replacement.
-                    return (final V value, final JsonWriter jsonWriter) ->
-                            jsonWriter.writeRawString(escapedReplacedText);
+                    return new RawStringResolver<>(escapedReplacedText);
                 }
             }
 
             // Otherwise, the unstable substitutor needs to be invoked always at
             // runtime.
             else {
-                return (final V value, final JsonWriter jsonWriter) -> {
-                    final String replacedText = substitutor.replace(value, fieldValue);
-                    jsonWriter.writeString(replacedText);
-                };
+                return new SubstitutingStringResolver<>(substitutor, fieldValue);
             }
 
         }
@@ -461,21 +485,87 @@ public final class TemplateResolvers {
             final String escapedFieldValue =
                     contextJsonWriter.use(() ->
                             contextJsonWriter.writeString(fieldValue));
-            return (final V value, final JsonWriter jsonWriter) ->
-                    jsonWriter.writeRawString(escapedFieldValue);
+            return new RawStringResolver<>(escapedFieldValue);
+        }
+
+    }
+
+    private static final class SubstitutingStringResolver<V>
+            implements TemplateResolver<V> {
+
+        private final TemplateResolverStringSubstitutor<V> substitutor;
+
+        private final String string;
+
+        private SubstitutingStringResolver(
+                final TemplateResolverStringSubstitutor<V> substitutor,
+                final String string) {
+            this.substitutor = substitutor;
+            this.string = string;
+        }
+
+        @Override
+        public void resolve(final V value, final JsonWriter jsonWriter) {
+            final String replacedString = substitutor.replace(value, string);
+            jsonWriter.writeString(replacedString);
+        }
+
+    }
+
+    private static final class RawStringResolver<V>
+            implements TemplateResolver<V> {
+
+        private final String rawString;
+
+        private RawStringResolver(final String rawString) {
+            this.rawString = rawString;
+        }
+
+        @Override
+        public void resolve(final V ignored, final JsonWriter jsonWriter) {
+            jsonWriter.writeRawString(rawString);
         }
 
     }
 
     private static <V> TemplateResolver<V> ofNumber(final Number number) {
-        final String numberString = String.valueOf(number);
-        return (final V ignored, final JsonWriter jsonWriter) ->
-                jsonWriter.writeRawString(numberString);
+        return new NumberResolver<>(number);
+    }
+
+    private static final class NumberResolver<V>
+            implements TemplateResolver<V> {
+
+        private final String numberString;
+
+        private NumberResolver(final Number number) {
+            this.numberString = String.valueOf(number);
+        }
+
+        @Override
+        public void resolve(final V ignored, final JsonWriter jsonWriter) {
+            jsonWriter.writeRawString(numberString);
+        }
+
     }
 
     private static <V> TemplateResolver<V> ofBoolean(final boolean value) {
-        return (final V ignored, final JsonWriter jsonWriter) ->
-                jsonWriter.writeBoolean(value);
+        return new BooleanResolver<>(value);
+    }
+
+    private static final class BooleanResolver<V>
+            implements TemplateResolver<V> {
+
+        private final boolean value;
+
+        private BooleanResolver(final boolean value) {
+            this.value = value;
+        }
+
+        @Override
+        public void resolve(final V ignored, final JsonWriter jsonWriter) {
+            jsonWriter.writeBoolean(value);
+        }
+
     }
 
 }

[logging-log4j2] 03/16: LOG4J2-3393 Go wild and embed ECS Layout for troubleshooting!

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit c4cac94470a5c6a1fa774b5dd9df53360d8ebb04
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Sun Feb 13 21:16:34 2022 +0100

    LOG4J2-3393 Go wild and embed ECS Layout for troubleshooting!
---
 .../java/co/elastic/logging/log4j2/LcsLayout.java  | 390 +++++++++++++++++++++
 .../template/json/JsonTemplateLayoutBenchmark.java |   6 +-
 .../json/JsonTemplateLayoutBenchmarkState.java     |  27 +-
 3 files changed, 408 insertions(+), 15 deletions(-)

diff --git a/log4j-perf/src/main/java/co/elastic/logging/log4j2/LcsLayout.java b/log4j-perf/src/main/java/co/elastic/logging/log4j2/LcsLayout.java
new file mode 100644
index 0000000..07d0f86
--- /dev/null
+++ b/log4j-perf/src/main/java/co/elastic/logging/log4j2/LcsLayout.java
@@ -0,0 +1,390 @@
+package co.elastic.logging.log4j2;
+
+
+import co.elastic.logging.EcsJsonSerializer;
+import co.elastic.logging.JsonUtils;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
+import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout;
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.layout.Encoder;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.lookup.StrSubstitutor;
+import org.apache.logging.log4j.core.pattern.PatternFormatter;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.MultiformatMessage;
+import org.apache.logging.log4j.message.ObjectMessage;
+import org.apache.logging.log4j.util.StringBuilderFormattable;
+
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+@Plugin(name = "LcsLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE)
+public class LcsLayout extends AbstractStringLayout {
+
+    public static final Charset UTF_8 = Charset.forName("UTF-8");
+    private static final ObjectMessageJacksonSerializer JACKSON_SERIALIZER = ObjectMessageJacksonSerializer.Resolver.resolve();
+    private static final MdcSerializer MDC_SERIALIZER = MdcSerializer.Resolver.resolve();
+    private static final MultiFormatHandler MULTI_FORMAT_HANDLER = MultiFormatHandler.Resolver.resolve();
+
+    private final KeyValuePair[] additionalFields;
+    private final PatternFormatter[][] fieldValuePatternFormatter;
+    private final boolean stackTraceAsArray;
+    private final String serviceName;
+    private final String eventDataset;
+    private final boolean includeMarkers;
+    private final boolean includeOrigin;
+    private final ConcurrentMap<Class<? extends MultiformatMessage>, Boolean> supportsJson = new ConcurrentHashMap<Class<? extends MultiformatMessage>, Boolean>();
+
+    private LcsLayout(Configuration config, String serviceName, String eventDataset, boolean includeMarkers, KeyValuePair[] additionalFields, boolean includeOrigin, boolean stackTraceAsArray) {
+        super(config, UTF_8, null, null);
+        this.serviceName = serviceName;
+        this.eventDataset = eventDataset;
+        this.includeMarkers = includeMarkers;
+        this.includeOrigin = includeOrigin;
+        this.stackTraceAsArray = stackTraceAsArray;
+        this.additionalFields = additionalFields;
+        fieldValuePatternFormatter = new PatternFormatter[additionalFields.length][];
+        for (int i = 0; i < additionalFields.length; i++) {
+            KeyValuePair additionalField = additionalFields[i];
+            if (additionalField.getValue().contains("%")) {
+                fieldValuePatternFormatter[i] = PatternLayout.createPatternParser(config)
+                        .parse(additionalField.getValue())
+                        .toArray(new PatternFormatter[0]);
+            }
+        }
+    }
+
+    @PluginBuilderFactory
+    public static LcsLayout.Builder newBuilder() {
+        return new LcsLayout.Builder();
+    }
+
+    private static boolean valueNeedsLookup(final String value) {
+        return value != null && value.contains("${");
+    }
+
+    @Override
+    public String toSerializable(LogEvent event) {
+        final StringBuilder text = toText(event, getStringBuilder(), false);
+        return text.toString();
+    }
+
+    @Override
+    public void encode(LogEvent event, ByteBufferDestination destination) {
+        final StringBuilder text = toText(event, getStringBuilder(), true);
+        final Encoder<StringBuilder> helper = getStringBuilderEncoder();
+        helper.encode(text, destination);
+    }
+
+    @Override
+    public String getContentType() {
+        return "application/json";
+    }
+
+    private StringBuilder toText(LogEvent event, StringBuilder builder, boolean gcFree) {
+        builder.append('{');//EcsJsonSerializer.serializeObjectStart(builder, event.getTimeMillis());
+//        EcsJsonSerializer.serializeLogLevel(builder, event.getLevel().toString());
+//        serializeMessage(builder, gcFree, event.getMessage(), event.getThrown());
+//        EcsJsonSerializer.serializeEcsVersion(builder);
+//        EcsJsonSerializer.serializeServiceName(builder, serviceName);
+//        EcsJsonSerializer.serializeEventDataset(builder, eventDataset);
+//        EcsJsonSerializer.serializeThreadName(builder, event.getThreadName());
+//        EcsJsonSerializer.serializeLoggerName(builder, event.getLoggerName());
+//        serializeAdditionalFieldsAndMDC(event, builder);
+//        serializeTags(event, builder);
+//        if (includeOrigin) {
+//            EcsJsonSerializer.serializeOrigin(builder, event.getSource());
+//        }
+//        EcsJsonSerializer.serializeException(builder, event.getThrown(), stackTraceAsArray);
+        EcsJsonSerializer.serializeObjectEnd(builder);
+        return builder;
+    }
+
+    private void serializeAdditionalFieldsAndMDC(LogEvent event, StringBuilder builder) {
+        final int length = additionalFields.length;
+        if (length > 0) {
+            final StrSubstitutor strSubstitutor = getConfiguration().getStrSubstitutor();
+            for (int i = 0; i < length; i++) {
+                KeyValuePair additionalField = additionalFields[i];
+                PatternFormatter[] formatters = fieldValuePatternFormatter[i];
+                CharSequence value = null;
+                if (formatters != null) {
+                    StringBuilder buffer = EcsJsonSerializer.getMessageStringBuilder();
+                    formatPattern(event, formatters, buffer);
+                    if (buffer.length() > 0) {
+                        value = buffer;
+                    }
+                } else if (valueNeedsLookup(additionalField.getValue())) {
+                    StringBuilder lookupValue = EcsJsonSerializer.getMessageStringBuilder();
+                    lookupValue.append(additionalField.getValue());
+                    if (strSubstitutor.replaceIn(event, lookupValue)) {
+                        value = lookupValue;
+                    }
+                } else {
+                    value = additionalField.getValue();
+                }
+
+                if (value != null) {
+                    builder.append('\"');
+                    JsonUtils.quoteAsString(additionalField.getKey(), builder);
+                    builder.append("\":\"");
+                    JsonUtils.quoteAsString(EcsJsonSerializer.toNullSafeString(value), builder);
+                    builder.append("\",");
+                }
+            }
+        }
+        MDC_SERIALIZER.serializeMdc(event, builder);
+    }
+
+    private static void formatPattern(LogEvent event, PatternFormatter[] formatters, StringBuilder buffer) {
+        final int len = formatters.length;
+        for (int i = 0; i < len; i++) {
+            formatters[i].format(event, buffer);
+        }
+    }
+
+    private void serializeTags(LogEvent event, StringBuilder builder) {
+        ThreadContext.ContextStack stack = event.getContextStack();
+        List<String> contextStack;
+        if (stack == null) {
+            contextStack = Collections.emptyList();
+        } else {
+            contextStack = stack.asList();
+        }
+        Marker marker = event.getMarker();
+        boolean hasTags = !contextStack.isEmpty() || (includeMarkers && marker != null);
+        if (hasTags) {
+            EcsJsonSerializer.serializeTagStart(builder);
+        }
+
+        if (!contextStack.isEmpty()) {
+            final int len = contextStack.size();
+            for (int i = 0; i < len; i++) {
+                builder.append('\"');
+                JsonUtils.quoteAsString(contextStack.get(i), builder);
+                builder.append("\",");
+            }
+        }
+
+        if (includeMarkers && marker != null) {
+            serializeMarker(builder, marker);
+        }
+
+        if (hasTags) {
+            EcsJsonSerializer.serializeTagEnd(builder);
+        }
+    }
+
+    private void serializeMarker(StringBuilder builder, Marker marker) {
+        EcsJsonSerializer.serializeSingleTag(builder, marker.getName());
+        if (marker.hasParents()) {
+            Marker[] parents = marker.getParents();
+            for (int i = 0; i < parents.length; i++) {
+                serializeMarker(builder, parents[i]);
+            }
+        }
+    }
+
+    private void serializeMessage(StringBuilder builder, boolean gcFree, Message message, Throwable thrown) {
+        if (message instanceof MultiformatMessage) {
+            MultiformatMessage multiformatMessage = (MultiformatMessage) message;
+            if (supportsJson(multiformatMessage)) {
+                serializeJsonMessage(builder, multiformatMessage);
+            } else {
+                serializeSimpleMessage(builder, gcFree, message, thrown);
+            }
+        } else if (JACKSON_SERIALIZER != null && message instanceof ObjectMessage) {
+            final StringBuilder jsonBuffer = EcsJsonSerializer.getMessageStringBuilder();
+            JACKSON_SERIALIZER.formatTo(jsonBuffer, (ObjectMessage) message);
+            addJson(builder, jsonBuffer);
+        } else {
+            serializeSimpleMessage(builder, gcFree, message, thrown);
+        }
+    }
+
+    private static void serializeJsonMessage(StringBuilder builder, MultiformatMessage message) {
+        final StringBuilder messageBuffer = EcsJsonSerializer.getMessageStringBuilder();
+        MULTI_FORMAT_HANDLER.formatJsonTo(message, messageBuffer);
+        addJson(builder, messageBuffer);
+    }
+
+    private static void addJson(StringBuilder buffer, StringBuilder jsonBuffer) {
+        if (isObject(jsonBuffer)) {
+            moveToRoot(jsonBuffer);
+            buffer.append(jsonBuffer);
+            buffer.append(", ");
+        } else {
+            buffer.append("\"message\":");
+            if (isString(jsonBuffer)) {
+                buffer.append(jsonBuffer);
+            } else {
+                // message always has to be a string to avoid mapping conflicts
+                buffer.append('"');
+                JsonUtils.quoteAsString(jsonBuffer, buffer);
+                buffer.append('"');
+            }
+            buffer.append(", ");
+        }
+    }
+
+    private void serializeSimpleMessage(StringBuilder builder, boolean gcFree, Message message, Throwable thrown) {
+        builder.append("\"message\":\"");
+        if (message instanceof CharSequence) {
+            JsonUtils.quoteAsString(((CharSequence) message), builder);
+        } else if (gcFree && message instanceof StringBuilderFormattable) {
+            final StringBuilder messageBuffer = EcsJsonSerializer.getMessageStringBuilder();
+            try {
+                ((StringBuilderFormattable) message).formatTo(messageBuffer);
+                JsonUtils.quoteAsString(messageBuffer, builder);
+            } finally {
+                trimToMaxSizeCopy(messageBuffer);
+            }
+        } else {
+            JsonUtils.quoteAsString(EcsJsonSerializer.toNullSafeString(message.getFormattedMessage()), builder);
+        }
+        builder.append("\", ");
+    }
+
+    static void trimToMaxSizeCopy(final StringBuilder stringBuilder) {
+        if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
+            stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
+            stringBuilder.trimToSize();
+        }
+    }
+
+    private static boolean isObject(StringBuilder messageBuffer) {
+        return messageBuffer.length() > 1 && messageBuffer.charAt(0) == '{' && messageBuffer.charAt(messageBuffer.length() - 1) == '}';
+    }
+
+    private static boolean isString(StringBuilder messageBuffer) {
+        return messageBuffer.length() > 1 && messageBuffer.charAt(0) == '"' && messageBuffer.charAt(messageBuffer.length() - 1) == '"';
+    }
+
+    private static void moveToRoot(StringBuilder messageBuffer) {
+        messageBuffer.setCharAt(0, ' ');
+        messageBuffer.setCharAt(messageBuffer.length() -1, ' ');
+    }
+
+    private boolean supportsJson(MultiformatMessage message) {
+        Boolean supportsJson = this.supportsJson.get(message.getClass());
+        if (supportsJson == null) {
+            supportsJson = false;
+            for (String format : message.getFormats()) {
+                if (format.equalsIgnoreCase("JSON")) {
+                    supportsJson = true;
+                    break;
+                }
+            }
+            this.supportsJson.put(message.getClass(), supportsJson);
+        }
+        return supportsJson;
+    }
+
+    public static class Builder implements org.apache.logging.log4j.core.util.Builder<LcsLayout> {
+
+        @PluginConfiguration
+        private Configuration configuration;
+        @PluginBuilderAttribute("serviceName")
+        private String serviceName;
+        @PluginBuilderAttribute("eventDataset")
+        private String eventDataset;
+        @PluginBuilderAttribute("includeMarkers")
+        private boolean includeMarkers = false;
+        @PluginBuilderAttribute("stackTraceAsArray")
+        private boolean stackTraceAsArray = false;
+        @PluginElement("AdditionalField")
+        private KeyValuePair[] additionalFields = new KeyValuePair[]{};
+        @PluginBuilderAttribute("includeOrigin")
+        private boolean includeOrigin = false;
+
+        Builder() {
+        }
+
+        public Configuration getConfiguration() {
+            return configuration;
+        }
+
+        public LcsLayout.Builder setConfiguration(final Configuration configuration) {
+            this.configuration = configuration;
+            return this;
+        }
+
+        public KeyValuePair[] getAdditionalFields() {
+            return additionalFields.clone();
+        }
+
+        public String getServiceName() {
+            return serviceName;
+        }
+
+        public String getEventDataset() {
+            return eventDataset;
+        }
+
+        public boolean isIncludeMarkers() {
+            return includeMarkers;
+        }
+
+        public boolean isIncludeOrigin() {
+            return includeOrigin;
+        }
+
+        /**
+         * Additional fields to set on each log event.
+         *
+         * @return this builder
+         */
+        public LcsLayout.Builder setAdditionalFields(final KeyValuePair[] additionalFields) {
+            this.additionalFields = additionalFields.clone();
+            return this;
+        }
+
+        public LcsLayout.Builder setServiceName(final String serviceName) {
+            this.serviceName = serviceName;
+            return this;
+        }
+
+        public LcsLayout.Builder setEventDataset(String eventDataset) {
+            this.eventDataset = eventDataset;
+            return this;
+        }
+
+        public LcsLayout.Builder setIncludeMarkers(final boolean includeMarkers) {
+            this.includeMarkers = includeMarkers;
+            return this;
+        }
+
+        public LcsLayout.Builder setIncludeOrigin(final boolean includeOrigin) {
+            this.includeOrigin = includeOrigin;
+            return this;
+        }
+
+        public LcsLayout.Builder setStackTraceAsArray(boolean stackTraceAsArray) {
+            this.stackTraceAsArray = stackTraceAsArray;
+            return this;
+        }
+
+        @Override
+        public LcsLayout build() {
+            return new LcsLayout(getConfiguration(), serviceName, EcsJsonSerializer.computeEventDataset(eventDataset, serviceName), includeMarkers, additionalFields, includeOrigin, stackTraceAsArray);
+        }
+
+        public boolean isStackTraceAsArray() {
+            return stackTraceAsArray;
+        }
+    }
+}
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
index dce0690..2f865fa 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
@@ -184,10 +184,10 @@ public class JsonTemplateLayoutBenchmark {
     }
 
     public static void main(String[] args) throws IOException {
-        System.out.format("Ready?");
-        System.in.read();
+//        System.out.format("Ready?");
+//        System.in.read();
         JsonTemplateLayoutBenchmarkState state = new JsonTemplateLayoutBenchmarkState();
-        int retryCount = 10_000;
+        int retryCount = 200_000;
         measureEcs(state, retryCount);
         measureJtl(state, retryCount);
     }
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
index 093af99..54c8c0b 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
@@ -17,6 +17,8 @@
 package org.apache.logging.log4j.layout.template.json;
 
 import co.elastic.logging.log4j2.EcsLayout;
+import co.elastic.logging.log4j2.LcsLayout;
+import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
@@ -53,7 +55,7 @@ public class JsonTemplateLayoutBenchmarkState {
 
     private final JsonLayout customJsonLayout;
 
-    private final EcsLayout ecsLayout;
+    private final LcsLayout ecsLayout;
 
     private final GelfLayout gelfLayout;
 
@@ -98,9 +100,10 @@ public class JsonTemplateLayoutBenchmarkState {
                 .newBuilder()
                 .setConfiguration(CONFIGURATION)
                 .setCharset(CHARSET)
-                .setEventTemplateUri("classpath:EcsLayout.json")
+                .setEventTemplate("{}")
+//                .setEventTemplateUri("classpath:EcsLayout.json")
                 .setRecyclerFactory(ThreadLocalRecyclerFactory.getInstance())
-                .setEventTemplateAdditionalFields(additionalFields)
+//                .setEventTemplateAdditionalFields(additionalFields)
                 .build();
     }
 
@@ -144,8 +147,8 @@ public class JsonTemplateLayoutBenchmarkState {
                 .build();
     }
 
-    private static EcsLayout createEcsLayout() {
-        final EcsLayout layout = EcsLayout
+    private static LcsLayout createEcsLayout() {
+        final LcsLayout layout = LcsLayout
                 .newBuilder()
                 .setConfiguration(CONFIGURATION)
                 .setServiceName("benchmark")
@@ -173,31 +176,31 @@ public class JsonTemplateLayoutBenchmarkState {
         return byteBufferDestination;
     }
 
-    JsonTemplateLayout getJsonTemplateLayout4JsonLayout() {
+    Layout<String> getJsonTemplateLayout4JsonLayout() {
         return jsonTemplateLayout4JsonLayout;
     }
 
-    JsonTemplateLayout getJsonTemplateLayout4EcsLayout() {
+    Layout<String> getJsonTemplateLayout4EcsLayout() {
         return jsonTemplateLayout4EcsLayout;
     }
 
-    JsonTemplateLayout getJsonTemplateLayout4GelfLayout() {
+    Layout<String> getJsonTemplateLayout4GelfLayout() {
         return jsonTemplateLayout4GelfLayout;
     }
 
-    JsonLayout getDefaultJsonLayout() {
+    Layout<String> getDefaultJsonLayout() {
         return defaultJsonLayout;
     }
 
-    JsonLayout getCustomJsonLayout() {
+    Layout<String> getCustomJsonLayout() {
         return customJsonLayout;
     }
 
-    EcsLayout getEcsLayout() {
+    Layout<String> getEcsLayout() {
         return ecsLayout;
     }
 
-    GelfLayout getGelfLayout() {
+    Layout<String> getGelfLayout() {
         return gelfLayout;
     }
 

[logging-log4j2] 04/16: LOG4J2-3393 Improve "blackhole" behavior in ByteBuffer consumption.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit a6046238a8dbe72ba4bd42f01ecad889fc2224b3
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 14 22:57:30 2022 +0100

    LOG4J2-3393 Improve "blackhole" behavior in ByteBuffer consumption.
---
 .../layout/template/json/BlackHoleByteBufferDestination.java   | 10 ++++++++--
 .../layout/template/json/JsonTemplateLayoutBenchmark.java      |  9 +++++----
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java
index 3c0f4fb..ca6041b 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.layout.template.json;
 
 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.layout.ByteBufferDestinationHelper;
 
 import java.nio.ByteBuffer;
 
@@ -35,16 +36,21 @@ class BlackHoleByteBufferDestination implements ByteBufferDestination {
 
     @Override
     public ByteBuffer drain(final ByteBuffer byteBuffer) {
+        byteBuffer.flip();
+        this.byteBuffer.clear();
+        this.byteBuffer.put(byteBuffer);
         byteBuffer.clear();
         return byteBuffer;
     }
 
     @Override
     public void writeBytes(final ByteBuffer byteBuffer) {
-        byteBuffer.clear();
+        ByteBufferDestinationHelper.writeToUnsynchronized(byteBuffer, this);
     }
 
     @Override
-    public void writeBytes(final byte[] buffer, final int offset, final int length) {}
+    public void writeBytes(final byte[] buffer, final int offset, final int length) {
+        ByteBufferDestinationHelper.writeToUnsynchronized(buffer, offset, length, this);
+    }
 
 }
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
index 2f865fa..0b3ca8b 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
@@ -172,15 +172,16 @@ public class JsonTemplateLayoutBenchmark {
             final Layout<String> layout,
             final List<LogEvent> logEvents,
             final ByteBufferDestination destination) {
+        final ByteBuffer byteBuffer = destination.getByteBuffer();
+        int checksum = 0;
         // noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
         for (int logEventIndex = 0; logEventIndex < logEvents.size(); logEventIndex++) {
             LogEvent logEvent = logEvents.get(logEventIndex);
             layout.encode(logEvent, destination);
+            checksum += byteBuffer.position();
+            byteBuffer.clear();
         }
-        final ByteBuffer byteBuffer = destination.getByteBuffer();
-        final int position = byteBuffer.position();
-        byteBuffer.clear();
-        return position;
+        return checksum;
     }
 
     public static void main(String[] args) throws IOException {

[logging-log4j2] 01/16: LOG4J2-3393 Refactor JTL TemplateResolvers into smaller components.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit a0a310f6671295817ddb0e4a83883e98fd0b9311
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 7 10:53:48 2022 +0100

    LOG4J2-3393 Refactor JTL TemplateResolvers into smaller components.
---
 .../template/json/resolver/TemplateResolvers.java  | 224 +++++++++++++++------
 1 file changed, 160 insertions(+), 64 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java
index 20ad802..450b874 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolvers.java
@@ -24,6 +24,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * Main class for compiling {@link TemplateResolver}s from a template.
@@ -192,6 +193,28 @@ public final class TemplateResolvers {
             return ofResolver(context, map);
         }
 
+        // Collect field resolver contexts.
+        List<FieldResolverContext<V>> fieldResolverContexts =
+                populateFieldResolverMethods(context, map);
+
+        // Short-circuit if the object is empty.
+        final int fieldCount = fieldResolverContexts.size();
+        if (fieldCount == 0) {
+            @SuppressWarnings("unchecked")
+            final TemplateResolver<V> emptyObjectResolver =
+                    (TemplateResolver<V>) EMPTY_OBJECT_RESOLVER;
+            return emptyObjectResolver;
+        }
+
+        // Create the resolver.
+        return new MapResolver<>(fieldResolverContexts);
+
+    }
+
+    private static <V, C extends TemplateResolverContext<V, C>> List<FieldResolverContext<V>> populateFieldResolverMethods(
+            final C context,
+            final Map<String, Object> map) {
+
         // Create resolver for each object field.
         final List<String> fieldNames = new ArrayList<>();
         final List<TemplateResolver<V>> fieldResolvers = new ArrayList<>();
@@ -204,15 +227,6 @@ public final class TemplateResolvers {
             }
         });
 
-        // Short-circuit if the object is empty.
-        final int fieldCount = fieldNames.size();
-        if (fieldCount == 0) {
-            @SuppressWarnings("unchecked")
-            final TemplateResolver<V> emptyObjectResolver =
-                    (TemplateResolver<V>) EMPTY_OBJECT_RESOLVER;
-            return emptyObjectResolver;
-        }
-
         // Prepare field names to avoid escape and truncation costs at runtime.
         final List<String> fieldPrefixes = fieldNames
                 .stream()
@@ -225,70 +239,152 @@ public final class TemplateResolvers {
                 })
                 .collect(Collectors.toList());
 
-        return new TemplateResolver<V>() {
-
-            @Override
-            public boolean isResolvable() {
-                // We have already excluded unresolvable ones while collecting
-                // the resolvers. Hence it is safe to return true here.
-                return true;
-            }
-
-            /**
-             * The parent resolver checking if each child is resolvable given
-             * the passed {@code value}.
-             *
-             * This is an optimization to skip the rendering of a parent if all
-             * its children are not resolvable given the passed {@code value}.
-             */
-            @Override
-            public boolean isResolvable(final V value) {
-                for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
-                    final TemplateResolver<V> fieldResolver = fieldResolvers.get(fieldIndex);
-                    final boolean resolvable = fieldResolver.isResolvable(value);
-                    if (resolvable) {
-                        return true;
-                    }
-                }
-                return false;
-            }
-
-            /**
-             * The parent resolver combining all child resolver executions.
-              */
-            @Override
-            public void resolve(final V value, final JsonWriter jsonWriter) {
-                final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
-                jsonWriter.writeObjectStart();
-                for (int resolvedFieldCount = 0, fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
+        // Collect field resolver contexts.
+        final int fieldCount = fieldNames.size();
+        return IntStream
+                .range(0, fieldCount)
+                .mapToObj(fieldIndex -> {
                     final TemplateResolver<V> fieldResolver = fieldResolvers.get(fieldIndex);
-                    final boolean resolvable = fieldResolver.isResolvable(value);
-                    if (!resolvable) {
-                        continue;
-                    }
-                    final boolean succeedingEntry = resolvedFieldCount > 0;
+                    final FieldResolverMethod<V> fieldResolverMethod;
                     final boolean flattening = fieldResolver.isFlattening();
                     if (flattening) {
-                        final int initLength = jsonWriterStringBuilder.length();
-                        fieldResolver.resolve(value, jsonWriter, succeedingEntry);
-                        final boolean resolved = jsonWriterStringBuilder.length() > initLength;
-                        if (resolved) {
-                            resolvedFieldCount++;
-                        }
+                        fieldResolverMethod = new FlatteningFieldResolverMethod<>(fieldResolver);
                     } else {
-                        if (succeedingEntry) {
-                            jsonWriter.writeSeparator();
-                        }
                         final String fieldPrefix = fieldPrefixes.get(fieldIndex);
-                        jsonWriter.writeRawString(fieldPrefix);
-                        fieldResolver.resolve(value, jsonWriter, succeedingEntry);
-                        resolvedFieldCount++;
+                        fieldResolverMethod = new PrefixedFieldResolverMethod<>(fieldPrefix, fieldResolver);
                     }
+                    return new FieldResolverContext<>(fieldResolver, fieldResolverMethod);
+                })
+                .collect(Collectors.toList());
+
+    }
+
+    private static final class FieldResolverContext<V> {
+
+        private final TemplateResolver<V> resolver;
+
+        private final FieldResolverMethod<V> resolverMethod;
+
+        private FieldResolverContext(final TemplateResolver<V> resolver, final FieldResolverMethod<V> resolverMethod) {
+            this.resolver = resolver;
+            this.resolverMethod = resolverMethod;
+        }
+
+    }
+
+    @FunctionalInterface
+    private interface FieldResolverMethod<V> {
+
+        boolean resolve(V value, JsonWriter jsonWriter, boolean succeedingEntry);
+
+    }
+
+    private static final class FlatteningFieldResolverMethod<V> implements FieldResolverMethod<V> {
+
+        private final TemplateResolver<V> fieldResolver;
+
+        private FlatteningFieldResolverMethod(final TemplateResolver<V> fieldResolver) {
+            this.fieldResolver = fieldResolver;
+        }
+
+        @Override
+        public boolean resolve(final V value, final JsonWriter jsonWriter, final boolean succeedingEntry) {
+            final boolean resolvable = fieldResolver.isResolvable(value);
+            if (!resolvable) {
+                return false;
+            }
+            final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder();
+            final int initLength = jsonWriterStringBuilder.length();
+            fieldResolver.resolve(value, jsonWriter, succeedingEntry);
+            return jsonWriterStringBuilder.length() > initLength;
+        }
+
+    }
+
+    private static final class PrefixedFieldResolverMethod<V> implements FieldResolverMethod<V> {
+
+        private final String fieldPrefix;
+
+        private final TemplateResolver<V> fieldResolver;
+
+        private PrefixedFieldResolverMethod(final String fieldPrefix, final TemplateResolver<V> fieldResolver) {
+            this.fieldPrefix = fieldPrefix;
+            this.fieldResolver = fieldResolver;
+        }
+
+        @Override
+        public boolean resolve(final V value, final JsonWriter jsonWriter, final boolean succeedingEntry) {
+            final boolean resolvable = fieldResolver.isResolvable(value);
+            if (!resolvable) {
+                return false;
+            }
+            if (succeedingEntry) {
+                jsonWriter.writeSeparator();
+            }
+            jsonWriter.writeRawString(fieldPrefix);
+            fieldResolver.resolve(value, jsonWriter, succeedingEntry);
+            return true;
+        }
+
+    }
+
+    private static final class MapResolver<V> implements TemplateResolver<V> {
+
+        private final List<FieldResolverContext<V>> fieldResolverContexts;
+
+        private MapResolver(final List<FieldResolverContext<V>> fieldResolverContexts) {
+            this.fieldResolverContexts = fieldResolverContexts;
+        }
+
+        @Override
+        public boolean isResolvable() {
+            // We have already excluded unresolvable ones while collecting
+            // the resolvers; it is safe to return true here.
+            return true;
+        }
+
+        /**
+         * The parent resolver checking if each child is resolvable given
+         * the passed {@code value}.
+         *
+         * This is an optimization to skip the rendering of a parent if all
+         * its children are not resolvable for the given {@code value}.
+         */
+        @Override
+        public boolean isResolvable(final V value) {
+            int fieldCount = fieldResolverContexts.size();
+            // noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
+            for (int fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
+                final TemplateResolver<V> fieldResolver = fieldResolverContexts.get(fieldIndex).resolver;
+                final boolean resolvable = fieldResolver.isResolvable(value);
+                if (resolvable) {
+                    return true;
                 }
-                jsonWriter.writeObjectEnd();
             }
+            return false;
+        }
 
-        };
+        /**
+         * The parent resolver combining all child resolver executions.
+         */
+        @Override
+        public void resolve(final V value, final JsonWriter jsonWriter) {
+            jsonWriter.writeObjectStart();
+            int fieldCount = fieldResolverContexts.size();
+            for (int resolvedFieldCount = 0, fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
+                FieldResolverContext<V> fieldResolverContext = fieldResolverContexts.get(fieldIndex);
+                final boolean resolvable = fieldResolverContext.resolver.isResolvable(value);
+                if (!resolvable) {
+                    continue;
+                }
+                final boolean succeedingEntry = resolvedFieldCount > 0;
+                final boolean resolved = fieldResolverContext.resolverMethod.resolve(value, jsonWriter, succeedingEntry);
+                if (resolved) {
+                    resolvedFieldCount++;
+                }
+            }
+            jsonWriter.writeObjectEnd();
+        }
 
     }
 

[logging-log4j2] 02/16: LOG4J2-3393 Create JTL benchmark main() for easy testing.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit cdade7459c359397a3c861997d7f39a1c9cf1f2d
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 7 10:54:30 2022 +0100

    LOG4J2-3393 Create JTL benchmark main() for easy testing.
---
 .../template/json/JsonTemplateLayoutBenchmark.java | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
index 1099625..dce0690 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
 import org.openjdk.jmh.annotations.Benchmark;
 
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.List;
 
@@ -182,4 +183,29 @@ public class JsonTemplateLayoutBenchmark {
         return position;
     }
 
+    public static void main(String[] args) throws IOException {
+        System.out.format("Ready?");
+        System.in.read();
+        JsonTemplateLayoutBenchmarkState state = new JsonTemplateLayoutBenchmarkState();
+        int retryCount = 10_000;
+        measureEcs(state, retryCount);
+        measureJtl(state, retryCount);
+    }
+
+    private static void measureJtl(JsonTemplateLayoutBenchmarkState state, int retryCount) {
+        long startInstantNanos = System.nanoTime();
+        for (int i = 0; i < retryCount; i++) {
+            liteJsonTemplateLayout4EcsLayout(state);
+        }
+        System.out.format("%.3fs%n", (System.nanoTime() - startInstantNanos) / 1e9);
+    }
+
+    private static void measureEcs(JsonTemplateLayoutBenchmarkState state, int retryCount) {
+        long startInstantNanos = System.nanoTime();
+        for (int i = 0; i < retryCount; i++) {
+            liteEcsLayout(state);
+        }
+        System.out.format("%.3fs%n", (System.nanoTime() - startInstantNanos) / 1e9);
+    }
+
 }

[logging-log4j2] 06/16: LOG4J2-3393 Use a single LogEvent in JMH benchmarks.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 7136e8c6d674e9cd41d342ea32fb27807070cdd5
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Fri Feb 18 16:50:32 2022 +0100

    LOG4J2-3393 Use a single LogEvent in JMH benchmarks.
---
 .../json/BlackHoleByteBufferDestination.java       |  6 +-
 .../template/json/JsonTemplateLayoutBenchmark.java | 80 +++++++++++-----------
 .../json/JsonTemplateLayoutBenchmarkState.java     | 18 +++--
 3 files changed, 58 insertions(+), 46 deletions(-)

diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java
index ca6041b..0fab5ab 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/BlackHoleByteBufferDestination.java
@@ -37,8 +37,10 @@ class BlackHoleByteBufferDestination implements ByteBufferDestination {
     @Override
     public ByteBuffer drain(final ByteBuffer byteBuffer) {
         byteBuffer.flip();
-        this.byteBuffer.clear();
-        this.byteBuffer.put(byteBuffer);
+        if (this.byteBuffer != byteBuffer) {
+            this.byteBuffer.clear();
+            this.byteBuffer.put(byteBuffer);
+        }
         byteBuffer.clear();
         return byteBuffer;
     }
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
index 0b3ca8b..58c5852 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
@@ -46,149 +46,151 @@ public class JsonTemplateLayoutBenchmark {
     public static int fullJsonTemplateLayout4JsonLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getJsonTemplateLayout4JsonLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteJsonTemplateLayout4JsonLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getJsonTemplateLayout4JsonLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     @Benchmark
     public static int fullJsonTemplateLayout4EcsLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getJsonTemplateLayout4EcsLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteJsonTemplateLayout4EcsLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getJsonTemplateLayout4EcsLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     @Benchmark
     public static int fullJsonTemplateLayout4GelfLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getJsonTemplateLayout4GelfLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteJsonTemplateLayout4GelfLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getJsonTemplateLayout4GelfLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     @Benchmark
     public static int fullDefaultJsonLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getDefaultJsonLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteDefaultJsonLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getDefaultJsonLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     @Benchmark
     public static int fullCustomJsonLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getCustomJsonLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteCustomJsonLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getCustomJsonLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     @Benchmark
     public static int fullEcsLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getEcsLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteEcsLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getEcsLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     @Benchmark
     public static int fullGelfLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getGelfLayout(),
-                state.getFullLogEvents(),
-                state.getByteBufferDestination());
+                state.getFullLogEvents());
     }
 
     @Benchmark
     public static int liteGelfLayout(
             final JsonTemplateLayoutBenchmarkState state) {
         return benchmark(
+                state,
                 state.getGelfLayout(),
-                state.getLiteLogEvents(),
-                state.getByteBufferDestination());
+                state.getLiteLogEvents());
     }
 
     private static int benchmark(
+            final JsonTemplateLayoutBenchmarkState state,
             final Layout<String> layout,
-            final List<LogEvent> logEvents,
+            final List<LogEvent> logEvents) {
+        final int logEventIndex = state.nextLogEventIndex();
+        final LogEvent logEvent = logEvents.get(logEventIndex);
+        return benchmark(layout, logEvent, state.getByteBufferDestination());
+    }
+
+    private static int benchmark(
+            final Layout<String> layout,
+            final LogEvent logEvent,
             final ByteBufferDestination destination) {
         final ByteBuffer byteBuffer = destination.getByteBuffer();
-        int checksum = 0;
-        // noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
-        for (int logEventIndex = 0; logEventIndex < logEvents.size(); logEventIndex++) {
-            LogEvent logEvent = logEvents.get(logEventIndex);
-            layout.encode(logEvent, destination);
-            checksum += byteBuffer.position();
-            byteBuffer.clear();
-        }
-        return checksum;
+        layout.encode(logEvent, destination);
+        return byteBuffer.position();
     }
 
     public static void main(String[] args) throws IOException {
 //        System.out.format("Ready?");
 //        System.in.read();
         JsonTemplateLayoutBenchmarkState state = new JsonTemplateLayoutBenchmarkState();
-        int retryCount = 200_000;
+        int retryCount = 200_000_000;
         measureEcs(state, retryCount);
         measureJtl(state, retryCount);
     }
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
index 54c8c0b..3fc5c5b 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmarkState.java
@@ -16,7 +16,6 @@
  */
 package org.apache.logging.log4j.layout.template.json;
 
-import co.elastic.logging.log4j2.EcsLayout;
 import co.elastic.logging.log4j2.LcsLayout;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
@@ -36,13 +35,15 @@ import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 
-@State(Scope.Benchmark)
+@State(Scope.Thread)
 public class JsonTemplateLayoutBenchmarkState {
 
     private static final Configuration CONFIGURATION = new DefaultConfiguration();
 
     private static final Charset CHARSET = StandardCharsets.UTF_8;
 
+    private static final int LOG_EVENT_COUNT = 1_000;
+
     private final ByteBufferDestination byteBufferDestination;
 
     private final JsonTemplateLayout jsonTemplateLayout4JsonLayout;
@@ -63,6 +64,8 @@ public class JsonTemplateLayoutBenchmarkState {
 
     private final List<LogEvent> liteLogEvents;
 
+    private int logEventIndex = 0;
+
     public JsonTemplateLayoutBenchmarkState() {
         this.byteBufferDestination = new BlackHoleByteBufferDestination(1024 * 512);
         this.jsonTemplateLayout4JsonLayout = createJsonTemplateLayout4JsonLayout();
@@ -72,9 +75,8 @@ public class JsonTemplateLayoutBenchmarkState {
         this.customJsonLayout = createCustomJsonLayout();
         this.ecsLayout = createEcsLayout();
         this.gelfLayout = createGelfLayout();
-        int logEventCount = 1_000;
-        this.fullLogEvents = LogEventFixture.createFullLogEvents(logEventCount);
-        this.liteLogEvents = LogEventFixture.createLiteLogEvents(logEventCount);
+        this.fullLogEvents = LogEventFixture.createFullLogEvents(LOG_EVENT_COUNT);
+        this.liteLogEvents = LogEventFixture.createLiteLogEvents(LOG_EVENT_COUNT);
     }
 
     private static JsonTemplateLayout createJsonTemplateLayout4JsonLayout() {
@@ -212,4 +214,10 @@ public class JsonTemplateLayoutBenchmarkState {
         return liteLogEvents;
     }
 
+    int nextLogEventIndex() {
+        final int currentLogEventIndex = logEventIndex;
+        logEventIndex = (logEventIndex + 1) % LOG_EVENT_COUNT;
+        return currentLogEventIndex;
+    }
+
 }

[logging-log4j2] 09/16: LOG4J2-3393 Remove redundant branching in JsonTemplateLayout.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 970e80e15688a79df46de78e7207699414159b63
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 21 20:43:12 2022 +0100

    LOG4J2-3393 Remove redundant branching in JsonTemplateLayout.
---
 .../logging/log4j/layout/template/json/JsonTemplateLayout.java    | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
index a585bc5..8747c98 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
@@ -287,13 +287,7 @@ public class JsonTemplateLayout implements StringLayout {
             stringBuilder.append(eventDelimiter);
 
             // Write to the destination.
-            if (encoder == null) {
-                final String eventJson = stringBuilder.toString();
-                final byte[] eventJsonBytes = StringEncoder.toBytes(eventJson, charset);
-                destination.writeBytes(eventJsonBytes, 0, eventJsonBytes.length);
-            } else {
-                encoder.encode(stringBuilder, destination);
-            }
+            encoder.encode(stringBuilder, destination);
 
         }
 

[logging-log4j2] 08/16: LOG4J2-3393 Avoid StringBuilderEncoder thread-local allocation in JsonTemplateLayout.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 264ae844ed6fcb95e351a7bd6487bc50a9b25152
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Sun Feb 20 21:34:34 2022 +0100

    LOG4J2-3393 Avoid StringBuilderEncoder thread-local allocation in JsonTemplateLayout.
---
 .../log4j/core/layout/StringBuilderEncoder.java    |  9 ++--
 .../log4j/core/layout/TextEncoderHelper.java       |  6 +--
 .../layout/template/json/JsonTemplateLayout.java   | 56 +++++++++++++++++-----
 3 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java
index fb02393..d300a74 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java
@@ -31,7 +31,6 @@ import org.apache.logging.log4j.status.StatusLogger;
  */
 public class StringBuilderEncoder implements Encoder<StringBuilder> {
 
-    private static final int DEFAULT_BYTE_BUFFER_SIZE = 8 * 1024;
     /**
      * This ThreadLocal uses raw and inconvenient Object[] to store three heterogeneous objects (CharEncoder, CharBuffer
      * and ByteBuffer) instead of a custom class, because it needs to contain JDK classes, no custom (Log4j) classes.
@@ -49,7 +48,7 @@ public class StringBuilderEncoder implements Encoder<StringBuilder> {
     private final int byteBufferSize;
 
     public StringBuilderEncoder(final Charset charset) {
-        this(charset, Constants.ENCODER_CHAR_BUFFER_SIZE, DEFAULT_BYTE_BUFFER_SIZE);
+        this(charset, Constants.ENCODER_CHAR_BUFFER_SIZE, Constants.ENCODER_BYTE_BUFFER_SIZE);
     }
 
     public StringBuilderEncoder(final Charset charset, final int charBufferSize, final int byteBufferSize) {
@@ -67,7 +66,7 @@ public class StringBuilderEncoder implements Encoder<StringBuilder> {
             final ByteBuffer byteBuffer = (ByteBuffer) threadLocalState[2];
             TextEncoderHelper.encodeText(charsetEncoder, charBuffer, byteBuffer, source, destination);
         } catch (final Exception ex) {
-            logEncodeTextException(ex, source, destination);
+            logEncodeTextException(ex, source);
             TextEncoderHelper.encodeTextFallBack(charset, source, destination);
         }
     }
@@ -90,8 +89,8 @@ public class StringBuilderEncoder implements Encoder<StringBuilder> {
         return threadLocalState;
     }
 
-    private void logEncodeTextException(final Exception ex, final StringBuilder text,
-            final ByteBufferDestination destination) {
+    private void logEncodeTextException(final Exception ex, final StringBuilder text) {
         StatusLogger.getLogger().error("Recovering from StringBuilderEncoder.encode('{}') error: {}", text, ex, ex);
     }
+
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/TextEncoderHelper.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/TextEncoderHelper.java
index 327386f..4191f57 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/TextEncoderHelper.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/TextEncoderHelper.java
@@ -48,11 +48,9 @@ public class TextEncoderHelper {
      * @param byteBuf thread-local buffer to temporarily hold converted bytes before copying them to the destination
      * @param text the text to convert and write to the destination
      * @param destination the destination to write the bytes to
-     * @throws CharacterCodingException if conversion failed
      */
-    static void encodeText(final CharsetEncoder charsetEncoder, final CharBuffer charBuf, final ByteBuffer byteBuf,
-            final StringBuilder text, final ByteBufferDestination destination)
-            throws CharacterCodingException {
+    public static void encodeText(final CharsetEncoder charsetEncoder, final CharBuffer charBuf, final ByteBuffer byteBuf,
+            final StringBuilder text, final ByteBufferDestination destination) {
         charsetEncoder.reset();
         if (text.length() > charBuf.capacity()) {
             encodeChunkedText(charsetEncoder, charBuf, byteBuf, text, destination);
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
index cf8658e..a585bc5 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
@@ -26,10 +26,7 @@ import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.layout.ByteBufferDestination;
-import org.apache.logging.log4j.core.layout.Encoder;
-import org.apache.logging.log4j.core.layout.LockingStringBuilderEncoder;
-import org.apache.logging.log4j.core.layout.StringBuilderEncoder;
+import org.apache.logging.log4j.core.layout.*;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.core.util.StringEncoder;
 import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext;
@@ -44,9 +41,14 @@ import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
 import org.apache.logging.log4j.layout.template.json.util.Recycler;
 import org.apache.logging.log4j.layout.template.json.util.RecyclerFactory;
 import org.apache.logging.log4j.layout.template.json.util.Uris;
+import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.Strings;
 
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
 import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -204,19 +206,49 @@ public class JsonTemplateLayout implements StringLayout {
             final JsonWriter jsonWriter) {
         return () -> {
             final JsonWriter clonedJsonWriter = jsonWriter.clone();
-            final Encoder<StringBuilder> encoder = createStringBuilderEncoder(charset);
+            final Encoder<StringBuilder> encoder = new StringBuilderEncoder(charset);
             return new Context(clonedJsonWriter, encoder);
         };
     }
 
-    private static Encoder<StringBuilder> createStringBuilderEncoder(
-            final Charset charset) {
-        if (Constants.ENABLE_DIRECT_ENCODERS) {
-            return Constants.ENABLE_THREADLOCALS
-                    ? new StringBuilderEncoder(charset)
-                    : new LockingStringBuilderEncoder(charset);
+    /**
+     * {@link org.apache.logging.log4j.core.layout.StringBuilderEncoder} clone replacing thread-local allocations with instance fields.
+     */
+    private static final class StringBuilderEncoder implements Encoder<StringBuilder> {
+
+        private final Charset charset;
+
+        private final CharsetEncoder charsetEncoder;
+
+        private final CharBuffer charBuffer;
+
+        private final ByteBuffer byteBuffer;
+
+        private StringBuilderEncoder(final Charset charset) {
+            this.charset = charset;
+            this.charsetEncoder = charset
+                    .newEncoder()
+                    .onMalformedInput(CodingErrorAction.REPLACE)
+                    .onUnmappableCharacter(CodingErrorAction.REPLACE);
+            this.charBuffer = CharBuffer.allocate(Constants.ENCODER_CHAR_BUFFER_SIZE);
+            this.byteBuffer = ByteBuffer.allocate(Constants.ENCODER_BYTE_BUFFER_SIZE);
         }
-        return null;
+
+        @Override
+        public void encode(
+                final StringBuilder source,
+                final ByteBufferDestination destination) {
+            try {
+                TextEncoderHelper.encodeText(charsetEncoder, charBuffer, byteBuffer, source, destination);
+            } catch (final Exception error) {
+                StatusLogger
+                        .getLogger()
+                        .error("TextEncoderHelper.encodeText() failure", error);
+                final byte[] bytes = source.toString().getBytes(charset);
+                destination.writeBytes(bytes, 0, bytes.length);
+            }
+        }
+
     }
 
     @Override

[logging-log4j2] 14/16: LOG4J2-3393 Clean-up wrong BiConsumer usages.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 69608b94d07885c52d9691b2107d06d42b395349
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 28 11:26:37 2022 +0100

    LOG4J2-3393 Clean-up wrong BiConsumer usages.
---
 .../logging/log4j/layout/template/json/resolver/PatternResolver.java    | 2 +-
 .../org/apache/logging/log4j/layout/template/json/util/JsonWriter.java  | 2 +-
 .../apache/logging/log4j/layout/template/json/util/JsonWriterTest.java  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PatternResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PatternResolver.java
index 8cd2991..02ffcf9 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PatternResolver.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PatternResolver.java
@@ -20,10 +20,10 @@ import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
 import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
-import org.apache.logging.log4j.util.BiConsumer;
 import org.apache.logging.log4j.util.Strings;
 
 import java.util.Optional;
+import java.util.function.BiConsumer;
 
 /**
  * Resolver delegating to {@link PatternLayout}.
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
index 991ef5b..300c7c1 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
@@ -16,7 +16,6 @@
  */
 package org.apache.logging.log4j.layout.template.json.util;
 
-import org.apache.logging.log4j.util.BiConsumer;
 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
 import org.apache.logging.log4j.util.StringBuilderFormattable;
 import org.apache.logging.log4j.util.StringMap;
@@ -27,6 +26,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.function.BiConsumer;
 
 /**
  * A simple JSON writer with support for common Java data types.
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java
index c519f75..5ce6e1f 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/JsonWriterTest.java
@@ -18,7 +18,6 @@ package org.apache.logging.log4j.layout.template.json.util;
 
 import org.apache.logging.log4j.core.impl.JdkMapAdapterStringMap;
 import org.apache.logging.log4j.layout.template.json.JacksonFixture;
-import org.apache.logging.log4j.util.BiConsumer;
 import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
 import org.apache.logging.log4j.util.SortedArrayStringMap;
 import org.apache.logging.log4j.util.StringBuilderFormattable;
@@ -39,6 +38,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Function;
 

[logging-log4j2] 11/16: LOG4J2-3393 JTL benchmark updates.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 8a48540001c53e8a9a4166c37d54480baaf05ad9
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 21 21:49:34 2022 +0100

    LOG4J2-3393 JTL benchmark updates.
---
 .../log4j/layout/template/json/JsonTemplateLayoutBenchmark.java    | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
index 58c5852..0ee01b8 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutBenchmark.java
@@ -190,9 +190,14 @@ public class JsonTemplateLayoutBenchmark {
 //        System.out.format("Ready?");
 //        System.in.read();
         JsonTemplateLayoutBenchmarkState state = new JsonTemplateLayoutBenchmarkState();
-        int retryCount = 200_000_000;
+        int retryCount = 500_000_000;
         measureEcs(state, retryCount);
         measureJtl(state, retryCount);
+//        while (true) {
+//            measureEcs(state, retryCount);
+//        }
+//        measureEcs(state, retryCount);
+//        measureJtl(state, retryCount);
     }
 
     private static void measureJtl(JsonTemplateLayoutBenchmarkState state, int retryCount) {

[logging-log4j2] 12/16: LOG4J2-3393 Make TextEncoderHelper.encodeText() fallbacks JIT-friendly.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 81905f95cbdb4a135c26a754ecfdefb447761ed1
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Tue Feb 22 09:56:20 2022 +0100

    LOG4J2-3393 Make TextEncoderHelper.encodeText() fallbacks JIT-friendly.
---
 .../log4j/core/layout/StringBuilderEncoder.java        |  2 +-
 .../log4j/layout/template/json/JsonTemplateLayout.java | 18 +++++++++++++-----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java
index d300a74..9af3316 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder.java
@@ -89,7 +89,7 @@ public class StringBuilderEncoder implements Encoder<StringBuilder> {
         return threadLocalState;
     }
 
-    private void logEncodeTextException(final Exception ex, final StringBuilder text) {
+    private static void logEncodeTextException(final Exception ex, final StringBuilder text) {
         StatusLogger.getLogger().error("Recovering from StringBuilderEncoder.encode('{}') error: {}", text, ex, ex);
     }
 
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
index 5e36817..4266dfc 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
@@ -240,14 +240,22 @@ public class JsonTemplateLayout implements StringLayout {
             try {
                 TextEncoderHelper.encodeText(charsetEncoder, charBuffer, byteBuffer, source, destination);
             } catch (final Exception error) {
-                StatusLogger
-                        .getLogger()
-                        .error("TextEncoderHelper.encodeText() failure", error);
-                final byte[] bytes = source.toString().getBytes(charset);
-                destination.writeBytes(bytes, 0, bytes.length);
+                fallbackEncode(charset, source, destination, error);
             }
         }
 
+        private /* for JIT-ergonomics: */ static void fallbackEncode(
+                final Charset charset,
+                final StringBuilder source,
+                final ByteBufferDestination destination,
+                final Exception error) {
+            StatusLogger
+                    .getLogger()
+                    .error("TextEncoderHelper.encodeText() failure", error);
+            final byte[] bytes = source.toString().getBytes(charset);
+            destination.writeBytes(bytes, 0, bytes.length);
+        }
+
     }
 
     @Override

[logging-log4j2] 13/16: LOG4J2-3393 Make JsonWriter garbage-free for StringMaps.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 6a19108e8100f0ba272d70368efba16f17d9432d
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 28 11:26:03 2022 +0100

    LOG4J2-3393 Make JsonWriter garbage-free for StringMaps.
---
 .../layout/template/json/util/JsonWriter.java      | 26 ++++++++++++----------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
index 2d5df72..991ef5b 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/JsonWriter.java
@@ -234,22 +234,24 @@ public final class JsonWriter implements AutoCloseable, Cloneable {
         } else {
             writeObjectStart();
             final boolean[] firstEntry = {true};
-            map.forEach((final String key, final Object value) -> {
-                if (key == null) {
-                    throw new IllegalArgumentException("null keys are not allowed");
-                }
-                if (firstEntry[0]) {
-                    firstEntry[0] = false;
-                } else {
-                    writeSeparator();
-                }
-                writeObjectKey(key);
-                writeValue(value);
-            });
+            map.forEach(this::writeStringMap, firstEntry);
             writeObjectEnd();
         }
     }
 
+    private void writeStringMap(final String key, final Object value, final boolean[] firstEntry) {
+        if (key == null) {
+            throw new IllegalArgumentException("null keys are not allowed");
+        }
+        if (firstEntry[0]) {
+            firstEntry[0] = false;
+        } else {
+            writeSeparator();
+        }
+        writeObjectKey(key);
+        writeValue(value);
+    }
+
     public void writeObject(final IndexedReadOnlyStringMap map) {
         if (map == null) {
             writeNull();

[logging-log4j2] 16/16: LOG4J2-3393 Optimize MessageResolver for CharSequence.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 227d598703487a089dd0141f1323011a30b75962
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Mar 14 11:55:31 2022 +0100

    LOG4J2-3393 Optimize MessageResolver for CharSequence.
---
 .../logging/log4j/layout/template/json/resolver/MessageResolver.java | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolver.java
index 2975e66..aa5e366 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolver.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolver.java
@@ -134,7 +134,10 @@ public final class MessageResolver implements EventResolver {
             jsonWriter.writeObjectStart();
             jsonWriter.writeObjectKey(fallbackKey);
         }
-        if (message instanceof StringBuilderFormattable) {
+        if (message instanceof CharSequence) {
+            final CharSequence sequence = (CharSequence) message;
+            jsonWriter.writeString(sequence);
+        } else if (message instanceof StringBuilderFormattable) {
             final StringBuilderFormattable formattable =
                     (StringBuilderFormattable) message;
             jsonWriter.writeString(formattable);

[logging-log4j2] 15/16: LOG4J2-3393 Fix revapi issues.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 6e6bd235ebdad89a27944a94e30f60c9b52982b8
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 28 12:09:20 2022 +0100

    LOG4J2-3393 Fix revapi issues.
---
 log4j-layout-template-json/revapi.json | 1596 ++++++++++++++++++--------------
 1 file changed, 880 insertions(+), 716 deletions(-)

diff --git a/log4j-layout-template-json/revapi.json b/log4j-layout-template-json/revapi.json
index 5737d30..a9745c1 100644
--- a/log4j-layout-template-json/revapi.json
+++ b/log4j-layout-template-json/revapi.json
@@ -16,721 +16,885 @@
     }
   },
   {
-    "extension": "revapi.ignore",
-    "configuration": [
-      {
-        "code": "java.method.returnTypeChanged",
-        "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::getEventTemplateAdditionalFields()",
-        "new": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField[] org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::getEventTemplateAdditionalFields()",
-        "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
-      },
-      {
-        "code": "java.method.parameterTypeChanged",
-        "old": "parameter org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::setEventTemplateAdditionalFields(===org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields===)",
-        "new": "parameter org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::setEventTemplateAdditionalFields(===org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField[]===)",
-        "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
-      },
-      {
-        "code": "java.class.removed",
-        "old": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields",
-        "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::getMdcKeyPattern()",
-        "justification": "Removed unused property getter."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::getNdcPattern()",
-        "justification": "Removed unused property getter."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
-        "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.Uris>",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
-        "interface": "java.io.Serializable",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::valueOf(java.lang.String)",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults[] org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::values()",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerInheritsFromClass",
-        "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.kindChanged",
-        "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults>",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
-        "interface": "java.io.Serializable",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers::valueOf(java.lang.String)",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers[] org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers::values()",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerInheritsFromClass",
-        "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.kindChanged",
-        "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers>",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
-        "interface": "java.io.Serializable",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.RecyclerFactories org.apache.logging.log4j.layout.template.json.util.RecyclerFactories::valueOf(java.lang.String)",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.RecyclerFactories[] org.apache.logging.log4j.layout.template.json.util.RecyclerFactories::values()",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerInheritsFromClass",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.kindChanged",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.RecyclerFactories>",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
-        "interface": "java.io.Serializable",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values::valueOf(java.lang.String)",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values[] org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values::values()",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerInheritsFromClass",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.kindChanged",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values>",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
-        "interface": "java.io.Serializable",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser org.apache.logging.log4j.layout.template.json.util.StringParameterParser::valueOf(java.lang.String)",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser[] org.apache.logging.log4j.layout.template.json.util.StringParameterParser::values()",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerInheritsFromClass",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.kindChanged",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.StringParameterParser>",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerImplementsInterface",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
-        "interface": "java.io.Serializable",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.Uris org.apache.logging.log4j.layout.template.json.util.Uris::valueOf(java.lang.String)",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.util.Uris[] org.apache.logging.log4j.layout.template.json.util.Uris::values()",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.noLongerInheritsFromClass",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.class.kindChanged",
-        "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
-        "justification": "Replaced 'enum' singletons with 'final class'es."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method char[] org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getBuffer()",
-        "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getCapacity()",
-        "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method int org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getPosition()",
-        "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method boolean org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::isTruncated()",
-        "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
-      },
-      {
-        "code": "java.class.visibilityReduced",
-        "old": "class org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedWriter",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedWriter",
-        "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Builder::setType(org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type)",
-        "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
-      },
-      {
-        "code": "java.class.removed",
-        "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type",
-        "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField::getType()",
-        "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"EndOfBatchResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::getTruncatedStringSuffix()",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.method.removed",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setStackTraceElementObjectResolver(org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver<java.lang.StackTraceElement>)",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.method.parameterTypeChanged",
-        "old": "parameter org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setSubstitutor(===org.apache.logging.log4j.core.lookup.StrSubstitutor===)",
-        "new": "parameter org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setSubstitutor(===org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor===)",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.method.returnTypeTypeParametersChanged",
-        "old": "method java.util.Map<java.lang.String, org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory<org.apache.logging.log4j.core.LogEvent, org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext, ? extends org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver<org.apache.logging.log4j.core.LogEvent>>> org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getResolverFactoryByName()",
-        "new": "method java.util.Map<java.lang.String, org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory> org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getResolverFactoryByName()",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.method.returnTypeChanged",
-        "old": "method org.apache.logging.log4j.core.lookup.StrSubstitutor org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getSubstitutor()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getSubstitutor()",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ExceptionResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ExceptionRootCauseResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"LevelResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"LoggerResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MainMapResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MapResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MarkerResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MessageParameterResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MessageResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"PatternResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"SourceResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.class.removed",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.StackTraceElementObjectResolverContext",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextDataResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextDataResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "method org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory::getInstance()",
-        "new": "method org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory::getInstance()",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"TimestampResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.added",
-        "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
-        "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
-        "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextStackResolverFactory\", category = \"JsonTemplateResolverFactory\")",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.annotation.attributeValueChanged",
-        "old": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
-        "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
-        "annotationType": "org.apache.logging.log4j.core.config.plugins.Plugin",
-        "attribute": "name",
-        "oldValue": "\"RecyclerFactory\"",
-        "newValue": "\"RecyclerFactoryConverter\"",
-        "justification": "LOG4J2-3004 Add plugin support."
-      },
-      {
-        "code": "java.class.removed",
-        "old": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
-        "justification": "LOG4J2-3004 Add plugin support."
-      }
-    ]
+    "extension": "revapi.differences",
+    "configuration": {
+      "differences": [
+        {
+          "ignore": true,
+          "code": "java.method.returnTypeChanged",
+          "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::getEventTemplateAdditionalFields()",
+          "new": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField[] org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::getEventTemplateAdditionalFields()",
+          "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
+        },
+        {
+          "ignore": true,
+          "code": "java.method.parameterTypeChanged",
+          "old": "parameter org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::setEventTemplateAdditionalFields(===org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields===)",
+          "new": "parameter org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.Builder::setEventTemplateAdditionalFields(===org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField[]===)",
+          "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
+        },
+        {
+          "ignore": true,
+          "code": "java.class.removed",
+          "old": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalFields",
+          "justification": "LOG4J2-2961 Refactored for simplicity since it was already broken due to missing @PluginBuilderAttribute annotations"
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::getMdcKeyPattern()",
+          "justification": "Removed unused property getter."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::getNdcPattern()",
+          "justification": "Removed unused property getter."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
+          "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.Uris>",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
+          "interface": "java.io.Serializable",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::valueOf(java.lang.String)",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults[] org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults::values()",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerInheritsFromClass",
+          "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.kindChanged",
+          "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults>",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "new": "class org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults",
+          "interface": "java.io.Serializable",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers::valueOf(java.lang.String)",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers[] org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers::values()",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerInheritsFromClass",
+          "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.kindChanged",
+          "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers>",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.TemplateResolvers",
+          "interface": "java.io.Serializable",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.RecyclerFactories org.apache.logging.log4j.layout.template.json.util.RecyclerFactories::valueOf(java.lang.String)",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.RecyclerFactories[] org.apache.logging.log4j.layout.template.json.util.RecyclerFactories::values()",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerInheritsFromClass",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.kindChanged",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.RecyclerFactories>",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories",
+          "interface": "java.io.Serializable",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values::valueOf(java.lang.String)",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values[] org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values::values()",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerInheritsFromClass",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.kindChanged",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values>",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser.Values",
+          "interface": "java.io.Serializable",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser org.apache.logging.log4j.layout.template.json.util.StringParameterParser::valueOf(java.lang.String)",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.StringParameterParser[] org.apache.logging.log4j.layout.template.json.util.StringParameterParser::values()",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerInheritsFromClass",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.kindChanged",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "interface": "java.lang.Comparable<org.apache.logging.log4j.layout.template.json.util.StringParameterParser>",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerImplementsInterface",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.StringParameterParser",
+          "interface": "java.io.Serializable",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::compareTo(E) @ org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.Class<E> java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::getDeclaringClass() @ org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::name() @ org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::ordinal() @ org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method <T extends java.lang.Enum<T extends java.lang.Enum<T>>> T java.lang.Enum<E extends java.lang.Enum<E extends java.lang.Enum<E>>>::valueOf(java.lang.Class<T>, java.lang.String) @ org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.Uris org.apache.logging.log4j.layout.template.json.util.Uris::valueOf(java.lang.String)",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.util.Uris[] org.apache.logging.log4j.layout.template.json.util.Uris::values()",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.noLongerInheritsFromClass",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.kindChanged",
+          "old": "enum org.apache.logging.log4j.layout.template.json.util.Uris",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.Uris",
+          "justification": "Replaced 'enum' singletons with 'final class'es."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method char[] org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getBuffer()",
+          "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getCapacity()",
+          "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method int org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::getPosition()",
+          "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method boolean org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedPrintWriter::isTruncated()",
+          "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.visibilityReduced",
+          "old": "class org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedWriter",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.TruncatingBufferedWriter",
+          "justification": "LOG4J2-2993 Massaged (internal) API to make method names more Java-like and restrict access if possible."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Builder org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Builder::setType(org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type)",
+          "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.removed",
+          "old": "enum org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type",
+          "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField.Type org.apache.logging.log4j.layout.template.json.JsonTemplateLayout.EventTemplateAdditionalField::getType()",
+          "justification": "LOG4J2-2973 Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to #format."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"EndOfBatchResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method java.lang.String org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::getTruncatedStringSuffix()",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.removed",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setStackTraceElementObjectResolver(org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver<java.lang.StackTraceElement>)",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.parameterTypeChanged",
+          "old": "parameter org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setSubstitutor(===org.apache.logging.log4j.core.lookup.StrSubstitutor===)",
+          "new": "parameter org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext.Builder::setSubstitutor(===org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor===)",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.returnTypeTypeParametersChanged",
+          "old": "method java.util.Map<java.lang.String, org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory<org.apache.logging.log4j.core.LogEvent, org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext, ? extends org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver<org.apache.logging.log4j.core.LogEvent>>> org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getResolverFactoryByName()",
+          "new": "method java.util.Map<java.lang.String, org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory> org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getResolverFactoryByName()",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.method.returnTypeChanged",
+          "old": "method org.apache.logging.log4j.core.lookup.StrSubstitutor org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getSubstitutor()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.EventResolverStringSubstitutor org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext::getSubstitutor()",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ExceptionResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ExceptionRootCauseResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"LevelResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"LoggerResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MainMapResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MapResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MarkerResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MessageParameterResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"MessageResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"PatternResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"SourceResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.removed",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.StackTraceElementObjectResolverContext",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextDataResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextDataResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "method org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory::getInstance()",
+          "new": "method org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory::getInstance()",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.PluginFactory",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"TimestampResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.added",
+          "old": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
+          "new": "class org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory",
+          "annotation": "@org.apache.logging.log4j.core.config.plugins.Plugin(name = \"ThreadContextStackResolverFactory\", category = \"JsonTemplateResolverFactory\")",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.annotation.attributeValueChanged",
+          "old": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
+          "new": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
+          "annotationType": "org.apache.logging.log4j.core.config.plugins.Plugin",
+          "attribute": "name",
+          "oldValue": "\"RecyclerFactory\"",
+          "newValue": "\"RecyclerFactoryConverter\"",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.removed",
+          "old": "class org.apache.logging.log4j.layout.template.json.util.RecyclerFactories.RecyclerFactoryConverter",
+          "justification": "LOG4J2-3004 Add plugin support."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.externalClassExposedInAPI",
+          "new": "missing-class org.apache.logging.log4j.util.IndexedReadOnlyStringMap",
+          "justification": "Used by org.apache.logging.log4j.layout.template.json.util.JsonWriter."
+        },
+        {
+          "ignore": true,
+          "code": "java.missing.newClass",
+          "new": "missing-class org.apache.logging.log4j.util.IndexedReadOnlyStringMap",
+          "justification": "Used by org.apache.logging.log4j.layout.template.json.util.JsonWriter."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.externalClassExposedInAPI",
+          "new": "missing-class org.apache.logging.log4j.util.StringBuilderFormattable",
+          "justification": "Used by org.apache.logging.log4j.layout.template.json.util.JsonWriter."
+        },
+        {
+          "ignore": true,
+          "code": "java.missing.newClass",
+          "new": "missing-class org.apache.logging.log4j.util.StringBuilderFormattable",
+          "justification": "Used by org.apache.logging.log4j.layout.template.json.util.JsonWriter."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.externalClassExposedInAPI",
+          "new": "missing-class org.apache.logging.log4j.util.StringMap",
+          "justification": "Used by org.apache.logging.log4j.layout.template.json.util.JsonWriter."
+        },
+        {
+          "ignore": true,
+          "code": "java.missing.newClass",
+          "new": "missing-class org.apache.logging.log4j.util.StringMap",
+          "justification": "Used by org.apache.logging.log4j.layout.template.json.util.JsonWriter."
+        },
+        {
+          "ignore": true,
+          "code": "java.class.nonPublicPartOfAPI",
+          "new": "interface org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverContext<V, C extends org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverContext<V, C>>",
+          "justification": "LOG4J2-3004 Add plugin support."
+        }
+      ]
+    }
   }
 ]

[logging-log4j2] 10/16: LOG4J2-3393 Inline context acquisition in JsonTemplateLayout.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit c907fcdd52fc14a04083856bdb3ddbbbd5b554d1
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Mon Feb 21 21:48:52 2022 +0100

    LOG4J2-3393 Inline context acquisition in JsonTemplateLayout.
---
 .../layout/template/json/JsonTemplateLayout.java   | 30 +++++++++++-----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
index 8747c98..5e36817 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java
@@ -73,8 +73,7 @@ public class JsonTemplateLayout implements StringLayout {
 
     private final Recycler<Context> contextRecycler;
 
-    // The class and fields are visible for tests.
-    static final class Context implements AutoCloseable {
+    private static final class Context implements AutoCloseable {
 
         final JsonWriter jsonWriter;
 
@@ -259,36 +258,42 @@ public class JsonTemplateLayout implements StringLayout {
 
     @Override
     public String toSerializable(final LogEvent event) {
-        final Context context = acquireContext();
+
+        // Acquire a context.
+        final Recycler<Context> contextRecycler = this.contextRecycler;
+        final Context context = contextRecycler.acquire();
         final JsonWriter jsonWriter = context.jsonWriter;
         final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
+
+        // Render the JSON.
         try {
             eventResolver.resolve(event, jsonWriter);
             stringBuilder.append(eventDelimiter);
             return stringBuilder.toString();
-        } finally {
+        }
+
+        // Release the context.
+        finally {
             contextRecycler.release(context);
         }
+
     }
 
     @Override
     public void encode(final LogEvent event, final ByteBufferDestination destination) {
 
         // Acquire a context.
-        final Context context = acquireContext();
+        final Recycler<Context> contextRecycler = this.contextRecycler;
+        final Context context = contextRecycler.acquire();
         final JsonWriter jsonWriter = context.jsonWriter;
         final StringBuilder stringBuilder = jsonWriter.getStringBuilder();
         final Encoder<StringBuilder> encoder = context.encoder;
 
+        // Render & write the JSON.
         try {
-
-            // Render the JSON.
             eventResolver.resolve(event, jsonWriter);
             stringBuilder.append(eventDelimiter);
-
-            // Write to the destination.
             encoder.encode(stringBuilder, destination);
-
         }
 
         // Release the context.
@@ -298,11 +303,6 @@ public class JsonTemplateLayout implements StringLayout {
 
     }
 
-    // Visible for tests.
-    Context acquireContext() {
-        return contextRecycler.acquire();
-    }
-
     @Override
     public byte[] getFooter() {
         return null;

[logging-log4j2] 05/16: LOG4J2-3393 Bump JMH from 1.21 to 1.34.

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LOG4J2-3393
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 35e0c202d7cde69674adcd9feaf8f1e622fa9d25
Author: Volkan Yazici <vo...@yazi.ci>
AuthorDate: Fri Feb 18 16:49:34 2022 +0100

    LOG4J2-3393 Bump JMH from 1.21 to 1.34.
---
 log4j-perf/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/log4j-perf/pom.xml b/log4j-perf/pom.xml
index 95e0db0..863dfb1 100644
--- a/log4j-perf/pom.xml
+++ b/log4j-perf/pom.xml
@@ -37,7 +37,7 @@
     <log4jParentDir>${basedir}/..</log4jParentDir>
     <docLabel>Apache Log4J Performance Tests</docLabel>
     <projectDir>/log4j-perf</projectDir>
-    <jmh.version>1.21</jmh.version>
+    <jmh.version>1.34</jmh.version>
     <uberjar.name>benchmarks</uberjar.name>
     <revapi.skip>true</revapi.skip>
     <maven.doap.skip>true</maven.doap.skip>