diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7607f821..771e57ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,9 +34,10 @@ jobs: - name: Build run: ./mvnw --batch-mode --no-transfer-progress --show-version --settings .github/maven/settings.xml verify - # Run tests against Jackson 2.12 to ensure runtime compatibility (do not recompile) - - name: Test Jackson 2.12.x - run: ./mvnw --batch-mode --no-transfer-progress --show-version --settings .github/maven/settings.xml -Pcompat-jackson surefire:test +# Re-enable after upgrading Jackson to 3.1+ +# # Run tests against Jackson 3.0.0 to ensure runtime compatibility (do not recompile) +# - name: Test Jackson 3.0.0 +# run: ./mvnw --batch-mode --no-transfer-progress --show-version --settings .github/maven/settings.xml -Pcompat-jackson surefire:test - name: Upload Test Reports to Github uses: actions/upload-artifact@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 730c8aa0..11509515 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,6 @@ jobs: release: name: release runs-on: ubuntu-24.04 - needs: [build] if: github.repository == 'logfellow/logstash-logback-encoder' && github.ref == 'refs/heads/main' steps: - name: Checkout Code diff --git a/README.md b/README.md index fbbfd1ef..3f8a0c20 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The structure of the output, and the data it contains, is fully configurable. * [Header Fields](#header-fields) * [Customizing Jackson](#customizing-jackson) * [Data Format](#data-format) - * [Customizing JSON Factory and Generator](#customizing-json-factory-and-generator) + * [Customizing TokenStreamFactory, ObjectMapper, and JsonGenerator](#customizing-tokenstreamfactory-objectmapper-and-jsongenerator) * [Registering Jackson Modules](#registering-jackson-modules) * [Customizing Character Escapes](#customizing-character-escapes) * [Masking](#masking) @@ -99,7 +99,7 @@ Maven style: net.logstash.logback logstash-logback-encoder - 8.1 + 9.0 - + ``` @@ -1678,7 +1706,7 @@ Specific values to be masked can be specified in several ways, as seen in the fo ```xml - + - + ``` @@ -1904,13 +1932,13 @@ Use `-1` to disable shortening entirely. The next table provides examples of the abbreviation algorithm in action. -|LENGTH|LOGGER NAME |SHORTENED | -|------|----------------------------|---------------------------| -|0 | `org.company.stack.Sample` | `Sample` | -|5 | `org.company.stack.Sample` | `o.c.s.Sample` | -|16 | `org.company.stack.Sample` | `o.c.stack.Sample` | -|22 | `org.company.stack.Sample` | `o.company.stack.Sample` | -|25 | `org.company.stack.Sample` | `org.company.stack.Sample`| +| LENGTH | LOGGER NAME | SHORTENED | +|--------|----------------------------|----------------------------| +| 0 | `org.company.stack.Sample` | `Sample` | +| 5 | `org.company.stack.Sample` | `o.c.s.Sample` | +| 16 | `org.company.stack.Sample` | `o.c.stack.Sample` | +| 22 | `org.company.stack.Sample` | `o.company.stack.Sample` | +| 25 | `org.company.stack.Sample` | `org.company.stack.Sample` | @@ -1931,7 +1959,7 @@ This converter can even be used within a `PatternLayout` to format stacktraces i ### Omit Common Frames -Nested stacktraces often contain redudant frames that can safely be omitted without loosing any valuable information. +Nested stacktraces often contain redundant frames that can safely be omitted without loosing any valuable information. The following example shows a standard stack trace of an exception with a single root cause: @@ -2300,9 +2328,7 @@ Multiple evaluators can be registered and are evaluated in the order in which th ### Stack Hashes -**To Be Documented** - -Computing and inlining hexadecimal hashes for each exception stack using the `inlineHash` or `stackHash` provider ([more info](stack-hash.md)). +Compute and inline hexadecimal hashes for each exception stack with the `inlineHash` or `stackHash` provider ([more info](stack-hash.md)). diff --git a/pom.xml b/pom.xml index 359bd22f..b688b88b 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ UTF-8 - 2.20.0 + 3.0.0 5.1.1 1.5.19 2.0.6 @@ -64,7 +64,10 @@ true - true + + false github @@ -116,7 +119,7 @@ - com.fasterxml.jackson + tools.jackson jackson-bom ${jackson.version} pom @@ -165,11 +168,11 @@ true - com.fasterxml.jackson.core + tools.jackson.core jackson-databind - com.fasterxml.jackson.dataformat + tools.jackson.dataformat jackson-dataformat-cbor - 11 + 17 META-INF/versions/* @@ -548,8 +551,8 @@ https://javadoc.io/doc/ch.qos.logback/logback-classic/${logback-core.version} https://javadoc.io/doc/ch.qos.logback.access/logback-access-common/${logback-access.version} - https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-core/${jackson.version} - https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/${jackson.version} + https://javadoc.io/doc/tools.jackson.core/jackson-core/${jackson.version} + https://javadoc.io/doc/tools.jackson.core/jackson-databind/${jackson.version} - false - - - github @@ -777,15 +767,19 @@ + diff --git a/src/main/java/net/logstash/logback/LogstashAccessFormatter.java b/src/main/java/net/logstash/logback/LogstashAccessFormatter.java index 069cb4d2..8336e800 100644 --- a/src/main/java/net/logstash/logback/LogstashAccessFormatter.java +++ b/src/main/java/net/logstash/logback/LogstashAccessFormatter.java @@ -44,7 +44,7 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.core.joran.spi.DefaultClass; import ch.qos.logback.core.spi.ContextAware; -import com.fasterxml.jackson.databind.JsonNode; +import tools.jackson.databind.JsonNode; /** * A {@link AccessEventCompositeJsonFormatter} that contains a common @@ -119,12 +119,11 @@ private void updateMessageProvider() { // // { "fieldName": "messagePattern" } // - String accessEventPattern = new StringBuilder("{\"") - .append(this.fieldNames.getMessage()) - .append("\": \"") - .append(escapeJson(this.messagePattern)) - .append("\"}") - .toString(); + String accessEventPattern = "{\"" + + this.fieldNames.getMessage() + + "\": \"" + + escapeJson(this.messagePattern) + + "\"}"; AccessEventPatternJsonProvider messagePatternProvider = new AccessEventPatternJsonProvider(); messagePatternProvider.setPattern(accessEventPattern); @@ -184,7 +183,7 @@ public String getCustomFieldsAsString() { } public void setCustomFieldsFromString(String customFields) { - if (customFields == null || customFields.length() == 0) { + if (customFields == null || customFields.isEmpty()) { getProviders().removeProvider(globalCustomFieldsProvider); globalCustomFieldsProvider = null; } else { diff --git a/src/main/java/net/logstash/logback/LogstashFormatter.java b/src/main/java/net/logstash/logback/LogstashFormatter.java index 31a93d23..75f6288e 100644 --- a/src/main/java/net/logstash/logback/LogstashFormatter.java +++ b/src/main/java/net/logstash/logback/LogstashFormatter.java @@ -45,9 +45,9 @@ import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.ContextAware; -import com.fasterxml.jackson.databind.JsonNode; import org.slf4j.MDC; import org.slf4j.event.KeyValuePair; +import tools.jackson.databind.JsonNode; /** * A {@link LoggingEventCompositeJsonFormatter} that contains a common @@ -176,7 +176,7 @@ public String getCustomFieldsAsString() { } public void setCustomFieldsFromString(String customFields) { - if (customFields == null || customFields.length() == 0) { + if (customFields == null || customFields.isEmpty()) { getProviders().removeProvider(globalCustomFieldsProvider); globalCustomFieldsProvider = null; } else { diff --git a/src/main/java/net/logstash/logback/argument/DeferredStructuredArgument.java b/src/main/java/net/logstash/logback/argument/DeferredStructuredArgument.java index c4dda45c..76aa8e94 100644 --- a/src/main/java/net/logstash/logback/argument/DeferredStructuredArgument.java +++ b/src/main/java/net/logstash/logback/argument/DeferredStructuredArgument.java @@ -15,15 +15,14 @@ */ package net.logstash.logback.argument; -import java.io.IOException; import java.util.Objects; import java.util.function.Supplier; import net.logstash.logback.marker.EmptyLogstashMarker; import ch.qos.logback.classic.spi.LoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Logger; +import tools.jackson.core.JsonGenerator; /** * A {@link StructuredArgument} that defers the creation of another {@link StructuredArgument} until @@ -66,7 +65,7 @@ public DeferredStructuredArgument(Supplier structu } @Override - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { getSuppliedValue().writeTo(generator); } diff --git a/src/main/java/net/logstash/logback/argument/StructuredArgument.java b/src/main/java/net/logstash/logback/argument/StructuredArgument.java index ae3e71ad..56cff381 100644 --- a/src/main/java/net/logstash/logback/argument/StructuredArgument.java +++ b/src/main/java/net/logstash/logback/argument/StructuredArgument.java @@ -15,12 +15,10 @@ */ package net.logstash.logback.argument; -import java.io.IOException; - import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Logger; +import tools.jackson.core.JsonGenerator; /** * A wrapper for an argument passed to a log method (e.g. {@link Logger#info(String, Object...)}) @@ -32,9 +30,8 @@ public interface StructuredArgument { * Writes the data associated with this argument to the given {@link JsonGenerator}. * * @param generator the {@link JsonGenerator} to produce JSON content - * @throws IOException if an I/O error occurs */ - void writeTo(JsonGenerator generator) throws IOException; + void writeTo(JsonGenerator generator); /** * Writes the data associated with this argument to a {@link String} to be diff --git a/src/main/java/net/logstash/logback/composite/AbstractCompositeJsonFormatter.java b/src/main/java/net/logstash/logback/composite/AbstractCompositeJsonFormatter.java index c719e831..4773c919 100644 --- a/src/main/java/net/logstash/logback/composite/AbstractCompositeJsonFormatter.java +++ b/src/main/java/net/logstash/logback/composite/AbstractCompositeJsonFormatter.java @@ -18,32 +18,38 @@ import java.io.Closeable; import java.io.IOException; import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; import java.util.Objects; import java.util.ServiceConfigurationError; -import net.logstash.logback.decorate.JsonFactoryDecorator; +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.dataformat.json.JsonDataFormatFactory; +import net.logstash.logback.decorate.CompositeJsonGeneratorDecorator; +import net.logstash.logback.decorate.CompositeMapperBuilderDecorator; +import net.logstash.logback.decorate.CompositeTokenStreamFactoryBuilderDecorator; +import net.logstash.logback.decorate.Decorator; import net.logstash.logback.decorate.JsonGeneratorDecorator; -import net.logstash.logback.decorate.NullJsonFactoryDecorator; -import net.logstash.logback.decorate.NullJsonGeneratorDecorator; +import net.logstash.logback.decorate.MapperBuilderDecorator; +import net.logstash.logback.decorate.TokenStreamFactoryBuilderDecorator; import net.logstash.logback.util.ProxyOutputStream; -import net.logstash.logback.util.SimpleObjectJsonGeneratorDelegate; import net.logstash.logback.util.ThreadLocalHolder; import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.spi.ContextAware; import ch.qos.logback.core.spi.ContextAwareBase; import ch.qos.logback.core.spi.DeferredProcessingAware; import ch.qos.logback.core.spi.LifeCycle; import ch.qos.logback.core.util.CloseUtil; -import com.fasterxml.jackson.core.JsonEncoding; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonFactory.Feature; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.io.SerializedString; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; +import tools.jackson.core.JsonEncoding; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.StreamWriteFeature; +import tools.jackson.core.TSFBuilder; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.cfg.MapperBuilder; /** * Formats logstash Events as JSON using {@link JsonProvider}s. @@ -66,21 +72,41 @@ public abstract class AbstractCompositeJsonFormatter DATA_FORMATS = Map.of( + DataFormatFactory.JSON, "net.logstash.logback.dataformat.json.JsonDataFormatFactory", + DataFormatFactory.YAML, "net.logstash.logback.dataformat.yaml.YamlDataFormatFactory", + DataFormatFactory.CBOR, "net.logstash.logback.dataformat.cbor.CborDataFormatFactory", + DataFormatFactory.SMILE, "net.logstash.logback.dataformat.smile.SmileDataFormatFactory"); /** - * Decorates the {@link #jsonFactory}. - * Allows customization of the {@link #jsonFactory}. + * Factory for creating builders for a data format supported by jackson. */ - private JsonFactoryDecorator jsonFactoryDecorator; + private DataFormatFactory dataFormatFactory = new JsonDataFormatFactory(); /** - * Decorates the generators generated by the {@link #jsonFactory}. + * Decorates the builder that builds the {@link #objectMapper}. + * Allows customization of the {@link #objectMapper}. + */ + private final CompositeMapperBuilderDecorator mapperBuilderDecorator = new CompositeMapperBuilderDecorator(); + + /** + * Decorates the builder that builds the {@link TokenStreamFactory} used by the {@link #objectMapper}. + * Allows customization of the {@link TokenStreamFactory}. + */ + private final CompositeTokenStreamFactoryBuilderDecorator tokenStreamFactoryBuilderDecorator = new CompositeTokenStreamFactoryBuilderDecorator(); + + /** + * Decorates the generators generated by the {@link #objectMapper}. * Allows customization of the generators. */ - private JsonGeneratorDecorator jsonGeneratorDecorator; + private final CompositeJsonGeneratorDecorator jsonGeneratorDecorator = new CompositeJsonGeneratorDecorator(); + + /** + * Used to create the {@link JsonGenerator}s for generating output. + */ + private ObjectMapper objectMapper; /** * The providers that are used to populate the output JSON object. @@ -105,18 +131,14 @@ public void start() { if (isStarted()) { return; } - if (jsonFactoryDecorator == null) { - jsonFactoryDecorator = new NullJsonFactoryDecorator(); - } - if (jsonGeneratorDecorator == null) { - jsonGeneratorDecorator = new NullJsonGeneratorDecorator(); - } if (jsonProviders.getProviders().isEmpty()) { addError("No providers configured"); } - jsonFactory = createJsonFactory(); + + objectMapper = createObjectMapper(); + jsonProviders.setContext(context); - jsonProviders.setJsonFactory(jsonFactory); + jsonProviders.setObjectMapper(objectMapper); jsonProviders.start(); threadLocalJsonFormatter = new ThreadLocalHolder<>(this::createJsonFormatter); @@ -128,7 +150,7 @@ public void stop() { if (isStarted()) { threadLocalJsonFormatter.close(); jsonProviders.stop(); - jsonFactory = null; + objectMapper = null; started = false; } } @@ -138,7 +160,38 @@ public boolean isStarted() { return started; } - + private ObjectMapper createObjectMapper() { + TokenStreamFactory tokenStreamFactory = createTokenStreamFactory(); + + MapperBuilder mapperBuilder = dataFormatFactory.createMapperBuilder(tokenStreamFactory) + /* + * Assume empty beans are ok. + */ + .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + + if (findAndRegisterJacksonModules) { + try { + mapperBuilder = mapperBuilder.findAndAddModules(); + } catch (ServiceConfigurationError serviceConfigurationError) { + addError("Error occurred while dynamically loading jackson modules", serviceConfigurationError); + } + } + + mapperBuilder = (MapperBuilder) this.mapperBuilderDecorator.decorate(mapperBuilder); + + return mapperBuilder.build(); + } + + private TokenStreamFactory createTokenStreamFactory() { + return ((TSFBuilder) tokenStreamFactoryBuilderDecorator.decorate(dataFormatFactory.createTokenStreamFactoryBuilder())) + /* + * Don't let the JsonGenerator close the underlying outputStream and let the + * encoder managed it. + */ + .disable(StreamWriteFeature.AUTO_CLOSE_TARGET) + .build(); + } + /** * Write an event in the given output stream. * @@ -216,7 +269,7 @@ public void dispose() { } @Override - public void close() throws IOException { + public void close() { AbstractCompositeJsonFormatter.this.threadLocalJsonFormatter.release(); } } @@ -235,56 +288,6 @@ public void disconnect() { } } - private JsonFactory createJsonFactory() { - ObjectMapper objectMapper = new ObjectMapper() - /* - * Assume empty beans are ok. - */ - .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); - - if (findAndRegisterJacksonModules) { - try { - objectMapper.findAndRegisterModules(); - } catch (ServiceConfigurationError serviceConfigurationError) { - addError("Error occurred while dynamically loading jackson modules", serviceConfigurationError); - } - } - - return decorateFactory(objectMapper.getFactory()); - } - - private JsonFactory decorateFactory(JsonFactory factory) { - JsonFactory factoryToDecorate = factory - /* - * When generators are flushed, don't flush the underlying outputStream. - * - * This allows some streaming optimizations when using an encoder. - * - * The encoder generally determines when the stream should be flushed - * by an 'immediateFlush' property. - * - * The 'immediateFlush' property of the encoder can be set to false - * when the appender performs the flushes at appropriate times - * (such as the end of a batch in the AbstractLogstashTcpSocketAppender). - * - * Set this prior to decorating, because some generators require - * FLUSH_PASSED_TO_STREAM to work properly (e.g. YAML) - */ - .disable(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM); - - return this.jsonFactoryDecorator.decorate(factoryToDecorate) - /* - * Jackson buffer recycling works by maintaining a pool of buffers per thread. This - * feature works best when one JsonGenerator is created per thread, typically in J2EE - * environments. - * - * Each JsonFormatter uses its own instance of JsonGenerator and is reused multiple times - * possibly on different threads. The memory buffers allocated by the JsonGenerator do - * not belong to a particular thread - hence the recycling feature should be disabled. - */ - .disable(Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING); - } - protected void writeEventToGenerator(JsonGenerator generator, Event event) throws IOException { generator.writeStartObject(); jsonProviders.writeTo(generator, event); @@ -298,52 +301,136 @@ protected void prepareForDeferredProcessing(Event event) { } private JsonGenerator createGenerator(OutputStream outputStream) throws IOException { - return decorateGenerator(jsonFactory.createGenerator(outputStream, encoding)); + return this.jsonGeneratorDecorator.decorate(objectMapper.createGenerator(outputStream, encoding)); } - private JsonGenerator decorateGenerator(JsonGenerator generator) { - JsonGenerator decorated = jsonGeneratorDecorator.decorate(new SimpleObjectJsonGeneratorDelegate(generator)) - /* - * Don't let the json generator close the underlying outputStream and let the - * encoder managed it. - */ - .disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); + /** + * Gets the name of the currently configured data format. + * + * @return the name of the currently configured data format. + */ + public String getDataFormat() { + return dataFormatFactory.getName(); + } + /** + * Sets the dataformat to one of the build-in data formats ( + * {@value DataFormatFactory#JSON}, + * {@value DataFormatFactory#YAML}, + * {@value DataFormatFactory#CBOR}, or + * {@value DataFormatFactory#SMILE}). + * + *

For non-JSON data formats, the appropriate Jackson data format module must be on the classpath.

+ * + *

To set a custom (non-builtin) data format, use {@link #setDataFormatFactory(DataFormatFactory)}

+ * + * @param dataFormat {@value DataFormatFactory#JSON}, + * {@value DataFormatFactory#YAML}, + * {@value DataFormatFactory#CBOR}, or + * {@value DataFormatFactory#SMILE} + * @see #setDataFormatFactory(DataFormatFactory) + */ + public void setDataFormat(String dataFormat) { + String dataFormatClassName = DATA_FORMATS.get(dataFormat); + if (dataFormatClassName == null) { + throw new IllegalArgumentException(String.format("Unknown data format: %s. Known data formats are: %s", dataFormat, String.join(",", DATA_FORMATS.keySet()))); + } try { - decorated = decorated - /* - * JsonGenerator are reused to serialize multiple log events. - * Change the default root value separator to an empty string instead of a single space. - */ - .setRootValueSeparator(new SerializedString(CoreConstants.EMPTY_STRING)); - } catch (UnsupportedOperationException e) { - /* - * Ignore. - * Some generators do not support setting the rootValueSeparator. - */ + setDataFormatFactory((DataFormatFactory) Class.forName(dataFormatClassName).getConstructor().newInstance()); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(String.format("Unable to instantiate %s. Ensure the appropriate jackson dataformat module is on the classpath.", dataFormatClassName), e); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + throw new IllegalArgumentException(String.format("Unable to instantiate %s.", dataFormatClassName), e); } + } - return decorated; + /** + * Gets the currently configured {@link DataFormatFactory}. + * + * @return the currently configured {@link DataFormatFactory}. + */ + public DataFormatFactory getDataFormatFactory() { + return dataFormatFactory; } - - public JsonFactory getJsonFactory() { - return jsonFactory; + + /** + * Sets the {@link DataFormatFactory} to be used for output. + * + *

For built-in formats, prefer using {@link #setDataFormat(String)}

+ * + * @param dataFormatFactory the {@link DataFormatFactory} to be used for output. + */ + public void setDataFormatFactory(DataFormatFactory dataFormatFactory) { + this.dataFormatFactory = Objects.requireNonNull(dataFormatFactory); } - public JsonFactoryDecorator getJsonFactoryDecorator() { - return jsonFactoryDecorator; + /** + * Adds the given decorator of type + * {@link MapperBuilderDecorator}, + * {@link TokenStreamFactoryBuilderDecorator}, or + * {@link JsonGeneratorDecorator}. + * + *

These decorators decorate Jackson objects.

+ * + * @param decorator the decorator to add (of type {@link MapperBuilderDecorator}, {@link TokenStreamFactoryBuilderDecorator}, or {@link JsonGeneratorDecorator}) + * @throws IllegalArgumentException if an unsupported decorator is added + */ + public void addDecorator(Decorator decorator) { + Objects.requireNonNull(decorator); + if (decorator instanceof MapperBuilderDecorator mapperBuilderDecoratorToAdd) { + addMapperBuilderDecorator(mapperBuilderDecoratorToAdd); + } else if (decorator instanceof TokenStreamFactoryBuilderDecorator tokenStreamFactoryBuilderDecoratorToAdd) { + addTokenStreamFactoryBuilderDecorator(tokenStreamFactoryBuilderDecoratorToAdd); + } else if (decorator instanceof JsonGeneratorDecorator jsonGeneratorDecoratorToAdd) { + addJsonGeneratorDecorator(jsonGeneratorDecoratorToAdd); + } else { + throw new IllegalArgumentException("Unknown decorator type:" + decorator.getClass().getName()); + } } - public void setJsonFactoryDecorator(JsonFactoryDecorator jsonFactoryDecorator) { - this.jsonFactoryDecorator = jsonFactoryDecorator; + public void addJsonGeneratorDecorator(JsonGeneratorDecorator jsonGeneratorDecoratorToAdd) { + jsonGeneratorDecorator.addDecorator(jsonGeneratorDecoratorToAdd); } - public JsonGeneratorDecorator getJsonGeneratorDecorator() { - return jsonGeneratorDecorator; + public void addTokenStreamFactoryBuilderDecorator(TokenStreamFactoryBuilderDecorator tokenStreamFactoryBuilderDecoratorToAdd) { + tokenStreamFactoryBuilderDecorator.addDecorator(tokenStreamFactoryBuilderDecoratorToAdd); + } + + public void addMapperBuilderDecorator(MapperBuilderDecorator mapperBuilderDecoratorToAdd) { + mapperBuilderDecorator.addDecorator(mapperBuilderDecoratorToAdd); } - public void setJsonGeneratorDecorator(JsonGeneratorDecorator jsonGeneratorDecorator) { - this.jsonGeneratorDecorator = jsonGeneratorDecorator; + /** + * Gets a mutable {@link CompositeTokenStreamFactoryBuilderDecorator} + * containing all the currently configured {@link TokenStreamFactoryBuilderDecorator}s. + * + * @return a mutable {@link CompositeTokenStreamFactoryBuilderDecorator} + * containing all the currently configured {@link TokenStreamFactoryBuilderDecorator}s. + */ + public CompositeTokenStreamFactoryBuilderDecorator getTokenStreamFactoryBuilderDecorator() { + return tokenStreamFactoryBuilderDecorator; + } + + /** + * Gets a mutable {@link CompositeMapperBuilderDecorator} + * containing all the currently configured {@link MapperBuilderDecorator}s. + * + * @return a mutable {@link CompositeMapperBuilderDecorator} + * containing all the currently configured {@link MapperBuilderDecorator}s. + */ + public CompositeMapperBuilderDecorator getMapperBuilderDecorator() { + return mapperBuilderDecorator; + } + + /** + * Gets a mutable {@link CompositeJsonGeneratorDecorator} + * containing all the currently configured {@link JsonGeneratorDecorator}s. + * + * @return a mutable {@link CompositeJsonGeneratorDecorator} + * containing all the currently configured {@link JsonGeneratorDecorator}s. + */ + public CompositeJsonGeneratorDecorator getJsonGeneratorDecorator() { + return jsonGeneratorDecorator; } public JsonProviders getProviders() { diff --git a/src/main/java/net/logstash/logback/composite/AbstractFormattedTimestampJsonProvider.java b/src/main/java/net/logstash/logback/composite/AbstractFormattedTimestampJsonProvider.java index fd7098c5..180f6b04 100644 --- a/src/main/java/net/logstash/logback/composite/AbstractFormattedTimestampJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/AbstractFormattedTimestampJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.time.Instant; @@ -29,7 +28,7 @@ import net.logstash.logback.util.TimeZoneUtils; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes the timestamp field as either: @@ -94,7 +93,7 @@ public abstract class AbstractFormattedTimestampJsonProvider formatter.format(tstamp)); + return new StringFormatterWriter(formatter::format); } static StringFormatterWriter with(FastISOTimestampFormatter formatter) { return new StringFormatterWriter(formatter::format); @@ -160,7 +159,7 @@ public void setFieldNames(FieldNames fieldNames) { } @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { timestampWriter.writeTo(generator, getFieldName(), getTimestampAsInstant(event)); } @@ -194,27 +193,27 @@ private TimestampWriter createTimestampWriter() { // Use our fast FastISOTimestampFormatter if suitable... // ZoneId zone = timeZone.toZoneId(); - if ("ISO_OFFSET_DATE_TIME".equals(constant)) { - return StringFormatterWriter.with(FastISOTimestampFormatter.isoOffsetDateTime(zone)); - } - if ("ISO_ZONED_DATE_TIME".equals(constant)) { - return StringFormatterWriter.with(FastISOTimestampFormatter.isoZonedDateTime(zone)); - } - if ("ISO_LOCAL_DATE_TIME".equals(constant)) { - return StringFormatterWriter.with(FastISOTimestampFormatter.isoLocalDateTime(zone)); - } - if ("ISO_DATE_TIME".equals(constant)) { - return StringFormatterWriter.with(FastISOTimestampFormatter.isoDateTime(zone)); + switch (constant) { + case "ISO_OFFSET_DATE_TIME" -> { + return StringFormatterWriter.with(FastISOTimestampFormatter.isoOffsetDateTime(zone)); + } + case "ISO_ZONED_DATE_TIME" -> { + return StringFormatterWriter.with(FastISOTimestampFormatter.isoZonedDateTime(zone)); + } + case "ISO_LOCAL_DATE_TIME" -> { + return StringFormatterWriter.with(FastISOTimestampFormatter.isoLocalDateTime(zone)); + } + case "ISO_DATE_TIME" -> { + return StringFormatterWriter.with(FastISOTimestampFormatter.isoDateTime(zone)); + } + case "ISO_INSTANT" -> { + return StringFormatterWriter.with(FastISOTimestampFormatter.isoInstant(zone)); + } + default -> { + DateTimeFormatter formatter = getStandardDateTimeFormatter(constant).withZone(zone); + return StringFormatterWriter.with(formatter); + } } - if ("ISO_INSTANT".equals(constant)) { - return StringFormatterWriter.with(FastISOTimestampFormatter.isoInstant(zone)); - } - - - // Otherwise try one of the default formatters... - // - DateTimeFormatter formatter = getStandardDateTimeFormatter(constant).withZone(zone); - return StringFormatterWriter.with(formatter); } diff --git a/src/main/java/net/logstash/logback/composite/AbstractNestedJsonProvider.java b/src/main/java/net/logstash/logback/composite/AbstractNestedJsonProvider.java index 0a9d2cbe..c9fea69b 100644 --- a/src/main/java/net/logstash/logback/composite/AbstractNestedJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/AbstractNestedJsonProvider.java @@ -15,21 +15,20 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.util.Objects; import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; /** * A {@link JsonProvider} that nests other providers within a subobject. * * @param type of event ({@link ILoggingEvent} or {@link IAccessEvent}). */ -public abstract class AbstractNestedJsonProvider extends AbstractFieldJsonProvider implements JsonFactoryAware { +public abstract class AbstractNestedJsonProvider extends AbstractFieldJsonProvider implements ObjectMapperAware { public static final String FIELD_NESTED = "nested"; @@ -56,9 +55,8 @@ public void stop() { } @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { - generator.writeFieldName(getFieldName()); - generator.writeStartObject(); + public void writeTo(JsonGenerator generator, Event event) { + generator.writeObjectPropertyStart(getFieldName()); jsonProviders.writeTo(generator, event); generator.writeEndObject(); } @@ -72,8 +70,8 @@ public void setProviders(JsonProviders jsonProviders) { } @Override - public void setJsonFactory(final JsonFactory jsonFactory) { - getProviders().setJsonFactory(Objects.requireNonNull(jsonFactory)); + public void setObjectMapper(ObjectMapper objectMapper) { + getProviders().setObjectMapper(Objects.requireNonNull(objectMapper)); } @Override diff --git a/src/main/java/net/logstash/logback/composite/AbstractPatternJsonProvider.java b/src/main/java/net/logstash/logback/composite/AbstractPatternJsonProvider.java index 5ad487a7..e88e93d3 100644 --- a/src/main/java/net/logstash/logback/composite/AbstractPatternJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/AbstractPatternJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.util.Objects; import net.logstash.logback.pattern.AbstractJsonPatternParser; @@ -25,42 +24,42 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; /** * Transforms an string containing patterns understood by PatternLayouts into JSON output. * Delegates most of the work to the {@link AbstractJsonPatternParser} that is to * parse the pattern specified. - * Subclasses must implement {@link #createParser(JsonFactory)} method so it returns parser valid for a specified event class. + * Subclasses must implement {@link #createParser()} method so it returns parser valid for a specified event class. * * @param type of event ({@link ILoggingEvent} or {@link IAccessEvent}). * * @author Dmitry Andrianov */ public abstract class AbstractPatternJsonProvider - extends AbstractJsonProvider implements JsonFactoryAware { + extends AbstractJsonProvider implements ObjectMapperAware { private NodeWriter nodeWriter; private String pattern; - private JsonFactory jsonFactory; + protected ObjectMapper objectMapper; /** - * When {@code true}, fields whose values are considered empty ({@link AbstractJsonPatternParser#isEmptyValue(Object)}}) + * When {@code true}, fields whose values are considered empty * will be omitted from JSON output. */ private boolean omitEmptyFields; @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { if (nodeWriter != null) { nodeWriter.write(generator, event); } } - protected abstract AbstractJsonPatternParser createParser(JsonFactory jsonFactory); + protected abstract AbstractJsonPatternParser createParser(); public String getPattern() { return pattern; @@ -69,16 +68,16 @@ public String getPattern() { public void setPattern(final String pattern) { this.pattern = pattern; } - + @Override - public void setJsonFactory(JsonFactory jsonFactory) { - this.jsonFactory = Objects.requireNonNull(jsonFactory); + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = Objects.requireNonNull(objectMapper); } @Override public void start() { - if (jsonFactory == null) { - throw new IllegalStateException("JsonFactory has not been set"); + if (objectMapper == null) { + throw new IllegalStateException("objectMapper has not been set"); } try { @@ -99,7 +98,7 @@ public void start() { * @throws JsonPatternException thrown in case of invalid pattern */ private NodeWriter initializeNodeWriter() throws JsonPatternException { - AbstractJsonPatternParser parser = createParser(this.jsonFactory); + AbstractJsonPatternParser parser = createParser(); parser.setOmitEmptyFields(omitEmptyFields); return parser.parse(pattern); } diff --git a/src/main/java/net/logstash/logback/composite/AbstractSequenceJsonProvider.java b/src/main/java/net/logstash/logback/composite/AbstractSequenceJsonProvider.java index c3b882e0..c87fd71a 100644 --- a/src/main/java/net/logstash/logback/composite/AbstractSequenceJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/AbstractSequenceJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; @@ -23,7 +22,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.DeferredProcessingAware; import ch.qos.logback.core.spi.SequenceNumberGenerator; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Outputs an incrementing sequence number. @@ -71,7 +70,7 @@ public void start() { @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { if (!isStarted()) { throw new IllegalStateException("Provider " + this.getClass().getName() + " is not started"); } @@ -110,7 +109,7 @@ protected Function createSequenceProvider() { if (getContext() == null || getContext().getSequenceNumberGenerator() == null) { this.addWarn("No defined in Logback configuration - revert to using a local incrementing sequence number."); - return new Function() { + return new Function<>() { private final AtomicLong sequence = new AtomicLong(0L); @Override diff --git a/src/main/java/net/logstash/logback/composite/AbstractThreadNameJsonProvider.java b/src/main/java/net/logstash/logback/composite/AbstractThreadNameJsonProvider.java index 379edc78..3ec6bab7 100644 --- a/src/main/java/net/logstash/logback/composite/AbstractThreadNameJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/AbstractThreadNameJsonProvider.java @@ -15,12 +15,10 @@ */ package net.logstash.logback.composite; -import java.io.IOException; - import net.logstash.logback.fieldnames.LogstashCommonFieldNames; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public abstract class AbstractThreadNameJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -31,7 +29,7 @@ public AbstractThreadNameJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { JsonWritingUtils.writeStringField(generator, getFieldName(), getThreadName(event)); } diff --git a/src/main/java/net/logstash/logback/composite/CompositeJsonFormatter.java b/src/main/java/net/logstash/logback/composite/CompositeJsonFormatter.java deleted file mode 100644 index 569cb074..00000000 --- a/src/main/java/net/logstash/logback/composite/CompositeJsonFormatter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.composite; - -import ch.qos.logback.core.spi.ContextAware; -import ch.qos.logback.core.spi.DeferredProcessingAware; - -/** - * @deprecated use {@link AbstractCompositeJsonFormatter} instead. - */ -@Deprecated -public abstract class CompositeJsonFormatter extends AbstractCompositeJsonFormatter { - - public CompositeJsonFormatter(ContextAware declaredOrigin) { - super(declaredOrigin); - } - -} diff --git a/src/main/java/net/logstash/logback/composite/ContextJsonProvider.java b/src/main/java/net/logstash/logback/composite/ContextJsonProvider.java index fc5c96a4..b29e315e 100644 --- a/src/main/java/net/logstash/logback/composite/ContextJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/ContextJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite; -import java.io.IOException; - import net.logstash.logback.fieldnames.LogstashCommonFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Context; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes properties from the {@link Context} into the JSON event. @@ -37,10 +35,10 @@ public class ContextJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { if (getContext() != null) { if (getFieldName() != null) { - generator.writeObjectFieldStart(getFieldName()); + generator.writeObjectPropertyStart(getFieldName()); } JsonWritingUtils.writeMapEntries(generator, context.getCopyOfPropertyMap()); diff --git a/src/main/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProvider.java b/src/main/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProvider.java index 3bf568ce..ee469d8c 100644 --- a/src/main/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProvider.java @@ -15,18 +15,17 @@ */ package net.logstash.logback.composite; -import java.io.IOException; -import java.util.Iterator; import java.util.Map.Entry; import java.util.Objects; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.exc.StreamReadException; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.node.ObjectNode; -public class GlobalCustomFieldsJsonProvider extends AbstractJsonProvider implements JsonFactoryAware { +public class GlobalCustomFieldsJsonProvider extends AbstractJsonProvider implements ObjectMapperAware { /** * The un-parsed custom fields string to use to initialize customFields @@ -40,24 +39,23 @@ public class GlobalCustomFieldsJsonProvider> fields = node.fields(); fields.hasNext();) { - Entry field = fields.next(); - generator.writeFieldName(field.getKey()); + for (Entry field : node.properties()) { + generator.writeName(field.getKey()); generator.writeTree(field.getValue()); } } @@ -79,13 +77,13 @@ private void initializeCustomFields() { if (customFieldsNode != null || customFields == null) { return; } - if (jsonFactory == null) { - throw new IllegalStateException("JsonFactory has not been set"); + if (objectMapper == null) { + throw new IllegalStateException("objectMapper has not been set"); } try { - this.customFieldsNode = JsonReadingUtils.readFullyAsObjectNode(this.jsonFactory, this.customFields); - } catch (IOException e) { + this.customFieldsNode = JsonReadingUtils.readFullyAsObjectNode(this.objectMapper, this.customFields); + } catch (StreamReadException e) { addError("[customFields] is not a valid JSON object", e); } } @@ -146,7 +144,7 @@ public void setCustomFieldsNode(ObjectNode customFields) { @Override - public void setJsonFactory(JsonFactory jsonFactory) { - this.jsonFactory = Objects.requireNonNull(jsonFactory); + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = Objects.requireNonNull(objectMapper); } } diff --git a/src/main/java/net/logstash/logback/composite/JsonProvider.java b/src/main/java/net/logstash/logback/composite/JsonProvider.java index 4db0e3fd..8dbe0218 100644 --- a/src/main/java/net/logstash/logback/composite/JsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/JsonProvider.java @@ -15,13 +15,11 @@ */ package net.logstash.logback.composite; -import java.io.IOException; - import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.ContextAware; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Contributes to the JSON output being written for the given Event. @@ -39,9 +37,8 @@ public interface JsonProvider extends Con * * @param generator the {@link JsonGenerator} to produce JSON content * @param event the event to convert into JSON - * @throws IOException if an I/O error occurs */ - void writeTo(JsonGenerator generator, Event event) throws IOException; + void writeTo(JsonGenerator generator, Event event); /** * Gives the provider a chance to perform more deferred processing diff --git a/src/main/java/net/logstash/logback/composite/JsonProviders.java b/src/main/java/net/logstash/logback/composite/JsonProviders.java index 4bed770f..70002681 100644 --- a/src/main/java/net/logstash/logback/composite/JsonProviders.java +++ b/src/main/java/net/logstash/logback/composite/JsonProviders.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -24,8 +23,8 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Context; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; /** * Contains a collection of {@link JsonProvider}s to be used to write @@ -39,7 +38,7 @@ * * @param type of event ({@link ILoggingEvent} or {@link IAccessEvent}). */ -public class JsonProviders implements JsonFactoryAware { +public class JsonProviders implements ObjectMapperAware { private final List> jsonProviders = new ArrayList<>(); @@ -73,7 +72,7 @@ public void removeProvider(JsonProvider provider) { } } - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { for (JsonProvider jsonProvider : jsonProviders) { jsonProvider.writeTo(generator, event); } @@ -84,12 +83,12 @@ protected void prepareForDeferredProcessing(Event event) { jsonProvider.prepareForDeferredProcessing(event); } } - + @Override - public void setJsonFactory(JsonFactory jsonFactory) { + public void setObjectMapper(ObjectMapper objectMapper) { for (JsonProvider jsonProvider : jsonProviders) { - if (jsonProvider instanceof JsonFactoryAware) { - ((JsonFactoryAware) jsonProvider).setJsonFactory(jsonFactory); + if (jsonProvider instanceof ObjectMapperAware) { + ((ObjectMapperAware) jsonProvider).setObjectMapper(objectMapper); } } } diff --git a/src/main/java/net/logstash/logback/composite/JsonReadingUtils.java b/src/main/java/net/logstash/logback/composite/JsonReadingUtils.java index 005da440..b48bcdd5 100644 --- a/src/main/java/net/logstash/logback/composite/JsonReadingUtils.java +++ b/src/main/java/net/logstash/logback/composite/JsonReadingUtils.java @@ -15,13 +15,11 @@ */ package net.logstash.logback.composite; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import tools.jackson.core.JsonParser; +import tools.jackson.core.exc.StreamReadException; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.node.ObjectNode; /** * Utilities for reading/parsing JSON string. @@ -41,31 +39,30 @@ private JsonReadingUtils() { /** * Fully read the supplied JSON string into the equivalent {@link JsonNode}. * - * Throws a {@link JsonParseException} if the string is not fully read after a first valid JsonNode is found. + * Throws a {@link StreamReadException} if the string is not fully read after a first valid JsonNode is found. * This may happen for input like 10 foobar that would otherwise return a NumericNode with value * {@code 10} leaving foobar unread. * - * @param jsonFactory the {@link JsonFactory} from which to obtain a {@link JsonParser} to read the JSON string. + * @param objectMapper the {@link ObjectMapper} from which to obtain a {@link JsonParser} to read the JSON string. * @param json the JSON string to read * @return the {@link JsonNode} corresponding to the input string or {@code null} if the string is null or empty. - * @throws IOException if there is either an underlying I/O problem or decoding issue */ - public static JsonNode readFully(JsonFactory jsonFactory, String json) throws IOException { + public static JsonNode readFully(ObjectMapper objectMapper, String json) { if (json == null) { return null; } final String trimmedJson = json.trim(); - try (JsonParser parser = jsonFactory.createParser(trimmedJson)) { + try (JsonParser parser = objectMapper.createParser(trimmedJson)) { final JsonNode tree = parser.readValueAsTree(); - if (parser.getCurrentLocation().getCharOffset() < trimmedJson.length()) { + if (parser.currentLocation().getCharOffset() < trimmedJson.length()) { /* * If the full trimmed string was not read, then the full trimmed string contains a json value plus other text. * For example, trimmedValue = '10 foobar', or 'true foobar', or '{"foo","bar"} baz'. * In these cases readTree will only read the first part, and will not read the remaining text. */ - throw new JsonParseException(parser, "unexpected character"); + throw new StreamReadException(parser, "unexpected character"); } return tree; @@ -74,22 +71,22 @@ public static JsonNode readFully(JsonFactory jsonFactory, String json) throws IO /** - * Fully read a JSON string into an {@link ObjectNode}, throwing a {@link JsonParseException} if the supplied string + * Fully read a JSON string into an {@link ObjectNode}, throwing a {@link StreamReadException} if the supplied string * is not a valid JSON object representation. * - * @param jsonFactory the {@link JsonFactory} from which to obtain a {@link JsonParser} to read the JSON string. + * @param objectMapper the {@link ObjectMapper} from which to obtain a {@link JsonParser} to read the JSON string. * @param json the JSON string to read * @return the {@link JsonNode} corresponding to the input string or {@code null} if the string is null or empty. - * @throws IOException if there is either an underlying I/O problem or decoding issue - * - * @see JsonReadingUtils#readFully(JsonFactory, String) + * + * @see JsonReadingUtils#readFully(ObjectMapper, String) */ - public static ObjectNode readFullyAsObjectNode(JsonFactory jsonFactory, String json) throws IOException { - final JsonNode node = readFully(jsonFactory, json); + public static ObjectNode readFullyAsObjectNode(ObjectMapper objectMapper, String json) { + final JsonNode node = readFully(objectMapper, json); if (node != null && !(node instanceof ObjectNode)) { - throw new JsonParseException(null, "expected a JSON object representation"); + throw new StreamReadException(null, "expected a JSON object representation"); } - return (ObjectNode) node; } + return (ObjectNode) node; + } } diff --git a/src/main/java/net/logstash/logback/composite/JsonWritingUtils.java b/src/main/java/net/logstash/logback/composite/JsonWritingUtils.java index 928389c8..ac205dd1 100644 --- a/src/main/java/net/logstash/logback/composite/JsonWritingUtils.java +++ b/src/main/java/net/logstash/logback/composite/JsonWritingUtils.java @@ -15,13 +15,11 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.util.Map; import net.logstash.logback.fieldnames.LogstashCommonFieldNames; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonMappingException; +import tools.jackson.core.JsonGenerator; /** * Utilities for writing JSON @@ -36,16 +34,12 @@ public class JsonWritingUtils { * * @param generator the {@link JsonGenerator} to produce JSON content * @param map map whose entries are written as JSON field/values - * - * @throws IOException if an I/O error occurs - * @throws JsonMappingException when problem to convert map values of type Object into JSON */ - public static void writeMapEntries(JsonGenerator generator, Map map) throws IOException, JsonMappingException { + public static void writeMapEntries(JsonGenerator generator, Map map) { if (map != null) { for (Map.Entry entry : map.entrySet()) { if (entry.getKey() != null && entry.getValue() != null) { - generator.writeFieldName(entry.getKey().toString()); - generator.writeObject(entry.getValue()); + generator.writePOJOProperty(entry.getKey().toString(), entry.getValue()); } } } @@ -58,12 +52,8 @@ public static void writeMapEntries(JsonGenerator generator, Map map) throw * @param generator the {@link JsonGenerator} to produce JSON content * @param fieldName name of the JSON property to write the map content under * @param map map whose entries are written as JSON field/values - * - * @throws IOException if an I/O error occurs - * @throws JsonMappingException when problem to convert map values of type Object into JSON - */ - public static void writeMapStringFields(JsonGenerator generator, String fieldName, Map map) throws IOException, JsonMappingException { + public static void writeMapStringFields(JsonGenerator generator, String fieldName, Map map) { writeMapStringFields(generator, fieldName, map, false); } @@ -75,13 +65,10 @@ public static void writeMapStringFields(JsonGenerator generator, String fieldNam * @param fieldName name of the JSON property to write the map content under * @param map map whose entries are written as JSON field/values * @param lowerCaseKeys when true, the map keys will be written in lower case. - * - * @throws IOException if an I/O error occurs - * @throws JsonMappingException when problem to convert map values of type Object into JSON */ - public static void writeMapStringFields(JsonGenerator generator, String fieldName, Map map, boolean lowerCaseKeys) throws IOException, JsonMappingException { + public static void writeMapStringFields(JsonGenerator generator, String fieldName, Map map, boolean lowerCaseKeys) { if (shouldWriteField(fieldName) && map != null && !map.isEmpty()) { - generator.writeObjectFieldStart(fieldName); + generator.writeObjectPropertyStart(fieldName); for (Map.Entry entry : map.entrySet()) { String key = entry.getKey() != null && lowerCaseKeys ? entry.getKey().toLowerCase() @@ -99,12 +86,10 @@ public static void writeMapStringFields(JsonGenerator generator, String fieldNam * @param generator the {@link JsonGenerator} to produce JSON content * @param fieldName the field name * @param fieldValues the field values - * - * @throws IOException if an I/O error occurs */ - public static void writeStringArrayField(JsonGenerator generator, String fieldName, String[] fieldValues) throws IOException { + public static void writeStringArrayField(JsonGenerator generator, String fieldName, String[] fieldValues) { if (shouldWriteField(fieldName) && fieldValues != null && fieldValues.length > 0) { - generator.writeArrayFieldStart(fieldName); + generator.writeArrayPropertyStart(fieldName); for (String fieldValue : fieldValues) { generator.writeString(fieldValue); } @@ -119,12 +104,10 @@ public static void writeStringArrayField(JsonGenerator generator, String fieldNa * @param generator the {@link JsonGenerator} to produce JSON content * @param fieldName the field name * @param fieldValue the field value - * - * @throws IOException if an I/O error occurs */ - public static void writeStringField(JsonGenerator generator, String fieldName, String fieldValue) throws IOException { + public static void writeStringField(JsonGenerator generator, String fieldName, String fieldValue) { if (shouldWriteField(fieldName) && fieldValue != null) { - generator.writeStringField(fieldName, fieldValue); + generator.writeStringProperty(fieldName, fieldValue); } } @@ -134,12 +117,10 @@ public static void writeStringField(JsonGenerator generator, String fieldName, S * @param generator the {@link JsonGenerator} to produce JSON content * @param fieldName the field name * @param fieldValue the field value - * - * @throws IOException if an I/O error occurs */ - public static void writeNumberField(JsonGenerator generator, String fieldName, int fieldValue) throws IOException { + public static void writeNumberField(JsonGenerator generator, String fieldName, int fieldValue) { if (shouldWriteField(fieldName)) { - generator.writeNumberField(fieldName, fieldValue); + generator.writeNumberProperty(fieldName, fieldValue); } } @@ -149,12 +130,10 @@ public static void writeNumberField(JsonGenerator generator, String fieldName, i * @param generator the {@link JsonGenerator} to produce JSON content * @param fieldName the field name * @param fieldValue the field value - * - * @throws IOException if an I/O error occurs */ - public static void writeNumberField(JsonGenerator generator, String fieldName, long fieldValue) throws IOException { + public static void writeNumberField(JsonGenerator generator, String fieldName, long fieldValue) { if (shouldWriteField(fieldName)) { - generator.writeNumberField(fieldName, fieldValue); + generator.writeNumberProperty(fieldName, fieldValue); } } diff --git a/src/main/java/net/logstash/logback/composite/LogstashVersionJsonProvider.java b/src/main/java/net/logstash/logback/composite/LogstashVersionJsonProvider.java index a6362e78..b83fa22c 100644 --- a/src/main/java/net/logstash/logback/composite/LogstashVersionJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/LogstashVersionJsonProvider.java @@ -15,14 +15,12 @@ */ package net.logstash.logback.composite; -import java.io.IOException; - import net.logstash.logback.fieldnames.LogstashCommonFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes a version field as a string value (by default) or a numeric value (if {@link #isWriteAsInteger()} is true). @@ -53,7 +51,7 @@ public LogstashVersionJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { if (writeAsInteger) { JsonWritingUtils.writeNumberField(generator, getFieldName(), versionAsInteger); } else { diff --git a/src/main/java/net/logstash/logback/composite/JsonFactoryAware.java b/src/main/java/net/logstash/logback/composite/ObjectMapperAware.java similarity index 78% rename from src/main/java/net/logstash/logback/composite/JsonFactoryAware.java rename to src/main/java/net/logstash/logback/composite/ObjectMapperAware.java index 8420f2cf..4e44b5bd 100644 --- a/src/main/java/net/logstash/logback/composite/JsonFactoryAware.java +++ b/src/main/java/net/logstash/logback/composite/ObjectMapperAware.java @@ -15,12 +15,13 @@ */ package net.logstash.logback.composite; -import com.fasterxml.jackson.core.JsonFactory; +import tools.jackson.databind.ObjectMapper; /** * Can be implemented by {@link JsonProvider}s to indicate that - * the provider needs to be injected with the {@link JsonFactory}. + * the provider needs to be injected with the {@link ObjectMapper}. */ -public interface JsonFactoryAware { - void setJsonFactory(JsonFactory jsonFactory); +public interface ObjectMapperAware { + + void setObjectMapper(ObjectMapper objectMapper); } diff --git a/src/main/java/net/logstash/logback/composite/SequenceJsonProvider.java b/src/main/java/net/logstash/logback/composite/SequenceJsonProvider.java index 498200da..40ff56d2 100644 --- a/src/main/java/net/logstash/logback/composite/SequenceJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/SequenceJsonProvider.java @@ -15,11 +15,10 @@ */ package net.logstash.logback.composite; -import java.io.IOException; import java.util.concurrent.atomic.AtomicLong; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Outputs an incrementing sequence number. @@ -39,7 +38,7 @@ public SequenceJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, Event iLoggingEvent) throws IOException { + public void writeTo(JsonGenerator generator, Event iLoggingEvent) { JsonWritingUtils.writeNumberField(generator, getFieldName(), sequenceNumber.incrementAndGet()); } diff --git a/src/main/java/net/logstash/logback/composite/UuidJsonProvider.java b/src/main/java/net/logstash/logback/composite/UuidJsonProvider.java index 8ba6e2f5..83523f9a 100644 --- a/src/main/java/net/logstash/logback/composite/UuidJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/UuidJsonProvider.java @@ -15,14 +15,12 @@ */ package net.logstash.logback.composite; -import java.io.IOException; - import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.uuid.EthernetAddress; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.NoArgGenerator; import com.fasterxml.uuid.impl.TimeBasedGenerator; +import tools.jackson.core.JsonGenerator; /** * Outputs random UUID as field value. @@ -64,7 +62,7 @@ public UuidJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, Event event) throws IOException { + public void writeTo(JsonGenerator generator, Event event) { JsonWritingUtils.writeStringField(generator, getFieldName(), uuids.generate().toString()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/AccessEventPatternJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/AccessEventPatternJsonProvider.java index 179dc09a..7ce4ad4e 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/AccessEventPatternJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/AccessEventPatternJsonProvider.java @@ -20,7 +20,6 @@ import net.logstash.logback.pattern.AccessEventJsonPatternParser; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonFactory; /** * @author Dmitry Andrianov @@ -28,8 +27,8 @@ public class AccessEventPatternJsonProvider extends AbstractPatternJsonProvider { @Override - protected AbstractJsonPatternParser createParser(JsonFactory jsonFactory) { - return new AccessEventJsonPatternParser(getContext(), jsonFactory); + protected AbstractJsonPatternParser createParser() { + return new AccessEventJsonPatternParser(getContext(), objectMapper); } } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/AccessMessageJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/AccessMessageJsonProvider.java index 7c141cc4..81fe274e 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/AccessMessageJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/AccessMessageJsonProvider.java @@ -15,14 +15,12 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.composite.loggingevent.MessageJsonProvider; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class AccessMessageJsonProvider extends AccessEventFormattedTimestampJsonProvider { @@ -33,7 +31,7 @@ public AccessMessageJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), String.format("%s - %s [%s] \"%s\" %s %s", diff --git a/src/main/java/net/logstash/logback/composite/accessevent/ContentLengthJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/ContentLengthJsonProvider.java index 0b51b8df..dbfb03b9 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/ContentLengthJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/ContentLengthJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class ContentLengthJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public ContentLengthJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeNumberField(generator, getFieldName(), event.getContentLength()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/ElapsedTimeJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/ElapsedTimeJsonProvider.java index 2699c662..b22a2006 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/ElapsedTimeJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/ElapsedTimeJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class ElapsedTimeJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public ElapsedTimeJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeNumberField(generator, getFieldName(), event.getElapsedTime()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/MethodJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/MethodJsonProvider.java index 6d68db5c..0886fa60 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/MethodJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/MethodJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class MethodJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public MethodJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getMethod()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/ProtocolJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/ProtocolJsonProvider.java index df04aad2..f465d809 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/ProtocolJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/ProtocolJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class ProtocolJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public ProtocolJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getProtocol()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/RemoteHostJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/RemoteHostJsonProvider.java index 359bb5b1..74bf1414 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/RemoteHostJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/RemoteHostJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class RemoteHostJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public RemoteHostJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getRemoteHost()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/RemoteUserJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/RemoteUserJsonProvider.java index 9cb58ae5..9c5a0b7a 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/RemoteUserJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/RemoteUserJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class RemoteUserJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public RemoteUserJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getRemoteUser()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProvider.java index 753afbee..a1de2178 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -26,7 +25,7 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.core.joran.spi.DefaultClass; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class RequestHeadersJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -38,7 +37,7 @@ public class RequestHeadersJsonProvider extends AbstractFieldJsonProvider headers; if (filter == null) { headers = event.getRequestHeaderMap(); diff --git a/src/main/java/net/logstash/logback/composite/accessevent/RequestedUriJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/RequestedUriJsonProvider.java index cc9009d3..e0cf8212 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/RequestedUriJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/RequestedUriJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class RequestedUriJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public RequestedUriJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getRequestURI()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/RequestedUrlJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/RequestedUrlJsonProvider.java index 50c435d8..f1e6cf69 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/RequestedUrlJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/RequestedUrlJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class RequestedUrlJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public RequestedUrlJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getRequestURL()); } diff --git a/src/main/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProvider.java index aae338e4..77caa6e6 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -26,7 +25,7 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.core.joran.spi.DefaultClass; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class ResponseHeadersJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -38,7 +37,7 @@ public class ResponseHeadersJsonProvider extends AbstractFieldJsonProvider headers; if (filter == null) { headers = event.getResponseHeaderMap(); diff --git a/src/main/java/net/logstash/logback/composite/accessevent/StatusCodeJsonProvider.java b/src/main/java/net/logstash/logback/composite/accessevent/StatusCodeJsonProvider.java index 6573566d..bbcbb1af 100644 --- a/src/main/java/net/logstash/logback/composite/accessevent/StatusCodeJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/accessevent/StatusCodeJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.accessevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashAccessFieldNames; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class StatusCodeJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public StatusCodeJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, IAccessEvent event) throws IOException { + public void writeTo(JsonGenerator generator, IAccessEvent event) { JsonWritingUtils.writeNumberField(generator, getFieldName(), event.getStatusCode()); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableClassNameJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableClassNameJsonProvider.java index 8fef86c5..17f134df 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableClassNameJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableClassNameJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.JsonWritingUtils; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public abstract class AbstractThrowableClassNameJsonProvider extends AbstractFieldJsonProvider { static final boolean DEFAULT_USE_SIMPLE_CLASS_NAME = true; @@ -35,7 +33,7 @@ public AbstractThrowableClassNameJsonProvider(String fieldName) { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { IThrowableProxy throwable = getThrowable(event.getThrowableProxy()); if (throwable != null) { String throwableClassName = determineClassName(throwable); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableMessageJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableMessageJsonProvider.java index 7ce27b3a..0b774a42 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableMessageJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/AbstractThrowableMessageJsonProvider.java @@ -15,14 +15,12 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.JsonWritingUtils; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Logs an exception message for a given logging event. Which exception to be @@ -36,7 +34,7 @@ protected AbstractThrowableMessageJsonProvider(String fieldName) { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { IThrowableProxy throwable = getThrowable(event); if (throwable != null) { String throwableMessage = throwable.getMessage(); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProvider.java index 3fc46571..91b26b8a 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.argument.StructuredArgument; import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Include the logging event's {@link ILoggingEvent#getArgumentArray()} in the JSON output. @@ -49,7 +47,7 @@ public class ArgumentsJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -38,13 +36,13 @@ public class CallerDataJsonProvider extends AbstractFieldJsonProvider { @@ -32,7 +30,7 @@ public ContextNameJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getLoggerContextVO().getName()); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java index ad31efc3..90ff5a72 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -27,8 +26,8 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.event.KeyValuePair; +import tools.jackson.core.JsonGenerator; /** * Includes key value pairs added from slf4j's fluent api in the output according to @@ -82,7 +81,7 @@ public void start() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { List keyValuePairs = event.getKeyValuePairs(); if (keyValuePairs == null || keyValuePairs.isEmpty()) { return; @@ -90,7 +89,7 @@ public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOExcep String fieldName = getFieldName(); if (fieldName != null) { - generator.writeObjectFieldStart(getFieldName()); + generator.writeObjectPropertyStart(getFieldName()); } for (KeyValuePair keyValuePair : keyValuePairs) { @@ -102,8 +101,7 @@ public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOExcep if (key == null) { key = keyValuePair.key; } - generator.writeFieldName(key); - generator.writeObject(keyValuePair.value); + generator.writePOJOProperty(key, keyValuePair.value); } } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProvider.java index 577574a2..a5a121aa 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class LogLevelJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public LogLevelJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getLevel().toString()); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProvider.java index 97dae005..23deb644 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProvider.java @@ -15,15 +15,13 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class LogLevelValueJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -34,7 +32,7 @@ public LogLevelValueJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { JsonWritingUtils.writeNumberField(generator, getFieldName(), event.getLevel().toInt()); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProvider.java index 06d0a61d..1b73ade8 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; import java.util.Objects; import net.logstash.logback.abbreviator.DefaultTargetLengthAbbreviator; @@ -28,7 +27,7 @@ import ch.qos.logback.classic.pattern.Abbreviator; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.joran.spi.DefaultClass; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class LoggerNameJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -45,7 +44,7 @@ public LoggerNameJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { if (!isStarted()) { throw new IllegalStateException("Generator is not started"); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventPatternJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventPatternJsonProvider.java index 036cdbe1..8c4871c4 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventPatternJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/LoggingEventPatternJsonProvider.java @@ -20,7 +20,6 @@ import net.logstash.logback.pattern.LoggingEventJsonPatternParser; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonFactory; /** * @author Dmitry Andrianov @@ -28,8 +27,8 @@ public class LoggingEventPatternJsonProvider extends AbstractPatternJsonProvider { @Override - protected AbstractJsonPatternParser createParser(JsonFactory jsonFactory) { - return new LoggingEventJsonPatternParser(getContext(), jsonFactory); + protected AbstractJsonPatternParser createParser() { + return new LoggingEventJsonPatternParser(getContext(), objectMapper); } } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProvider.java index 7ef458d7..68cabe25 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; import java.util.Iterator; import java.util.List; @@ -25,8 +24,8 @@ import net.logstash.logback.marker.Markers; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * A {@link JsonProvider} that processes {@link LogstashMarker}s @@ -35,11 +34,11 @@ public class LogstashMarkersJsonProvider extends AbstractJsonProvider { @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { writeLogstashMarkerIfNecessary(generator, event.getMarkerList()); } - private void writeLogstashMarkerIfNecessary(JsonGenerator generator, List markers) throws IOException { + private void writeLogstashMarkerIfNecessary(JsonGenerator generator, List markers) { if (markers != null) { for (Marker marker: markers) { writeLogstashMarkerIfNecessary(generator, marker); @@ -47,7 +46,7 @@ private void writeLogstashMarkerIfNecessary(JsonGenerator generator, List mdcProperties = event.getMDCPropertyMap(); if (mdcProperties != null && !mdcProperties.isEmpty()) { @@ -107,7 +106,7 @@ public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOExcep fieldName = entry.getKey(); } if (!hasWrittenStart && getFieldName() != null) { - generator.writeObjectFieldStart(getFieldName()); + generator.writeObjectPropertyStart(getFieldName()); hasWrittenStart = true; } writeMdcEntry(generator, fieldName, entry.getKey(), entry.getValue()); @@ -184,15 +183,14 @@ public void addMdcKeyFieldName(String mdcKeyFieldName) { * @param mdcKey the key of the MDC map entry. * @param mdcValue the value of the MDC map entry. */ - private void writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) throws IOException { + private void writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) { for (MdcEntryWriter mdcEntryWriter : this.mdcEntryWriters) { if (mdcEntryWriter.writeMdcEntry(generator, fieldName, mdcKey, mdcValue)) { return; } } - generator.writeFieldName(fieldName); - generator.writeObject(mdcValue); + generator.writePOJOProperty(fieldName, mdcValue); } } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/MessageJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/MessageJsonProvider.java index 427b5a74..ee081f2f 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/MessageJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/MessageJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; import java.util.regex.Pattern; import net.logstash.logback.composite.AbstractFieldJsonProvider; @@ -25,7 +24,7 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class MessageJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -38,7 +37,7 @@ public MessageJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { if (messageSplitPattern != null) { String[] multiLineMessage = messageSplitPattern.split(event.getFormattedMessage()); JsonWritingUtils.writeStringArrayField(generator, getFieldName(), multiLineMessage); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProvider.java index d78247b8..7d074d7b 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProvider.java @@ -15,13 +15,11 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.JsonWritingUtils; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class RawMessageJsonProvider extends AbstractFieldJsonProvider { @@ -32,7 +30,7 @@ public RawMessageJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { JsonWritingUtils.writeStringField(generator, getFieldName(), event.getMessage()); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProvider.java index 25e2d3bb..7eab1149 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProvider.java @@ -15,8 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; @@ -25,7 +23,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * A JSON provider that, for any log event with a stack trace, @@ -48,13 +46,13 @@ public RootStackTraceElementJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { IThrowableProxy throwableProxy = event.getThrowableProxy(); - if (throwableProxy != null && throwableProxy instanceof ThrowableProxy) { + if (throwableProxy instanceof ThrowableProxy) { if (throwableProxy.getStackTraceElementProxyArray().length > 0) { StackTraceElement stackTraceElement = throwableProxy.getStackTraceElementProxyArray()[0].getStackTraceElement(); - generator.writeObjectFieldStart(getFieldName()); + generator.writeObjectPropertyStart(getFieldName()); JsonWritingUtils.writeStringField(generator, classFieldName, stackTraceElement.getClassName()); JsonWritingUtils.writeStringField(generator, methodFieldName, stackTraceElement.getMethodName()); generator.writeEndObject(); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/StackHashJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/StackHashJsonProvider.java index 59ef3f7d..7d968ea0 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/StackHashJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/StackHashJsonProvider.java @@ -17,7 +17,6 @@ import static net.logstash.logback.util.StringUtils.commaDelimitedListToStringArray; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -31,7 +30,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * A JSON provider that adds a {@code stack_hash} Json field on a log with a stack trace @@ -103,7 +102,7 @@ public List getExcludes() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { assertIsStarted(); IThrowableProxy throwableProxy = event.getThrowableProxy(); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProvider.java index 7bfe3e51..52f88b02 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProvider.java @@ -15,8 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; - import net.logstash.logback.composite.AbstractFieldJsonProvider; import net.logstash.logback.composite.FieldNamesAware; import net.logstash.logback.composite.JsonWritingUtils; @@ -26,7 +24,7 @@ import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class StackTraceJsonProvider extends AbstractFieldJsonProvider implements FieldNamesAware { @@ -60,7 +58,7 @@ public void stop() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { IThrowableProxy throwableProxy = event.getThrowableProxy(); if (throwableProxy != null) { JsonWritingUtils.writeStringField(generator, getFieldName(), throwableConverter.convert(event)); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/TagsJsonProvider.java b/src/main/java/net/logstash/logback/composite/loggingevent/TagsJsonProvider.java index acc09070..3999b4f4 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/TagsJsonProvider.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/TagsJsonProvider.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.composite.loggingevent; -import java.io.IOException; import java.util.Iterator; import java.util.List; @@ -25,8 +24,8 @@ import net.logstash.logback.marker.LogstashMarker; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * Writes {@link Marker} names as an array to the 'tags' field. @@ -43,7 +42,7 @@ public TagsJsonProvider() { } @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { /* * Don't write the tags field unless we actually have a tag to write. */ @@ -56,7 +55,7 @@ public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOExcep } } - private boolean writeTagIfNecessary(JsonGenerator generator, boolean hasWrittenStart, final List markers) throws IOException { + private boolean writeTagIfNecessary(JsonGenerator generator, boolean hasWrittenStart, final List markers) { if (markers != null) { for (Marker marker: markers) { hasWrittenStart |= writeTagIfNecessary(generator, hasWrittenStart, marker); @@ -66,11 +65,11 @@ private boolean writeTagIfNecessary(JsonGenerator generator, boolean hasWrittenS return hasWrittenStart; } - private boolean writeTagIfNecessary(JsonGenerator generator, boolean hasWrittenStart, final Marker marker) throws IOException { + private boolean writeTagIfNecessary(JsonGenerator generator, boolean hasWrittenStart, final Marker marker) { if (marker != null) { if (!LogstashMarkersJsonProvider.isLogstashMarker(marker)) { if (!hasWrittenStart) { - generator.writeArrayFieldStart(getFieldName()); + generator.writeArrayPropertyStart(getFieldName()); hasWrittenStart = true; } generator.writeString(marker.getName()); diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriter.java b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriter.java index eb728e36..5f0b507e 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriter.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriter.java @@ -15,9 +15,7 @@ */ package net.logstash.logback.composite.loggingevent.mdc; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes boolean values (instead of String values) for any MDC values that equal "true" or "false", ignoring case. @@ -25,15 +23,13 @@ public class BooleanMdcEntryWriter implements MdcEntryWriter { @Override - public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) throws IOException { + public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) { if ("true".equalsIgnoreCase(mdcValue)) { - generator.writeFieldName(fieldName); - generator.writeBoolean(true); + generator.writeBooleanProperty(fieldName, true); return true; } if ("false".equalsIgnoreCase(mdcValue)) { - generator.writeFieldName(fieldName); - generator.writeBoolean(false); + generator.writeBooleanProperty(fieldName, false); return true; } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriter.java b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriter.java index e9b6593e..ed2fda2c 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriter.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriter.java @@ -15,10 +15,9 @@ */ package net.logstash.logback.composite.loggingevent.mdc; -import java.io.IOException; import java.util.regex.Pattern; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes double values (instead of String values) for any MDC values that can be parsed as a double, @@ -29,12 +28,11 @@ public class DoubleMdcEntryWriter implements MdcEntryWriter { private static final Pattern DOUBLE_PATTERN = doublePattern(); @Override - public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) throws IOException { + public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) { if (shouldParse(mdcValue)) { try { double parsedValue = Double.parseDouble(mdcValue); - generator.writeFieldName(fieldName); - generator.writeNumber(parsedValue); + generator.writeNumberProperty(fieldName, parsedValue); return true; } catch (NumberFormatException ignore) { } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriter.java b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriter.java index b90d138c..1279494a 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriter.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriter.java @@ -15,9 +15,7 @@ */ package net.logstash.logback.composite.loggingevent.mdc; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes long values (instead of String values) for any MDC values that can be parsed as a long (radix 10). @@ -25,12 +23,11 @@ public class LongMdcEntryWriter implements MdcEntryWriter { @Override - public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) throws IOException { + public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) { if (shouldParse(mdcValue)) { try { long parsedValue = Long.parseLong(mdcValue); - generator.writeFieldName(fieldName); - generator.writeNumber(parsedValue); + generator.writeNumberProperty(fieldName, parsedValue); return true; } catch (NumberFormatException ignore) { } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/MdcEntryWriter.java b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/MdcEntryWriter.java index 91b074c0..581c3535 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/MdcEntryWriter.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/MdcEntryWriter.java @@ -15,9 +15,7 @@ */ package net.logstash.logback.composite.loggingevent.mdc; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes an entry from the {@link org.slf4j.MDC} to the {@link JsonGenerator}. @@ -35,6 +33,6 @@ public interface MdcEntryWriter { * @param mdcValue the value of the MDC map entry. * @return true if this {@link MdcEntryWriter} handled the output of the entry, otherwise return false. */ - boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) throws IOException; + boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue); } diff --git a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriter.java b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriter.java index e6038915..636e6799 100644 --- a/src/main/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriter.java +++ b/src/main/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriter.java @@ -15,13 +15,12 @@ */ package net.logstash.logback.composite.loggingevent.mdc; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes MDC entries by delegating to other instances of {@link MdcEntryWriter} if MDC key matches the given include @@ -41,7 +40,7 @@ public class RegexFilteringMdcEntryWriter implements MdcEntryWriter { private final List mdcEntryWriters = new ArrayList<>(); @Override - public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) throws IOException { + public boolean writeMdcEntry(JsonGenerator generator, String fieldName, String mdcKey, String mdcValue) { if (shouldWrite(mdcKey)) { for (MdcEntryWriter mdcEntryWriter : this.mdcEntryWriters) { if (mdcEntryWriter.writeMdcEntry(generator, fieldName, mdcKey, mdcValue)) { diff --git a/src/main/java/net/logstash/logback/dataformat/DataFormatFactory.java b/src/main/java/net/logstash/logback/dataformat/DataFormatFactory.java new file mode 100644 index 00000000..84e40661 --- /dev/null +++ b/src/main/java/net/logstash/logback/dataformat/DataFormatFactory.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.dataformat; + +import tools.jackson.core.TSFBuilder; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.MapperBuilder; + +/** + * Factory for creating builders for a jackson data format. + * + * @param Type of TokenStreamFactory + * @param Type of TokenStreamFactory.TSFBuilder (that builds the TokenStreamFactory) + * @param Type of ObjectMapper + * @param Type of MapperBuilder (that builds the ObjectMapper) + */ +public interface DataFormatFactory< + F extends TokenStreamFactory, + FB extends TSFBuilder, + M extends ObjectMapper, + MB extends MapperBuilder> { + + String JSON = "json"; + String YAML = "yaml"; + String SMILE = "smile"; + String CBOR = "cbor"; + + /** + * Returns the name of the data format. + * @return the name of the data format. + */ + String getName(); + + /** + * Creates and returns a new {@link TokenStreamFactory} for this data format. + * + * @return a new {@link TokenStreamFactory} for this data format. + */ + FB createTokenStreamFactoryBuilder(); + + /** + * Creates and returns a new {@link MapperBuilder} for this data format backed by the given factory. + * + * @param factory the factory constructed from the builder returned by {@link #createTokenStreamFactoryBuilder()} (perhaps decorated with other configuration) + * @return a new {@link MapperBuilder} for this data format backed by the given factory. + */ + MB createMapperBuilder(F factory); +} diff --git a/src/main/java/net/logstash/logback/dataformat/cbor/CborDataFormatFactory.java b/src/main/java/net/logstash/logback/dataformat/cbor/CborDataFormatFactory.java new file mode 100644 index 00000000..6f56c30b --- /dev/null +++ b/src/main/java/net/logstash/logback/dataformat/cbor/CborDataFormatFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.dataformat.cbor; + +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.decorate.TokenStreamFactoryFeatureDecorator; +import net.logstash.logback.decorate.cbor.CborWriteFeatureDecorator; + +import tools.jackson.core.StreamWriteFeature; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.dataformat.cbor.CBORFactory; +import tools.jackson.dataformat.cbor.CBORFactoryBuilder; +import tools.jackson.dataformat.cbor.CBORMapper; +import tools.jackson.dataformat.cbor.CBORWriteFeature; + +/** + * A {@link DataFormatFactory} for the CBOR data format. + * + *

See also {@link CborWriteFeatureDecorator} for configuring {@link CBORWriteFeature}s, + * and {@link TokenStreamFactoryFeatureDecorator} for configuring {@link TokenStreamFactory.Feature}s

+ */ +public class CborDataFormatFactory implements DataFormatFactory { + + @Override + public String getName() { + return CBOR; + } + + @Override + public CBORFactoryBuilder createTokenStreamFactoryBuilder() { + return CBORFactory.builder() + /* + * When CBORGenerator is flushed, flush the internal buffer to the underlying outputStream, + * but don't flush the underlying outputStream. + * + * This allows some streaming optimizations when using an encoder. + * + * The encoder generally determines when the stream should be flushed + * by an 'immediateFlush' property. + * + * The 'immediateFlush' property of the encoder can be set to false + * when the appender performs the flushes at appropriate times + * (such as the end of a batch in the AbstractLogstashTcpSocketAppender). + */ + .disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM); + } + + @Override + public CBORMapper.Builder createMapperBuilder(CBORFactory factory) { + return CBORMapper.builder(factory); + } +} diff --git a/src/main/java/net/logstash/logback/dataformat/json/JsonDataFormatFactory.java b/src/main/java/net/logstash/logback/dataformat/json/JsonDataFormatFactory.java new file mode 100644 index 00000000..b5d8ed48 --- /dev/null +++ b/src/main/java/net/logstash/logback/dataformat/json/JsonDataFormatFactory.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.dataformat.json; + +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.decorate.TokenStreamFactoryFeatureDecorator; +import net.logstash.logback.decorate.json.JsonWriteFeatureDecorator; + +import ch.qos.logback.core.CoreConstants; +import tools.jackson.core.StreamWriteFeature; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.core.io.SerializedString; +import tools.jackson.core.json.JsonFactory; +import tools.jackson.core.json.JsonFactoryBuilder; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.json.JsonMapper; + +/** + * A {@link DataFormatFactory} for the JSON data format. + * + *

See also {@link JsonWriteFeatureDecorator} for configuring {@link JsonWriteFeature}s, + * and {@link TokenStreamFactoryFeatureDecorator} for configuring {@link TokenStreamFactory.Feature}s

+ */ +public class JsonDataFormatFactory implements DataFormatFactory { + + @Override + public String getName() { + return JSON; + } + + @Override + public JsonFactoryBuilder createTokenStreamFactoryBuilder() { + return JsonFactory.builder() + /* + * When JsonGenerator is flushed, flush the internal buffer to the underlying outputStream, + * but don't flush the underlying outputStream. + * + * This allows some streaming optimizations when using an encoder. + * + * The encoder generally determines when the stream should be flushed + * by an 'immediateFlush' property. + * + * The 'immediateFlush' property of the encoder can be set to false + * when the appender performs the flushes at appropriate times + * (such as the end of a batch in the AbstractLogstashTcpSocketAppender). + */ + .disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM) + /* + * JsonGenerator are reused to serialize multiple log events. + * Change the default root value separator to an empty string instead of a single space. + */ + .rootValueSeparator(new SerializedString(CoreConstants.EMPTY_STRING)); + } + + @Override + public JsonMapper.Builder createMapperBuilder(JsonFactory factory) { + return JsonMapper.builder(factory); + } +} diff --git a/src/main/java/net/logstash/logback/dataformat/smile/SmileDataFormatFactory.java b/src/main/java/net/logstash/logback/dataformat/smile/SmileDataFormatFactory.java new file mode 100644 index 00000000..d1f48158 --- /dev/null +++ b/src/main/java/net/logstash/logback/dataformat/smile/SmileDataFormatFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.dataformat.smile; + +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.decorate.TokenStreamFactoryFeatureDecorator; +import net.logstash.logback.decorate.smile.SmileWriteFeatureDecorator; + +import tools.jackson.core.StreamWriteFeature; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.dataformat.smile.SmileFactory; +import tools.jackson.dataformat.smile.SmileFactoryBuilder; +import tools.jackson.dataformat.smile.SmileMapper; +import tools.jackson.dataformat.smile.SmileWriteFeature; + +/** + * A {@link DataFormatFactory} for the Smile data format. + * + *

See also {@link SmileWriteFeatureDecorator} for configuring {@link SmileWriteFeature} features + * and {@link TokenStreamFactoryFeatureDecorator} for configuring {@link TokenStreamFactory.Feature}s

+ */ +public class SmileDataFormatFactory implements DataFormatFactory { + + @Override + public String getName() { + return SMILE; + } + + @Override + public SmileFactoryBuilder createTokenStreamFactoryBuilder() { + return SmileFactory.builder() + /* + * When SmileGenerator is flushed, flush the internal buffer to the underlying outputStream, + * but don't flush the underlying outputStream. + * + * This allows some streaming optimizations when using an encoder. + * + * The encoder generally determines when the stream should be flushed + * by an 'immediateFlush' property. + * + * The 'immediateFlush' property of the encoder can be set to false + * when the appender performs the flushes at appropriate times + * (such as the end of a batch in the AbstractLogstashTcpSocketAppender). + */ + .disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM); + } + + @Override + public SmileMapper.Builder createMapperBuilder(SmileFactory factory) { + return SmileMapper.builder(factory); + } +} diff --git a/src/main/java/net/logstash/logback/dataformat/yaml/YamlDataFormatFactory.java b/src/main/java/net/logstash/logback/dataformat/yaml/YamlDataFormatFactory.java new file mode 100644 index 00000000..aec55086 --- /dev/null +++ b/src/main/java/net/logstash/logback/dataformat/yaml/YamlDataFormatFactory.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.dataformat.yaml; + +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.decorate.TokenStreamFactoryFeatureDecorator; +import net.logstash.logback.decorate.yaml.YamlWriteFeatureDecorator; + +import tools.jackson.core.StreamWriteFeature; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.dataformat.yaml.YAMLFactory; +import tools.jackson.dataformat.yaml.YAMLFactoryBuilder; +import tools.jackson.dataformat.yaml.YAMLGenerator; +import tools.jackson.dataformat.yaml.YAMLMapper; + +/** + * A {@link DataFormatFactory} for the YAML data format. + * + *

See also {@link YamlWriteFeatureDecorator} for configuring {@link YAMLGenerator} features + * and {@link TokenStreamFactoryFeatureDecorator} for configuring {@link TokenStreamFactory.Feature}s

+ */ +public class YamlDataFormatFactory implements DataFormatFactory { + + @Override + public String getName() { + return YAML; + } + + @Override + public YAMLFactoryBuilder createTokenStreamFactoryBuilder() { + return YAMLFactory.builder() + /* + * YAMLGenerator needs to pass the flush to the stream. + * It doesn't maintain an internal buffer like the other generators. + * To see this, look at the .flush() implementations of each of the generator classes. + */ + .enable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM); + } + + @Override + public YAMLMapper.Builder createMapperBuilder(YAMLFactory factory) { + return YAMLMapper.builder(factory); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/CompositeJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/CompositeDecorator.java similarity index 58% rename from src/main/java/net/logstash/logback/decorate/CompositeJsonFactoryDecorator.java rename to src/main/java/net/logstash/logback/decorate/CompositeDecorator.java index ce13dd9b..081848ab 100644 --- a/src/main/java/net/logstash/logback/decorate/CompositeJsonFactoryDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/CompositeDecorator.java @@ -15,32 +15,29 @@ */ package net.logstash.logback.decorate; -import java.util.ArrayList; import java.util.List; - -import com.fasterxml.jackson.core.JsonFactory; +import java.util.concurrent.CopyOnWriteArrayList; /** * Combines a list of decorators into a single decorator, so multiple decorators can be used together. */ -public class CompositeJsonFactoryDecorator implements JsonFactoryDecorator { +public class CompositeDecorator> implements Decorator { - private final List decorators = new ArrayList<>(); + private final List decorators = new CopyOnWriteArrayList<>(); - @Override - public JsonFactory decorate(JsonFactory factory) { - JsonFactory decoratedFactory = factory; - for (JsonFactoryDecorator decorator : decorators) { - decoratedFactory = decorator.decorate(decoratedFactory); + public T decorate(T decoratable) { + T decorated = decoratable; + for (Decorator decorator : decorators) { + decorated = decorator.decorate(decorated); } - return decoratedFactory; + return decorated; } - - public void addDecorator(JsonFactoryDecorator decorator) { + + public void addDecorator(D decorator) { decorators.add(decorator); } - public boolean removeDecorator(JsonFactoryDecorator decorator) { + public boolean removeDecorator(D decorator) { return decorators.remove(decorator); } diff --git a/src/main/java/net/logstash/logback/decorate/CompositeJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/CompositeJsonGeneratorDecorator.java index 92c5de8c..38b20bb9 100644 --- a/src/main/java/net/logstash/logback/decorate/CompositeJsonGeneratorDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/CompositeJsonGeneratorDecorator.java @@ -15,33 +15,12 @@ */ package net.logstash.logback.decorate; -import java.util.ArrayList; -import java.util.List; - -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Combines a list of decorators into a single decorator, so multiple decorators can be used together. */ -public class CompositeJsonGeneratorDecorator implements JsonGeneratorDecorator { - - private final List decorators = new ArrayList<>(); - - @Override - public JsonGenerator decorate(JsonGenerator generator) { - JsonGenerator decoratedGenerator = generator; - for (JsonGeneratorDecorator decorator : decorators) { - decoratedGenerator = decorator.decorate(decoratedGenerator); - } - return decoratedGenerator; - } - - public void addDecorator(JsonGeneratorDecorator decorator) { - decorators.add(decorator); - } - - public boolean removeDecorator(JsonGeneratorDecorator decorator) { - return decorators.remove(decorator); - } - +public class CompositeJsonGeneratorDecorator + extends CompositeDecorator + implements JsonGeneratorDecorator { } diff --git a/src/main/java/net/logstash/logback/decorate/NullJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/CompositeMapperBuilderDecorator.java similarity index 61% rename from src/main/java/net/logstash/logback/decorate/NullJsonGeneratorDecorator.java rename to src/main/java/net/logstash/logback/decorate/CompositeMapperBuilderDecorator.java index 7c3a5a04..3cce8777 100644 --- a/src/main/java/net/logstash/logback/decorate/NullJsonGeneratorDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/CompositeMapperBuilderDecorator.java @@ -15,17 +15,13 @@ */ package net.logstash.logback.decorate; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.MapperBuilder; /** - * A {@link JsonGeneratorDecorator} that doesn't do any decoration. - * It just returns the generator as-is. + * Combines a list of decorators into a single decorator, so multiple decorators can be used together. */ -public class NullJsonGeneratorDecorator implements JsonGeneratorDecorator { - - @Override - public JsonGenerator decorate(JsonGenerator generator) { - return generator; - } - +public class CompositeMapperBuilderDecorator> + extends CompositeDecorator> + implements MapperBuilderDecorator { } diff --git a/src/main/java/net/logstash/logback/decorate/FeatureJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/CompositeTokenStreamFactoryBuilderDecorator.java similarity index 60% rename from src/main/java/net/logstash/logback/decorate/FeatureJsonGeneratorDecorator.java rename to src/main/java/net/logstash/logback/decorate/CompositeTokenStreamFactoryBuilderDecorator.java index 0f7957f9..8f70286a 100644 --- a/src/main/java/net/logstash/logback/decorate/FeatureJsonGeneratorDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/CompositeTokenStreamFactoryBuilderDecorator.java @@ -15,14 +15,13 @@ */ package net.logstash.logback.decorate; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.TSFBuilder; +import tools.jackson.core.TokenStreamFactory; /** - * A {@link JsonGeneratorDecorator} that allows enabling/disabling of {@link JsonGenerator} features. + * Combines a list of decorators into a single decorator, so multiple decorators can be used together. */ -public class FeatureJsonGeneratorDecorator extends FeatureDecorator implements JsonGeneratorDecorator { - - public FeatureJsonGeneratorDecorator() { - super(JsonGenerator.Feature.class, JsonGenerator::enable, JsonGenerator::disable); - } +public class CompositeTokenStreamFactoryBuilderDecorator> + extends CompositeDecorator> + implements TokenStreamFactoryBuilderDecorator { } diff --git a/src/main/java/net/logstash/logback/decorate/DateTimeFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/DateTimeFeatureDecorator.java new file mode 100644 index 00000000..ae77bc98 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/DateTimeFeatureDecorator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.DateTimeFeature; +import tools.jackson.databind.cfg.MapperBuilder; + +/** + * A {@link MapperBuilderDecorator} that allows enabling/disabling of {@link DateTimeFeature} features. + */ +public class DateTimeFeatureDecorator> + extends FeatureDecorator + implements MapperBuilderDecorator { + + public DateTimeFeatureDecorator() { + super(DateTimeFeature.class); + } + + @Override + protected B configure(B builder, DateTimeFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/NullJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/Decorator.java similarity index 65% rename from src/main/java/net/logstash/logback/decorate/NullJsonFactoryDecorator.java rename to src/main/java/net/logstash/logback/decorate/Decorator.java index 989b6a21..2415d23c 100644 --- a/src/main/java/net/logstash/logback/decorate/NullJsonFactoryDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/Decorator.java @@ -15,17 +15,18 @@ */ package net.logstash.logback.decorate; -import com.fasterxml.jackson.core.JsonFactory; - /** - * A {@link JsonFactoryDecorator} that doesn't do any decoration. - * It just returns the factory as-is. + * Decorates an object. + * + * @param the type of object to decorate */ -public class NullJsonFactoryDecorator implements JsonFactoryDecorator { - - @Override - public JsonFactory decorate(JsonFactory factory) { - return factory; - } +public interface Decorator { + /** + * Decorates the given {@code decoratable}. + * + * @param decoratable the object to decorate + * @return the decorated object (can be a different from the object passed in as an arg) + */ + T decorate(T decoratable); } diff --git a/src/main/java/net/logstash/logback/decorate/EscapeNonAsciiJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/EnumFeatureDecorator.java similarity index 52% rename from src/main/java/net/logstash/logback/decorate/EscapeNonAsciiJsonFactoryDecorator.java rename to src/main/java/net/logstash/logback/decorate/EnumFeatureDecorator.java index 2e8c55b9..e7ec8410 100644 --- a/src/main/java/net/logstash/logback/decorate/EscapeNonAsciiJsonFactoryDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/EnumFeatureDecorator.java @@ -15,20 +15,23 @@ */ package net.logstash.logback.decorate; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.EnumFeature; +import tools.jackson.databind.cfg.MapperBuilder; /** - * Enables the {@link com.fasterxml.jackson.core.JsonGenerator.Feature#ESCAPE_NON_ASCII} feature on the {@link JsonFactory}. - * - * Prior to 5.0, {@link com.fasterxml.jackson.core.JsonGenerator.Feature#ESCAPE_NON_ASCII} was enabled by default. - * In 5.0, the feature is disabled by default, and can be re-enabled with this decorator. + * A {@link MapperBuilderDecorator} that allows enabling/disabling of {@link EnumFeature} features. */ -public class EscapeNonAsciiJsonFactoryDecorator implements JsonFactoryDecorator { +public class EnumFeatureDecorator> + extends FeatureDecorator + implements MapperBuilderDecorator { - @Override - public JsonFactory decorate(JsonFactory factory) { - return factory.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + public EnumFeatureDecorator() { + super(EnumFeature.class); } + @Override + protected B configure(B builder, EnumFeature feature, boolean state) { + return builder.configure(feature, state); + } } diff --git a/src/main/java/net/logstash/logback/decorate/FeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/FeatureDecorator.java index 148c9730..ec3cb0bd 100644 --- a/src/main/java/net/logstash/logback/decorate/FeatureDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/FeatureDecorator.java @@ -17,60 +17,55 @@ import java.util.ArrayList; import java.util.List; -import java.util.function.BiFunction; - -import com.fasterxml.jackson.core.JsonFactory; /** - * A generic decorator that allows enabling/disabling of Jackson features. + * A generic decorator that allows enabling/disabling of Jackson features by feature name. * - * @param Type of object being decorated (e.g. {@link JsonFactory}) - * @param Feature enum type (e.g. {@link com.fasterxml.jackson.core.JsonFactory.Feature}) + * @param Type of object being decorated (e.g. {@link tools.jackson.core.json.JsonFactory}) + * @param Feature enum type (e.g. {@link tools.jackson.core.json.JsonWriteFeature}) */ -public class FeatureDecorator> { +public abstract class FeatureDecorator> implements Decorator { /** - * Jackson feature enum type (e.g. {@link JsonFactory.Feature}) + * Jackson feature enum type (e.g. {@link tools.jackson.core.json.JsonWriteFeature}) */ private final Class enumType; - /** - * Function to enable a feature. - */ - private final BiFunction enableFunction; - /** - * Function to disable a feature. - */ - private final BiFunction disableFunction; /** * Features to enable */ private final List enables = new ArrayList<>(); + /** * Features to disable */ private final List disables = new ArrayList<>(); - protected FeatureDecorator( - Class enumType, - BiFunction enableFunction, - BiFunction disableFunction) { + protected FeatureDecorator(Class enumType) { this.enumType = enumType; - this.enableFunction = enableFunction; - this.disableFunction = disableFunction; } - public T decorate(T target) { - T modifiedTarget = target; + public T decorate(T decoratable) { + T decorated = decoratable; for (F feature : enables) { - modifiedTarget = enableFunction.apply(modifiedTarget, feature); + decorated = configure(decorated, feature, true); } for (F feature : disables) { - modifiedTarget = disableFunction.apply(modifiedTarget, feature); + decorated = configure(decorated, feature, false); } - return modifiedTarget; + return decorated; } + /** + * Configures the given feature on the given decoratable. + * + * @param decoratable the object to configure + * @param feature the feature to enable or disable + * @param state true to enable the feature, false to disable the feature. + * @return the decorated object + */ + protected abstract T configure(T decoratable, F feature, boolean state); + /** * Enables the feature with the given name. * Reflectively called by logback when reading xml configuration. @@ -88,6 +83,7 @@ public void addEnable(String feature) { public void enable(F feature) { enables.add(feature); } + /** * Disables the feature with the given name. * Reflectively called by logback when reading xml configuration. @@ -96,6 +92,7 @@ public void enable(F feature) { public void addDisable(String feature) { disable(Enum.valueOf(enumType, feature)); } + /** * Disables the given feature. * Use this method for programmatic configuration. diff --git a/src/main/java/net/logstash/logback/decorate/JsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/JsonGeneratorDecorator.java index b19c11a7..888a4601 100644 --- a/src/main/java/net/logstash/logback/decorate/JsonGeneratorDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/JsonGeneratorDecorator.java @@ -15,23 +15,12 @@ */ package net.logstash.logback.decorate; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Decorates the {@link JsonGenerator} used for serializing json. *

* Allows you to customize the {@link JsonGenerator}. */ -public interface JsonGeneratorDecorator { - - /** - * Decorates the given generator, and returns the decorated generator. - * - *

The returned decorator does not need to be the same object as the given generator.

- * - * @param generator the generator to decorate - * @return the decorated generator - */ - JsonGenerator decorate(JsonGenerator generator); - +public interface JsonGeneratorDecorator extends Decorator { } diff --git a/src/main/java/net/logstash/logback/decorate/JsonNodeFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/JsonNodeFeatureDecorator.java new file mode 100644 index 00000000..dc7a6121 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/JsonNodeFeatureDecorator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.JsonNodeFeature; +import tools.jackson.databind.cfg.MapperBuilder; + +/** + * A {@link MapperBuilderDecorator} that allows enabling/disabling of {@link JsonNodeFeature} features. + */ +public class JsonNodeFeatureDecorator> + extends FeatureDecorator + implements MapperBuilderDecorator { + + public JsonNodeFeatureDecorator() { + super(JsonNodeFeature.class); + } + + @Override + protected B configure(B builder, JsonNodeFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/MapperBuilderDecorator.java b/src/main/java/net/logstash/logback/decorate/MapperBuilderDecorator.java new file mode 100644 index 00000000..15f1a5ee --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/MapperBuilderDecorator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import net.logstash.logback.composite.AbstractCompositeJsonFormatter; + +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.MapperBuilder; + +/** + * Decorates the {@link MapperBuilder} used by a + * {@link AbstractCompositeJsonFormatter} to create an {@link ObjectMapper}. + *

+ * This allows you to customize the mapper used by the formatters. + *

+ * Implementations must be idempotent. + * The decorator configured on a formatter is called each time a formatter is started, + * and there is no way to 'un-decorate' the mapper when the formatter is stopped. + * So, the mapper could be decorated multiple times if the formatter is restarted. + */ +public interface MapperBuilderDecorator> extends Decorator { + +} diff --git a/src/main/java/net/logstash/logback/decorate/FeatureJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/MapperFeatureDecorator.java similarity index 50% rename from src/main/java/net/logstash/logback/decorate/FeatureJsonFactoryDecorator.java rename to src/main/java/net/logstash/logback/decorate/MapperFeatureDecorator.java index db85bbf6..693a5992 100644 --- a/src/main/java/net/logstash/logback/decorate/FeatureJsonFactoryDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/MapperFeatureDecorator.java @@ -15,14 +15,23 @@ */ package net.logstash.logback.decorate; -import com.fasterxml.jackson.core.JsonFactory; +import tools.jackson.databind.MapperFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.cfg.MapperBuilder; /** - * A {@link JsonFactoryDecorator} that allows enabling/disabling of {@link JsonFactory} features. + * A {@link MapperBuilderDecorator} that allows enabling/disabling of {@link MapperFeature} features. */ -public class FeatureJsonFactoryDecorator extends FeatureDecorator implements JsonFactoryDecorator { +public class MapperFeatureDecorator> + extends FeatureDecorator + implements MapperBuilderDecorator { - public FeatureJsonFactoryDecorator() { - super(JsonFactory.Feature.class, JsonFactory::enable, JsonFactory::disable); + public MapperFeatureDecorator() { + super(MapperFeature.class); + } + + @Override + protected B configure(B builder, MapperFeature feature, boolean state) { + return builder.configure(feature, state); } } diff --git a/src/main/java/net/logstash/logback/decorate/PrettyPrintingJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/PrettyPrintingDecorator.java similarity index 56% rename from src/main/java/net/logstash/logback/decorate/PrettyPrintingJsonGeneratorDecorator.java rename to src/main/java/net/logstash/logback/decorate/PrettyPrintingDecorator.java index 7b9a63ab..8fe431ff 100644 --- a/src/main/java/net/logstash/logback/decorate/PrettyPrintingJsonGeneratorDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/PrettyPrintingDecorator.java @@ -16,20 +16,28 @@ package net.logstash.logback.decorate; import ch.qos.logback.core.CoreConstants; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import tools.jackson.core.PrettyPrinter; +import tools.jackson.core.util.DefaultPrettyPrinter; +import tools.jackson.core.util.Separators; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.cfg.MapperBuilder; /** - * Enables pretty printing on the {@link JsonGenerator} + * Enables pretty printing on a {@link MapperBuilder}. */ -public class PrettyPrintingJsonGeneratorDecorator implements JsonGeneratorDecorator { +public class PrettyPrintingDecorator> implements MapperBuilderDecorator { - private DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter() + private Separators separators = PrettyPrinter.DEFAULT_SEPARATORS .withRootSeparator(CoreConstants.EMPTY_STRING); + private DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(separators); + @Override - public JsonGenerator decorate(JsonGenerator generator) { - return generator.setPrettyPrinter(prettyPrinter); + public B decorate(B mapperBuilder) { + return mapperBuilder + .enable(SerializationFeature.INDENT_OUTPUT) + .defaultPrettyPrinter(prettyPrinter); } /** @@ -41,25 +49,21 @@ public JsonGenerator decorate(JsonGenerator generator) { * {@code [SPACE]} in the xml configuration.

* * @param rootSeparator the new root separator - * @see DefaultPrettyPrinter#withRootSeparator(String) + * @see Separators#withRootSeparator(String) */ public void setRootSeparator(String rootSeparator) { - prettyPrinter = prettyPrinter.withRootSeparator( - rootSeparator == null ? null : rootSeparator.replace("[SPACE]", " ")); + separators = separators.withRootSeparator(rootSeparator == null ? null : rootSeparator.replace("[SPACE]", " ")); + prettyPrinter = prettyPrinter.withSeparators(separators); } /** * Sets whether spaces appear in object entries. * * @param spacesInObjectEntries whether spaces appear in object entries. - * @see DefaultPrettyPrinter#withSpacesInObjectEntries() - * @see DefaultPrettyPrinter#withoutSpacesInObjectEntries() + * @see Separators#withObjectEntrySpacing(Separators.Spacing) */ public void setSpacesInObjectEntries(boolean spacesInObjectEntries) { - if (spacesInObjectEntries) { - prettyPrinter = prettyPrinter.withSpacesInObjectEntries(); - } else { - prettyPrinter = prettyPrinter.withoutSpacesInObjectEntries(); - } + separators = separators.withObjectNameValueSpacing(spacesInObjectEntries ? Separators.Spacing.BOTH : Separators.Spacing.NONE); + prettyPrinter = prettyPrinter.withSeparators(separators); } } diff --git a/src/main/java/net/logstash/logback/decorate/SerializationFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/SerializationFeatureDecorator.java new file mode 100644 index 00000000..1c43ff68 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/SerializationFeatureDecorator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.cfg.MapperBuilder; + +/** + * A {@link MapperBuilderDecorator} that allows enabling/disabling of {@link SerializationFeature} features. + */ +public class SerializationFeatureDecorator> + extends FeatureDecorator + implements MapperBuilderDecorator { + + public SerializationFeatureDecorator() { + super(SerializationFeature.class); + } + + @Override + protected B configure(B builder, SerializationFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/StreamWriteFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/StreamWriteFeatureDecorator.java new file mode 100644 index 00000000..39b3815d --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/StreamWriteFeatureDecorator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import tools.jackson.core.StreamWriteFeature; +import tools.jackson.core.TSFBuilder; +import tools.jackson.core.TokenStreamFactory; + +/** + * A {@link TokenStreamFactoryBuilderDecorator} that allows enabling/disabling of {@link StreamWriteFeature} features. + */ +public class StreamWriteFeatureDecorator> + extends FeatureDecorator + implements TokenStreamFactoryBuilderDecorator { + + public StreamWriteFeatureDecorator() { + super(StreamWriteFeature.class); + } + + @Override + protected B configure(B builder, StreamWriteFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/JsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/TokenStreamFactoryBuilderDecorator.java similarity index 56% rename from src/main/java/net/logstash/logback/decorate/JsonFactoryDecorator.java rename to src/main/java/net/logstash/logback/decorate/TokenStreamFactoryBuilderDecorator.java index e9bdd4c1..b4ff7ac8 100644 --- a/src/main/java/net/logstash/logback/decorate/JsonFactoryDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/TokenStreamFactoryBuilderDecorator.java @@ -17,36 +17,20 @@ import net.logstash.logback.composite.AbstractCompositeJsonFormatter; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.MappingJsonFactory; +import tools.jackson.core.TSFBuilder; +import tools.jackson.core.TokenStreamFactory; /** - * Decorates the {@link JsonFactory} used by a + * Decorates the {@link TSFBuilder} used by a * {@link AbstractCompositeJsonFormatter}. *

* This allows you to customize the factory used by the formatters. *

* Implementations must be idempotent. * The decorator configured on a formatter is called each time a formatter is started, - * and there is no way to 'un-decorate' the factory when when formatter is stopped. + * and there is no way to 'un-decorate' the factory when the formatter is stopped. * So, the factory could be decorated multiple times if the formatter is restarted. */ -public interface JsonFactoryDecorator { - - /** - * Decorates the given {@link JsonFactory}. - * - *

By default, returns the given factory unchanged.

- * - *

Note that the default {@link JsonFactory} created by logstash-logback-encoder - * is a {@link MappingJsonFactory}, but can be changed by {@link JsonFactoryDecorator}s - * to any subclass of {@link JsonFactory}.

- * - * @param factory the factory to decorate - * @return the decorated {@link JsonFactory} - */ - default JsonFactory decorate(JsonFactory factory) { - return factory; - } - +public interface TokenStreamFactoryBuilderDecorator> + extends Decorator { } diff --git a/src/main/java/net/logstash/logback/decorate/TokenStreamFactoryFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/TokenStreamFactoryFeatureDecorator.java new file mode 100644 index 00000000..0140c816 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/TokenStreamFactoryFeatureDecorator.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import tools.jackson.core.TSFBuilder; +import tools.jackson.core.TokenStreamFactory; + +/** + * A {@link TokenStreamFactoryBuilderDecorator} that allows enabling/disabling of {@link TokenStreamFactory.Feature} features. + */ +public class TokenStreamFactoryFeatureDecorator> + extends FeatureDecorator + implements TokenStreamFactoryBuilderDecorator { + + public TokenStreamFactoryFeatureDecorator() { + super(TokenStreamFactory.Feature.class); + } + + @Override + protected B configure(B builder, TokenStreamFactory.Feature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/cbor/CborFeatureJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/cbor/CborFeatureJsonGeneratorDecorator.java deleted file mode 100644 index 6a836d37..00000000 --- a/src/main/java/net/logstash/logback/decorate/cbor/CborFeatureJsonGeneratorDecorator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate.cbor; - -import net.logstash.logback.decorate.FeatureDecorator; -import net.logstash.logback.decorate.JsonGeneratorDecorator; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; - -/** - * A {@link JsonGeneratorDecorator} that allows enabling/disabling of {@link CBORGenerator} features. - * - *

Only valid for {@link CBORGenerator}s. - * Use in conjunction with {@link CborJsonFactoryDecorator}.

- */ -public class CborFeatureJsonGeneratorDecorator extends FeatureDecorator implements JsonGeneratorDecorator { - - public CborFeatureJsonGeneratorDecorator() { - super(CBORGenerator.Feature.class, CBORGenerator::enable, CBORGenerator::disable); - } - - @Override - public JsonGenerator decorate(JsonGenerator generator) { - if (!(generator instanceof CBORGenerator)) { - throw new ClassCastException("Expected generator to be of type " + CBORGenerator.class.getName() + ". See " + CborJsonFactoryDecorator.class.getName()); - } - return super.decorate((CBORGenerator) generator); - } -} diff --git a/src/main/java/net/logstash/logback/decorate/cbor/CborJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/cbor/CborJsonFactoryDecorator.java deleted file mode 100644 index ad3fcdce..00000000 --- a/src/main/java/net/logstash/logback/decorate/cbor/CborJsonFactoryDecorator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate.cbor; - -import net.logstash.logback.decorate.JsonFactoryDecorator; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.cbor.CBORFactory; -import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; - -/** - * A {@link JsonFactoryDecorator} that will switch the output - * to binary CBOR output instead of JSON text. - * - *

See also {@link CborFeatureJsonGeneratorDecorator} for configuring {@link CBORGenerator} features.

- */ -public class CborJsonFactoryDecorator implements JsonFactoryDecorator { - - @Override - public JsonFactory decorate(JsonFactory factory) { - CBORFactory cborFactory = new CBORFactory(); - ObjectMapper mapper = new ObjectMapper(cborFactory); - cborFactory.setCodec(mapper); - return cborFactory; - } -} diff --git a/src/main/java/net/logstash/logback/decorate/cbor/CborWriteFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/cbor/CborWriteFeatureDecorator.java new file mode 100644 index 00000000..1184d0b1 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/cbor/CborWriteFeatureDecorator.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate.cbor; + +import net.logstash.logback.decorate.FeatureDecorator; +import net.logstash.logback.decorate.TokenStreamFactoryBuilderDecorator; + +import tools.jackson.dataformat.cbor.CBORFactory; +import tools.jackson.dataformat.cbor.CBORFactoryBuilder; +import tools.jackson.dataformat.cbor.CBORWriteFeature; + +/** + * A {@link TokenStreamFactoryBuilderDecorator} that allows enabling/disabling of {@link CBORWriteFeature} features. + */ +public class CborWriteFeatureDecorator + extends FeatureDecorator + implements TokenStreamFactoryBuilderDecorator { + + public CborWriteFeatureDecorator() { + super(CBORWriteFeature.class); + } + + @Override + protected CBORFactoryBuilder configure(CBORFactoryBuilder builder, CBORWriteFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/CharacterEscapesJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/json/CharacterEscapesDecorator.java similarity index 89% rename from src/main/java/net/logstash/logback/decorate/CharacterEscapesJsonFactoryDecorator.java rename to src/main/java/net/logstash/logback/decorate/json/CharacterEscapesDecorator.java index ccbdbda1..07e6b5d3 100644 --- a/src/main/java/net/logstash/logback/decorate/CharacterEscapesJsonFactoryDecorator.java +++ b/src/main/java/net/logstash/logback/decorate/json/CharacterEscapesDecorator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.logstash.logback.decorate; +package net.logstash.logback.decorate.json; import java.util.ArrayList; import java.util.Arrays; @@ -21,22 +21,24 @@ import java.util.List; import java.util.Objects; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.SerializableString; -import com.fasterxml.jackson.core.io.CharacterEscapes; -import com.fasterxml.jackson.core.io.SerializedString; +import net.logstash.logback.decorate.TokenStreamFactoryBuilderDecorator; + +import tools.jackson.core.SerializableString; +import tools.jackson.core.io.CharacterEscapes; +import tools.jackson.core.io.SerializedString; +import tools.jackson.core.json.JsonFactory; +import tools.jackson.core.json.JsonFactoryBuilder; /** - * A {@link JsonFactoryDecorator} that can be used to customize the {@link JsonFactory#setCharacterEscapes(CharacterEscapes)}. + * A {@link TokenStreamFactoryBuilderDecorator} that can be used to customize the {@link JsonFactoryBuilder#characterEscapes(CharacterEscapes)}. * * For example, you could change the escape sequence used for newline characters from '\n' to '\u2028' */ -public class CharacterEscapesJsonFactoryDecorator implements JsonFactoryDecorator { +public class CharacterEscapesDecorator implements TokenStreamFactoryBuilderDecorator { /** - * A {@link CharacterEscapes} implementation that has been created from the registered {@link CharacterEscapesJsonFactoryDecorator#escapes} + * A {@link CharacterEscapes} implementation that has been created from the registered {@link CharacterEscapesDecorator#escapes} */ - @SuppressWarnings("serial") private static class CustomizedCharacterEscapes extends CharacterEscapes { /** @@ -149,7 +151,7 @@ public void setTarget(String target) { if (target == null || target.length() != 1) { throw new IllegalArgumentException("target's length must be 1"); } - setTargetCharacterCode((int) target.charAt(0)); + setTargetCharacterCode(target.charAt(0)); } /** @@ -158,7 +160,7 @@ public void setTarget(String target) { * @param targetCharacter the target character */ public void setTargetCharacter(char targetCharacter) { - setTargetCharacterCode((char) targetCharacter); + setTargetCharacterCode(targetCharacter); } public int getTargetCharacterCode() { @@ -236,22 +238,22 @@ public int hashCode() { private final List escapes = new ArrayList<>(); /** - * Indicates when the {@link CharacterEscapesJsonFactoryDecorator#characterEscapes} field needs to be re-initialized. + * Indicates when the {@link CharacterEscapesDecorator#characterEscapes} field needs to be re-initialized. */ private boolean needsInitialization = true; /** - * A {@link CharacterEscapes} implementation that has been created from the registered {@link CharacterEscapesJsonFactoryDecorator#escapes} + * A {@link CharacterEscapes} implementation that has been created from the registered {@link CharacterEscapesDecorator#escapes} */ private CustomizedCharacterEscapes characterEscapes; @Override - public JsonFactory decorate(JsonFactory factory) { + public JsonFactoryBuilder decorate(JsonFactoryBuilder builder) { if (needsInitialization) { characterEscapes = new CustomizedCharacterEscapes(includeStandardAsciiEscapesForJSON, escapes); needsInitialization = false; } - return factory.setCharacterEscapes(characterEscapes); + return builder.characterEscapes(characterEscapes); } public boolean isIncludeStandardAsciiEscapesForJSON() { diff --git a/src/main/java/net/logstash/logback/decorate/json/JsonWriteFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/json/JsonWriteFeatureDecorator.java new file mode 100644 index 00000000..bf4cabc0 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/json/JsonWriteFeatureDecorator.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate.json; + +import net.logstash.logback.decorate.FeatureDecorator; +import net.logstash.logback.decorate.TokenStreamFactoryBuilderDecorator; + +import tools.jackson.core.json.JsonFactory; +import tools.jackson.core.json.JsonFactoryBuilder; +import tools.jackson.core.json.JsonWriteFeature; + +/** + * A {@link TokenStreamFactoryBuilderDecorator} that allows enabling/disabling of {@link JsonWriteFeature} features. + */ +public class JsonWriteFeatureDecorator + extends FeatureDecorator + implements TokenStreamFactoryBuilderDecorator { + + public JsonWriteFeatureDecorator() { + super(JsonWriteFeature.class); + } + + @Override + protected JsonFactoryBuilder configure(JsonFactoryBuilder builder, JsonWriteFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/smile/SmileFeatureJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/smile/SmileFeatureJsonGeneratorDecorator.java deleted file mode 100644 index 9e2f7942..00000000 --- a/src/main/java/net/logstash/logback/decorate/smile/SmileFeatureJsonGeneratorDecorator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate.smile; - -import net.logstash.logback.decorate.FeatureDecorator; -import net.logstash.logback.decorate.JsonGeneratorDecorator; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.dataformat.smile.SmileGenerator; - -/** - * A {@link JsonGeneratorDecorator} that allows enabling/disabling of {@link SmileGenerator} features. - * - *

Only valid for {@link SmileGenerator}s. - * Use in conjunction with {@link SmileJsonFactoryDecorator}.

- */ -public class SmileFeatureJsonGeneratorDecorator extends FeatureDecorator implements JsonGeneratorDecorator { - - public SmileFeatureJsonGeneratorDecorator() { - super(SmileGenerator.Feature.class, SmileGenerator::enable, SmileGenerator::disable); - } - - @Override - public JsonGenerator decorate(JsonGenerator generator) { - if (!(generator instanceof SmileGenerator)) { - throw new ClassCastException("Expected generator to be of type " + SmileGenerator.class.getName() + ". See " + SmileJsonFactoryDecorator.class.getName()); - } - return super.decorate((SmileGenerator) generator); - } -} diff --git a/src/main/java/net/logstash/logback/decorate/smile/SmileJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/smile/SmileJsonFactoryDecorator.java deleted file mode 100644 index bd1150b8..00000000 --- a/src/main/java/net/logstash/logback/decorate/smile/SmileJsonFactoryDecorator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate.smile; - -import net.logstash.logback.decorate.JsonFactoryDecorator; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.smile.SmileFactory; -import com.fasterxml.jackson.dataformat.smile.SmileGenerator; - -/** - * A {@link JsonFactoryDecorator} that will switch the output - * to binary smile output instead of JSON text. - * - *

See also {@link SmileFeatureJsonGeneratorDecorator} for configuring {@link SmileGenerator} features.

- */ -public class SmileJsonFactoryDecorator implements JsonFactoryDecorator { - - @Override - public JsonFactory decorate(JsonFactory factory) { - SmileFactory smileFactory = new SmileFactory(); - ObjectMapper mapper = new ObjectMapper(smileFactory); - smileFactory.setCodec(mapper); - return smileFactory; - } -} diff --git a/src/main/java/net/logstash/logback/decorate/smile/SmileWriteFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/smile/SmileWriteFeatureDecorator.java new file mode 100644 index 00000000..e8931a98 --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/smile/SmileWriteFeatureDecorator.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate.smile; + +import net.logstash.logback.decorate.FeatureDecorator; +import net.logstash.logback.decorate.TokenStreamFactoryBuilderDecorator; + +import tools.jackson.dataformat.smile.SmileFactory; +import tools.jackson.dataformat.smile.SmileFactoryBuilder; +import tools.jackson.dataformat.smile.SmileWriteFeature; + +/** + * A {@link TokenStreamFactoryBuilderDecorator} that allows enabling/disabling of {@link SmileWriteFeature} features. + */ +public class SmileWriteFeatureDecorator + extends FeatureDecorator + implements TokenStreamFactoryBuilderDecorator { + + public SmileWriteFeatureDecorator() { + super(SmileWriteFeature.class); + } + + @Override + protected SmileFactoryBuilder configure(SmileFactoryBuilder builder, SmileWriteFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/decorate/yaml/YamlFeatureJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/decorate/yaml/YamlFeatureJsonGeneratorDecorator.java deleted file mode 100644 index 3a982d90..00000000 --- a/src/main/java/net/logstash/logback/decorate/yaml/YamlFeatureJsonGeneratorDecorator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate.yaml; - -import net.logstash.logback.decorate.FeatureDecorator; -import net.logstash.logback.decorate.JsonGeneratorDecorator; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; - -/** - * A {@link JsonGeneratorDecorator} that allows enabling/disabling of {@link YAMLGenerator} features. - * - *

Only valid for {@link YAMLGenerator}s. - * Use in conjunction with {@link YamlJsonFactoryDecorator}.

- */ -public class YamlFeatureJsonGeneratorDecorator extends FeatureDecorator implements JsonGeneratorDecorator { - - public YamlFeatureJsonGeneratorDecorator() { - super(YAMLGenerator.Feature.class, YAMLGenerator::enable, YAMLGenerator::disable); - } - - @Override - public JsonGenerator decorate(JsonGenerator generator) { - if (!(generator instanceof YAMLGenerator)) { - throw new ClassCastException("Expected generator to be of type " + YAMLGenerator.class.getName() + ". See " + YamlJsonFactoryDecorator.class.getName()); - } - return super.decorate((YAMLGenerator) generator); - } -} diff --git a/src/main/java/net/logstash/logback/decorate/yaml/YamlJsonFactoryDecorator.java b/src/main/java/net/logstash/logback/decorate/yaml/YamlJsonFactoryDecorator.java deleted file mode 100644 index c89ff979..00000000 --- a/src/main/java/net/logstash/logback/decorate/yaml/YamlJsonFactoryDecorator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate.yaml; - -import net.logstash.logback.decorate.JsonFactoryDecorator; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; - -/** - * A {@link JsonFactoryDecorator} that will switch the output - * to YAML output instead of JSON text. - * - *

See also {@link YamlFeatureJsonGeneratorDecorator} for configuring {@link YAMLGenerator} features.

- */ -public class YamlJsonFactoryDecorator implements JsonFactoryDecorator { - - @Override - public JsonFactory decorate(JsonFactory factory) { - YAMLFactory yamlFactory = new YAMLFactory(); - ObjectMapper mapper = new ObjectMapper(yamlFactory); - yamlFactory.setCodec(mapper); - /* - * YAMLGenerator needs to pass the flush to the stream. - * It doesn't maintain an internal buffer like the other generators. - * To see this, look at the .flush() implementations of each of the generator classes. - */ - yamlFactory.enable(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM); - return yamlFactory; - } -} diff --git a/src/main/java/net/logstash/logback/decorate/yaml/YamlWriteFeatureDecorator.java b/src/main/java/net/logstash/logback/decorate/yaml/YamlWriteFeatureDecorator.java new file mode 100644 index 00000000..111fd6db --- /dev/null +++ b/src/main/java/net/logstash/logback/decorate/yaml/YamlWriteFeatureDecorator.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate.yaml; + +import net.logstash.logback.decorate.FeatureDecorator; +import net.logstash.logback.decorate.JsonGeneratorDecorator; +import net.logstash.logback.decorate.TokenStreamFactoryBuilderDecorator; + +import tools.jackson.dataformat.yaml.YAMLFactory; +import tools.jackson.dataformat.yaml.YAMLFactoryBuilder; +import tools.jackson.dataformat.yaml.YAMLWriteFeature; + +/** + * A {@link JsonGeneratorDecorator} that allows enabling/disabling of {@link YAMLWriteFeature} features. + */ +public class YamlWriteFeatureDecorator + extends FeatureDecorator + implements TokenStreamFactoryBuilderDecorator { + + public YamlWriteFeatureDecorator() { + super(YAMLWriteFeature.class); + } + + @Override + protected YAMLFactoryBuilder configure(YAMLFactoryBuilder builder, YAMLWriteFeature feature, boolean state) { + return builder.configure(feature, state); + } +} diff --git a/src/main/java/net/logstash/logback/encoder/CompositeJsonEncoder.java b/src/main/java/net/logstash/logback/encoder/CompositeJsonEncoder.java index ab5244ca..e555e2f0 100644 --- a/src/main/java/net/logstash/logback/encoder/CompositeJsonEncoder.java +++ b/src/main/java/net/logstash/logback/encoder/CompositeJsonEncoder.java @@ -22,8 +22,11 @@ import net.logstash.logback.composite.AbstractCompositeJsonFormatter; import net.logstash.logback.composite.JsonProviders; -import net.logstash.logback.decorate.JsonFactoryDecorator; -import net.logstash.logback.decorate.JsonGeneratorDecorator; +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.decorate.CompositeJsonGeneratorDecorator; +import net.logstash.logback.decorate.CompositeMapperBuilderDecorator; +import net.logstash.logback.decorate.CompositeTokenStreamFactoryBuilderDecorator; +import net.logstash.logback.decorate.Decorator; import net.logstash.logback.util.ReusableByteBuffer; import net.logstash.logback.util.ThreadLocalReusableByteBuffer; @@ -139,22 +142,20 @@ public void start() { @SuppressWarnings({ "unchecked", "rawtypes" }) private void startWrapped(Encoder wrapped) { - if (wrapped instanceof LayoutWrappingEncoder) { + if (wrapped instanceof LayoutWrappingEncoder layoutWrappedEncoder) { /* * Convenience hack to ensure the same charset is used in most cases. * * The charset for other encoders must be configured * on the wrapped encoder configuration. */ - LayoutWrappingEncoder layoutWrappedEncoder = (LayoutWrappingEncoder) wrapped; layoutWrappedEncoder.setCharset(charset); - if (layoutWrappedEncoder.getLayout() instanceof PatternLayoutBase) { + if (layoutWrappedEncoder.getLayout() instanceof PatternLayoutBase layout) { /* * Don't ensure exception output (for ILoggingEvents) * or line separation (for IAccessEvents) */ - PatternLayoutBase layout = (PatternLayoutBase) layoutWrappedEncoder.getLayout(); layout.setPostCompileProcessor(null); /* * The pattern will be re-parsed during start. @@ -206,15 +207,35 @@ public void setProviders(JsonProviders jsonProviders) { formatter.setProviders(jsonProviders); } - public JsonFactoryDecorator getJsonFactoryDecorator() { - return formatter.getJsonFactoryDecorator(); + public String getDataFormat() { + return formatter.getDataFormat(); } - public void setJsonFactoryDecorator(JsonFactoryDecorator jsonFactoryDecorator) { - formatter.setJsonFactoryDecorator(jsonFactoryDecorator); + public void setDataFormat(String dataFormat) { + formatter.setDataFormat(dataFormat); } - public JsonGeneratorDecorator getJsonGeneratorDecorator() { + public DataFormatFactory getDataFormatFactory() { + return formatter.getDataFormatFactory(); + } + + public void setDataFormatFactory(DataFormatFactory dataFormatFactory) { + formatter.setDataFormatFactory(dataFormatFactory); + } + + public void addDecorator(Decorator decorator) { + formatter.addDecorator(decorator); + } + + public CompositeTokenStreamFactoryBuilderDecorator getTokenStreamFactoryBuilderDecorator() { + return formatter.getTokenStreamFactoryBuilderDecorator(); + } + + public CompositeMapperBuilderDecorator getMapperBuilderDecorator() { + return formatter.getMapperBuilderDecorator(); + } + + public CompositeJsonGeneratorDecorator getJsonGeneratorDecorator() { return formatter.getJsonGeneratorDecorator(); } @@ -224,7 +245,7 @@ public String getEncoding() { /** * The character encoding to use (default = "{@code UTF-8}"). - * Must an encoding supported by {@link com.fasterxml.jackson.core.JsonEncoding} + * Must an encoding supported by {@link tools.jackson.core.JsonEncoding} * * @param encodingName encoding name */ @@ -236,10 +257,6 @@ public void setFindAndRegisterJacksonModules(boolean findAndRegisterJacksonModul formatter.setFindAndRegisterJacksonModules(findAndRegisterJacksonModules); } - public void setJsonGeneratorDecorator(JsonGeneratorDecorator jsonGeneratorDecorator) { - formatter.setJsonGeneratorDecorator(jsonGeneratorDecorator); - } - public String getLineSeparator() { return lineSeparator; } diff --git a/src/main/java/net/logstash/logback/layout/CompositeJsonLayout.java b/src/main/java/net/logstash/logback/layout/CompositeJsonLayout.java index efd99b8d..92453e05 100644 --- a/src/main/java/net/logstash/logback/layout/CompositeJsonLayout.java +++ b/src/main/java/net/logstash/logback/layout/CompositeJsonLayout.java @@ -23,8 +23,11 @@ import net.logstash.logback.composite.AbstractCompositeJsonFormatter; import net.logstash.logback.composite.JsonProviders; -import net.logstash.logback.decorate.JsonFactoryDecorator; -import net.logstash.logback.decorate.JsonGeneratorDecorator; +import net.logstash.logback.dataformat.DataFormatFactory; +import net.logstash.logback.decorate.CompositeJsonGeneratorDecorator; +import net.logstash.logback.decorate.CompositeMapperBuilderDecorator; +import net.logstash.logback.decorate.CompositeTokenStreamFactoryBuilderDecorator; +import net.logstash.logback.decorate.Decorator; import net.logstash.logback.encoder.CompositeJsonEncoder; import net.logstash.logback.encoder.SeparatorParser; import net.logstash.logback.util.ReusableByteBuffer; @@ -47,7 +50,7 @@ public abstract class CompositeJsonLayout * Separator to use between events. * *

By default, this is null (for backwards compatibility), indicating no separator. - * Note that this default is different than the default of {@link CompositeJsonEncoder#lineSeparator}. + * Note that this default is different from the default of {@link CompositeJsonEncoder#lineSeparator}. * In a future major release, the default will likely change to be the same as {@link CompositeJsonEncoder#lineSeparator}.

*/ private String lineSeparator; @@ -140,12 +143,11 @@ public void start() { } private void startWrapped(Layout wrapped) { - if (wrapped instanceof PatternLayoutBase) { + if (wrapped instanceof PatternLayoutBase layout) { /* * Don't ensure exception output (for ILoggingEvents) * or line separation (for IAccessEvents) */ - PatternLayoutBase layout = (PatternLayoutBase) wrapped; layout.setPostCompileProcessor(null); /* * The pattern will be re-parsed during start. @@ -195,20 +197,36 @@ public void setImmediateFlush(boolean immediateFlush) { this.immediateFlush = immediateFlush; } - public JsonFactoryDecorator getJsonFactoryDecorator() { - return formatter.getJsonFactoryDecorator(); + public String getDataFormat() { + return formatter.getDataFormat(); } - public void setJsonFactoryDecorator(JsonFactoryDecorator jsonFactoryDecorator) { - formatter.setJsonFactoryDecorator(jsonFactoryDecorator); + public void setDataFormat(String dataFormat) { + formatter.setDataFormat(dataFormat); } - public JsonGeneratorDecorator getJsonGeneratorDecorator() { - return formatter.getJsonGeneratorDecorator(); + public DataFormatFactory getDataFormatFactory() { + return formatter.getDataFormatFactory(); + } + + public void setDataFormatFactory(DataFormatFactory dataFormatFactory) { + formatter.setDataFormatFactory(dataFormatFactory); + } + + public void addDecorator(Decorator decorator) { + formatter.addDecorator(decorator); } - public void setJsonGeneratorDecorator(JsonGeneratorDecorator jsonGeneratorDecorator) { - formatter.setJsonGeneratorDecorator(jsonGeneratorDecorator); + public CompositeTokenStreamFactoryBuilderDecorator getTokenStreamFactoryBuilderDecorator() { + return formatter.getTokenStreamFactoryBuilderDecorator(); + } + + public CompositeMapperBuilderDecorator getMapperBuilderDecorator() { + return formatter.getMapperBuilderDecorator(); + } + + public CompositeJsonGeneratorDecorator getJsonGeneratorDecorator() { + return formatter.getJsonGeneratorDecorator(); } public void setFindAndRegisterJacksonModules(boolean findAndRegisterJacksonModules) { diff --git a/src/main/java/net/logstash/logback/marker/DeferredLogstashMarker.java b/src/main/java/net/logstash/logback/marker/DeferredLogstashMarker.java index 40f5a0bc..0594c3f8 100644 --- a/src/main/java/net/logstash/logback/marker/DeferredLogstashMarker.java +++ b/src/main/java/net/logstash/logback/marker/DeferredLogstashMarker.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.marker; -import java.io.IOException; import java.util.Iterator; import java.util.Objects; import java.util.function.Supplier; @@ -23,8 +22,8 @@ import net.logstash.logback.appender.AsyncDisruptorAppender; import ch.qos.logback.classic.AsyncAppender; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * A {@link LogstashMarker} that defers the creation of another {@link LogstashMarker} until @@ -39,7 +38,6 @@ * the supplier will be invoked when the first appender encodes the marker. * That same supplied value will be used when the next appender encodes the marker.

*/ -@SuppressWarnings("serial") public class DeferredLogstashMarker extends LogstashMarker { public static final String DEFERRED_MARKER_NAME = "DEFERRED"; @@ -61,7 +59,7 @@ public DeferredLogstashMarker(Supplier logstashMarkerS } @Override - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { writeMarker(generator, getSuppliedValue()); } @@ -86,7 +84,7 @@ private LogstashMarker getSuppliedValue() { return suppliedValue; } - private void writeMarker(JsonGenerator generator, Marker marker) throws IOException { + private void writeMarker(JsonGenerator generator, Marker marker) { if (marker == null) { return; } diff --git a/src/main/java/net/logstash/logback/marker/EmptyLogstashMarker.java b/src/main/java/net/logstash/logback/marker/EmptyLogstashMarker.java index 025aba02..ce0e9c91 100644 --- a/src/main/java/net/logstash/logback/marker/EmptyLogstashMarker.java +++ b/src/main/java/net/logstash/logback/marker/EmptyLogstashMarker.java @@ -15,12 +15,10 @@ */ package net.logstash.logback.marker; -import java.io.IOException; - import net.logstash.logback.argument.StructuredArgument; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * An empty marker that does nothing itself, but can be used as a base marker when you want to conditionally chain other markers with {@link #and(Marker)}. @@ -36,7 +34,6 @@ * } * */ -@SuppressWarnings("serial") public class EmptyLogstashMarker extends LogstashMarker implements StructuredArgument { public static final String EMPTY_MARKER_NAME = "EMPTY"; @@ -46,7 +43,7 @@ public EmptyLogstashMarker() { } @Override - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { // no-op } diff --git a/src/main/java/net/logstash/logback/marker/LogstashMarker.java b/src/main/java/net/logstash/logback/marker/LogstashMarker.java index 8d2efb6e..fbb12c02 100755 --- a/src/main/java/net/logstash/logback/marker/LogstashMarker.java +++ b/src/main/java/net/logstash/logback/marker/LogstashMarker.java @@ -15,17 +15,14 @@ */ package net.logstash.logback.marker; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * A {@link Marker} that is known and understood by the logstash logback encoder. *

* In particular these markers are used to write data into the logstash json event via {@link #writeTo(JsonGenerator)}. */ -@SuppressWarnings("serial") public abstract class LogstashMarker extends LogstashBasicMarker implements Iterable { public static final String MARKER_NAME_PREFIX = "LS_"; @@ -73,9 +70,8 @@ public T with(Marker reference) { * Writes the data associated with this marker to the given {@link JsonGenerator}. * * @param generator the generator to which to write the output of this marker. - * @throws IOException if there was an error writing to the generator */ - public abstract void writeTo(JsonGenerator generator) throws IOException; + public abstract void writeTo(JsonGenerator generator); @Override public void add(Marker reference) { diff --git a/src/main/java/net/logstash/logback/marker/MapEntriesAppendingMarker.java b/src/main/java/net/logstash/logback/marker/MapEntriesAppendingMarker.java index 62ab4fdb..ea12f3d9 100755 --- a/src/main/java/net/logstash/logback/marker/MapEntriesAppendingMarker.java +++ b/src/main/java/net/logstash/logback/marker/MapEntriesAppendingMarker.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.marker; -import java.io.IOException; import java.util.Map; import java.util.Objects; @@ -23,9 +22,9 @@ import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider; import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; /** * A {@link Marker} OR {@link StructuredArgument} that appends entries @@ -67,7 +66,6 @@ * } * */ -@SuppressWarnings("serial") public class MapEntriesAppendingMarker extends LogstashMarker implements StructuredArgument { public static final String MARKER_NAME = LogstashMarker.MARKER_NAME_PREFIX + "MAP_FIELDS"; @@ -83,11 +81,10 @@ public MapEntriesAppendingMarker(Map map) { } @Override - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { if (map != null) { for (Map.Entry entry : map.entrySet()) { - generator.writeFieldName(String.valueOf(entry.getKey())); - generator.writeObject(entry.getValue()); + generator.writePOJOProperty(String.valueOf(entry.getKey()), entry.getValue()); } } } @@ -105,11 +102,10 @@ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } - if (!(obj instanceof MapEntriesAppendingMarker)) { + if (!(obj instanceof MapEntriesAppendingMarker other)) { return false; } - MapEntriesAppendingMarker other = (MapEntriesAppendingMarker) obj; return Objects.equals(this.map, other.map); } diff --git a/src/main/java/net/logstash/logback/marker/ObjectAppendingMarker.java b/src/main/java/net/logstash/logback/marker/ObjectAppendingMarker.java index ac83509f..9d412f7d 100755 --- a/src/main/java/net/logstash/logback/marker/ObjectAppendingMarker.java +++ b/src/main/java/net/logstash/logback/marker/ObjectAppendingMarker.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.marker; -import java.io.IOException; import java.util.Objects; import net.logstash.logback.argument.StructuredArgument; @@ -23,9 +22,9 @@ import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider; import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; /** * A {@link Marker} OR {@link StructuredArgument} that @@ -67,7 +66,6 @@ * } * */ -@SuppressWarnings("serial") public class ObjectAppendingMarker extends SingleFieldAppendingMarker { public static final String MARKER_NAME = SingleFieldAppendingMarker.MARKER_NAME_PREFIX + "OBJECT"; @@ -89,8 +87,8 @@ public ObjectAppendingMarker(String fieldName, Object fieldValue, String message } @Override - protected void writeFieldValue(JsonGenerator generator) throws IOException { - generator.writeObject(fieldValue); + protected void writeFieldValue(JsonGenerator generator) { + generator.writePOJO(fieldValue); } @Override @@ -106,11 +104,10 @@ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } - if (!(obj instanceof ObjectAppendingMarker)) { + if (!(obj instanceof ObjectAppendingMarker other)) { return false; } - ObjectAppendingMarker other = (ObjectAppendingMarker) obj; return Objects.equals(this.fieldValue, other.fieldValue); } diff --git a/src/main/java/net/logstash/logback/marker/ObjectFieldsAppendingMarker.java b/src/main/java/net/logstash/logback/marker/ObjectFieldsAppendingMarker.java index 6db27fa2..8a25a367 100755 --- a/src/main/java/net/logstash/logback/marker/ObjectFieldsAppendingMarker.java +++ b/src/main/java/net/logstash/logback/marker/ObjectFieldsAppendingMarker.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.marker; -import java.io.IOException; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -25,13 +24,11 @@ import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider; import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.util.NameTransformer; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.SerializationContext; +import tools.jackson.databind.ValueSerializer; +import tools.jackson.databind.util.NameTransformer; /** * A {@link Marker} OR {@link StructuredArgument} that @@ -76,7 +73,6 @@ * * Note that if the object cannot be unwrapped, then nothing will be written. */ -@SuppressWarnings("serial") public class ObjectFieldsAppendingMarker extends LogstashMarker implements StructuredArgument { public static final String MARKER_NAME = LogstashMarker.MARKER_NAME_PREFIX + "OBJECT_FIELDS"; @@ -89,7 +85,7 @@ public class ObjectFieldsAppendingMarker extends LogstashMarker implements Struc * * Since apps will typically serialize the same types of objects repeatedly, they shouldn't grow too much. */ - private static final Map serializerHelper = new ConcurrentHashMap<>(); + private static final Map, ValueSerializer> unwrappingSerializerCache = new ConcurrentHashMap<>(); public ObjectFieldsAppendingMarker(Object object) { super(MARKER_NAME); @@ -97,10 +93,21 @@ public ObjectFieldsAppendingMarker(Object object) { } @Override - public void writeTo(JsonGenerator generator) throws IOException { - if (this.object != null) { - SerializerHelper helper = getSerializerHelper(generator); - helper.serialize(generator, this.object); + public void writeTo(JsonGenerator generator) { + if (this.object != null && generator.objectWriteContext() instanceof SerializationContext serializationContext) { + + ValueSerializer valueSerializer = serializationContext.findValueSerializer(this.object.getClass()); + + ValueSerializer unwrappingSerializer = unwrappingSerializerCache.computeIfAbsent(valueSerializer, + vs -> vs.unwrappingSerializer(NameTransformer.NOP)); + + /* + * Make sure the serializer accepts to serialize in an "unwrapped" fashion. + * This may not be the case for serializer for Number types for instance. + */ + if (unwrappingSerializer.isUnwrappingSerializer()) { + unwrappingSerializer.serialize(this.object, generator, serializationContext); + } } } @@ -119,11 +126,10 @@ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } - if (!(obj instanceof ObjectFieldsAppendingMarker)) { + if (!(obj instanceof ObjectFieldsAppendingMarker other)) { return false; } - ObjectFieldsAppendingMarker other = (ObjectFieldsAppendingMarker) obj; return Objects.equals(this.object, other.object); } @@ -138,59 +144,4 @@ public int hashCode() { } - /** - * Get a {@link SerializerHelper} suitable for use with the given {@link JsonGenerator}. - * - * @param gen the {@link JsonGenerator} for which an helper should be returned - * @return a {@link SerializerHelper} - */ - private static SerializerHelper getSerializerHelper(JsonGenerator gen) { - ObjectMapper mapper = (ObjectMapper) gen.getCodec(); - return serializerHelper.computeIfAbsent(mapper, SerializerHelper::new); - } - - private static class SerializerHelper { - private final SerializerProvider serializers; - private final ConcurrentHashMap, JsonSerializer> cache = new ConcurrentHashMap<>(); - - SerializerHelper(ObjectMapper mapper) { - this.serializers = mapper.getSerializerProviderInstance(); - } - - /** - * Serialize the given value using the supplied generator - * - * @param gen the {@link JsonGenerator} to use to serialize the value - * @param value the value to serialize - * @throws IOException thrown when the underlying {@link JsonGenerator} could not be created - * or when it has problems to serialize the given value - */ - public void serialize(JsonGenerator gen, Object value) throws IOException { - if (value != null) { - JsonSerializer unwrappingSerializer = getUnwrappingSerializer(value.getClass()); - - /* - * Make sure the serializer accepts to serialize in an "unwrapped" fashion. - * This may not be the case for serializer for Number types for instance. - */ - if (unwrappingSerializer.isUnwrappingSerializer()) { - unwrappingSerializer.serialize(value, gen, serializers); - } - } - } - - private JsonSerializer getUnwrappingSerializer(Class type) throws JsonMappingException { - JsonSerializer serializer = cache.get(type); - if (serializer == null) { - serializer = createUnwrappingSerializer(type); - cache.put(type, serializer); - } - return serializer; - } - - private JsonSerializer createUnwrappingSerializer(Class type) throws JsonMappingException { - JsonSerializer serializer = serializers.findValueSerializer(type); - return serializer.unwrappingSerializer(NameTransformer.NOP); - } - } } diff --git a/src/main/java/net/logstash/logback/marker/RawJsonAppendingMarker.java b/src/main/java/net/logstash/logback/marker/RawJsonAppendingMarker.java index a9334226..4aa929b1 100755 --- a/src/main/java/net/logstash/logback/marker/RawJsonAppendingMarker.java +++ b/src/main/java/net/logstash/logback/marker/RawJsonAppendingMarker.java @@ -15,15 +15,14 @@ */ package net.logstash.logback.marker; -import java.io.IOException; import java.util.Objects; import net.logstash.logback.argument.StructuredArgument; import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider; import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * A {@link Marker} OR {@link StructuredArgument} that @@ -40,7 +39,6 @@ * the raw string is written as the field value. * Note that using {@link RawJsonAppendingMarker} as a {@link StructuredArgument} is not very common. */ -@SuppressWarnings("serial") public class RawJsonAppendingMarker extends SingleFieldAppendingMarker { public static final String MARKER_NAME = SingleFieldAppendingMarker.MARKER_NAME_PREFIX + "RAW"; @@ -61,7 +59,7 @@ public RawJsonAppendingMarker(String fieldName, String rawJson, String messageFo } @Override - protected void writeFieldValue(JsonGenerator generator) throws IOException { + protected void writeFieldValue(JsonGenerator generator) { generator.writeRawValue(rawJson); } @@ -78,11 +76,10 @@ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } - if (!(obj instanceof RawJsonAppendingMarker)) { + if (!(obj instanceof RawJsonAppendingMarker other)) { return false; } - RawJsonAppendingMarker other = (RawJsonAppendingMarker) obj; return Objects.equals(this.rawJson, other.rawJson); } diff --git a/src/main/java/net/logstash/logback/marker/SingleFieldAppendingMarker.java b/src/main/java/net/logstash/logback/marker/SingleFieldAppendingMarker.java index 099b3d89..8507a029 100755 --- a/src/main/java/net/logstash/logback/marker/SingleFieldAppendingMarker.java +++ b/src/main/java/net/logstash/logback/marker/SingleFieldAppendingMarker.java @@ -15,7 +15,6 @@ */ package net.logstash.logback.marker; -import java.io.IOException; import java.util.Objects; import net.logstash.logback.argument.StructuredArgument; @@ -23,8 +22,8 @@ import net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider; import net.logstash.logback.composite.loggingevent.LogstashMarkersJsonProvider; -import com.fasterxml.jackson.core.JsonGenerator; import org.slf4j.Marker; +import tools.jackson.core.JsonGenerator; /** * A {@link Marker} OR {@link StructuredArgument} that appends @@ -46,7 +45,6 @@ * {@link #getFieldValue()} will be substituted in {1} in the {@link #messageFormatPattern}. * Subclasses must override {@link #getFieldValue()} to provide the field value to include. */ -@SuppressWarnings("serial") public abstract class SingleFieldAppendingMarker extends LogstashMarker implements StructuredArgument { public static final String MARKER_NAME_PREFIX = LogstashMarker.MARKER_NAME_PREFIX + "APPEND_"; @@ -80,7 +78,7 @@ public String getFieldName() { return fieldName; } - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { writeFieldName(generator); writeFieldValue(generator); } @@ -89,19 +87,17 @@ public void writeTo(JsonGenerator generator) throws IOException { * Writes the field name to the generator. * * @param generator the generator to write JSON - * @throws IOException if an I/O error occurs */ - protected void writeFieldName(JsonGenerator generator) throws IOException { - generator.writeFieldName(getFieldName()); + protected void writeFieldName(JsonGenerator generator) { + generator.writeName(getFieldName()); } /** * Writes the field value to the generator. * * @param generator the generator to write JSON - * @throws IOException if an I/O error occurs */ - protected abstract void writeFieldValue(JsonGenerator generator) throws IOException; + protected abstract void writeFieldValue(JsonGenerator generator); @Override public String toStringSelf() { @@ -139,11 +135,10 @@ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } - if (!(obj instanceof SingleFieldAppendingMarker)) { + if (!(obj instanceof SingleFieldAppendingMarker other)) { return false; } - SingleFieldAppendingMarker other = (SingleFieldAppendingMarker) obj; return this.fieldName.equals(other.fieldName); } diff --git a/src/main/java/net/logstash/logback/mask/FieldMasker.java b/src/main/java/net/logstash/logback/mask/FieldMasker.java index 2b183a6a..66b9e3a0 100644 --- a/src/main/java/net/logstash/logback/mask/FieldMasker.java +++ b/src/main/java/net/logstash/logback/mask/FieldMasker.java @@ -15,8 +15,8 @@ */ package net.logstash.logback.mask; -import com.fasterxml.jackson.core.JsonStreamContext; -import com.fasterxml.jackson.databind.node.NullNode; +import tools.jackson.core.TokenStreamContext; +import tools.jackson.databind.node.NullNode; /** * Masks JSON fields within a JSON stream. @@ -50,5 +50,5 @@ public interface FieldMasker { * To write a JSON null value as the masked value, return {@link NullNode#instance}. * To write {@value MaskingJsonGenerator#MASK}, the return {@link MaskingJsonGenerator#MASK MaskingJsonGenerator.MASK} */ - Object mask(JsonStreamContext context); + Object mask(TokenStreamContext context); } diff --git a/src/main/java/net/logstash/logback/mask/FieldNameBasedFieldMasker.java b/src/main/java/net/logstash/logback/mask/FieldNameBasedFieldMasker.java index be1e7d73..0bed04a9 100644 --- a/src/main/java/net/logstash/logback/mask/FieldNameBasedFieldMasker.java +++ b/src/main/java/net/logstash/logback/mask/FieldNameBasedFieldMasker.java @@ -19,7 +19,7 @@ import java.util.Objects; import java.util.Set; -import com.fasterxml.jackson.core.JsonStreamContext; +import tools.jackson.core.TokenStreamContext; /** * Masks values of specific JSON field names within a JSON stream. @@ -39,8 +39,8 @@ public FieldNameBasedFieldMasker(Set fieldNamesToMask, Object mask) { } @Override - public Object mask(JsonStreamContext context) { - return context.hasCurrentName() && fieldNamesToMask.contains(context.getCurrentName()) + public Object mask(TokenStreamContext context) { + return context.hasCurrentName() && fieldNamesToMask.contains(context.currentName()) ? mask : null; } diff --git a/src/main/java/net/logstash/logback/mask/MaskingJsonGenerator.java b/src/main/java/net/logstash/logback/mask/MaskingJsonGenerator.java index 5081b2c8..c37932a6 100644 --- a/src/main/java/net/logstash/logback/mask/MaskingJsonGenerator.java +++ b/src/main/java/net/logstash/logback/mask/MaskingJsonGenerator.java @@ -24,11 +24,12 @@ import java.util.Collection; import java.util.Collections; -import com.fasterxml.jackson.core.Base64Variant; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonStreamContext; -import com.fasterxml.jackson.core.SerializableString; -import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; +import tools.jackson.core.Base64Variant; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.SerializableString; +import tools.jackson.core.TokenStreamContext; +import tools.jackson.core.exc.JacksonIOException; +import tools.jackson.core.util.JsonGeneratorDelegate; /** @@ -88,11 +89,6 @@ public class MaskingJsonGenerator extends JsonGeneratorDelegate { */ private int maskDepth = 0; - @FunctionalInterface - private interface ThrowingRunnable { - void run() throws E; - } - /** * @param delegate the generator to which to write potentially masked JSON * @param fieldMaskers {@link FieldMasker}s to mask fields @@ -108,7 +104,7 @@ public MaskingJsonGenerator( } @Override - public void writeArray(int[] array, int offset, int length) throws IOException { + public JsonGenerator writeArray(int[] array, int offset, int length) { /* * Delegate to writeArrayStart, writeNumber, and writeArrayEnd * so that masking can be performed. @@ -123,10 +119,11 @@ public void writeArray(int[] array, int offset, int length) throws IOException { writeNumber(array[i]); } writeEndArray(); + return this; } @Override - public void writeArray(long[] array, int offset, int length) throws IOException { + public JsonGenerator writeArray(long[] array, int offset, int length) { /* * Delegate to writeArrayStart, writeNumber, and writeArrayEnd * so that masking can be performed. @@ -141,10 +138,11 @@ public void writeArray(long[] array, int offset, int length) throws IOException writeNumber(array[i]); } writeEndArray(); + return this; } @Override - public void writeArray(double[] array, int offset, int length) throws IOException { + public JsonGenerator writeArray(double[] array, int offset, int length) { /* * Delegate to writeArrayStart, writeNumber, and writeArrayEnd * so that masking can be performed. @@ -159,24 +157,25 @@ public void writeArray(double[] array, int offset, int length) throws IOExceptio writeNumber(array[i]); } writeEndArray(); + return this; } @Override - public void writeFieldName(SerializableString name) throws IOException { - writeFieldName(() -> super.writeFieldName(name)); + public JsonGenerator writeName(SerializableString name) { + return writeName(() -> super.writeName(name)); } @Override - public void writeFieldName(String name) throws IOException { - writeFieldName(() -> super.writeFieldName(name)); + public JsonGenerator writeName(String name) { + return writeName(() -> super.writeName(name)); } @Override - public void writeFieldId(long id) throws IOException { - writeFieldName(() -> super.writeFieldId(id)); + public JsonGenerator writePropertyId(long id) { + return writeName(() -> super.writePropertyId(id)); } - private void writeFieldName(ThrowingRunnable doWriteFieldName) throws IOException { + private JsonGenerator writeName(Runnable doWriteFieldName) { if (maskingInProgress()) { /* @@ -205,37 +204,41 @@ private void writeFieldName(ThrowingRunnable doWriteFieldName) thro * Write the masked value. * No other values will be written when masking is in progress. */ - delegate.writeObject(maskedValue); + delegate.writePOJO(maskedValue); incrementMaskDepth(); } } + return this; } @Override - public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException { + public JsonGenerator writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) { if (!maskingInProgress()) { super.writeBinary(b64variant, data, offset, len); } + return this; } @Override - public void writeBinary(byte[] data) throws IOException { + public JsonGenerator writeBinary(byte[] data) { if (!maskingInProgress()) { super.writeBinary(data); } + return this; } @Override - public void writeBinary(byte[] data, int offset, int len) throws IOException { + public JsonGenerator writeBinary(byte[] data, int offset, int len) { if (!maskingInProgress()) { super.writeBinary(data, offset, len); } + return this; } @Override - public int writeBinary(Base64Variant b64variant, InputStream data, int dataLength) throws IOException { + public int writeBinary(Base64Variant b64variant, InputStream data, int dataLength) { if (!maskingInProgress()) { return super.writeBinary(b64variant, data, dataLength); } else { @@ -244,7 +247,7 @@ public int writeBinary(Base64Variant b64variant, InputStream data, int dataLengt } @Override - public int writeBinary(InputStream data, int dataLength) throws IOException { + public int writeBinary(InputStream data, int dataLength) { if (!maskingInProgress()) { return super.writeBinary(data, dataLength); } else { @@ -252,262 +255,285 @@ public int writeBinary(InputStream data, int dataLength) throws IOException { } } - private int readAndDiscard(InputStream data) throws IOException { - int bytesRead = 0; - while (data.read() != -1) { - bytesRead++; + private int readAndDiscard(InputStream data) { + try { + int bytesRead = 0; + while (data.read() != -1) { + bytesRead++; + } + return bytesRead; + } catch (IOException e) { + throw JacksonIOException.construct(e, this); } - return bytesRead; } @Override - public void writeBoolean(boolean state) throws IOException { + public JsonGenerator writeBoolean(boolean state) { if (!maskingInProgress()) { super.writeBoolean(state); } + return this; } @Override - public void writeEmbeddedObject(Object object) throws IOException { + public JsonGenerator writeEmbeddedObject(Object object) { if (!maskingInProgress()) { super.writeEmbeddedObject(object); } + return this; } @Override - public void writeNull() throws IOException { + public JsonGenerator writeNull() { if (!maskingInProgress()) { super.writeNull(); } + return this; } @Override - public void writeNumber(BigDecimal v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(BigDecimal v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(BigInteger v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(BigInteger v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(double v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(double v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(float v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(float v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(int v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(int v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(short v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(short v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(long v) throws IOException { - writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); + public JsonGenerator writeNumber(long v) { + return writePotentiallyMaskedValue(v, () -> super.writeNumber(v)); } @Override - public void writeNumber(String encodedValue) throws IOException { - writePotentiallyMaskedValue(encodedValue, () -> super.writeNumber(encodedValue)); + public JsonGenerator writeNumber(String encodedValue) { + return writePotentiallyMaskedValue(encodedValue, () -> super.writeNumber(encodedValue)); } @Override - public void writeObjectId(Object id) throws IOException { + public JsonGenerator writeObjectId(Object id) { if (!maskingInProgress()) { super.writeObjectId(id); } + return this; } @Override - public void writeObjectRef(Object id) throws IOException { + public JsonGenerator writeObjectRef(Object id) { if (!maskingInProgress()) { super.writeObjectRef(id); } + return this; } @Override - public void writeOmittedField(String fieldName) throws IOException { + public JsonGenerator writeOmittedProperty(String fieldName) { if (!maskingInProgress()) { - super.writeOmittedField(fieldName); + super.writeOmittedProperty(fieldName); } + return this; } @Override - public void writeRaw(char c) throws IOException { + public JsonGenerator writeRaw(char c) { if (!maskingInProgress()) { super.writeRaw(c); } + return this; } @Override - public void writeRaw(char[] text, int offset, int len) throws IOException { + public JsonGenerator writeRaw(char[] text, int offset, int len) { if (!maskingInProgress()) { super.writeRaw(text, offset, len); } + return this; } @Override - public void writeRaw(String text) throws IOException { + public JsonGenerator writeRaw(String text) { if (!maskingInProgress()) { super.writeRaw(text); } + return this; } @Override - public void writeRaw(String text, int offset, int len) throws IOException { + public JsonGenerator writeRaw(String text, int offset, int len) { if (!maskingInProgress()) { super.writeRaw(text, offset, len); } + return this; } @Override - public void writeRaw(SerializableString raw) throws IOException { + public JsonGenerator writeRaw(SerializableString raw) { if (!maskingInProgress()) { super.writeRaw(raw); } + return this; } @Override - public void writeRawValue(String text) throws IOException { + public JsonGenerator writeRawValue(String text) { if (!maskingInProgress()) { super.writeRawValue(text); } + return this; } @Override - public void writeRawValue(String text, int offset, int len) throws IOException { + public JsonGenerator writeRawValue(String text, int offset, int len) { if (!maskingInProgress()) { super.writeRawValue(text, offset, len); } + return this; } @Override - public void writeRawValue(char[] text, int offset, int len) throws IOException { + public JsonGenerator writeRawValue(char[] text, int offset, int len) { if (!maskingInProgress()) { super.writeRawValue(text, offset, len); } + return this; } @Override - public void writeRawUTF8String(byte[] text, int offset, int length) throws IOException { + public JsonGenerator writeRawUTF8String(byte[] text, int offset, int length) { if (!maskingInProgress()) { super.writeRawUTF8String(text, offset, length); } + return this; } @Override - public void writeStartArray(int size) throws IOException { - if (!maskingInProgress()) { - super.writeStartArray(size); - } - } - - @Override - public void writeStartArray() throws IOException { + public JsonGenerator writeStartArray() { if (!maskingInProgress()) { super.writeStartArray(); } + return this; } + @Override - public void writeStartArray(Object forValue) throws IOException { + public JsonGenerator writeStartArray(Object forValue) { if (!maskingInProgress()) { super.writeStartArray(forValue); } + return this; } @Override - public void writeStartArray(Object forValue, int size) throws IOException { + public JsonGenerator writeStartArray(Object forValue, int size) { if (!maskingInProgress()) { super.writeStartArray(forValue, size); } + return this; } @Override - public void writeStartObject() throws IOException { + public JsonGenerator writeStartObject() { if (!maskingInProgress()) { super.writeStartObject(); } else { incrementMaskDepth(); } + return this; } @Override - public void writeStartObject(Object forValue) throws IOException { + public JsonGenerator writeStartObject(Object forValue) { if (!maskingInProgress()) { super.writeStartObject(forValue); } else { incrementMaskDepth(); } + return this; } @Override - public void writeStartObject(Object forValue, int size) throws IOException { + public JsonGenerator writeStartObject(Object forValue, int size) { if (!maskingInProgress()) { super.writeStartObject(forValue, size); } else { incrementMaskDepth(); } + return this; } @Override - public void writeString(char[] text, int offset, int len) throws IOException { - writePotentiallyMaskedValue(new String(text, offset, len), () -> super.writeString(text, offset, len)); + public JsonGenerator writeString(char[] text, int offset, int len) { + return writePotentiallyMaskedValue(new String(text, offset, len), () -> super.writeString(text, offset, len)); } @Override - public void writeString(String text) throws IOException { - writePotentiallyMaskedValue(text, () -> super.writeString(text)); + public JsonGenerator writeString(String text) { + return writePotentiallyMaskedValue(text, () -> super.writeString(text)); } @Override - public void writeString(SerializableString text) throws IOException { - writePotentiallyMaskedValue(text.getValue(), () -> super.writeString(text)); + public JsonGenerator writeString(SerializableString text) { + return writePotentiallyMaskedValue(text.getValue(), () -> super.writeString(text)); } @Override - public void writeString(Reader reader, int len) throws IOException { + public JsonGenerator writeString(Reader reader, int len) { if (!maskingInProgress()) { super.writeString(reader, len); } + return this; } @Override - public void writeUTF8String(byte[] text, int offset, int length) throws IOException { - writePotentiallyMaskedValue(new String(text, offset, length, StandardCharsets.UTF_8), () -> super.writeUTF8String(text, offset, length)); + public JsonGenerator writeUTF8String(byte[] text, int offset, int length) { + return writePotentiallyMaskedValue(new String(text, offset, length, StandardCharsets.UTF_8), () -> super.writeUTF8String(text, offset, length)); } @Override - public void writeTypeId(Object id) throws IOException { + public JsonGenerator writeTypeId(Object id) { if (!maskingInProgress()) { super.writeTypeId(id); } + return this; } @Override - public void writeEndArray() throws IOException { + public JsonGenerator writeEndArray() { if (!maskingInProgress()) { super.writeEndArray(); } + return this; } @Override - public void writeEndObject() throws IOException { + public JsonGenerator writeEndObject() { if (maskingInProgress()) { decrementMaskDepth(); } if (!maskingInProgress()) { super.writeEndObject(); } + return this; } /** @@ -515,7 +541,7 @@ public void writeEndObject() throws IOException { * otherwise returns null. */ private Object getMaskedValueForCurrentPath() { - JsonStreamContext context = getOutputContext(); + TokenStreamContext context = streamWriteContext(); for (FieldMasker fieldMasker : fieldMaskers) { Object maskedValue = fieldMasker.mask(context); if (maskedValue != null) { @@ -530,7 +556,7 @@ private Object getMaskedValueForCurrentPath() { * otherwise returns null. */ private Object getMaskedValueForCurrentPathAndValue(Object originalValue) { - JsonStreamContext context = getOutputContext(); + TokenStreamContext context = streamWriteContext(); Object localValue = originalValue; for (ValueMasker valueMasker : valueMaskers) { Object maskedValue = valueMasker.mask(context, localValue); @@ -544,15 +570,16 @@ private Object getMaskedValueForCurrentPathAndValue(Object originalValue) { return null; } - private void writePotentiallyMaskedValue(Object value, ThrowingRunnable doWriteUnmaskedValue) throws IOException { + private JsonGenerator writePotentiallyMaskedValue(Object value, Runnable doWriteUnmaskedValue) { if (!maskingInProgress()) { Object maskedValue = getMaskedValueForCurrentPathAndValue(value); if (maskedValue != null) { - delegate.writeObject(maskedValue); + delegate.writePOJO(maskedValue); } else { doWriteUnmaskedValue.run(); } } + return this; } private void incrementMaskDepth() { diff --git a/src/main/java/net/logstash/logback/mask/MaskingJsonGeneratorDecorator.java b/src/main/java/net/logstash/logback/mask/MaskingJsonGeneratorDecorator.java index d3b0f376..db47c7aa 100644 --- a/src/main/java/net/logstash/logback/mask/MaskingJsonGeneratorDecorator.java +++ b/src/main/java/net/logstash/logback/mask/MaskingJsonGeneratorDecorator.java @@ -32,7 +32,7 @@ import net.logstash.logback.decorate.JsonGeneratorDecorator; import ch.qos.logback.core.spi.LifeCycle; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * A {@link JsonGeneratorDecorator} that wraps a {@link JsonGenerator} with a {@link MaskingJsonGenerator}, @@ -271,22 +271,22 @@ private List getEffectiveFieldMaskers() { }) ); - return Collections.unmodifiableList(Stream.concat( + return Stream.concat( fieldNamesByMask.entrySet().stream() .map(entry -> new FieldNameBasedFieldMasker(entry.getValue(), entry.getKey())), Stream.concat( pathFieldMaskers.stream(), fieldMaskers.stream())) - .collect(Collectors.toList())); + .collect(Collectors.toUnmodifiableList()); } private List getEffectiveValueMaskers() { - return Collections.unmodifiableList(Stream.concat( + return Stream.concat( Stream.concat(Stream.of(valuesWithDefaultMask), valueMaskSuppliers.stream().map(Supplier::get)) .flatMap(valueMask -> valueMask.values.stream() .map(value -> new RegexValueMasker(value, valueMask.mask))), valueMaskers.stream()) - .collect(Collectors.toList())); + .collect(Collectors.toUnmodifiableList()); } diff --git a/src/main/java/net/logstash/logback/mask/PathBasedFieldMasker.java b/src/main/java/net/logstash/logback/mask/PathBasedFieldMasker.java index 3a9d3dc2..c724ea95 100644 --- a/src/main/java/net/logstash/logback/mask/PathBasedFieldMasker.java +++ b/src/main/java/net/logstash/logback/mask/PathBasedFieldMasker.java @@ -17,7 +17,7 @@ import java.util.Objects; -import com.fasterxml.jackson.core.JsonStreamContext; +import tools.jackson.core.TokenStreamContext; /** * Masks values of an absolute or partial path within a JSON stream. @@ -196,8 +196,8 @@ static void validatePathToMask(String pathToMask) { } @Override - public Object mask(JsonStreamContext context) { - JsonStreamContext currentContext = context; + public Object mask(TokenStreamContext context) { + TokenStreamContext currentContext = context; for (int i = tokens.length; --i >= 0; currentContext = currentContext.getParent()) { if (!currentLeafMatches(currentContext, tokens[i])) { return null; @@ -208,13 +208,13 @@ public Object mask(JsonStreamContext context) { : null; } - private boolean currentLeafMatches(JsonStreamContext context, String leafName) { + private boolean currentLeafMatches(TokenStreamContext context, String leafName) { if (context != null) { if (WILDCARD_TOKEN.equals(leafName)) { return true; } if (context.hasCurrentName()) { - return context.getCurrentName().equals(leafName); + return context.currentName().equals(leafName); } if (context.hasCurrentIndex()) { return Integer.toString(context.getCurrentIndex()).equals(leafName); diff --git a/src/main/java/net/logstash/logback/mask/RegexValueMasker.java b/src/main/java/net/logstash/logback/mask/RegexValueMasker.java index eabd33ec..be70c4ac 100644 --- a/src/main/java/net/logstash/logback/mask/RegexValueMasker.java +++ b/src/main/java/net/logstash/logback/mask/RegexValueMasker.java @@ -19,7 +19,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.fasterxml.jackson.core.JsonStreamContext; +import tools.jackson.core.TokenStreamContext; /** * Masks values based on a regular expression. @@ -47,7 +47,7 @@ public RegexValueMasker(Pattern pattern, Object mask) { } @Override - public Object mask(JsonStreamContext context, Object o) { + public Object mask(TokenStreamContext context, Object o) { if (o instanceof CharSequence) { Matcher matcher = pattern.matcher((CharSequence) o); if (mask instanceof String) { diff --git a/src/main/java/net/logstash/logback/mask/ValueMasker.java b/src/main/java/net/logstash/logback/mask/ValueMasker.java index 568d01f8..776298c8 100644 --- a/src/main/java/net/logstash/logback/mask/ValueMasker.java +++ b/src/main/java/net/logstash/logback/mask/ValueMasker.java @@ -15,8 +15,8 @@ */ package net.logstash.logback.mask; -import com.fasterxml.jackson.core.JsonStreamContext; -import com.fasterxml.jackson.databind.node.NullNode; +import tools.jackson.core.TokenStreamContext; +import tools.jackson.databind.node.NullNode; /** * Masks JSON string and number values within a JSON stream. @@ -51,5 +51,5 @@ public interface ValueMasker { * To write a JSON null value as the masked value, return {@link NullNode#instance}. * To write {@value MaskingJsonGenerator#MASK}, the return {@link MaskingJsonGenerator#MASK MaskingJsonGenerator.MASK} */ - Object mask(JsonStreamContext context, Object value); + Object mask(TokenStreamContext context, Object value); } diff --git a/src/main/java/net/logstash/logback/pattern/AbstractJsonPatternParser.java b/src/main/java/net/logstash/logback/pattern/AbstractJsonPatternParser.java index 34a4f254..d911e3fd 100644 --- a/src/main/java/net/logstash/logback/pattern/AbstractJsonPatternParser.java +++ b/src/main/java/net/logstash/logback/pattern/AbstractJsonPatternParser.java @@ -15,10 +15,8 @@ */ package net.logstash.logback.pattern; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -31,17 +29,16 @@ import ch.qos.logback.core.Context; import ch.qos.logback.core.pattern.PatternLayoutBase; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonPointer; -import com.fasterxml.jackson.core.filter.FilteringGeneratorDelegate; -import com.fasterxml.jackson.core.filter.TokenFilter; -import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.JsonPointer; +import tools.jackson.core.exc.StreamReadException; +import tools.jackson.core.filter.FilteringGeneratorDelegate; +import tools.jackson.core.filter.TokenFilter; +import tools.jackson.core.filter.TokenFilter.Inclusion; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.node.ArrayNode; +import tools.jackson.databind.node.ObjectNode; /** * Parser that takes a JSON pattern, resolves all the conversion specifiers and returns an instance @@ -60,7 +57,7 @@ public abstract class AbstractJsonPatternParser { public static final Pattern OPERATION_PATTERN = Pattern.compile("\\# (\\w+) (?: \\{ (.*) \\} )", Pattern.COMMENTS); private final Context context; - private final JsonFactory jsonFactory; + private final ObjectMapper objectMapper; private final Map> operations = new HashMap<>(); @@ -71,9 +68,9 @@ public abstract class AbstractJsonPatternParser { */ private boolean omitEmptyFields; - AbstractJsonPatternParser(final Context context, final JsonFactory jsonFactory) { + AbstractJsonPatternParser(final Context context, ObjectMapper objectMapper) { this.context = Objects.requireNonNull(context); - this.jsonFactory = Objects.requireNonNull(jsonFactory); + this.objectMapper = Objects.requireNonNull(objectMapper); addOperation("asLong", new AsLongOperation()); addOperation("asDouble", new AsDoubleOperation()); addOperation("asBoolean", new AsBooleanOperation()); @@ -123,11 +120,10 @@ public Boolean apply(String value) { if (StringUtils.isEmpty(value)) { return null; } - return Boolean.valueOf( - "true".equalsIgnoreCase(value) + return "true".equalsIgnoreCase(value) || "1".equals(value) || "yes".equalsIgnoreCase(value) - || "y".equalsIgnoreCase(value)); + || "y".equalsIgnoreCase(value); } } @@ -135,11 +131,9 @@ protected class AsJsonOperation implements Operation { @Override public JsonNode apply(final String value) { try { - return JsonReadingUtils.readFully(jsonFactory, value); - } catch (JsonParseException e) { + return JsonReadingUtils.readFully(objectMapper, value); + } catch (StreamReadException e) { throw new IllegalArgumentException("Failed to convert '" + value + "' into a JSON object", e); - } catch (IOException e) { - throw new IllegalStateException("Unexpected IOException when reading JSON value (was '" + value + "')", e); } } } @@ -148,11 +142,9 @@ protected class TryJsonOperation implements Operation { @Override public Object apply(final String value) { try { - return JsonReadingUtils.readFully(jsonFactory, value); - } catch (JsonParseException e) { + return JsonReadingUtils.readFully(objectMapper, value); + } catch (StreamReadException e) { return value; - } catch (IOException e) { - throw new IllegalStateException("Unexpected IOException when reading JSON value (was '" + value + "')", e); } } } @@ -298,9 +290,9 @@ public NodeWriter parse(String pattern) throws JsonPatternException { } final ObjectNode node; - try (JsonParser jsonParser = jsonFactory.createParser(pattern)) { - node = JsonReadingUtils.readFullyAsObjectNode(jsonFactory, pattern); - } catch (IOException e) { + try { + node = JsonReadingUtils.readFullyAsObjectNode(objectMapper, pattern); + } catch (StreamReadException e) { throw new JsonPatternException("pattern is not a valid JSON object", e); } @@ -319,12 +311,12 @@ public NodeWriter parse(String pattern) throws JsonPatternException { * @throws JsonPatternException denotes an invalid pattern */ private NodeWriter parseNode(JsonPointer location, JsonNode node) throws JsonPatternException { - if (node.isTextual()) { + if (node.isString()) { try { - ValueGetter getter = makeComputableValueGetter(node.asText()); + ValueGetter getter = makeComputableValueGetter(node.asString()); return new ValueWriter<>(getter); } catch (RuntimeException e) { - String msg = "Invalid JSON property '" + location + "' (was '" + node.asText() + "'): " + e.getMessage(); + String msg = "Invalid JSON property '" + location + "' (was '" + node.asString() + "'): " + e.getMessage(); throw new JsonPatternException(msg, e); } } @@ -369,14 +361,12 @@ private ArrayWriter parseArray(JsonPointer location, ArrayNode node) thro private ObjectWriter parseObject(JsonPointer location, ObjectNode node) throws JsonPatternException { ObjectWriter writer = new ObjectWriter<>(); - for (Iterator> nodeFields = node.fields(); nodeFields.hasNext();) { - Map.Entry field = nodeFields.next(); + for (Map.Entry property : node.properties()) { + String propertyName = property.getKey(); + JsonNode propertyValue = property.getValue(); - String fieldName = field.getKey(); - JsonNode fieldValue = field.getValue(); - - NodeWriter fieldWriter = parseNode(appendPath(location, fieldName), fieldValue); - writer.addField(fieldName, fieldWriter); + NodeWriter fieldWriter = parseNode(appendPath(location, propertyName), propertyValue); + writer.addField(propertyName, fieldWriter); } return writer; @@ -407,13 +397,13 @@ public void addField(String fieldName, NodeWriter fieldValue) { } @Override - public void write(JsonGenerator generator, Event event) throws IOException { + public void write(JsonGenerator generator, Event event) { generator.writeStartObject(); writeFields(generator, event); generator.writeEndObject(); } - protected void writeFields(JsonGenerator generator, Event event) throws IOException { + protected void writeFields(JsonGenerator generator, Event event) { for (Field field: this.fields) { field.write(generator, event); } @@ -428,8 +418,8 @@ private static class Field { this.writer = writer; } - public void write(JsonGenerator generator, E event) throws IOException { - generator.writeFieldName(name); + public void write(JsonGenerator generator, E event) { + generator.writeName(name); writer.write(generator, event); } } @@ -443,7 +433,7 @@ protected static class ArrayWriter implements NodeWriter { this.items = items; } - public void write(JsonGenerator generator, Event event) throws IOException { + public void write(JsonGenerator generator, Event event) { generator.writeStartArray(); for (NodeWriter item : items) { item.write(generator, event); @@ -460,8 +450,8 @@ protected static class ValueWriter implements NodeWriter { this.getter = getter; } - public void write(JsonGenerator generator, Event event) throws IOException { - generator.writeObject(getValue(event)); + public void write(JsonGenerator generator, Event event) { + generator.writePOJO(getValue(event)); } private Object getValue(Event event) { @@ -482,7 +472,7 @@ private static class RootWriter implements NodeWriter { } @Override - public void write(JsonGenerator generator, Event event) throws IOException { + public void write(JsonGenerator generator, Event event) { delegate.writeFields(generator, event); } } @@ -497,13 +487,13 @@ private static class OmitEmptyFieldWriter implements NodeWriter { } @Override - public void write(JsonGenerator generator, Event event) throws IOException { + public void write(JsonGenerator generator, Event event) { ReusableFilteringGenerator filteringGenerator = filteringGenerators.get(); try { filteringGenerator.connect(generator); delegate.write(filteringGenerator, event); - } catch (RuntimeException | IOException e) { + } catch (RuntimeException e) { filteringGenerators.remove(); throw e; @@ -567,7 +557,6 @@ public void setOmitEmptyFields(boolean omitEmptyFields) { } - @SuppressWarnings("serial") public static class JsonPatternException extends Exception { public JsonPatternException(String message, Throwable cause) { super(message, cause); diff --git a/src/main/java/net/logstash/logback/pattern/AccessEventJsonPatternParser.java b/src/main/java/net/logstash/logback/pattern/AccessEventJsonPatternParser.java index c1a68e19..b88594df 100644 --- a/src/main/java/net/logstash/logback/pattern/AccessEventJsonPatternParser.java +++ b/src/main/java/net/logstash/logback/pattern/AccessEventJsonPatternParser.java @@ -19,15 +19,15 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.core.Context; import ch.qos.logback.core.pattern.PatternLayoutBase; -import com.fasterxml.jackson.core.JsonFactory; +import tools.jackson.databind.ObjectMapper; /** * @author Dmitry Andrianov */ public class AccessEventJsonPatternParser extends AbstractJsonPatternParser { - public AccessEventJsonPatternParser(final Context context, final JsonFactory jsonFactory) { - super(context, jsonFactory); + public AccessEventJsonPatternParser(Context context, ObjectMapper objectMapper) { + super(context, objectMapper); addOperation("nullNA", new NullNaValueOperation()); } diff --git a/src/main/java/net/logstash/logback/pattern/LoggingEventJsonPatternParser.java b/src/main/java/net/logstash/logback/pattern/LoggingEventJsonPatternParser.java index 0e268540..4325f07d 100644 --- a/src/main/java/net/logstash/logback/pattern/LoggingEventJsonPatternParser.java +++ b/src/main/java/net/logstash/logback/pattern/LoggingEventJsonPatternParser.java @@ -19,15 +19,15 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Context; import ch.qos.logback.core.pattern.PatternLayoutBase; -import com.fasterxml.jackson.core.JsonFactory; +import tools.jackson.databind.ObjectMapper; /** * @author Dmitry Andrianov */ public class LoggingEventJsonPatternParser extends AbstractJsonPatternParser { - public LoggingEventJsonPatternParser(final Context context, final JsonFactory jsonFactory) { - super(context, jsonFactory); + public LoggingEventJsonPatternParser(Context context, ObjectMapper objectMapper) { + super(context, objectMapper); } /** diff --git a/src/main/java/net/logstash/logback/pattern/NodeWriter.java b/src/main/java/net/logstash/logback/pattern/NodeWriter.java index fc96265e..36762d57 100644 --- a/src/main/java/net/logstash/logback/pattern/NodeWriter.java +++ b/src/main/java/net/logstash/logback/pattern/NodeWriter.java @@ -15,9 +15,7 @@ */ package net.logstash.logback.pattern; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; /** * Writes a JSON pattern node into JSON generator supplied. @@ -32,7 +30,6 @@ public interface NodeWriter { * * @param generator the generator to which to write the node * @param event the event from which to get data to write - * @throws IOException if an I/O error occurs */ - void write(JsonGenerator generator, Event event) throws IOException; + void write(JsonGenerator generator, Event event); } diff --git a/src/main/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegate.java b/src/main/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegate.java index 41712e17..adb76c6e 100644 --- a/src/main/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegate.java +++ b/src/main/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegate.java @@ -15,23 +15,20 @@ */ package net.logstash.logback.util; -import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.Iterator; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.util.JsonGeneratorDelegate; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.node.ArrayNode; /** - * JsonGenerator with an optimized implementation of the {@link #writeObject(Object)} method that tries + * JsonGenerator with an optimized implementation of the {@link #writePOJO(Object)} method that tries * to call appropriate write method for the given untyped Object and delegates to the underlying generator * as fallback. */ @@ -39,140 +36,137 @@ public class SimpleObjectJsonGeneratorDelegate extends JsonGeneratorDelegate { public SimpleObjectJsonGeneratorDelegate(JsonGenerator delegate) { super(delegate, false); } - + @Override - public void writeObject(Object value) throws IOException { + public JsonGenerator writePOJO(Object value) { if (value == null) { writeNull(); - return; + return this; } if (value instanceof String) { writeString((String) value); - return; + return this; } - if (value instanceof Number) { - Number n = (Number) value; + if (value instanceof Number n) { if (n instanceof Integer) { writeNumber(n.intValue()); - return; + return this; } if (n instanceof Long) { writeNumber(n.longValue()); - return; + return this; } if (n instanceof Double) { writeNumber(n.doubleValue()); - return; + return this; } if (n instanceof Float) { writeNumber(n.floatValue()); - return; + return this; } if (n instanceof Short) { writeNumber(n.shortValue()); - return; + return this; } if (n instanceof Byte) { writeNumber(n.byteValue()); - return; + return this; } if (n instanceof BigInteger) { writeNumber((BigInteger) n); - return; + return this; } if (n instanceof BigDecimal) { writeNumber((BigDecimal) n); - return; + return this; } if (n instanceof AtomicInteger) { writeNumber(((AtomicInteger) n).get()); - return; + return this; } if (n instanceof AtomicLong) { writeNumber(((AtomicLong) n).get()); - return; + return this; } } if (value instanceof byte[]) { writeBinary((byte[]) value); - return; + return this; } if (value instanceof Boolean) { writeBoolean((Boolean) value); - return; + return this; } if (value instanceof AtomicBoolean) { writeBoolean(((AtomicBoolean) value).get()); - return; + return this; } - if (value instanceof JsonNode) { - JsonNode node = (JsonNode) value; - + if (value instanceof JsonNode node) { + switch (node.getNodeType()) { case NULL: writeNull(); - return; + return this; case STRING: - writeString(node.asText()); - return; + writeString(node.asString()); + return this; case BOOLEAN: writeBoolean(node.asBoolean()); - return; + return this; case BINARY: writeBinary(node.binaryValue()); - return; + return this; case NUMBER: if (node.isInt()) { writeNumber(node.intValue()); - return; + return this; } if (node.isLong()) { writeNumber(node.longValue()); - return; + return this; } if (node.isShort()) { writeNumber(node.shortValue()); - return; + return this; } if (node.isDouble()) { writeNumber(node.doubleValue()); - return; + return this; } if (node.isFloat()) { writeNumber(node.floatValue()); - return; + return this; } if (node.isBigDecimal()) { writeNumber(node.decimalValue()); - return; + return this; } if (node.isBigInteger()) { writeNumber(node.bigIntegerValue()); - return; + return this; } case OBJECT: writeStartObject(node); - for (Iterator> entries = ((ObjectNode) node).fields(); entries.hasNext();) { - Entry entry = entries.next(); - writeObjectField(entry.getKey(), entry.getValue()); + for (Entry entry : node.properties()) { + writePOJOProperty(entry.getKey(), entry.getValue()); } writeEndObject(); - return; + return this; case ARRAY: ArrayNode arrayNode = (ArrayNode) node; int size = arrayNode.size(); writeStartArray(arrayNode, size); - for (Iterator elements = arrayNode.elements(); elements.hasNext();) { - writeObject(elements.next()); + for (JsonNode jsonNode : arrayNode.elements()) { + writePOJO(jsonNode); } writeEndArray(); - return; + return this; default: // default case is handled below @@ -183,6 +177,7 @@ public void writeObject(Object value) throws IOException { // Default case if not handled by one of the specialized methods above // - delegate.writeObject(value); + delegate.writePOJO(value); + return this; } } diff --git a/src/test/java/net/logstash/logback/ConfigurationTest.java b/src/test/java/net/logstash/logback/ConfigurationTest.java index e8331c9e..3ffe9537 100644 --- a/src/test/java/net/logstash/logback/ConfigurationTest.java +++ b/src/test/java/net/logstash/logback/ConfigurationTest.java @@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import java.io.IOException; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.util.List; @@ -65,13 +64,13 @@ import ch.qos.logback.core.OutputStreamAppender; import ch.qos.logback.core.encoder.Encoder; import ch.qos.logback.core.read.ListAppender; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; +import tools.jackson.core.JsonParser; +import tools.jackson.core.type.TypeReference; +import tools.jackson.databind.json.JsonMapper; public class ConfigurationTest { @@ -79,7 +78,7 @@ public class ConfigurationTest { private final ListAppender listAppender = (ListAppender) LOGGER.getAppender("listAppender"); - private final JsonFactory jsonFactory = new MappingJsonFactory(); + private final JsonMapper jsonMapper = JsonMapper.builder().build(); @BeforeEach public void setup() { @@ -87,7 +86,7 @@ public void setup() { } @Test - public void testLogstashEncoderAppender() throws IOException { + public void testLogstashEncoderAppender() { LoggingEventCompositeJsonEncoder encoder = getEncoder("logstashEncoderAppender"); List> providers = encoder.getProviders().getProviders(); @@ -99,7 +98,7 @@ public void testLogstashEncoderAppender() throws IOException { } @Test - public void testLoggingEventCompositeJsonEncoderAppender() throws IOException { + public void testLoggingEventCompositeJsonEncoderAppender() { LoggingEventCompositeJsonEncoder encoder = getEncoder("loggingEventCompositeJsonEncoderAppender"); List> providers = encoder.getProviders().getProviders(); @@ -113,7 +112,7 @@ public void testLoggingEventCompositeJsonEncoderAppender() throws IOException { } @Test - public void testAppenderHasListener() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + public void testAppenderHasListener() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { LoggingEventAsyncDisruptorAppender appender = getAppender("asyncAppender"); Field listenersField = AsyncDisruptorAppender.class.getDeclaredField("listeners"); listenersField.setAccessible(true); @@ -241,15 +240,13 @@ private > T getInstance(List> T getEncoder(String appenderName) { return (T) this.>getAppender(appenderName).getEncoder(); } - private Map parseJson(final String text) throws IOException { - return jsonFactory.createParser(text).readValueAs(new TypeReference>() { - }); + private Map parseJson(final String text) { + try (JsonParser parser = jsonMapper.createParser(text)) { + return jsonMapper.readValue(parser, new TypeReference<>() { }); + } } } diff --git a/src/test/java/net/logstash/logback/TestJsonProvider.java b/src/test/java/net/logstash/logback/TestJsonProvider.java index 711dcf29..f901ca68 100644 --- a/src/test/java/net/logstash/logback/TestJsonProvider.java +++ b/src/test/java/net/logstash/logback/TestJsonProvider.java @@ -15,17 +15,15 @@ */ package net.logstash.logback; -import java.io.IOException; - import net.logstash.logback.composite.AbstractJsonProvider; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; +import tools.jackson.core.JsonGenerator; public class TestJsonProvider extends AbstractJsonProvider { @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { + public void writeTo(JsonGenerator generator, ILoggingEvent event) { } } diff --git a/src/test/java/net/logstash/logback/appender/DelegatingAsyncDisruptorAppenderTest.java b/src/test/java/net/logstash/logback/appender/DelegatingAsyncDisruptorAppenderTest.java index 97d16599..40d923fe 100644 --- a/src/test/java/net/logstash/logback/appender/DelegatingAsyncDisruptorAppenderTest.java +++ b/src/test/java/net/logstash/logback/appender/DelegatingAsyncDisruptorAppenderTest.java @@ -53,7 +53,7 @@ public class DelegatingAsyncDisruptorAppenderTest { private static final int VERIFICATION_TIMEOUT = 1000 * 30; - private DelegatingAsyncDisruptorAppender> appender = new DelegatingAsyncDisruptorAppender>() { }; + private final DelegatingAsyncDisruptorAppender> appender = new DelegatingAsyncDisruptorAppender<>() { }; @Mock private ILoggingEvent event; @@ -67,7 +67,7 @@ public class DelegatingAsyncDisruptorAppenderTest { @BeforeEach public void setup() { outputStreamDelegate.setImmediateFlush(false); - outputStreamDelegate.setEncoder(new EchoEncoder()); + outputStreamDelegate.setEncoder(new EchoEncoder<>()); outputStreamDelegate.setOutputStream(outputStream); appender.setContext(new LoggerContext()); @@ -81,8 +81,8 @@ public void tearDown() { @Test public void appenderStartStop() { - Appender delegate1 = spy(new TestAppender()); - Appender delegate2 = spy(new TestAppender()); + Appender delegate1 = spy(new TestAppender<>()); + Appender delegate2 = spy(new TestAppender<>()); appender.addAppender(delegate1); appender.addAppender(delegate2); @@ -119,9 +119,9 @@ public void appenderStartStop() { * Event is forwarded to appenders in the order they were registered. */ @Test - public void handlerCalled() throws Exception { - Appender delegate1 = spy(new TestAppender()); - Appender delegate2 = spy(new TestAppender()); + public void handlerCalled() { + Appender delegate1 = spy(new TestAppender<>()); + Appender delegate2 = spy(new TestAppender<>()); appender.addAppender(delegate1); appender.addAppender(delegate2); @@ -139,12 +139,12 @@ public void handlerCalled() throws Exception { * Event is forwarded to all appenders even after first threw an exception */ @Test - public void handlerCalledAfterException() throws Exception { - Appender delegate1 = spy(new TestAppender()); + public void handlerCalledAfterException() { + Appender delegate1 = spy(new TestAppender<>()); LogbackException exception = new LogbackException("boum"); doThrow(exception).when(delegate1).doAppend(event); - Appender delegate2 = spy(new TestAppender()); + Appender delegate2 = spy(new TestAppender<>()); appender.addAppender(delegate1); appender.addAppender(delegate2); @@ -242,7 +242,7 @@ public void notFlushedWhenImmediateFlush() throws Exception { * Flush appenders implementing "Flushable" at end of batch */ @Test - public void flushFlushable() throws Exception { + public void flushFlushable() { FlushableAppender flushableDelegate = spy(new FlushableAppender()); appender.addAppender(flushableDelegate); @@ -306,7 +306,7 @@ protected void append(E eventObject) { private static class FlushableAppender extends TestAppender implements Flushable { @Override - public void flush() throws IOException { + public void flush() { } } } diff --git a/src/test/java/net/logstash/logback/appender/LogstashTcpSocketAppenderTest.java b/src/test/java/net/logstash/logback/appender/LogstashTcpSocketAppenderTest.java index e10be66f..aadca8a2 100644 --- a/src/test/java/net/logstash/logback/appender/LogstashTcpSocketAppenderTest.java +++ b/src/test/java/net/logstash/logback/appender/LogstashTcpSocketAppenderTest.java @@ -88,16 +88,16 @@ public class LogstashTcpSocketAppenderTest extends AbstractLogbackTest { @Mock private ILoggingEvent event1; - @Mock(lenient = true) + @Mock(strictness = Mock.Strictness.LENIENT) private SocketFactory socketFactory; - @Mock(lenient = true) + @Mock(strictness = Mock.Strictness.LENIENT) private Socket socket; @Mock private OutputStream outputStream; - @Mock(lenient = true) + @Mock(strictness = Mock.Strictness.LENIENT) private Encoder encoder; @Mock @@ -125,7 +125,7 @@ public void setup() throws Exception { when(encoder.encode(event1)).thenReturn("event1".getBytes(StandardCharsets.UTF_8)); appender.addListener(listener); - appender.addListener(new TcpAppenderListener() { + appender.addListener(new TcpAppenderListener<>() { @Override public void eventSent(Appender appender, Socket socket, ILoggingEvent event, long durationInNanos) { @@ -528,7 +528,7 @@ public void testInitialSendDelay() throws Exception { // Capture time events are sent final Map tstamps = new HashMap<>(); - appender.addListener(new TcpAppenderListener() { + appender.addListener(new TcpAppenderListener<>() { @Override public void eventSent(Appender appender, Socket socket, ILoggingEvent event, long durationInNanos) { tstamps.put(event, System.currentTimeMillis()); @@ -565,7 +565,7 @@ public void eventSent(Appender appender, Socket socket, ILoggingE * Assert that waiting for initialSendDelay is aborted immediately when the appender is stopped. */ @Test - public void testStopWhileWaitingInitialSendDelay() throws Exception { + public void testStopWhileWaitingInitialSendDelay() { appender.addDestination("localhost:10000"); appender.setInitialSendDelay(Duration.buildByMilliseconds(30000)); appender.setShutdownGracePeriod(Duration.buildByMilliseconds(0)); @@ -922,7 +922,7 @@ private SocketAddress host(final String host, final int port) { } private ArgumentMatcher hasHostAndPort(final String host, final int port) { - return new ArgumentMatcher() { + return new ArgumentMatcher<>() { @Override public boolean matches(SocketAddress argument) { diff --git a/src/test/java/net/logstash/logback/argument/DeferredStructuredArgumentTest.java b/src/test/java/net/logstash/logback/argument/DeferredStructuredArgumentTest.java index 451c0c4d..617c5e25 100644 --- a/src/test/java/net/logstash/logback/argument/DeferredStructuredArgumentTest.java +++ b/src/test/java/net/logstash/logback/argument/DeferredStructuredArgumentTest.java @@ -21,18 +21,20 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.io.IOException; import java.io.StringWriter; import java.util.function.Supplier; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class DeferredStructuredArgumentTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); public static class MyClass { private String myField; @@ -51,7 +53,7 @@ public void setMyField(String myField) { } @Test - public void testWriteTo() throws IOException { + public void testWriteTo() { @SuppressWarnings("unchecked") Supplier supplier = mock(Supplier.class); @@ -59,7 +61,7 @@ public void testWriteTo() throws IOException { when(supplier.get()).thenReturn(new MyClass("value")); StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); StructuredArgument structuredArgument = StructuredArguments.defer(() -> StructuredArguments.kv("myObject", supplier.get())); diff --git a/src/test/java/net/logstash/logback/composite/AbstractPatternJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/AbstractPatternJsonProviderTest.java index 548eed7d..dc53bb87 100644 --- a/src/test/java/net/logstash/logback/composite/AbstractPatternJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/AbstractPatternJsonProviderTest.java @@ -30,11 +30,11 @@ import ch.qos.logback.core.spi.DeferredProcessingAware; import ch.qos.logback.core.status.Status; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; public class AbstractPatternJsonProviderTest extends AbstractLogbackTest { @@ -43,7 +43,7 @@ public class AbstractPatternJsonProviderTest extends AbstractLogbackTest { private DeferredProcessingAware event; @Mock - private JsonFactory jsonFactory; + private ObjectMapper objectMapper; @Mock private AbstractJsonPatternParser parser; @@ -55,14 +55,14 @@ public class AbstractPatternJsonProviderTest extends AbstractLogbackTest { public void setup() throws Exception { super.setup(); - provider = new AbstractPatternJsonProvider() { + provider = new AbstractPatternJsonProvider<>() { @Override - protected AbstractJsonPatternParser createParser(JsonFactory jsonFactory) { + protected AbstractJsonPatternParser createParser() { return parser; } }; provider.setContext(context); - provider.setJsonFactory(jsonFactory); + provider.setObjectMapper(objectMapper); } @@ -129,6 +129,6 @@ public void invalidConfiguration() throws Exception { && status.getOrigin() == provider); // Provider output "nothing" after a configuration error - verifyNoInteractions(jsonFactory); + verifyNoInteractions(objectMapper); } } diff --git a/src/test/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProviderTest.java index c7ff357a..d1d4f134 100644 --- a/src/test/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/GlobalCustomFieldsJsonProviderTest.java @@ -25,36 +25,35 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.status.Status; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.NumericNode; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.node.JsonNodeFactory; +import tools.jackson.databind.node.NumericNode; public class GlobalCustomFieldsJsonProviderTest extends AbstractLogbackTest { @InjectMocks - private GlobalCustomFieldsJsonProvider provider = new GlobalCustomFieldsJsonProvider(); + private GlobalCustomFieldsJsonProvider provider = new GlobalCustomFieldsJsonProvider<>(); @Mock private ILoggingEvent event; - private StringWriter writer = new StringWriter(); + private final StringWriter writer = new StringWriter(); private JsonGenerator generator; @BeforeEach public void setup() throws Exception { super.setup(); - - JsonFactory factory = new MappingJsonFactory(); - provider.setJsonFactory(factory); - generator = factory.createGenerator(writer); + + JsonMapper jsonMapper = JsonMapper.builder().build(); + provider.setObjectMapper(jsonMapper); + generator = jsonMapper.createGenerator(writer); } @AfterEach diff --git a/src/test/java/net/logstash/logback/composite/LogstashVersionJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/LogstashVersionJsonProviderTest.java index 146117fb..8d6dfda8 100644 --- a/src/test/java/net/logstash/logback/composite/LogstashVersionJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/LogstashVersionJsonProviderTest.java @@ -17,21 +17,19 @@ import static org.mockito.Mockito.verify; -import java.io.IOException; - import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LogstashVersionJsonProviderTest { - private LogstashVersionJsonProvider provider = new LogstashVersionJsonProvider(); + private final LogstashVersionJsonProvider provider = new LogstashVersionJsonProvider<>(); @Mock private JsonGenerator generator; @@ -40,51 +38,51 @@ public class LogstashVersionJsonProviderTest { private ILoggingEvent event; @Test - public void testVersionAsNumeric() throws IOException { + public void testVersionAsNumeric() { provider.setWriteAsInteger(true); provider.writeTo(generator, event); - verify(generator).writeNumberField(LogstashVersionJsonProvider.FIELD_VERSION, Long.parseLong(LogstashVersionJsonProvider.DEFAULT_VERSION)); + verify(generator).writeNumberProperty(LogstashVersionJsonProvider.FIELD_VERSION, Long.parseLong(LogstashVersionJsonProvider.DEFAULT_VERSION)); } @Test - public void testVersionAsString() throws IOException { + public void testVersionAsString() { provider.writeTo(generator, event); - verify(generator).writeStringField(LogstashVersionJsonProvider.FIELD_VERSION, LogstashVersionJsonProvider.DEFAULT_VERSION); + verify(generator).writeStringProperty(LogstashVersionJsonProvider.FIELD_VERSION, LogstashVersionJsonProvider.DEFAULT_VERSION); } @Test - public void testNonDefaultVersionAsNumeric() throws IOException { + public void testNonDefaultVersionAsNumeric() { provider.setVersion("800"); provider.setWriteAsInteger(true); provider.writeTo(generator, event); - verify(generator).writeNumberField(LogstashVersionJsonProvider.FIELD_VERSION, 800L); + verify(generator).writeNumberProperty(LogstashVersionJsonProvider.FIELD_VERSION, 800L); } @Test - public void testNonDefaultVersionAsString() throws IOException { + public void testNonDefaultVersionAsString() { provider.setVersion("800"); provider.writeTo(generator, event); - verify(generator).writeStringField(LogstashVersionJsonProvider.FIELD_VERSION, "800"); + verify(generator).writeStringProperty(LogstashVersionJsonProvider.FIELD_VERSION, "800"); } @Test - public void testFieldName() throws IOException { + public void testFieldName() { provider.setFieldName("newFieldName"); provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", LogstashVersionJsonProvider.DEFAULT_VERSION); + verify(generator).writeStringProperty("newFieldName", LogstashVersionJsonProvider.DEFAULT_VERSION); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setVersion("newFieldName"); @@ -92,7 +90,7 @@ public void testFieldNames() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", LogstashVersionJsonProvider.DEFAULT_VERSION); + verify(generator).writeStringProperty("newFieldName", LogstashVersionJsonProvider.DEFAULT_VERSION); } } diff --git a/src/test/java/net/logstash/logback/composite/SequenceJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/SequenceJsonProviderTest.java index 51abb33d..5fcfe5c6 100644 --- a/src/test/java/net/logstash/logback/composite/SequenceJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/SequenceJsonProviderTest.java @@ -20,17 +20,17 @@ import java.io.IOException; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) @Deprecated public class SequenceJsonProviderTest { - private SequenceJsonProvider provider = new SequenceJsonProvider<>(); + private final SequenceJsonProvider provider = new SequenceJsonProvider<>(); @Mock private JsonGenerator generator; @@ -42,7 +42,7 @@ public class SequenceJsonProviderTest { public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeNumberField(SequenceJsonProvider.FIELD_SEQUENCE, 1L); + verify(generator).writeNumberProperty(SequenceJsonProvider.FIELD_SEQUENCE, 1L); } @@ -52,6 +52,6 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeNumberField("newFieldName", 1L); + verify(generator).writeNumberProperty("newFieldName", 1L); } } diff --git a/src/test/java/net/logstash/logback/composite/UuidJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/UuidJsonProviderTest.java index c7b4774e..ed064f05 100644 --- a/src/test/java/net/logstash/logback/composite/UuidJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/UuidJsonProviderTest.java @@ -15,24 +15,21 @@ */ package net.logstash.logback.composite; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.matches; import static org.mockito.Mockito.verify; -import java.io.IOException; - import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class UuidJsonProviderTest { public static final String UUID = "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"; - private UuidJsonProvider provider = new UuidJsonProvider<>(); + private final UuidJsonProvider provider = new UuidJsonProvider<>(); @Mock private JsonGenerator generator; @@ -41,37 +38,41 @@ public class UuidJsonProviderTest { private ILoggingEvent event; @Test - public void testDefaultName() throws IOException { + public void testDefaultName() { provider.writeTo(generator, event); - verify(generator).writeStringField(eq(UuidJsonProvider.FIELD_UUID), matches(UUID)); + verify(generator).writeName(UuidJsonProvider.FIELD_UUID); + verify(generator).writeString(matches(UUID)); } @Test - public void testFieldName() throws IOException { + public void testFieldName() { provider.setFieldName("newFieldName"); provider.writeTo(generator, event); - verify(generator).writeStringField(eq("newFieldName"), matches(UUID)); + verify(generator).writeName("newFieldName"); + verify(generator).writeString(matches(UUID)); } @Test - public void testStrategy() throws IOException { + public void testStrategy() { provider.setStrategy(UuidJsonProvider.STRATEGY_TIME); provider.writeTo(generator, event); - verify(generator).writeStringField(eq("uuid"), matches(UUID)); + verify(generator).writeName("uuid"); + verify(generator).writeString(matches(UUID)); } @Test - public void testEthernet() throws IOException { + public void testEthernet() { provider.setStrategy(UuidJsonProvider.STRATEGY_TIME); provider.setEthernet("00:C0:F0:3D:5B:7C"); provider.writeTo(generator, event); - verify(generator).writeStringField(eq("uuid"), matches(UUID)); + verify(generator).writeName("uuid"); + verify(generator).writeString(matches(UUID)); } } diff --git a/src/test/java/net/logstash/logback/composite/accessevent/AccessEventNestedJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/accessevent/AccessEventNestedJsonProviderTest.java index bd09b320..baab8903 100644 --- a/src/test/java/net/logstash/logback/composite/accessevent/AccessEventNestedJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/accessevent/AccessEventNestedJsonProviderTest.java @@ -17,10 +17,7 @@ import static org.mockito.Mockito.inOrder; -import java.io.IOException; - import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -28,6 +25,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class AccessEventNestedJsonProviderTest { @@ -50,7 +48,7 @@ void beforeEach() { } @Test - public void testWrite() throws IOException { + public void testWrite() { provider.setFieldName("newFieldName"); @@ -58,8 +56,7 @@ public void testWrite() throws IOException { InOrder inOrder = inOrder(generator, providers); - inOrder.verify(generator).writeFieldName("newFieldName"); - inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeObjectPropertyStart("newFieldName"); inOrder.verify(providers).writeTo(generator, event); inOrder.verify(generator).writeEndObject(); } diff --git a/src/test/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProviderTest.java index a408db3b..95006c4c 100644 --- a/src/test/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/accessevent/RequestHeadersJsonProviderTest.java @@ -24,20 +24,20 @@ import java.util.Map; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class RequestHeadersJsonProviderTest { - private RequestHeadersJsonProvider provider = new RequestHeadersJsonProvider(); + private final RequestHeadersJsonProvider provider = new RequestHeadersJsonProvider(); - private Map headers = new LinkedHashMap(); + private final Map headers = new LinkedHashMap<>(); @Mock private JsonGenerator generator; @@ -53,7 +53,7 @@ public void setup() { } @Test - public void testNoFieldName() throws IOException { + public void testNoFieldName() { provider.writeTo(generator, event); verifyNoMoreInteractions(generator); } @@ -65,28 +65,34 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("fieldName"); - inOrder.verify(generator).writeStringField("headerA", "valueA"); - inOrder.verify(generator).writeStringField("headerB", "valueB"); + inOrder.verify(generator).writeName("fieldName"); + inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeName("headerA"); + inOrder.verify(generator).writeString("valueA"); + inOrder.verify(generator).writeName("headerB"); + inOrder.verify(generator).writeString("valueB"); inOrder.verify(generator).writeEndObject(); inOrder.verifyNoMoreInteractions(); } @Test - public void testFieldNameWithLowerCase() throws IOException { + public void testFieldNameWithLowerCase() { provider.setFieldName("fieldName"); provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("fieldName"); - inOrder.verify(generator).writeStringField("headera", "valueA"); - inOrder.verify(generator).writeStringField("headerb", "valueB"); + inOrder.verify(generator).writeName("fieldName"); + inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeName("headera"); + inOrder.verify(generator).writeString("valueA"); + inOrder.verify(generator).writeName("headerb"); + inOrder.verify(generator).writeString("valueB"); inOrder.verify(generator).writeEndObject(); inOrder.verifyNoMoreInteractions(); } @Test - public void testFilter() throws IOException { + public void testFilter() { IncludeExcludeHeaderFilter filter = new IncludeExcludeHeaderFilter(); filter.addInclude("headerb"); @@ -96,8 +102,10 @@ public void testFilter() throws IOException { provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("fieldName"); - inOrder.verify(generator).writeStringField("headerb", "valueB"); + inOrder.verify(generator).writeName("fieldName"); + inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeName("headerb"); + inOrder.verify(generator).writeString("valueB"); inOrder.verify(generator).writeEndObject(); inOrder.verifyNoMoreInteractions(); } diff --git a/src/test/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProviderTest.java index 2f1326ef..bd47705f 100644 --- a/src/test/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/accessevent/ResponseHeadersJsonProviderTest.java @@ -24,20 +24,20 @@ import java.util.Map; import ch.qos.logback.access.common.spi.IAccessEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class ResponseHeadersJsonProviderTest { - private ResponseHeadersJsonProvider provider = new ResponseHeadersJsonProvider(); + private final ResponseHeadersJsonProvider provider = new ResponseHeadersJsonProvider(); - private Map headers = new LinkedHashMap(); + private final Map headers = new LinkedHashMap<>(); @Mock private JsonGenerator generator; @@ -53,7 +53,7 @@ public void setup() { } @Test - public void testNoFieldName() throws IOException { + public void testNoFieldName() { provider.setLowerCaseHeaderNames(false); provider.writeTo(generator, event); verifyNoMoreInteractions(generator); @@ -66,28 +66,34 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("fieldName"); - inOrder.verify(generator).writeStringField("headerA", "valueA"); - inOrder.verify(generator).writeStringField("headerB", "valueB"); + inOrder.verify(generator).writeName("fieldName"); + inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeName("headerA"); + inOrder.verify(generator).writeString("valueA"); + inOrder.verify(generator).writeName("headerB"); + inOrder.verify(generator).writeString("valueB"); inOrder.verify(generator).writeEndObject(); inOrder.verifyNoMoreInteractions(); } @Test - public void testFieldNameWithLowerCase() throws IOException { + public void testFieldNameWithLowerCase() { provider.setFieldName("fieldName"); provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("fieldName"); - inOrder.verify(generator).writeStringField("headera", "valueA"); - inOrder.verify(generator).writeStringField("headerb", "valueB"); + inOrder.verify(generator).writeName("fieldName"); + inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeName("headera"); + inOrder.verify(generator).writeString("valueA"); + inOrder.verify(generator).writeName("headerb"); + inOrder.verify(generator).writeString("valueB"); inOrder.verify(generator).writeEndObject(); inOrder.verifyNoMoreInteractions(); } @Test - public void testFilter() throws IOException { + public void testFilter() { IncludeExcludeHeaderFilter filter = new IncludeExcludeHeaderFilter(); filter.addInclude("headerb"); @@ -97,8 +103,10 @@ public void testFilter() throws IOException { provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("fieldName"); - inOrder.verify(generator).writeStringField("headerb", "valueB"); + inOrder.verify(generator).writeName("fieldName"); + inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeName("headerb"); + inOrder.verify(generator).writeString("valueB"); inOrder.verify(generator).writeEndObject(); inOrder.verifyNoMoreInteractions(); } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProviderTest.java index a3a21bd4..8e708324 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/ArgumentsJsonProviderTest.java @@ -18,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import java.io.IOException; import java.io.StringWriter; import java.util.LinkedHashMap; import java.util.Map; @@ -26,34 +25,32 @@ import net.logstash.logback.argument.StructuredArguments; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; @ExtendWith(MockitoExtension.class) public class ArgumentsJsonProviderTest { - private ArgumentsJsonProvider provider = new ArgumentsJsonProvider(); + private final ArgumentsJsonProvider provider = new ArgumentsJsonProvider(); - private JsonFactory factory = new MappingJsonFactory(); + private final ObjectMapper objectMapper = JsonMapper.builder().build(); - private StringWriter writer = new StringWriter(); + private final StringWriter writer = new StringWriter(); private JsonGenerator generator; @Mock private ILoggingEvent event; - private Object[] arguments; - private static class Foo { - private String k6 = "v6"; + private final String k6 = "v6"; @SuppressWarnings("unused") public String getK6() { @@ -62,14 +59,14 @@ public String getK6() { } @BeforeEach - public void setup() throws IOException { + public void setup() { - generator = factory.createGenerator(writer); + generator = objectMapper.createGenerator(writer); - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); map.put("k4", "v4"); map.put("k5", "v5"); - arguments = new Object[] { + Object[] arguments = new Object[]{ StructuredArguments.keyValue("k0", "v0"), StructuredArguments.keyValue("k1", "v1", "{0}=[{1}]"), StructuredArguments.value("k2", "v2"), @@ -83,7 +80,7 @@ public void setup() throws IOException { } @Test - public void testUnwrapped() throws IOException { + public void testUnwrapped() { generator.writeStartObject(); provider.writeTo(generator, event); generator.writeEndObject(); @@ -104,7 +101,7 @@ public void testUnwrapped() throws IOException { } @Test - public void testWrapped() throws IOException { + public void testWrapped() { provider.setFieldName("args"); generator.writeStartObject(); @@ -130,7 +127,7 @@ public void testWrapped() throws IOException { @Test - public void testIncludeNonStructuredArguments() throws IOException { + public void testIncludeNonStructuredArguments() { provider.setIncludeNonStructuredArguments(true); generator.writeStartObject(); @@ -154,7 +151,7 @@ public void testIncludeNonStructuredArguments() throws IOException { } @Test - public void testIncludeNonStructuredArgumentsAndCustomPrefix() throws IOException { + public void testIncludeNonStructuredArgumentsAndCustomPrefix() { provider.setIncludeNonStructuredArguments(true); provider.setNonStructuredArgumentsFieldPrefix("prefix"); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/CallerDataJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/CallerDataJsonProviderTest.java index 685d5683..1b4d7c37 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/CallerDataJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/CallerDataJsonProviderTest.java @@ -26,19 +26,19 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class CallerDataJsonProviderTest { private static final StackTraceElement CALLER_DATA = new StackTraceElement("declaringClass", "methodName", "fileName", 100); - private CallerDataJsonProvider provider = new CallerDataJsonProvider(); + private final CallerDataJsonProvider provider = new CallerDataJsonProvider(); @Mock private JsonGenerator generator; @@ -51,7 +51,7 @@ private void setupCallerData() { } @Test - public void testUnwrapped() throws IOException { + public void testUnwrapped() { setupCallerData(); provider.writeTo(generator, event); @@ -61,14 +61,14 @@ public void testUnwrapped() throws IOException { InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeStringField(CallerDataJsonProvider.FIELD_CALLER_CLASS_NAME, CALLER_DATA.getClassName()); - inOrder.verify(generator).writeStringField(CallerDataJsonProvider.FIELD_CALLER_METHOD_NAME, CALLER_DATA.getMethodName()); - inOrder.verify(generator).writeStringField(CallerDataJsonProvider.FIELD_CALLER_FILE_NAME, CALLER_DATA.getFileName()); - inOrder.verify(generator).writeNumberField(CallerDataJsonProvider.FIELD_CALLER_LINE_NUMBER, CALLER_DATA.getLineNumber()); + inOrder.verify(generator).writeStringProperty(CallerDataJsonProvider.FIELD_CALLER_CLASS_NAME, CALLER_DATA.getClassName()); + inOrder.verify(generator).writeStringProperty(CallerDataJsonProvider.FIELD_CALLER_METHOD_NAME, CALLER_DATA.getMethodName()); + inOrder.verify(generator).writeStringProperty(CallerDataJsonProvider.FIELD_CALLER_FILE_NAME, CALLER_DATA.getFileName()); + inOrder.verify(generator).writeNumberProperty(CallerDataJsonProvider.FIELD_CALLER_LINE_NUMBER, CALLER_DATA.getLineNumber()); } @Test - public void testWrapped() throws IOException { + public void testWrapped() { setupCallerData(); provider.setFieldName("caller"); @@ -77,16 +77,16 @@ public void testWrapped() throws IOException { InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("caller"); - inOrder.verify(generator).writeStringField(CallerDataJsonProvider.FIELD_CALLER_CLASS_NAME, CALLER_DATA.getClassName()); - inOrder.verify(generator).writeStringField(CallerDataJsonProvider.FIELD_CALLER_METHOD_NAME, CALLER_DATA.getMethodName()); - inOrder.verify(generator).writeStringField(CallerDataJsonProvider.FIELD_CALLER_FILE_NAME, CALLER_DATA.getFileName()); - inOrder.verify(generator).writeNumberField(CallerDataJsonProvider.FIELD_CALLER_LINE_NUMBER, CALLER_DATA.getLineNumber()); + inOrder.verify(generator).writeObjectPropertyStart("caller"); + inOrder.verify(generator).writeStringProperty(CallerDataJsonProvider.FIELD_CALLER_CLASS_NAME, CALLER_DATA.getClassName()); + inOrder.verify(generator).writeStringProperty(CallerDataJsonProvider.FIELD_CALLER_METHOD_NAME, CALLER_DATA.getMethodName()); + inOrder.verify(generator).writeStringProperty(CallerDataJsonProvider.FIELD_CALLER_FILE_NAME, CALLER_DATA.getFileName()); + inOrder.verify(generator).writeNumberProperty(CallerDataJsonProvider.FIELD_CALLER_LINE_NUMBER, CALLER_DATA.getLineNumber()); inOrder.verify(generator).writeEndObject(); } @Test - public void testNoCallerData() throws IOException { + public void testNoCallerData() { provider.writeTo(generator, event); verifyNoMoreInteractions(generator); @@ -106,16 +106,16 @@ public void testFieldName() throws IOException { InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("caller"); - inOrder.verify(generator).writeStringField("class", CALLER_DATA.getClassName()); - inOrder.verify(generator).writeStringField("method", CALLER_DATA.getMethodName()); - inOrder.verify(generator).writeStringField("file", CALLER_DATA.getFileName()); - inOrder.verify(generator).writeNumberField("line", CALLER_DATA.getLineNumber()); + inOrder.verify(generator).writeObjectPropertyStart("caller"); + inOrder.verify(generator).writeStringProperty("class", CALLER_DATA.getClassName()); + inOrder.verify(generator).writeStringProperty("method", CALLER_DATA.getMethodName()); + inOrder.verify(generator).writeStringProperty("file", CALLER_DATA.getFileName()); + inOrder.verify(generator).writeNumberProperty("line", CALLER_DATA.getLineNumber()); inOrder.verify(generator).writeEndObject(); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { setupCallerData(); LogstashFieldNames fieldNames = new LogstashFieldNames(); @@ -131,16 +131,16 @@ public void testFieldNames() throws IOException { InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("caller"); - inOrder.verify(generator).writeStringField("class", CALLER_DATA.getClassName()); - inOrder.verify(generator).writeStringField("method", CALLER_DATA.getMethodName()); - inOrder.verify(generator).writeStringField("file", CALLER_DATA.getFileName()); - inOrder.verify(generator).writeNumberField("line", CALLER_DATA.getLineNumber()); + inOrder.verify(generator).writeObjectPropertyStart("caller"); + inOrder.verify(generator).writeStringProperty("class", CALLER_DATA.getClassName()); + inOrder.verify(generator).writeStringProperty("method", CALLER_DATA.getMethodName()); + inOrder.verify(generator).writeStringProperty("file", CALLER_DATA.getFileName()); + inOrder.verify(generator).writeNumberProperty("line", CALLER_DATA.getLineNumber()); inOrder.verify(generator).writeEndObject(); } @Test - public void testPrepareForDeferredProcessing() throws IOException { + public void testPrepareForDeferredProcessing() { provider.prepareForDeferredProcessing(event); verify(event).getCallerData(); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/ContextNameJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/ContextNameJsonProviderTest.java index d3ea19ce..0a891df6 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/ContextNameJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/ContextNameJsonProviderTest.java @@ -22,16 +22,16 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.LoggerContextVO; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class ContextNameJsonProviderTest { - private ContextNameJsonProvider provider = new ContextNameJsonProvider(); + private final ContextNameJsonProvider provider = new ContextNameJsonProvider(); @Mock private JsonGenerator generator; @@ -50,7 +50,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField(ContextNameJsonProvider.FIELD_CONTEXT_NAME, "testcontext"); + verify(generator).writeStringProperty(ContextNameJsonProvider.FIELD_CONTEXT_NAME, "testcontext"); } @Test @@ -62,7 +62,7 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "testcontext"); + verify(generator).writeStringProperty("newFieldName", "testcontext"); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java index 7dc6ef49..ab53bfd4 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/KeyValuePairsJsonProviderTest.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.when; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -27,20 +26,19 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.event.KeyValuePair; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.json.JsonMapper; @ExtendWith(MockitoExtension.class) public class KeyValuePairsJsonProviderTest { - private KeyValuePairsJsonProvider provider = new KeyValuePairsJsonProvider(); + private final KeyValuePairsJsonProvider provider = new KeyValuePairsJsonProvider(); private ByteArrayOutputStream resultStream; private JsonGenerator generator; @@ -48,35 +46,32 @@ public class KeyValuePairsJsonProviderTest { @Mock private ILoggingEvent event; - private List keyValuePairs; - @BeforeEach public void setup() throws Exception { - keyValuePairs = new ArrayList<>(); + List keyValuePairs = new ArrayList<>(); keyValuePairs.add(new KeyValuePair("name1", "value1")); keyValuePairs.add(new KeyValuePair("name2", 2023)); keyValuePairs.add(new KeyValuePair("name3", new TestValue())); when(event.getKeyValuePairs()).thenReturn(keyValuePairs); resultStream = new ByteArrayOutputStream(); - generator = new JsonFactory().createGenerator(resultStream); - generator.setCodec(new ObjectMapper()); + generator = JsonMapper.builder().build().createGenerator(resultStream); } @Test - public void testUnwrapped() throws IOException { + public void testUnwrapped() { assertThat(generateJson()) .isEqualTo("{\"name1\":\"value1\",\"name2\":2023,\"name3\":{\"a\":1}}"); } @Test - public void testWrapped() throws IOException { + public void testWrapped() { provider.setFieldName("kvp"); assertThat(generateJson()) .isEqualTo("{\"kvp\":{\"name1\":\"value1\",\"name2\":2023,\"name3\":{\"a\":1}}}"); } @Test - public void testWrappedUsingFieldNames() throws IOException { + public void testWrappedUsingFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setKeyValuePair("kvp"); provider.setFieldNames(fieldNames); @@ -85,7 +80,7 @@ public void testWrappedUsingFieldNames() throws IOException { } @Test - public void testInclude() throws IOException { + public void testInclude() { provider.setIncludeKeyNames(Collections.singletonList("name1")); assertThat(generateJson()) @@ -93,7 +88,7 @@ public void testInclude() throws IOException { } @Test - public void testExclude() throws IOException { + public void testExclude() { provider.setExcludeKeyNames(Collections.singletonList("name1")); assertThat(generateJson()) @@ -101,14 +96,14 @@ public void testExclude() throws IOException { } @Test - public void testAlternativeFieldName() throws IOException { + public void testAlternativeFieldName() { provider.addKeyFieldName("name1=alternativeName1"); assertThat(generateJson()) .isEqualTo("{\"alternativeName1\":\"value1\",\"name2\":2023,\"name3\":{\"a\":1}}"); } - private String generateJson() throws IOException { + private String generateJson() { generator.writeStartObject(); provider.writeTo(generator, event); generator.writeEndObject(); @@ -117,7 +112,7 @@ private String generateJson() throws IOException { return resultStream.toString(); } - private class TestValue { + private static class TestValue { private final int a = 1; public int getA() { diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProviderTest.java index c7c0277e..6b738913 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelJsonProviderTest.java @@ -24,16 +24,16 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LogLevelJsonProviderTest { - private LogLevelJsonProvider provider = new LogLevelJsonProvider(); + private final LogLevelJsonProvider provider = new LogLevelJsonProvider(); @Mock private JsonGenerator generator; @@ -48,7 +48,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField(LogLevelJsonProvider.FIELD_LEVEL, Level.WARN.toString()); + verify(generator).writeStringProperty(LogLevelJsonProvider.FIELD_LEVEL, Level.WARN.toString()); } @Test @@ -59,11 +59,11 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", Level.WARN.toString()); + verify(generator).writeStringProperty("newFieldName", Level.WARN.toString()); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setLevel("newFieldName"); @@ -73,7 +73,7 @@ public void testFieldNames() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", Level.WARN.toString()); + verify(generator).writeStringProperty("newFieldName", Level.WARN.toString()); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProviderTest.java index c7447aea..187d0b56 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LogLevelValueJsonProviderTest.java @@ -24,16 +24,16 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LogLevelValueJsonProviderTest { - private LogLevelValueJsonProvider provider = new LogLevelValueJsonProvider(); + private final LogLevelValueJsonProvider provider = new LogLevelValueJsonProvider(); @Mock private JsonGenerator generator; @@ -48,7 +48,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeNumberField(LogLevelValueJsonProvider.FIELD_LEVEL_VALUE, Level.WARN.toInt()); + verify(generator).writeNumberProperty(LogLevelValueJsonProvider.FIELD_LEVEL_VALUE, Level.WARN.toInt()); } @Test @@ -59,11 +59,11 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeNumberField("newFieldName", Level.WARN.toInt()); + verify(generator).writeNumberProperty("newFieldName", Level.WARN.toInt()); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setLevelValue("newFieldName"); @@ -73,7 +73,7 @@ public void testFieldNames() throws IOException { provider.writeTo(generator, event); - verify(generator).writeNumberField("newFieldName", Level.WARN.toInt()); + verify(generator).writeNumberProperty("newFieldName", Level.WARN.toInt()); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProviderTest.java index a886386b..0b42cac0 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LoggerNameJsonProviderTest.java @@ -23,16 +23,16 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LoggerNameJsonProviderTest { - private LoggerNameJsonProvider provider = new LoggerNameJsonProvider(); + private final LoggerNameJsonProvider provider = new LoggerNameJsonProvider(); @Mock private JsonGenerator generator; @@ -41,12 +41,12 @@ public class LoggerNameJsonProviderTest { private ILoggingEvent event; @Test - public void testFullName() throws IOException { + public void testFullName() { when(event.getLoggerName()).thenReturn(getClass().getName()); writeEvent(); - verify(generator).writeStringField(LoggerNameJsonProvider.FIELD_LOGGER_NAME, getClass().getName()); + verify(generator).writeStringProperty(LoggerNameJsonProvider.FIELD_LOGGER_NAME, getClass().getName()); } @Test @@ -57,11 +57,11 @@ public void testFieldName() throws IOException { writeEvent(); - verify(generator).writeStringField("newFieldName", getClass().getName()); + verify(generator).writeStringProperty("newFieldName", getClass().getName()); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setLogger("newFieldName"); @@ -71,32 +71,32 @@ public void testFieldNames() throws IOException { writeEvent(); - verify(generator).writeStringField("newFieldName", getClass().getName()); + verify(generator).writeStringProperty("newFieldName", getClass().getName()); } @Test - public void testShortName() throws IOException { + public void testShortName() { provider.setShortenedLoggerNameLength(5); when(event.getLoggerName()).thenReturn(getClass().getName()); writeEvent(); - verify(generator).writeStringField(LoggerNameJsonProvider.FIELD_LOGGER_NAME, "n.l.l.c.l.LoggerNameJsonProviderTest"); + verify(generator).writeStringProperty(LoggerNameJsonProvider.FIELD_LOGGER_NAME, "n.l.l.c.l.LoggerNameJsonProviderTest"); } @Test - public void testShortName_zeroLength() throws IOException { + public void testShortName_zeroLength() { provider.setShortenedLoggerNameLength(0); when(event.getLoggerName()).thenReturn(getClass().getName()); writeEvent(); - verify(generator).writeStringField(LoggerNameJsonProvider.FIELD_LOGGER_NAME, "LoggerNameJsonProviderTest"); + verify(generator).writeStringProperty(LoggerNameJsonProvider.FIELD_LOGGER_NAME, "LoggerNameJsonProviderTest"); } - protected void writeEvent() throws IOException { + protected void writeEvent() { if (!provider.isStarted()) { provider.start(); } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventCompositeJsonFormatterTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventCompositeJsonFormatterTest.java index e3eac043..451ce93d 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventCompositeJsonFormatterTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventCompositeJsonFormatterTest.java @@ -21,7 +21,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -33,21 +32,21 @@ import net.logstash.logback.argument.StructuredArguments; import net.logstash.logback.composite.AbstractJsonProvider; import net.logstash.logback.decorate.JsonGeneratorDecorator; -import net.logstash.logback.decorate.NullJsonGeneratorDecorator; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.ContextAware; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.exc.JacksonIOException; +import tools.jackson.core.util.JsonGeneratorDelegate; @ExtendWith(MockitoExtension.class) public class LoggingEventCompositeJsonFormatterTest { - private LoggingEventCompositeJsonFormatter formatter = new LoggingEventCompositeJsonFormatter(mock(ContextAware.class)); + private final LoggingEventCompositeJsonFormatter formatter = new LoggingEventCompositeJsonFormatter(mock(ContextAware.class)); @Mock private ILoggingEvent event; @@ -76,8 +75,9 @@ public void testDoesNotFailOnEmptyBeans() throws IOException { */ @Test public void testReused() throws IOException { - JsonGeneratorDecorator decorator = spy(new NullJsonGeneratorDecorator()); - formatter.setJsonGeneratorDecorator(decorator); + JsonGeneratorDecorator decorator = mock(JsonGeneratorDecorator.class); + when(decorator.decorate(any())).thenAnswer(invocation -> invocation.getArgument(0)); + formatter.addDecorator(decorator); formatter.start(); try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { @@ -95,8 +95,9 @@ public void testReused() throws IOException { */ @Test public void testNotReusedAfterIOException() throws IOException { - JsonGeneratorDecorator decorator = spy(new NullJsonGeneratorDecorator()); - formatter.setJsonGeneratorDecorator(decorator); + JsonGeneratorDecorator decorator = mock(JsonGeneratorDecorator.class); + when(decorator.decorate(any())).thenAnswer(invocation -> invocation.getArgument(0)); + formatter.addDecorator(decorator); formatter.start(); OutputStream bos = mock(OutputStream.class); @@ -104,7 +105,7 @@ public void testNotReusedAfterIOException() throws IOException { .doCallRealMethod() .when(bos).write(any(byte[].class), any(int.class), any(int.class)); - assertThatThrownBy(() -> formatter.writeEvent(event, bos)).isInstanceOf(IOException.class); + assertThatThrownBy(() -> formatter.writeEvent(event, bos)).isInstanceOf(JacksonIOException.class); formatter.writeEvent(event, bos); // Two instances created because the first was discarded because of the exception @@ -117,19 +118,20 @@ public void testNotReusedAfterIOException() throws IOException { */ @Test public void testNotReusedAfterEncoderException() throws IOException { - JsonGeneratorDecorator decorator = spy(new NullJsonGeneratorDecorator()); - formatter.setJsonGeneratorDecorator(decorator); - formatter.getProviders().addProvider(new AbstractJsonProvider() { + JsonGeneratorDecorator decorator = mock(JsonGeneratorDecorator.class); + when(decorator.decorate(any())).thenAnswer(invocation -> invocation.getArgument(0)); + formatter.addDecorator(decorator); + formatter.getProviders().addProvider(new AbstractJsonProvider<>() { @Override - public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException { - throw new IOException("Exception thrown by JsonProvider"); + public void writeTo(JsonGenerator generator, ILoggingEvent event) { + throw JacksonIOException.construct(new IOException("Exception thrown by JsonProvider")); } }); formatter.start(); try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { - assertThatThrownBy(() -> formatter.writeEvent(event, bos)).isInstanceOf(IOException.class); - assertThatThrownBy(() -> formatter.writeEvent(event, bos)).isInstanceOf(IOException.class); + assertThatThrownBy(() -> formatter.writeEvent(event, bos)).isInstanceOf(JacksonIOException.class); + assertThatThrownBy(() -> formatter.writeEvent(event, bos)).isInstanceOf(JacksonIOException.class); // Two instances created because the first was discarded because of the exception verify(decorator, times(2)).decorate(any(JsonGenerator.class)); @@ -142,10 +144,11 @@ public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOExcep @Test public void testOverriddenJsonGeneratorWriteObjectIsHonored() throws IOException { when(event.getArgumentArray()).thenReturn(new Object[] {StructuredArguments.keyValue("answer", 42)}); - formatter.setJsonGeneratorDecorator(generator -> new JsonGeneratorDelegate(generator) { + + formatter.addJsonGeneratorDecorator(generator -> new JsonGeneratorDelegate(generator) { @Override - public void writeObject(final Object pojo) throws IOException { - super.writeObject(String.format("is <%s>", pojo)); + public JsonGenerator writePOJO(final Object pojo) { + return super.writePOJO(String.format("is <%s>", pojo)); } }); ((LoggingEventJsonProviders) formatter.getProviders()).addArguments(new ArgumentsJsonProvider()); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventFormattedTimestampJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventFormattedTimestampJsonProviderTest.java index ba75d016..cd050b9f 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventFormattedTimestampJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventFormattedTimestampJsonProviderTest.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.io.IOException; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -28,12 +27,12 @@ import net.logstash.logback.composite.AbstractFormattedTimestampJsonProvider; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LoggingEventFormattedTimestampJsonProviderTest { @@ -55,35 +54,35 @@ public void setup() { @Test - public void withDefaults() throws IOException { + public void withDefaults() { LoggingEventFormattedTimestampJsonProvider provider = new LoggingEventFormattedTimestampJsonProvider(); provider.writeTo(generator, event); String expectedValue = DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(now); - verify(generator).writeStringField(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); + verify(generator).writeStringProperty(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); } @Test - public void customTimeZone() throws IOException { + public void customTimeZone() { LoggingEventFormattedTimestampJsonProvider provider = new LoggingEventFormattedTimestampJsonProvider(); provider.setTimeZone("UTC"); provider.writeTo(generator, event); String expectedValue = DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.of("UTC")).format(now); - verify(generator).writeStringField(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); + verify(generator).writeStringProperty(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); } @Test - public void constant() throws IOException { + public void constant() { LoggingEventFormattedTimestampJsonProvider provider = new LoggingEventFormattedTimestampJsonProvider(); provider.setPattern("[RFC_1123_DATE_TIME]"); // use a DateTimeFormatter pattern not supported by the FastISOTimestampFormatter provider.writeTo(generator, event); String expectedValue = DateTimeFormatter.RFC_1123_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(now); - verify(generator).writeStringField(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); + verify(generator).writeStringProperty(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); } @Test @@ -95,7 +94,7 @@ public void unknownConstant() { } @Test - public void customPattern() throws IOException { + public void customPattern() { LoggingEventFormattedTimestampJsonProvider provider = new LoggingEventFormattedTimestampJsonProvider(); String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS"; provider.setPattern(pattern); @@ -103,26 +102,26 @@ public void customPattern() throws IOException { provider.writeTo(generator, event); String expectedValue = DateTimeFormatter.ofPattern(pattern).withZone(TimeZone.getDefault().toZoneId()).format(now); - verify(generator).writeStringField(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); + verify(generator).writeStringProperty(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, expectedValue); } @Test - public void unixEpochAsNumber() throws IOException { + public void unixEpochAsNumber() { LoggingEventFormattedTimestampJsonProvider provider = new LoggingEventFormattedTimestampJsonProvider(); provider.setPattern(AbstractFormattedTimestampJsonProvider.UNIX_TIMESTAMP_AS_NUMBER); provider.writeTo(generator, event); - verify(generator).writeNumberField(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, event.getTimeStamp()); + verify(generator).writeNumberProperty(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, event.getTimeStamp()); } @Test - public void unixEpochAsString() throws IOException { + public void unixEpochAsString() { LoggingEventFormattedTimestampJsonProvider provider = new LoggingEventFormattedTimestampJsonProvider(); provider.setPattern(AbstractFormattedTimestampJsonProvider.UNIX_TIMESTAMP_AS_STRING); provider.writeTo(generator, event); - verify(generator).writeStringField(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, Long.toString(event.getTimeStamp())); + verify(generator).writeStringProperty(AbstractFormattedTimestampJsonProvider.FIELD_TIMESTAMP, Long.toString(event.getTimeStamp())); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventNestedJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventNestedJsonProviderTest.java index 380c75c6..34ac3c8d 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventNestedJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventNestedJsonProviderTest.java @@ -18,12 +18,7 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.verify; -import java.io.IOException; - import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonFactoryBuilder; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -31,6 +26,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.json.JsonMapper; @ExtendWith(MockitoExtension.class) public class LoggingEventNestedJsonProviderTest { @@ -53,7 +50,7 @@ void beforeEach() { } @Test - public void testWrite() throws IOException { + public void testWrite() { provider.setFieldName("newFieldName"); @@ -61,8 +58,7 @@ public void testWrite() throws IOException { InOrder inOrder = inOrder(generator, providers); - inOrder.verify(generator).writeFieldName("newFieldName"); - inOrder.verify(generator).writeStartObject(); + inOrder.verify(generator).writeObjectPropertyStart("newFieldName"); inOrder.verify(providers).writeTo(generator, event); inOrder.verify(generator).writeEndObject(); } @@ -81,12 +77,12 @@ public void startStopProviders() { } /* - * JsonFactory set on the enclosed JsonProviders as well + * ObjectMapper set on the enclosed JsonProviders as well */ @Test - public void jsonFactoryOnProviders() { - JsonFactory jsonFactory = new JsonFactoryBuilder().build(); - provider.setJsonFactory(jsonFactory); - verify(providers).setJsonFactory(jsonFactory); + public void objectMapperOnProviders() { + JsonMapper jsonMapper = JsonMapper.builder().build(); + provider.setObjectMapper(jsonMapper); + verify(providers).setObjectMapper(jsonMapper); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventThreadNameJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventThreadNameJsonProviderTest.java index 9bd2f503..b988b3cf 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventThreadNameJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LoggingEventThreadNameJsonProviderTest.java @@ -23,16 +23,16 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LoggingEventThreadNameJsonProviderTest { - private LoggingEventThreadNameJsonProvider provider = new LoggingEventThreadNameJsonProvider(); + private final LoggingEventThreadNameJsonProvider provider = new LoggingEventThreadNameJsonProvider(); @Mock private JsonGenerator generator; @@ -47,7 +47,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField(LoggingEventThreadNameJsonProvider.FIELD_THREAD_NAME, "threadName"); + verify(generator).writeStringProperty(LoggingEventThreadNameJsonProvider.FIELD_THREAD_NAME, "threadName"); } @Test @@ -58,11 +58,11 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "threadName"); + verify(generator).writeStringProperty("newFieldName", "threadName"); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setThread("newFieldName"); @@ -72,7 +72,7 @@ public void testFieldNames() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "threadName"); + verify(generator).writeStringProperty("newFieldName", "threadName"); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProviderTest.java index 00a668b1..dfe268fd 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/LogstashMarkersJsonProviderTest.java @@ -19,18 +19,16 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import java.io.IOException; - import net.logstash.logback.marker.LogstashMarker; import ch.qos.logback.classic.spi.LoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.Marker; import org.slf4j.MarkerFactory; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class LogstashMarkersJsonProviderTest { @@ -38,7 +36,7 @@ public class LogstashMarkersJsonProviderTest { @Mock private JsonGenerator generator; - private LogstashMarkersJsonProvider provider = new LogstashMarkersJsonProvider(); + private final LogstashMarkersJsonProvider provider = new LogstashMarkersJsonProvider(); private int markerCount; @@ -53,7 +51,7 @@ public void noMarkers() { * */ @Test - public void singleMarker() throws IOException { + public void singleMarker() { // event: // * basic1 -> marker1 -> marker11 @@ -78,7 +76,7 @@ public void singleMarker() throws IOException { @Test - public void multipleMarkers() throws IOException { + public void multipleMarkers() { // event: // * basic1 -> marker1 // * marker2 @@ -126,7 +124,7 @@ private static class TestLogstashMarker extends LogstashMarker { } @Override - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { // noop } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/MdcJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/MdcJsonProviderTest.java index b73365d6..2f991adc 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/MdcJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/MdcJsonProviderTest.java @@ -21,7 +21,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import java.io.IOException; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -32,18 +31,18 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class MdcJsonProviderTest { - private MdcJsonProvider provider = new MdcJsonProvider(); + private final MdcJsonProvider provider = new MdcJsonProvider(); @Mock private JsonGenerator generator; @@ -55,7 +54,7 @@ public class MdcJsonProviderTest { @BeforeEach public void setup() { - mdc = new LinkedHashMap(); + mdc = new LinkedHashMap<>(); mdc.put("name1", "value1"); mdc.put("name2", "value2"); mdc.put("name3", "value3"); @@ -63,37 +62,31 @@ public void setup() { } @Test - public void testUnwrapped() throws IOException { + public void testUnwrapped() { provider.writeTo(generator, event); - verify(generator).writeFieldName("name1"); - verify(generator).writeObject("value1"); - verify(generator).writeFieldName("name2"); - verify(generator).writeObject("value2"); - verify(generator).writeFieldName("name3"); - verify(generator).writeObject("value3"); + verify(generator).writePOJOProperty("name1", "value1"); + verify(generator).writePOJOProperty("name2", "value2"); + verify(generator).writePOJOProperty("name3", "value3"); } @Test - public void testWrapped() throws IOException { + public void testWrapped() { provider.setFieldName("mdc"); provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("mdc"); - inOrder.verify(generator).writeFieldName("name1"); - inOrder.verify(generator).writeObject("value1"); - inOrder.verify(generator).writeFieldName("name2"); - inOrder.verify(generator).writeObject("value2"); - inOrder.verify(generator).writeFieldName("name3"); - inOrder.verify(generator).writeObject("value3"); + inOrder.verify(generator).writeObjectPropertyStart("mdc"); + inOrder.verify(generator).writePOJOProperty("name1", "value1"); + inOrder.verify(generator).writePOJOProperty("name2", "value2"); + inOrder.verify(generator).writePOJOProperty("name3", "value3"); inOrder.verify(generator).writeEndObject(); } @Test - public void testWrappedUsingFieldNames() throws IOException { + public void testWrappedUsingFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setMdc("mdc"); @@ -102,60 +95,48 @@ public void testWrappedUsingFieldNames() throws IOException { provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart("mdc"); - inOrder.verify(generator).writeFieldName("name1"); - inOrder.verify(generator).writeObject("value1"); - inOrder.verify(generator).writeFieldName("name2"); - inOrder.verify(generator).writeObject("value2"); - inOrder.verify(generator).writeFieldName("name3"); - inOrder.verify(generator).writeObject("value3"); + inOrder.verify(generator).writeObjectPropertyStart("mdc"); + inOrder.verify(generator).writePOJOProperty("name1", "value1"); + inOrder.verify(generator).writePOJOProperty("name2", "value2"); + inOrder.verify(generator).writePOJOProperty("name3", "value3"); inOrder.verify(generator).writeEndObject(); } @Test - public void testInclude() throws IOException { + public void testInclude() { provider.setIncludeMdcKeyNames(Collections.singletonList("name1")); provider.writeTo(generator, event); - verify(generator).writeFieldName("name1"); - verify(generator).writeObject("value1"); - verify(generator, never()).writeFieldName("name2"); - verify(generator, never()).writeObject("value2"); - verify(generator, never()).writeFieldName("name3"); - verify(generator, never()).writeObject("value3"); + verify(generator).writePOJOProperty("name1", "value1"); + verify(generator, never()).writePOJOProperty("name2", "value2"); + verify(generator, never()).writePOJOProperty("name3", "value3"); } @Test - public void testExclude() throws IOException { + public void testExclude() { provider.setExcludeMdcKeyNames(Collections.singletonList("name1")); provider.writeTo(generator, event); - verify(generator, never()).writeFieldName("name1"); - verify(generator, never()).writeObject("value1"); - verify(generator).writeFieldName("name2"); - verify(generator).writeObject("value2"); - verify(generator).writeFieldName("name3"); - verify(generator).writeObject("value3"); + verify(generator, never()).writePOJOProperty("name1", "value1"); + verify(generator).writePOJOProperty("name2", "value2"); + verify(generator).writePOJOProperty("name3", "value3"); } @Test - public void testAlternateFieldName() throws IOException { + public void testAlternateFieldName() { provider.addMdcKeyFieldName("name1=alternateName1"); provider.writeTo(generator, event); - verify(generator).writeFieldName("alternateName1"); - verify(generator).writeObject("value1"); - verify(generator).writeFieldName("name2"); - verify(generator).writeObject("value2"); - verify(generator).writeFieldName("name3"); - verify(generator).writeObject("value3"); + verify(generator).writePOJOProperty("alternateName1", "value1"); + verify(generator).writePOJOProperty("name2", "value2"); + verify(generator).writePOJOProperty("name3", "value3"); } @Test - public void testMdcEntryWriters() throws IOException { + public void testMdcEntryWriters() { mdc = new LinkedHashMap<>(); mdc.put("long", "4711"); mdc.put("double", "2.71828"); @@ -172,18 +153,18 @@ public void testMdcEntryWriters() throws IOException { provider.writeTo(generator, event); - verify(generator).writeFieldName("long"); + verify(generator).writeName("long"); verify(generator).writeNumber(4711L); - verify(generator).writeFieldName("double"); + verify(generator).writeName("double"); verify(generator).writeNumber(2.71828); - verify(generator).writeFieldName("bool"); + verify(generator).writeName("bool"); verify(generator).writeBoolean(true); - verify(generator).writeFieldName("string_bool"); - verify(generator).writeObject("trueblue"); - verify(generator).writeFieldName("string_hex"); - verify(generator).writeObject("0xBAD"); - verify(generator).writeFieldName("empty"); - verify(generator).writeObject(""); + verify(generator).writeName("string_bool"); + verify(generator).writePOJO("trueblue"); + verify(generator).writeName("string_hex"); + verify(generator).writePOJO("0xBAD"); + verify(generator).writeName("empty"); + verify(generator).writePOJO(""); verifyNoMoreInteractions(generator); } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/MessageJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/MessageJsonProviderTest.java index 7ccea893..aaec26be 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/MessageJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/MessageJsonProviderTest.java @@ -25,16 +25,16 @@ import net.logstash.logback.fieldnames.LogstashFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class MessageJsonProviderTest { - private MessageJsonProvider provider = new MessageJsonProvider(); + private final MessageJsonProvider provider = new MessageJsonProvider(); @Mock private JsonGenerator generator; @@ -49,7 +49,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField(MessageJsonProvider.FIELD_MESSAGE, "message"); + verify(generator).writeStringProperty(MessageJsonProvider.FIELD_MESSAGE, "message"); } @Test @@ -60,11 +60,11 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "message"); + verify(generator).writeStringProperty("newFieldName", "message"); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setMessage("newFieldName"); @@ -74,11 +74,11 @@ public void testFieldNames() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "message"); + verify(generator).writeStringProperty("newFieldName", "message"); } @Test - public void testMessageSplitDisabledByDefault() throws Exception { + public void testMessageSplitDisabledByDefault() { assertThat(provider.getMessageSplitRegex()).isNull(); mockEventMessage("###"); @@ -88,7 +88,7 @@ public void testMessageSplitDisabledByDefault() throws Exception { } @Test - public void testMessageSplitDisabledForNullRegex() throws Exception { + public void testMessageSplitDisabledForNullRegex() { provider.setMessageSplitRegex(null); assertThat(provider.getMessageSplitRegex()).isNull(); @@ -99,7 +99,7 @@ public void testMessageSplitDisabledForNullRegex() throws Exception { } @Test - public void testMessageSplitDisabledForEmptyRegex() throws Exception { + public void testMessageSplitDisabledForEmptyRegex() { provider.setMessageSplitRegex(""); assertThat(provider.getMessageSplitRegex()).isNull(); @@ -110,7 +110,7 @@ public void testMessageSplitDisabledForEmptyRegex() throws Exception { } @Test - public void testMessageSplitWithSystemSeparator() throws IOException { + public void testMessageSplitWithSystemSeparator() { provider.setMessageSplitRegex("SYSTEM"); assertThat(provider.getMessageSplitRegex()).isEqualTo(System.lineSeparator()); @@ -121,7 +121,7 @@ public void testMessageSplitWithSystemSeparator() throws IOException { } @Test - public void testMessageSplitWithUnixSeparator() throws IOException { + public void testMessageSplitWithUnixSeparator() { provider.setMessageSplitRegex("UNIX"); assertThat(provider.getMessageSplitRegex()).isEqualTo("\n"); @@ -132,7 +132,7 @@ public void testMessageSplitWithUnixSeparator() throws IOException { } @Test - public void testMessageSplitWithWindowsSeparator() throws IOException { + public void testMessageSplitWithWindowsSeparator() { provider.setMessageSplitRegex("WINDOWS"); assertThat(provider.getMessageSplitRegex()).isEqualTo("\r\n"); @@ -143,7 +143,7 @@ public void testMessageSplitWithWindowsSeparator() throws IOException { } @Test - public void testMessageSplitWithCustomRegex() throws IOException { + public void testMessageSplitWithCustomRegex() { provider.setMessageSplitRegex("#+"); assertThat(provider.getMessageSplitRegex()).isEqualTo("#+"); @@ -155,9 +155,8 @@ public void testMessageSplitWithCustomRegex() throws IOException { @Test public void testMessageSplitWithInvalidRegex() { - assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> { - provider.setMessageSplitRegex("++"); - }); + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> + provider.setMessageSplitRegex("++")); } private void mockEventMessage(String lineSeparator) { @@ -165,13 +164,13 @@ private void mockEventMessage(String lineSeparator) { when(event.getFormattedMessage()).thenReturn(message); } - private void verifySingleLineMessageGenerated(String lineSeparator) throws IOException { + private void verifySingleLineMessageGenerated(String lineSeparator) { String message = buildMultiLineMessage(lineSeparator); - verify(generator).writeStringField(MessageJsonProvider.FIELD_MESSAGE, message); + verify(generator).writeStringProperty(MessageJsonProvider.FIELD_MESSAGE, message); } - private void verifyMultiLineMessageGenerated() throws IOException { - verify(generator).writeArrayFieldStart(MessageJsonProvider.FIELD_MESSAGE); + private void verifyMultiLineMessageGenerated() { + verify(generator).writeArrayPropertyStart(MessageJsonProvider.FIELD_MESSAGE); verify(generator).writeString("line1"); verify(generator).writeString("line2"); verify(generator).writeString("line3"); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProviderTest.java index eca2e931..14aac938 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/RawMessageJsonProviderTest.java @@ -21,16 +21,16 @@ import java.io.IOException; import ch.qos.logback.classic.spi.ILoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class RawMessageJsonProviderTest { - private RawMessageJsonProvider provider = new RawMessageJsonProvider(); + private final RawMessageJsonProvider provider = new RawMessageJsonProvider(); @Mock private JsonGenerator generator; @@ -45,7 +45,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField(RawMessageJsonProvider.FIELD_RAW_MESSAGE, "raw_message"); + verify(generator).writeStringProperty(RawMessageJsonProvider.FIELD_RAW_MESSAGE, "raw_message"); } @Test @@ -56,7 +56,7 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "raw_message"); + verify(generator).writeStringProperty("newFieldName", "raw_message"); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProviderTest.java index c66eb17d..9dbeed74 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/RootStackTraceElementJsonProviderTest.java @@ -18,24 +18,22 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.when; -import java.io.IOException; - import net.logstash.logback.fieldnames.ShortenedFieldNames; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.StackTraceElementProxy; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class RootStackTraceElementJsonProviderTest { - private RootStackTraceElementJsonProvider provider = new RootStackTraceElementJsonProvider(); + private final RootStackTraceElementJsonProvider provider = new RootStackTraceElementJsonProvider(); @Mock private JsonGenerator generator; @@ -49,10 +47,10 @@ public class RootStackTraceElementJsonProviderTest { @Mock private StackTraceElementProxy steProxy; - private StackTraceElement ste = new StackTraceElement("TestDeclaringClass", "testMethodName", "testFileName", 0); + private final StackTraceElement ste = new StackTraceElement("TestDeclaringClass", "testMethodName", "testFileName", 0); @Test - public void testStackTraceElementIsWritten() throws IOException { + public void testStackTraceElementIsWritten() { // GIVEN when(event.getThrowableProxy()).thenReturn(throwableProxy); StackTraceElementProxy[] steArray = new StackTraceElementProxy[]{steProxy}; @@ -64,14 +62,14 @@ public void testStackTraceElementIsWritten() throws IOException { // THEN InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart(RootStackTraceElementJsonProvider.FIELD_STACKTRACE_ELEMENT); - inOrder.verify(generator).writeStringField(RootStackTraceElementJsonProvider.FIELD_CLASS_NAME, "TestDeclaringClass"); - inOrder.verify(generator).writeStringField(RootStackTraceElementJsonProvider.FIELD_METHOD_NAME, "testMethodName"); + inOrder.verify(generator).writeObjectPropertyStart(RootStackTraceElementJsonProvider.FIELD_STACKTRACE_ELEMENT); + inOrder.verify(generator).writeStringProperty(RootStackTraceElementJsonProvider.FIELD_CLASS_NAME, "TestDeclaringClass"); + inOrder.verify(generator).writeStringProperty(RootStackTraceElementJsonProvider.FIELD_METHOD_NAME, "testMethodName"); inOrder.verify(generator).writeEndObject(); } @Test - public void testOverrideFieldNameWithShortNames() throws IOException { + public void testOverrideFieldNameWithShortNames() { // GIVEN when(event.getThrowableProxy()).thenReturn(throwableProxy); StackTraceElementProxy[] steArray = new StackTraceElementProxy[]{steProxy}; @@ -83,9 +81,9 @@ public void testOverrideFieldNameWithShortNames() throws IOException { // THEN InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeObjectFieldStart(RootStackTraceElementJsonProvider.FIELD_STACKTRACE_ELEMENT); - inOrder.verify(generator).writeStringField(ShortenedFieldNames.FIELD_CLASS, "TestDeclaringClass"); - inOrder.verify(generator).writeStringField(ShortenedFieldNames.FIELD_METHOD, "testMethodName"); + inOrder.verify(generator).writeObjectPropertyStart(RootStackTraceElementJsonProvider.FIELD_STACKTRACE_ELEMENT); + inOrder.verify(generator).writeStringProperty(ShortenedFieldNames.FIELD_CLASS, "TestDeclaringClass"); + inOrder.verify(generator).writeStringProperty(ShortenedFieldNames.FIELD_METHOD, "testMethodName"); inOrder.verify(generator).writeEndObject(); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/SequenceJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/SequenceJsonProviderTest.java index e3101dd4..9afa6c74 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/SequenceJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/SequenceJsonProviderTest.java @@ -31,16 +31,16 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.SequenceNumberGenerator; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class SequenceJsonProviderTest extends AbstractLogbackTest { - private SequenceJsonProvider provider = new SequenceJsonProvider(); + private final SequenceJsonProvider provider = new SequenceJsonProvider(); @Mock private JsonGenerator generator; @@ -51,7 +51,7 @@ public class SequenceJsonProviderTest extends AbstractLogbackTest { @Test public void testNoContext() { - assertThatThrownBy(() -> provider.start()).isInstanceOf(IllegalStateException.class); + assertThatThrownBy(provider::start).isInstanceOf(IllegalStateException.class); } @@ -69,24 +69,24 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeNumberField(SequenceJsonProvider.FIELD_SEQUENCE, 1L); + verify(generator).writeNumberProperty(SequenceJsonProvider.FIELD_SEQUENCE, 1L); } @Test - public void testCustomFieldName() throws IOException { + public void testCustomFieldName() { provider.setContext(context); provider.setFieldName("newFieldName"); provider.start(); provider.writeTo(generator, event); - verify(generator).writeNumberField("newFieldName", 1L); + verify(generator).writeNumberProperty("newFieldName", 1L); } @Test - public void testNoSequenceGeneratorInContext() throws IOException { + public void testNoSequenceGeneratorInContext() { context.setSequenceNumberGenerator(null); provider.setContext(context); provider.start(); @@ -98,17 +98,19 @@ public void testNoSequenceGeneratorInContext() throws IOException { // assert the local generator produces the expected output provider.writeTo(generator, event); - verify(generator).writeNumberField(SequenceJsonProvider.FIELD_SEQUENCE, 1L); - + verify(generator).writeName(SequenceJsonProvider.FIELD_SEQUENCE); + verify(generator).writeNumber(1L); + provider.writeTo(generator, event); - verify(generator).writeNumberField(SequenceJsonProvider.FIELD_SEQUENCE, 2L); - + verify(generator, times(2)).writeName(SequenceJsonProvider.FIELD_SEQUENCE); + verify(generator).writeNumber(2L); + verify(event, never()).getSequenceNumber(); } @Test - public void testSequenceGeneratorInContext() throws IOException { + public void testSequenceGeneratorInContext() { // Set a SequenceNumberGenerator to the context SequenceNumberGenerator seqGenerator = mock(SequenceNumberGenerator.class); context.setSequenceNumberGenerator(seqGenerator); @@ -124,7 +126,7 @@ public void testSequenceGeneratorInContext() throws IOException { // assert expected output provider.writeTo(generator, event); - verify(generator).writeNumberField(SequenceJsonProvider.FIELD_SEQUENCE, 123L); + verify(generator).writeNumberProperty(SequenceJsonProvider.FIELD_SEQUENCE, 123L); verify(event, times(1)).getSequenceNumber(); } @@ -149,7 +151,7 @@ public Long apply(ILoggingEvent t) { // assert expected output provider.writeTo(generator, event); - verify(generator).writeNumberField(SequenceJsonProvider.FIELD_SEQUENCE, 456L); + verify(generator).writeNumberProperty(SequenceJsonProvider.FIELD_SEQUENCE, 456L); verify(sequenceProvider).apply(event); verify(event, never()).getSequenceNumber(); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/StackHashJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/StackHashJsonProviderTest.java index 8f5ffa58..5baa9aa5 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/StackHashJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/StackHashJsonProviderTest.java @@ -16,7 +16,6 @@ package net.logstash.logback.composite.loggingevent; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -25,12 +24,12 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class StackHashJsonProviderTest { @@ -44,7 +43,7 @@ public class StackHashJsonProviderTest { @Mock private ThrowableProxy throwableProxy; - private static Pattern HEX_PATTERN = Pattern.compile("[0-9a-fA-F]{1,8}"); + private static final Pattern HEX_PATTERN = Pattern.compile("[0-9a-fA-F]{1,8}"); @Test public void testDefaultName() throws IOException { @@ -58,8 +57,9 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); // THEN ArgumentCaptor hashCaptor = ArgumentCaptor.forClass(String.class); - verify(generator).writeStringField(eq(StackHashJsonProvider.FIELD_NAME), hashCaptor.capture()); - + verify(generator).writeName(StackHashJsonProvider.FIELD_NAME); + verify(generator).writeString(hashCaptor.capture()); + assertThat(hashCaptor.getValue()).matches(HEX_PATTERN); } @@ -76,8 +76,9 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); // THEN ArgumentCaptor hashCaptor = ArgumentCaptor.forClass(String.class); - verify(generator).writeStringField(eq("newFieldName"), hashCaptor.capture()); - + verify(generator).writeName("newFieldName"); + verify(generator).writeString(hashCaptor.capture()); + assertThat(hashCaptor.getValue()).matches(HEX_PATTERN); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProviderTest.java index 64727d99..3814eead 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/StackTraceJsonProviderTest.java @@ -25,17 +25,17 @@ import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class StackTraceJsonProviderTest { - private StackTraceJsonProvider provider = new StackTraceJsonProvider(); + private final StackTraceJsonProvider provider = new StackTraceJsonProvider(); @Mock private JsonGenerator generator; @@ -62,7 +62,7 @@ public void testDefaultName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField(StackTraceJsonProvider.FIELD_STACK_TRACE, "stack"); + verify(generator).writeStringProperty(StackTraceJsonProvider.FIELD_STACK_TRACE, "stack"); } @Test @@ -73,11 +73,11 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "stack"); + verify(generator).writeStringProperty("newFieldName", "stack"); } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setStackTrace("newFieldName"); @@ -87,7 +87,7 @@ public void testFieldNames() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "stack"); + verify(generator).writeStringProperty("newFieldName", "stack"); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/TagsJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/TagsJsonProviderTest.java index caaea35c..ae587fd3 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/TagsJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/TagsJsonProviderTest.java @@ -18,14 +18,11 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.spy; -import java.io.IOException; - import net.logstash.logback.fieldnames.LogstashFieldNames; import net.logstash.logback.marker.LogstashMarker; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.LoggingEvent; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -35,44 +32,41 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.Marker; import org.slf4j.MarkerFactory; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class TagsJsonProviderTest { - private TagsJsonProvider provider = new TagsJsonProvider(); + private final TagsJsonProvider provider = new TagsJsonProvider(); @Mock private JsonGenerator generator; private ILoggingEvent event; - private Marker marker1; - private LogstashMarker marker2; - private Marker marker3; - private Marker marker4; - @BeforeEach public void setup() { - marker1 = createBasicMarker("marker1"); - marker2 = createLogstashMarker("marker2"); - marker3 = createBasicMarker("marker3"); + Marker marker1 = createBasicMarker("marker1"); + LogstashMarker marker2 = createLogstashMarker("marker2"); + Marker marker3 = createBasicMarker("marker3"); marker1.add(marker2); marker2.add(marker3); - - marker4 = createBasicMarker("marker4"); + + Marker marker4 = createBasicMarker("marker4"); event = createEvent(marker1, marker4); } @Test - public void testDefaultName() throws IOException { + public void testDefaultName() { provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeArrayFieldStart(TagsJsonProvider.FIELD_TAGS); + inOrder.verify(generator).writeName(TagsJsonProvider.FIELD_TAGS); + inOrder.verify(generator).writeStartArray(); inOrder.verify(generator).writeString("marker1"); inOrder.verify(generator).writeString("marker3"); inOrder.verify(generator).writeString("marker4"); @@ -82,14 +76,15 @@ public void testDefaultName() throws IOException { } @Test - public void testFieldName() throws IOException { + public void testFieldName() { provider.setFieldName("newFieldName"); provider.writeTo(generator, event); InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeArrayFieldStart("newFieldName"); + inOrder.verify(generator).writeName("newFieldName"); + inOrder.verify(generator).writeStartArray(); inOrder.verify(generator).writeString("marker1"); inOrder.verify(generator).writeString("marker3"); inOrder.verify(generator).writeString("marker4"); @@ -99,7 +94,7 @@ public void testFieldName() throws IOException { } @Test - public void testFieldNames() throws IOException { + public void testFieldNames() { LogstashFieldNames fieldNames = new LogstashFieldNames(); fieldNames.setTags("newFieldName"); provider.setFieldNames(fieldNames); @@ -108,7 +103,8 @@ public void testFieldNames() throws IOException { InOrder inOrder = inOrder(generator); - inOrder.verify(generator).writeArrayFieldStart("newFieldName"); + inOrder.verify(generator).writeName("newFieldName"); + inOrder.verify(generator).writeStartArray(); inOrder.verify(generator).writeString("marker1"); inOrder.verify(generator).writeString("marker3"); inOrder.verify(generator).writeString("marker4"); @@ -146,7 +142,7 @@ private static class TestLogstashMarker extends LogstashMarker { } @Override - public void writeTo(JsonGenerator generator) throws IOException { + public void writeTo(JsonGenerator generator) { // noop } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableClassNameJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableClassNameJsonProviderTest.java index 1e8c9f76..d624ea07 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableClassNameJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableClassNameJsonProviderTest.java @@ -15,25 +15,24 @@ */ package net.logstash.logback.composite.loggingevent; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import java.io.IOException; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class ThrowableClassNameJsonProviderTest { - private ThrowableClassNameJsonProvider provider = new ThrowableClassNameJsonProvider(); + private final ThrowableClassNameJsonProvider provider = new ThrowableClassNameJsonProvider(); @Mock private JsonGenerator generator; @@ -50,35 +49,35 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", throwable.getClass().getSimpleName()); + verify(generator).writeStringProperty("newFieldName", throwable.getClass().getSimpleName()); } @Test - public void testFieldNameWithNestedException() throws IOException { + public void testFieldNameWithNestedException() { IOException throwable = new IOException(new IllegalArgumentException()); when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(throwable)); provider.writeTo(generator, event); verify(generator) - .writeStringField(ThrowableClassNameJsonProvider.FIELD_NAME, throwable.getClass().getSimpleName()); + .writeStringProperty(ThrowableClassNameJsonProvider.FIELD_NAME, throwable.getClass().getSimpleName()); } @Test - public void testNoThrowable() throws IOException { + public void testNoThrowable() { provider.writeTo(generator, event); - verify(generator, times(0)).writeStringField(anyString(), anyString()); + verifyNoInteractions(generator); } @Test - public void testUseFullClassName() throws IOException { + public void testUseFullClassName() { provider.setUseSimpleClassName(false); IOException throwable = new IOException(); when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(throwable)); provider.writeTo(generator, event); - verify(generator).writeStringField(ThrowableClassNameJsonProvider.FIELD_NAME, throwable.getClass().getName()); + verify(generator).writeStringProperty(ThrowableClassNameJsonProvider.FIELD_NAME, throwable.getClass().getName()); } } diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableMessageJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableMessageJsonProviderTest.java index bce05fe0..97348581 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableMessageJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableMessageJsonProviderTest.java @@ -24,16 +24,16 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class ThrowableMessageJsonProviderTest { - private ThrowableMessageJsonProvider provider = new ThrowableMessageJsonProvider(); + private final ThrowableMessageJsonProvider provider = new ThrowableMessageJsonProvider(); @Mock private JsonGenerator generator; @@ -50,11 +50,11 @@ public void testFieldName() throws IOException { provider.writeTo(generator, event); - verify(generator).writeStringField("newFieldName", "kaput"); + verify(generator).writeStringProperty("newFieldName", "kaput"); } @Test - public void testNoThrowable() throws IOException { + public void testNoThrowable() { when(event.getThrowableProxy()).thenReturn(null); provider.writeTo(generator, event); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseClassNameJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseClassNameJsonProviderTest.java index d0ef66b0..b2c6f03a 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseClassNameJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseClassNameJsonProviderTest.java @@ -15,10 +15,8 @@ */ package net.logstash.logback.composite.loggingevent; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -28,16 +26,16 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class ThrowableRootCauseClassNameJsonProviderTest { - private AbstractThrowableClassNameJsonProvider provider = new ThrowableRootCauseClassNameJsonProvider(); + private final AbstractThrowableClassNameJsonProvider provider = new ThrowableRootCauseClassNameJsonProvider(); @Mock private JsonGenerator generator; @@ -46,45 +44,45 @@ public class ThrowableRootCauseClassNameJsonProviderTest { private ILoggingEvent event; @Test - public void testFieldName() throws IOException { + public void testFieldName() { check(ThrowableRootCauseClassNameJsonProvider.FIELD_NAME); } @Test - public void testCustomFieldName() throws IOException { + public void testCustomFieldName() { provider.setFieldName("newFieldName"); check("newFieldName"); } @Test - public void testFieldNameWithoutNestedException() throws IOException { + public void testFieldNameWithoutNestedException() { IOException throwable = new IOException(); check(ThrowableRootCauseClassNameJsonProvider.FIELD_NAME, throwable, throwable.getClass().getSimpleName()); } - private void check(String fieldName) throws IOException { + private void check(String fieldName) { check(fieldName, new IOException(new IllegalArgumentException(new IllegalStateException())), IllegalStateException.class.getSimpleName()); } - private void check(String fieldName, Throwable throwable, String expectedClassName) throws IOException { + private void check(String fieldName, Throwable throwable, String expectedClassName) { when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(throwable)); provider.writeTo(generator, event); - verify(generator).writeStringField(fieldName, expectedClassName); + verify(generator).writeStringProperty(fieldName, expectedClassName); } @Test - public void testNoThrowable() throws IOException { + public void testNoThrowable() { provider.writeTo(generator, event); - verify(generator, times(0)).writeStringField(anyString(), anyString()); + verifyNoInteractions(generator); } @Test - public void testCircularReference() throws IOException { + public void testCircularReference() { IThrowableProxy baz = mock(IThrowableProxy.class, "baz"); IThrowableProxy bar = mock(IThrowableProxy.class, "bar"); IThrowableProxy foo = mock(IThrowableProxy.class, "foo"); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseMessageJsonProviderTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseMessageJsonProviderTest.java index 527f5793..87a432c4 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseMessageJsonProviderTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/ThrowableRootCauseMessageJsonProviderTest.java @@ -16,28 +16,25 @@ package net.logstash.logback.composite.loggingevent; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import java.io.IOException; - import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class ThrowableRootCauseMessageJsonProviderTest { - private AbstractThrowableMessageJsonProvider provider = new ThrowableRootCauseMessageJsonProvider(); + private final AbstractThrowableMessageJsonProvider provider = new ThrowableRootCauseMessageJsonProvider(); @Mock private JsonGenerator generator; @@ -46,7 +43,7 @@ public class ThrowableRootCauseMessageJsonProviderTest { private ILoggingEvent event; @Test - public void testNoThrowable() throws IOException { + public void testNoThrowable() { when(event.getThrowableProxy()).thenReturn(null); provider.writeTo(generator, event); @@ -56,36 +53,39 @@ public void testNoThrowable() throws IOException { } @Test - public void testDefaultFieldName() throws IOException { + public void testDefaultFieldName() { when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(new Exception("kaput"))); provider.writeTo(generator, event); - verify(generator).writeStringField("throwable_root_cause_message", "kaput"); + verify(generator).writeName("throwable_root_cause_message"); + verify(generator).writeString("kaput"); } @Test - public void testCustomFieldName() throws IOException { + public void testCustomFieldName() { when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(new Exception("kaput"))); provider.setFieldName("some_custom_field"); provider.writeTo(generator, event); - verify(generator).writeStringField("some_custom_field", "kaput"); + verify(generator).writeName("some_custom_field"); + verify(generator).writeString("kaput"); } @Test - public void testNestedException() throws IOException { + public void testNestedException() { Exception foo = new Exception("foo", new Exception("bar", new Exception("baz"))); when(event.getThrowableProxy()).thenReturn(new ThrowableProxy(foo)); provider.writeTo(generator, event); - verify(generator).writeStringField(anyString(), eq("baz")); + verify(generator).writeName(anyString()); + verify(generator).writeString("baz"); } @Test - public void testCircularReference() throws IOException { + public void testCircularReference() { IThrowableProxy foo = mock(IThrowableProxy.class, "foo"); IThrowableProxy bar = mock(IThrowableProxy.class, "bar"); IThrowableProxy baz = mock(IThrowableProxy.class, "baz"); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriterTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriterTest.java index 890fc710..1472fec7 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriterTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/BooleanMdcEntryWriterTest.java @@ -20,14 +20,12 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) class BooleanMdcEntryWriterTest { @@ -44,11 +42,11 @@ class BooleanMdcEntryWriterTest { "False", "TRUE" }) - void valid(String value) throws IOException { + void valid(String value) { boolean result = mdcEntryWriter.writeMdcEntry(generator, "otherName", "name", value); assertThat(result).isTrue(); - verify(generator).writeFieldName("otherName"); + verify(generator).writeName("otherName"); verify(generator).writeBoolean(Boolean.parseBoolean(value)); verifyNoMoreInteractions(generator); } @@ -61,7 +59,7 @@ void valid(String value) throws IOException { "trueblue", "" }) - void invalid(String value) throws IOException { + void invalid(String value) { boolean result = mdcEntryWriter.writeMdcEntry(generator, "otherName", "name", value); assertThat(result).isFalse(); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriterTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriterTest.java index a9f02925..cef4f763 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriterTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/DoubleMdcEntryWriterTest.java @@ -20,14 +20,12 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) class DoubleMdcEntryWriterTest { @@ -49,11 +47,11 @@ class DoubleMdcEntryWriterTest { "2.2250738585072014E-308", "1.7976931348623157E+308" }) - void valid(String value) throws IOException { + void valid(String value) { boolean result = mdcEntryWriter.writeMdcEntry(generator, "otherName", "name", value); assertThat(result).isTrue(); - verify(generator).writeFieldName("otherName"); + verify(generator).writeName("otherName"); verify(generator).writeNumber(Double.parseDouble(value)); verifyNoMoreInteractions(generator); } @@ -68,7 +66,7 @@ void valid(String value) throws IOException { "-Infinity", "" }) - void invalid(String value) throws IOException { + void invalid(String value) { boolean result = mdcEntryWriter.writeMdcEntry(generator, "otherName", "name", value); assertThat(result).isFalse(); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriterTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriterTest.java index 5074e7fe..312b4b95 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriterTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/LongMdcEntryWriterTest.java @@ -20,14 +20,12 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) class LongMdcEntryWriterTest { @@ -46,11 +44,11 @@ class LongMdcEntryWriterTest { "-9223372036854775808", "9223372036854775807" }) - void valid(String value) throws IOException { + void valid(String value) { boolean result = mdcEntryWriter.writeMdcEntry(generator, "otherName", "name", value); assertThat(result).isTrue(); - verify(generator).writeFieldName("otherName"); + verify(generator).writeName("otherName"); verify(generator).writeNumber(Long.parseLong(value)); verifyNoMoreInteractions(generator); } @@ -67,7 +65,7 @@ void valid(String value) throws IOException { "-", "" }) - void invalid(String value) throws IOException { + void invalid(String value) { boolean result = mdcEntryWriter.writeMdcEntry(generator, "otherName", "name", value); assertThat(result).isFalse(); diff --git a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriterTest.java b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriterTest.java index 28fdbe04..0a97a8e4 100644 --- a/src/test/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriterTest.java +++ b/src/test/java/net/logstash/logback/composite/loggingevent/mdc/RegexFilteringMdcEntryWriterTest.java @@ -22,15 +22,13 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) class RegexFilteringMdcEntryWriterTest { @@ -43,7 +41,7 @@ class RegexFilteringMdcEntryWriterTest { private MdcEntryWriter mockedMdcEntryWriter; @Test - void noIncludeAndNoExcludePattern() throws IOException { + void noIncludeAndNoExcludePattern() { mockMdcEntryWriter(); boolean result = mdcEntryWriter.writeMdcEntry(generator, "field", "key", "value"); @@ -54,7 +52,7 @@ void noIncludeAndNoExcludePattern() throws IOException { } @Test - void noMdcEntryWriter() throws IOException { + void noMdcEntryWriter() { boolean result = mdcEntryWriter.writeMdcEntry(generator, "field", "key", "value"); assertThat(result).isFalse(); @@ -68,7 +66,7 @@ void noMdcEntryWriter() throws IOException { "exclude,excl.*,false", "other,excl.*,false" }) - void includeAndExcludePattern(String mdcKey, String excludePattern, boolean entryWritten) throws IOException { + void includeAndExcludePattern(String mdcKey, String excludePattern, boolean entryWritten) { if (entryWritten) { mockMdcEntryWriter(); } @@ -84,7 +82,7 @@ void includeAndExcludePattern(String mdcKey, String excludePattern, boolean entr verifyNoMoreInteractions(mockedMdcEntryWriter); } - private void mockMdcEntryWriter() throws IOException { + private void mockMdcEntryWriter() { when(mockedMdcEntryWriter.writeMdcEntry(eq(generator), anyString(), anyString(), anyString())).thenReturn(true); mdcEntryWriter.addMdcEntryWriter(mockedMdcEntryWriter); } diff --git a/src/test/java/net/logstash/logback/decorate/cbor/CborJsonFactoryDecoratorTest.java b/src/test/java/net/logstash/logback/dataformat/cbor/CborDataFormatFactoryTest.java similarity index 90% rename from src/test/java/net/logstash/logback/decorate/cbor/CborJsonFactoryDecoratorTest.java rename to src/test/java/net/logstash/logback/dataformat/cbor/CborDataFormatFactoryTest.java index 9e015f11..38a96c00 100644 --- a/src/test/java/net/logstash/logback/decorate/cbor/CborJsonFactoryDecoratorTest.java +++ b/src/test/java/net/logstash/logback/dataformat/cbor/CborDataFormatFactoryTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.logstash.logback.decorate.cbor; +package net.logstash.logback.dataformat.cbor; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @@ -24,6 +24,7 @@ import net.logstash.logback.composite.loggingevent.LoggingEventCompositeJsonFormatter; import net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders; import net.logstash.logback.composite.loggingevent.MessageJsonProvider; +import net.logstash.logback.dataformat.DataFormatFactory; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.ContextAware; @@ -33,7 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class CborJsonFactoryDecoratorTest { +class CborDataFormatFactoryTest { @Mock private ContextAware contextAware; @@ -43,14 +44,12 @@ class CborJsonFactoryDecoratorTest { @Test void test() throws IOException { - CborJsonFactoryDecorator decorator = new CborJsonFactoryDecorator(); - LoggingEventJsonProviders providers = new LoggingEventJsonProviders(); providers.addMessage(new MessageJsonProvider()); LoggingEventCompositeJsonFormatter formatter = new LoggingEventCompositeJsonFormatter(contextAware); formatter.setProviders(providers); - formatter.setJsonFactoryDecorator(decorator); + formatter.setDataFormat(DataFormatFactory.CBOR); formatter.start(); when(event.getFormattedMessage()).thenReturn("a message"); diff --git a/src/test/java/net/logstash/logback/decorate/smile/SmileJsonFactoryDecoratorTest.java b/src/test/java/net/logstash/logback/dataformat/smile/SmileDataFormatFactoryTest.java similarity index 90% rename from src/test/java/net/logstash/logback/decorate/smile/SmileJsonFactoryDecoratorTest.java rename to src/test/java/net/logstash/logback/dataformat/smile/SmileDataFormatFactoryTest.java index 07bdcae1..ab7514e2 100644 --- a/src/test/java/net/logstash/logback/decorate/smile/SmileJsonFactoryDecoratorTest.java +++ b/src/test/java/net/logstash/logback/dataformat/smile/SmileDataFormatFactoryTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.logstash.logback.decorate.smile; +package net.logstash.logback.dataformat.smile; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @@ -24,6 +24,7 @@ import net.logstash.logback.composite.loggingevent.LoggingEventCompositeJsonFormatter; import net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders; import net.logstash.logback.composite.loggingevent.MessageJsonProvider; +import net.logstash.logback.dataformat.DataFormatFactory; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.ContextAware; @@ -33,7 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class SmileJsonFactoryDecoratorTest { +class SmileDataFormatFactoryTest { @Mock private ContextAware contextAware; @@ -43,14 +44,12 @@ class SmileJsonFactoryDecoratorTest { @Test void test() throws IOException { - SmileJsonFactoryDecorator decorator = new SmileJsonFactoryDecorator(); - LoggingEventJsonProviders providers = new LoggingEventJsonProviders(); providers.addMessage(new MessageJsonProvider()); LoggingEventCompositeJsonFormatter formatter = new LoggingEventCompositeJsonFormatter(contextAware); formatter.setProviders(providers); - formatter.setJsonFactoryDecorator(decorator); + formatter.setDataFormat(DataFormatFactory.SMILE); formatter.start(); when(event.getFormattedMessage()).thenReturn("a message"); diff --git a/src/test/java/net/logstash/logback/decorate/yaml/YamlJsonFactoryDecoratorTest.java b/src/test/java/net/logstash/logback/dataformat/yaml/YamlDataFormatFactoryTest.java similarity index 85% rename from src/test/java/net/logstash/logback/decorate/yaml/YamlJsonFactoryDecoratorTest.java rename to src/test/java/net/logstash/logback/dataformat/yaml/YamlDataFormatFactoryTest.java index a44f41f8..591483c5 100644 --- a/src/test/java/net/logstash/logback/decorate/yaml/YamlJsonFactoryDecoratorTest.java +++ b/src/test/java/net/logstash/logback/dataformat/yaml/YamlDataFormatFactoryTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.logstash.logback.decorate.yaml; +package net.logstash.logback.dataformat.yaml; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; @@ -25,6 +25,7 @@ import net.logstash.logback.composite.loggingevent.LoggingEventCompositeJsonFormatter; import net.logstash.logback.composite.loggingevent.LoggingEventJsonProviders; import net.logstash.logback.composite.loggingevent.MessageJsonProvider; +import net.logstash.logback.dataformat.DataFormatFactory; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.spi.ContextAware; @@ -34,7 +35,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class YamlJsonFactoryDecoratorTest { +class YamlDataFormatFactoryTest { @Mock private ContextAware contextAware; @@ -44,14 +45,12 @@ class YamlJsonFactoryDecoratorTest { @Test void test() throws IOException { - YamlJsonFactoryDecorator decorator = new YamlJsonFactoryDecorator(); - LoggingEventJsonProviders providers = new LoggingEventJsonProviders(); providers.addMessage(new MessageJsonProvider()); LoggingEventCompositeJsonFormatter formatter = new LoggingEventCompositeJsonFormatter(contextAware); formatter.setProviders(providers); - formatter.setJsonFactoryDecorator(decorator); + formatter.setDataFormat(DataFormatFactory.YAML); formatter.start(); when(event.getFormattedMessage()).thenReturn("a message"); @@ -59,7 +58,7 @@ void test() throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); formatter.writeEvent(event, baos); - assertThat(new String(baos.toByteArray(), StandardCharsets.UTF_8)).isEqualTo("---\nmessage: \"a message\""); + assertThat(baos.toString(StandardCharsets.UTF_8)).isEqualTo("---\nmessage: \"a message\""); } } diff --git a/src/test/java/net/logstash/logback/decorate/CharacterEscapesJsonFactoryDecoratorTest.java b/src/test/java/net/logstash/logback/decorate/CharacterEscapesJsonFactoryDecoratorTest.java deleted file mode 100644 index ba5606b6..00000000 --- a/src/test/java/net/logstash/logback/decorate/CharacterEscapesJsonFactoryDecoratorTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.StringWriter; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import org.junit.jupiter.api.Test; - -public class CharacterEscapesJsonFactoryDecoratorTest { - - @Test - public void basicEscape() throws Exception { - CharacterEscapesJsonFactoryDecorator decorator = new CharacterEscapesJsonFactoryDecorator(); - decorator.addEscape(new CharacterEscapesJsonFactoryDecorator.Escape("\n", "_")); - decorator.addEscape(new CharacterEscapesJsonFactoryDecorator.Escape(" ", "===")); - decorator.addEscape(new CharacterEscapesJsonFactoryDecorator.Escape("y", "!")); - decorator.addEscape(new CharacterEscapesJsonFactoryDecorator.Escape("ё", "?")); - - StringWriter writer = new StringWriter(); - JsonFactory factory = decorator.decorate(new MappingJsonFactory()); - JsonGenerator generator = factory.createGenerator(writer); - - generator.writeStartObject(); - generator.writeStringField("message", "My message\nМоё сообщение"); - generator.writeEndObject(); - generator.flush(); - - assertThat(writer).hasToString("{\"message\":\"M!===message_Мо?===сообщение\"}"); - } - - @Test - public void noEscapeSequence() throws Exception { - CharacterEscapesJsonFactoryDecorator.Escape noEscapeSequence = new CharacterEscapesJsonFactoryDecorator.Escape(); - noEscapeSequence.setTarget("z"); - - CharacterEscapesJsonFactoryDecorator decorator = new CharacterEscapesJsonFactoryDecorator(); - decorator.addEscape(noEscapeSequence); - decorator.addEscape(new CharacterEscapesJsonFactoryDecorator.Escape(10, "===")); - - StringWriter writer = new StringWriter(); - JsonFactory factory = decorator.decorate(new MappingJsonFactory()); - JsonGenerator generator = factory.createGenerator(writer); - - generator.writeStartObject(); - generator.writeStringField("message", ".z.\n.y."); - generator.writeEndObject(); - generator.flush(); - - assertThat(writer).hasToString("{\"message\":\"..===.y.\"}"); - } - - @Test - public void noStandard() throws Exception { - CharacterEscapesJsonFactoryDecorator decorator = new CharacterEscapesJsonFactoryDecorator(); - decorator.setIncludeStandardAsciiEscapesForJSON(false); - - StringWriter writer = new StringWriter(); - JsonFactory factory = decorator.decorate(new MappingJsonFactory()); - JsonGenerator generator = factory.createGenerator(writer); - - generator.writeStartObject(); - generator.writeStringField("message", "foo\nbar"); - generator.writeEndObject(); - generator.flush(); - - assertThat(writer).hasToString("{\"message\":\"foo\nbar\"}"); - } - -} diff --git a/src/test/java/net/logstash/logback/decorate/FeatureJsonFactoryDecoratorTest.java b/src/test/java/net/logstash/logback/decorate/FeatureJsonFactoryDecoratorTest.java deleted file mode 100644 index a5f17ef9..00000000 --- a/src/test/java/net/logstash/logback/decorate/FeatureJsonFactoryDecoratorTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.core.JsonFactory; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class FeatureJsonFactoryDecoratorTest { - - @Mock - private JsonFactory jsonFactory; - - @Test - public void test() { - FeatureJsonFactoryDecorator decorator = new FeatureJsonFactoryDecorator(); - decorator.addDisable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES.name()); - decorator.addEnable(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW.name()); - - when(jsonFactory.enable(any(JsonFactory.Feature.class))).thenReturn(jsonFactory); - when(jsonFactory.disable(any(JsonFactory.Feature.class))).thenReturn(jsonFactory); - - JsonFactory decoratedFactory = decorator.decorate(jsonFactory); - - verify(jsonFactory).disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES); - verify(jsonFactory).enable(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW); - - assertThat(decoratedFactory).isSameAs(jsonFactory); - } -} diff --git a/src/test/java/net/logstash/logback/decorate/PrettyPrintingDecoratorTest.java b/src/test/java/net/logstash/logback/decorate/PrettyPrintingDecoratorTest.java new file mode 100644 index 00000000..d88135c4 --- /dev/null +++ b/src/test/java/net/logstash/logback/decorate/PrettyPrintingDecoratorTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.StringWriter; +import java.util.Collections; + +import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.json.JsonMapper; + + +class PrettyPrintingDecoratorTest { + + @Test + void defaultOptions() { + PrettyPrintingDecorator decorator = new PrettyPrintingDecorator<>(); + + StringWriter writer = new StringWriter(); + JsonGenerator generator = decorator.decorate(JsonMapper.builder()).build().createGenerator(writer); + + generator.writePOJO(Collections.singletonMap("key1", "value1")); + generator.writePOJO(Collections.singletonMap("key2", "value2")); + + generator.flush(); + writer.flush(); + assertThat(writer.toString()).isEqualTo("{\n \"key1\" : \"value1\"\n}{\n \"key2\" : \"value2\"\n}"); + } + + @Test + void customRootSeparator() { + PrettyPrintingDecorator decorator = new PrettyPrintingDecorator<>(); + decorator.setRootSeparator(" "); + + StringWriter writer = new StringWriter(); + JsonGenerator generator = decorator.decorate(JsonMapper.builder()).build().createGenerator(writer); + + generator.writePOJO(Collections.singletonMap("key1", "value1")); + generator.writePOJO(Collections.singletonMap("key2", "value2")); + + generator.flush(); + writer.flush(); + assertThat(writer.toString()).isEqualTo("{\n \"key1\" : \"value1\"\n} {\n \"key2\" : \"value2\"\n}"); + } + + @Test + void customRootSeparatorWithSpace() { + PrettyPrintingDecorator decorator = new PrettyPrintingDecorator<>(); + decorator.setRootSeparator("[SPACE]"); + + StringWriter writer = new StringWriter(); + JsonGenerator generator = decorator.decorate(JsonMapper.builder()).build().createGenerator(writer); + + generator.writePOJO(Collections.singletonMap("key1", "value1")); + generator.writePOJO(Collections.singletonMap("key2", "value2")); + + generator.flush(); + writer.flush(); + assertThat(writer.toString()).isEqualTo("{\n \"key1\" : \"value1\"\n} {\n \"key2\" : \"value2\"\n}"); + } + + @Test + void noSpacesInObjectEntries() { + PrettyPrintingDecorator decorator = new PrettyPrintingDecorator<>(); + decorator.setSpacesInObjectEntries(false); + + StringWriter writer = new StringWriter(); + JsonGenerator generator = decorator.decorate(JsonMapper.builder()).build().createGenerator(writer); + + generator.writePOJO(Collections.singletonMap("key1", "value1")); + generator.writePOJO(Collections.singletonMap("key2", "value2")); + + generator.flush(); + writer.flush(); + assertThat(writer.toString()).isEqualTo("{\n \"key1\":\"value1\"\n}{\n \"key2\":\"value2\"\n}"); + } +} diff --git a/src/test/java/net/logstash/logback/decorate/PrettyPrintingJsonGeneratorDecoratorTest.java b/src/test/java/net/logstash/logback/decorate/PrettyPrintingJsonGeneratorDecoratorTest.java deleted file mode 100644 index c346f5a1..00000000 --- a/src/test/java/net/logstash/logback/decorate/PrettyPrintingJsonGeneratorDecoratorTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2013-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.logstash.logback.decorate; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.Collections; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - - -class PrettyPrintingJsonGeneratorDecoratorTest { - - @Test - void defaultOptions() throws IOException { - PrettyPrintingJsonGeneratorDecorator decorator = new PrettyPrintingJsonGeneratorDecorator(); - - StringWriter writer = new StringWriter(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonGenerator generator = decorator.decorate(objectMapper.createGenerator(writer)); - - generator.writeObject(Collections.singletonMap("key1", "value1")); - generator.writeObject(Collections.singletonMap("key2", "value2")); - - generator.flush(); - writer.flush(); - assertThat(writer.toString()).isEqualTo("{\n \"key1\" : \"value1\"\n}{\n \"key2\" : \"value2\"\n}"); - } - - @Test - void customRootSeparator() throws IOException { - PrettyPrintingJsonGeneratorDecorator decorator = new PrettyPrintingJsonGeneratorDecorator(); - decorator.setRootSeparator(" "); - - StringWriter writer = new StringWriter(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonGenerator generator = decorator.decorate(objectMapper.createGenerator(writer)); - - generator.writeObject(Collections.singletonMap("key1", "value1")); - generator.writeObject(Collections.singletonMap("key2", "value2")); - - generator.flush(); - writer.flush(); - assertThat(writer.toString()).isEqualTo("{\n \"key1\" : \"value1\"\n} {\n \"key2\" : \"value2\"\n}"); - } - - @Test - void customRootSeparatorWithSpace() throws IOException { - PrettyPrintingJsonGeneratorDecorator decorator = new PrettyPrintingJsonGeneratorDecorator(); - decorator.setRootSeparator("[SPACE]"); - - StringWriter writer = new StringWriter(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonGenerator generator = decorator.decorate(objectMapper.createGenerator(writer)); - - generator.writeObject(Collections.singletonMap("key1", "value1")); - generator.writeObject(Collections.singletonMap("key2", "value2")); - - generator.flush(); - writer.flush(); - assertThat(writer.toString()).isEqualTo("{\n \"key1\" : \"value1\"\n} {\n \"key2\" : \"value2\"\n}"); - } - - @Test - void noSpacesInObjectEntries() throws IOException { - PrettyPrintingJsonGeneratorDecorator decorator = new PrettyPrintingJsonGeneratorDecorator(); - decorator.setSpacesInObjectEntries(false); - - StringWriter writer = new StringWriter(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonGenerator generator = decorator.decorate(objectMapper.createGenerator(writer)); - - generator.writeObject(Collections.singletonMap("key1", "value1")); - generator.writeObject(Collections.singletonMap("key2", "value2")); - - generator.flush(); - writer.flush(); - assertThat(writer.toString()).isEqualTo("{\n \"key1\":\"value1\"\n}{\n \"key2\":\"value2\"\n}"); - } -} diff --git a/src/test/java/net/logstash/logback/decorate/TokenStreamFactoryFeatureDecoratorTest.java b/src/test/java/net/logstash/logback/decorate/TokenStreamFactoryFeatureDecoratorTest.java new file mode 100644 index 00000000..e2a4b33f --- /dev/null +++ b/src/test/java/net/logstash/logback/decorate/TokenStreamFactoryFeatureDecoratorTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import tools.jackson.core.TokenStreamFactory; +import tools.jackson.core.json.JsonFactory; +import tools.jackson.core.json.JsonFactoryBuilder; + +public class TokenStreamFactoryFeatureDecoratorTest { + + @Test + public void test() { + TokenStreamFactoryFeatureDecorator decorator = new TokenStreamFactoryFeatureDecorator<>(); + decorator.addDisable(TokenStreamFactory.Feature.CANONICALIZE_PROPERTY_NAMES.name()); + decorator.addEnable(TokenStreamFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW.name()); + + + JsonFactoryBuilder builder = JsonFactory.builder() + .enable(TokenStreamFactory.Feature.CANONICALIZE_PROPERTY_NAMES) + .disable(TokenStreamFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW); + + JsonFactory jsonFactory = decorator.decorate(builder).build(); + + assertThat(jsonFactory.isEnabled(TokenStreamFactory.Feature.CANONICALIZE_PROPERTY_NAMES)).isFalse(); + assertThat(jsonFactory.isEnabled(TokenStreamFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW)).isTrue(); + } +} diff --git a/src/test/java/net/logstash/logback/decorate/json/CharacterEscapesDecoratorTest.java b/src/test/java/net/logstash/logback/decorate/json/CharacterEscapesDecoratorTest.java new file mode 100644 index 00000000..549104c6 --- /dev/null +++ b/src/test/java/net/logstash/logback/decorate/json/CharacterEscapesDecoratorTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.logstash.logback.decorate.json; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.StringWriter; + +import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonFactory; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; + +public class CharacterEscapesDecoratorTest { + + @Test + public void basicEscape() { + CharacterEscapesDecorator decorator = new CharacterEscapesDecorator(); + decorator.addEscape(new CharacterEscapesDecorator.Escape("\n", "_")); + decorator.addEscape(new CharacterEscapesDecorator.Escape(" ", "===")); + decorator.addEscape(new CharacterEscapesDecorator.Escape("y", "!")); + decorator.addEscape(new CharacterEscapesDecorator.Escape("ё", "?")); + + StringWriter writer = new StringWriter(); + ObjectMapper objectMapper = JsonMapper.builder(decorator.decorate(JsonFactory.builder()).build()).build(); + JsonGenerator generator = objectMapper.createGenerator(writer); + + generator.writeStartObject(); + generator.writeStringProperty("message", "My message\nМоё сообщение"); + generator.writeEndObject(); + generator.flush(); + + assertThat(writer.toString()).isEqualTo("{\"message\":\"M!===message_Мо?===сообщение\"}"); + } + + @Test + public void noEscapeSequence() { + CharacterEscapesDecorator.Escape noEscapeSequence = new CharacterEscapesDecorator.Escape(); + noEscapeSequence.setTarget("z"); + + CharacterEscapesDecorator decorator = new CharacterEscapesDecorator(); + decorator.addEscape(noEscapeSequence); + decorator.addEscape(new CharacterEscapesDecorator.Escape(10, "===")); + + StringWriter writer = new StringWriter(); + ObjectMapper objectMapper = JsonMapper.builder(decorator.decorate(JsonFactory.builder()).build()).build(); + JsonGenerator generator = objectMapper.createGenerator(writer); + + generator.writeStartObject(); + generator.writeStringProperty("message", ".z.\n.y."); + generator.writeEndObject(); + generator.flush(); + + assertThat(writer.toString()).isEqualTo("{\"message\":\"..===.y.\"}"); + } + + @Test + public void noStandard() { + CharacterEscapesDecorator decorator = new CharacterEscapesDecorator(); + decorator.setIncludeStandardAsciiEscapesForJSON(false); + + StringWriter writer = new StringWriter(); + ObjectMapper objectMapper = JsonMapper.builder(decorator.decorate(JsonFactory.builder()).build()).build(); + JsonGenerator generator = objectMapper.createGenerator(writer); + + generator.writeStartObject(); + generator.writeStringProperty("message", "foo\nbar"); + generator.writeEndObject(); + generator.flush(); + + assertThat(writer.toString()).isEqualTo("{\"message\":\"foo\nbar\"}"); + } + +} diff --git a/src/test/java/net/logstash/logback/encoder/CompositeJsonEncoderTest.java b/src/test/java/net/logstash/logback/encoder/CompositeJsonEncoderTest.java index 923347af..149681c0 100644 --- a/src/test/java/net/logstash/logback/encoder/CompositeJsonEncoderTest.java +++ b/src/test/java/net/logstash/logback/encoder/CompositeJsonEncoderTest.java @@ -42,13 +42,14 @@ import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import ch.qos.logback.core.status.OnConsoleStatusListener; import ch.qos.logback.core.status.StatusManager; -import com.fasterxml.jackson.core.JsonEncoding; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonEncoding; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.exc.JacksonIOException; @SuppressWarnings("unchecked") @ExtendWith(MockitoExtension.class) @@ -58,9 +59,9 @@ public class CompositeJsonEncoderTest { private AbstractCompositeJsonFormatter formatter; - private LoggerContext context = new LoggerContext(); + private final LoggerContext context = new LoggerContext(); - private StatusManager statusManager = new BasicStatusManager(); + private final StatusManager statusManager = new BasicStatusManager(); @Mock private ILoggingEvent event; @@ -186,7 +187,7 @@ public void streamingEncode() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); assertThatNoException().isThrownBy(() -> encoder.encode(event, bos)); - assertThat(new String(bos.toByteArray())).isEqualTo("{}"); + assertThat(bos.toString()).isEqualTo("{}"); } @@ -195,10 +196,10 @@ public void streamingEncode() { */ @Test public void testLineEndings() { - // Use a brand new default instance to get rid of configuration done by the #setup() method + // Use a new default instance to get rid of configuration done by the #setup() method TestCompositeJsonEncoder encoder = new TestCompositeJsonEncoder(); - assertThat(encoder.getLineSeparator()).isEqualTo(System.getProperty("line.separator")); + assertThat(encoder.getLineSeparator()).isEqualTo(System.lineSeparator()); encoder.setLineSeparator("UNIX"); assertThat(encoder.getLineSeparator()).isEqualTo("\n"); @@ -213,7 +214,7 @@ public void testLineEndings() { assertThat(encoder.getLineSeparator()).isEqualTo("foo"); encoder.setLineSeparator("SYSTEM"); - assertThat(encoder.getLineSeparator()).isEqualTo(System.getProperty("line.separator")); + assertThat(encoder.getLineSeparator()).isEqualTo(System.lineSeparator()); encoder.setLineSeparator(""); assertThat(encoder.getLineSeparator()).isNull(); @@ -221,10 +222,10 @@ public void testLineEndings() { /* - * Failure to encode event should log an warning status + * Failure to encode event should log a warning status */ @Test - public void testIOException() throws IOException { + public void testIOException() { encoder.exceptionToThrow = new IOException(); encoder.start(); @@ -247,7 +248,7 @@ public void testIOException_streaming() throws IOException { OutputStream stream = mock(OutputStream.class); doThrow(exception).when(stream).write(any(byte[].class), any(int.class), any(int.class)); - assertThatCode(() -> encoder.encode(event, stream)).isInstanceOf(IOException.class); + assertThatCode(() -> encoder.encode(event, stream)).isInstanceOf(JacksonIOException.class); assertThat(statusManager.getCopyOfStatusList()) .noneMatch(s -> s.getMessage().startsWith("Error encountered while encoding log event.")); diff --git a/src/test/java/net/logstash/logback/encoder/LogstashAccessEncoderTest.java b/src/test/java/net/logstash/logback/encoder/LogstashAccessEncoderTest.java index 60ac4ead..e1a6c2fb 100644 --- a/src/test/java/net/logstash/logback/encoder/LogstashAccessEncoderTest.java +++ b/src/test/java/net/logstash/logback/encoder/LogstashAccessEncoderTest.java @@ -29,9 +29,9 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.core.Context; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; public class LogstashAccessEncoderTest { @@ -39,7 +39,7 @@ public class LogstashAccessEncoderTest { private final LogstashAccessEncoder encoder = new LogstashAccessEncoder(); @Test - public void basicsAreIncluded_logback12OrLater() throws Exception { + public void basicsAreIncluded_logback12OrLater() { final long timestamp = System.currentTimeMillis(); @@ -57,20 +57,20 @@ public void basicsAreIncluded_logback12OrLater() throws Exception { } protected void verifyBasics(final long timestamp, IAccessEvent event, JsonNode node) { - assertThat(node.get("timestamp").textValue()).isEqualTo(DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(Instant.ofEpochMilli(timestamp))); - assertThat(node.get("@version").textValue()).isEqualTo("1"); - assertThat(node.get("message").textValue()).isEqualTo(String.format("%s - %s [%s] \"%s\" %s %s", event.getRemoteHost(), event.getRemoteUser(), + assertThat(node.get("timestamp").asString()).isEqualTo(DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(Instant.ofEpochMilli(timestamp))); + assertThat(node.get("@version").asString()).isEqualTo("1"); + assertThat(node.get("message").asString()).isEqualTo(String.format("%s - %s [%s] \"%s\" %s %s", event.getRemoteHost(), event.getRemoteUser(), DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()) .format(Instant.ofEpochMilli(event.getTimeStamp())), event.getRequestURL(), event.getStatusCode(), event.getContentLength())); - assertThat(node.get("method").textValue()).isEqualTo(event.getMethod()); - assertThat(node.get("protocol").textValue()).isEqualTo(event.getProtocol()); + assertThat(node.get("method").asString()).isEqualTo(event.getMethod()); + assertThat(node.get("protocol").asString()).isEqualTo(event.getProtocol()); assertThat(node.get("status_code").asInt()).isEqualTo(event.getStatusCode()); - assertThat(node.get("requested_url").textValue()).isEqualTo(event.getRequestURL()); - assertThat(node.get("requested_uri").textValue()).isEqualTo(event.getRequestURI()); - assertThat(node.get("remote_host").textValue()).isEqualTo(event.getRemoteHost()); - assertThat(node.get("remote_user").textValue()).isEqualTo(event.getRemoteUser()); + assertThat(node.get("requested_url").asString()).isEqualTo(event.getRequestURL()); + assertThat(node.get("requested_uri").asString()).isEqualTo(event.getRequestURI()); + assertThat(node.get("remote_host").asString()).isEqualTo(event.getRemoteHost()); + assertThat(node.get("remote_user").asString()).isEqualTo(event.getRemoteUser()); assertThat(node.get("content_length").asLong()).isEqualTo(event.getContentLength()); assertThat(node.get("elapsed_time").asLong()).isEqualTo(event.getElapsedTime()); assertThat(node.get("request_headers")).isNull(); @@ -78,7 +78,7 @@ protected void verifyBasics(final long timestamp, IAccessEvent event, JsonNode n } @Test - public void propertiesInContextAreIncluded() throws Exception { + public void propertiesInContextAreIncluded() { Map propertyMap = new HashMap<>(); propertyMap.put("thing_one", "One"); propertyMap.put("thing_two", "Three"); @@ -94,12 +94,12 @@ public void propertiesInContextAreIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("thing_two").asString()).isEqualTo("Three"); } @Test - public void requestAndResponseHeadersAreIncluded() throws Exception { + public void requestAndResponseHeadersAreIncluded() { IAccessEvent event = mockBasicILoggingEvent(); @@ -111,13 +111,13 @@ public void requestAndResponseHeadersAreIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); assertThat(node.get("request_headers").size()).isEqualTo(2); - assertThat(node.get("request_headers").get("user-agent").textValue()).isEqualTo("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"); - assertThat(node.get("request_headers").get("accept").textValue()).isEqualTo("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); + assertThat(node.get("request_headers").get("user-agent").asString()).isEqualTo("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"); + assertThat(node.get("request_headers").get("accept").asString()).isEqualTo("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); assertThat(node.get("request_headers").get("unknown")).isNull(); assertThat(node.get("response_headers").size()).isEqualTo(2); - assertThat(node.get("response_headers").get("content-type").textValue()).isEqualTo("text/html; charset=UTF-8"); - assertThat(node.get("response_headers").get("content-length").textValue()).isEqualTo("42"); + assertThat(node.get("response_headers").get("content-type").asString()).isEqualTo("text/html; charset=UTF-8"); + assertThat(node.get("response_headers").get("content-length").asString()).isEqualTo("42"); assertThat(node.get("response_headers").get("unknown")).isNull(); } @@ -129,7 +129,7 @@ public void testCustomFields() { } @Test - public void unixTimestampAsNumber() throws Exception { + public void unixTimestampAsNumber() { final long timestamp = System.currentTimeMillis(); IAccessEvent event = mockBasicILoggingEvent(); @@ -145,7 +145,7 @@ public void unixTimestampAsNumber() throws Exception { } @Test - public void unixTimestampAsString() throws Exception { + public void unixTimestampAsString() { final long timestamp = System.currentTimeMillis(); IAccessEvent event = mockBasicILoggingEvent(); @@ -157,11 +157,11 @@ public void unixTimestampAsString() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("@timestamp").textValue()).isEqualTo(Long.toString(timestamp)); + assertThat(node.get("@timestamp").asString()).isEqualTo(Long.toString(timestamp)); } @Test - public void customMessagePattern() throws Exception { + public void customMessagePattern() { IAccessEvent event = mockBasicILoggingEvent(); @@ -175,14 +175,14 @@ public void customMessagePattern() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("msg").textValue()).isEqualTo("https://123.123.123.123/my/uri 200 123"); + assertThat(node.get("msg").asString()).isEqualTo("https://123.123.123.123/my/uri 200 123"); encoder.stop(); encoder.setMessagePattern(null); encoder.start(); - assertThat(MAPPER.readTree(encoder.encode(event)).get("msg").textValue()) + assertThat(MAPPER.readTree(encoder.encode(event)).get("msg").asString()) .startsWith("123.123.123.123 - remote-user ") .endsWith("\"https://123.123.123.123/my/uri\" 200 123"); } @@ -199,14 +199,12 @@ private IAccessEvent mockBasicILoggingEvent() { when(event.getStatusCode()).thenReturn(200); when(event.getTimeStamp()).thenReturn(System.currentTimeMillis()); when(event.getElapsedTime()).thenReturn(246L); - when(event.getRequestHeaderMap()).thenReturn(new HashMap() {{ - put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"); - put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); - }}); - when(event.getResponseHeaderMap()).thenReturn(new HashMap() {{ - put("Content-Type", "text/html; charset=UTF-8"); - put("Content-Length", "42"); - }}); + when(event.getRequestHeaderMap()).thenReturn(Map.of( + "User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36", + "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")); + when(event.getResponseHeaderMap()).thenReturn(Map.of( + "Content-Type", "text/html; charset=UTF-8", + "Content-Length", "42")); return event; } diff --git a/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java b/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java index 0d4cf982..bae465ca 100644 --- a/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java +++ b/src/test/java/net/logstash/logback/encoder/LogstashEncoderTest.java @@ -25,7 +25,7 @@ import static org.mockito.Mockito.when; import java.io.File; -import java.io.IOException; +import java.io.FileNotFoundException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.time.Instant; @@ -42,7 +42,8 @@ import net.logstash.logback.composite.loggingevent.mdc.BooleanMdcEntryWriter; import net.logstash.logback.composite.loggingevent.mdc.DoubleMdcEntryWriter; import net.logstash.logback.composite.loggingevent.mdc.LongMdcEntryWriter; -import net.logstash.logback.decorate.JsonFactoryDecorator; +import net.logstash.logback.decorate.PrettyPrintingDecorator; +import net.logstash.logback.decorate.json.JsonWriteFeatureDecorator; import net.logstash.logback.fieldnames.LogstashCommonFieldNames; import net.logstash.logback.fieldnames.ShortenedFieldNames; @@ -54,11 +55,6 @@ import ch.qos.logback.classic.spi.ThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxyUtil; import ch.qos.logback.core.Context; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; import org.assertj.core.util.Files; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -69,11 +65,17 @@ import org.slf4j.MarkerFactory; import org.slf4j.event.KeyValuePair; import org.slf4j.helpers.NOPMDCAdapter; +import tools.jackson.core.JsonParser; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class LogstashEncoderTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); - private static final ObjectMapper MAPPER = new ObjectMapper(FACTORY); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); private final LogstashEncoder encoder = new LogstashEncoder(); private Instant now; @@ -84,7 +86,7 @@ public void setup() { } @Test - public void basicsAreIncluded_logback12() throws Exception { + public void basicsAreIncluded_logback12() { ILoggingEvent event = mockBasicILoggingEvent(Level.ERROR); encoder.start(); @@ -96,18 +98,18 @@ public void basicsAreIncluded_logback12() throws Exception { } protected void verifyBasics(Instant timestamp, JsonNode node) { - assertThat(node.get("@timestamp").textValue()).isEqualTo( + assertThat(node.get("@timestamp").asString()).isEqualTo( DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(timestamp)); - assertThat(node.get("@version").textValue()).isEqualTo("1"); - assertThat(node.get("logger_name").textValue()).isEqualTo("LoggerName"); - assertThat(node.get("thread_name").textValue()).isEqualTo("ThreadName"); - assertThat(node.get("message").textValue()).isEqualTo("My message"); - assertThat(node.get("level").textValue()).isEqualTo("ERROR"); + assertThat(node.get("@version").asString()).isEqualTo("1"); + assertThat(node.get("logger_name").asString()).isEqualTo("LoggerName"); + assertThat(node.get("thread_name").asString()).isEqualTo("ThreadName"); + assertThat(node.get("message").asString()).isEqualTo("My message"); + assertThat(node.get("level").asString()).isEqualTo("ERROR"); assertThat(node.get("level_value").intValue()).isEqualTo(40000); } @Test - public void basicsAreIncludedWithShortenedNames() throws Exception { + public void basicsAreIncludedWithShortenedNames() { ILoggingEvent event = mockBasicILoggingEvent(Level.ERROR); encoder.setFieldNames(new ShortenedFieldNames()); @@ -116,28 +118,24 @@ public void basicsAreIncludedWithShortenedNames() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("@timestamp").textValue()).isEqualTo( + assertThat(node.get("@timestamp").asString()).isEqualTo( DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(now)); - assertThat(node.get("@version").textValue()).isEqualTo("1"); - assertThat(node.get("logger").textValue()).isEqualTo("LoggerName"); - assertThat(node.get("thread").textValue()).isEqualTo("ThreadName"); - assertThat(node.get("message").textValue()).isEqualTo("My message"); - assertThat(node.get("level").textValue()).isEqualTo("ERROR"); + assertThat(node.get("@version").asString()).isEqualTo("1"); + assertThat(node.get("logger").asString()).isEqualTo("LoggerName"); + assertThat(node.get("thread").asString()).isEqualTo("ThreadName"); + assertThat(node.get("message").asString()).isEqualTo("My message"); + assertThat(node.get("level").asString()).isEqualTo("ERROR"); assertThat(node.get("levelVal").intValue()).isEqualTo(40000); } @Test public void customDecorators() { encoder.stop(); - encoder.setJsonFactoryDecorator(new JsonFactoryDecorator() { - - @Override - public JsonFactory decorate(JsonFactory factory) { - return factory.disable(JsonGenerator.Feature.QUOTE_FIELD_NAMES); - } - }); - - encoder.setJsonGeneratorDecorator(JsonGenerator::useDefaultPrettyPrinter); + JsonWriteFeatureDecorator decorator = new JsonWriteFeatureDecorator(); + decorator.disable(JsonWriteFeature.QUOTE_PROPERTY_NAMES); + encoder.addDecorator(decorator); + + encoder.addDecorator(new PrettyPrintingDecorator<>()); encoder.start(); @@ -155,7 +153,7 @@ public JsonFactory decorate(JsonFactory factory) { } @Test - public void loggerNameIsShortenedProperly() throws Exception { + public void loggerNameIsShortenedProperly() { final int length = 36; final String shortenedLoggerName = new TargetLengthBasedClassNameAbbreviator(length) .abbreviate(DateTimeFormatter.class.getCanonicalName()); @@ -170,18 +168,18 @@ public void loggerNameIsShortenedProperly() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("@timestamp").textValue()).isEqualTo( + assertThat(node.get("@timestamp").asString()).isEqualTo( DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getDefault().toZoneId()).format(now)); - assertThat(node.get("@version").textValue()).isEqualTo("1"); - assertThat(node.get("logger").textValue()).isEqualTo(shortenedLoggerName); - assertThat(node.get("thread").textValue()).isEqualTo("ThreadName"); - assertThat(node.get("message").textValue()).isEqualTo("My message"); - assertThat(node.get("level").textValue()).isEqualTo("ERROR"); + assertThat(node.get("@version").asString()).isEqualTo("1"); + assertThat(node.get("logger").asString()).isEqualTo(shortenedLoggerName); + assertThat(node.get("thread").asString()).isEqualTo("ThreadName"); + assertThat(node.get("message").asString()).isEqualTo("My message"); + assertThat(node.get("level").asString()).isEqualTo("ERROR"); assertThat(node.get("levelVal").intValue()).isEqualTo(40000); } @Test - public void includingThrowableProxyIncludesStackTrace() throws Exception { + public void includingThrowableProxyIncludesStackTrace() { ThrowableProxy throwableProxy = new ThrowableProxy(new Exception("My goodness")); LoggingEvent event = mockBasicILoggingEvent(Level.ERROR); @@ -192,11 +190,11 @@ public void includingThrowableProxyIncludesStackTrace() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("stack_trace").textValue()).isEqualTo(ThrowableProxyUtil.asString(throwableProxy)); + assertThat(node.get("stack_trace").asString()).isEqualTo(ThrowableProxyUtil.asString(throwableProxy)); } @Test - public void mdcAllIncluded() throws Exception { + public void mdcAllIncluded() { Map mdcMap = new HashMap<>(); mdcMap.put("thing_one", "One"); mdcMap.put("thing_two", "Three"); @@ -208,12 +206,12 @@ public void mdcAllIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("thing_two").asString()).isEqualTo("Three"); } @Test - public void mdcSomeIncluded() throws Exception { + public void mdcSomeIncluded() { Map mdcMap = new HashMap<>(); mdcMap.put("thing_one", "One"); mdcMap.put("thing_two", "Three"); @@ -227,12 +225,12 @@ public void mdcSomeIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); assertThat(node.get("thing_two")).isNull(); } @Test - public void mdcSomeExcluded() throws Exception { + public void mdcSomeExcluded() { Map mdcMap = new HashMap<>(); mdcMap.put("thing_one", "One"); mdcMap.put("thing_two", "Three"); @@ -245,12 +243,12 @@ public void mdcSomeExcluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); assertThat(node.get("thing_two")).isNull(); } @Test - public void mdcNoneIncluded() throws Exception { + public void mdcNoneIncluded() { Map mdcMap = new HashMap<>(); mdcMap.put("thing_one", "One"); mdcMap.put("thing_two", "Three"); @@ -268,7 +266,7 @@ public void mdcNoneIncluded() throws Exception { } @Test - public void propertiesInMDCAreIncludedInSubObject() throws Exception { + public void propertiesInMDCAreIncludedInSubObject() { Map mdcMap = new HashMap<>(); mdcMap.put("thing_one", "One"); mdcMap.put("thing_two", "Three"); @@ -281,8 +279,8 @@ public void propertiesInMDCAreIncludedInSubObject() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("mdc").get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("mdc").get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("mdc").get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("mdc").get("thing_two").asString()).isEqualTo("Three"); } @Test @@ -297,7 +295,7 @@ public void nullMDCDoesNotCauseEverythingToBlowUp() { } @Test - public void mdcEntryWriters() throws Exception { + public void mdcEntryWriters() { Map mdcMap = new HashMap<>(); mdcMap.put("long", "4711"); mdcMap.put("double", "2.71828"); @@ -317,11 +315,11 @@ public void mdcEntryWriters() throws Exception { assertThat(node.get("long").longValue()).isEqualTo(4711L); assertThat(node.get("double").doubleValue()).isEqualTo(2.71828); assertThat(node.get("bool").booleanValue()).isTrue(); - assertThat(node.get("default").textValue()).isEqualTo("string"); + assertThat(node.get("default").asString()).isEqualTo("string"); } @Test - public void kvpAllIncluded() throws Exception { + public void kvpAllIncluded() { List kvp = new ArrayList<>(); kvp.add(new KeyValuePair("thing_one", "One")); kvp.add(new KeyValuePair("thing_two", "Three")); @@ -334,12 +332,12 @@ public void kvpAllIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("thing_two").asString()).isEqualTo("Three"); } @Test - public void kvpSomeIncluded() throws Exception { + public void kvpSomeIncluded() { List kvp = new ArrayList<>(); kvp.add(new KeyValuePair("thing_one", "One")); kvp.add(new KeyValuePair("thing_two", "Three")); @@ -354,12 +352,12 @@ public void kvpSomeIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); assertThat(node.get("thing_two")).isNull(); } @Test - public void kvpSomeExcluded() throws Exception { + public void kvpSomeExcluded() { List kvp = new ArrayList<>(); kvp.add(new KeyValuePair("thing_one", "One")); kvp.add(new KeyValuePair("thing_two", "Three")); @@ -374,12 +372,12 @@ public void kvpSomeExcluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); assertThat(node.get("thing_two")).isNull(); } @Test - public void kvpNoneIncluded() throws Exception { + public void kvpNoneIncluded() { List kvp = new ArrayList<>(); kvp.add(new KeyValuePair("thing_one", "One")); kvp.add(new KeyValuePair("thing_two", "Three")); @@ -398,7 +396,7 @@ public void kvpNoneIncluded() throws Exception { } @Test - public void propertiesInKVPAreIncludedInSubObject() throws Exception { + public void propertiesInKVPAreIncludedInSubObject() { List kvp = new ArrayList<>(); kvp.add(new KeyValuePair("thing_one", "One")); kvp.add(new KeyValuePair("thing_two", "Three")); @@ -412,8 +410,8 @@ public void propertiesInKVPAreIncludedInSubObject() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("kvp").get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("kvp").get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("kvp").get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("kvp").get("thing_two").asString()).isEqualTo("Three"); } @Test @@ -426,7 +424,7 @@ public void nullKVPDoesNotCauseEverythingToBlowUp() { } @Test - public void callerDataIsIncluded() throws Exception { + public void callerDataIsIncluded() { LoggingEvent event = mockBasicILoggingEvent(Level.ERROR); StackTraceElement[] stackTraceElements = { @@ -440,14 +438,14 @@ public void callerDataIsIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("caller_class_name").textValue()).isEqualTo(stackTraceElements[0].getClassName()); - assertThat(node.get("caller_method_name").textValue()).isEqualTo(stackTraceElements[0].getMethodName()); - assertThat(node.get("caller_file_name").textValue()).isEqualTo(stackTraceElements[0].getFileName()); + assertThat(node.get("caller_class_name").asString()).isEqualTo(stackTraceElements[0].getClassName()); + assertThat(node.get("caller_method_name").asString()).isEqualTo(stackTraceElements[0].getMethodName()); + assertThat(node.get("caller_file_name").asString()).isEqualTo(stackTraceElements[0].getFileName()); assertThat(node.get("caller_line_number").intValue()).isEqualTo(stackTraceElements[0].getLineNumber()); } @Test - public void callerDataIsIncludedInSubObject() throws Exception { + public void callerDataIsIncludedInSubObject() { LoggingEvent event = mockBasicILoggingEvent(Level.ERROR); StackTraceElement[] stackTraceElements = { @@ -461,18 +459,18 @@ public void callerDataIsIncludedInSubObject() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("caller").get("caller_class_name").textValue()) + assertThat(node.get("caller").get("caller_class_name").asString()) .isEqualTo(stackTraceElements[0].getClassName()); - assertThat(node.get("caller").get("caller_method_name").textValue()) + assertThat(node.get("caller").get("caller_method_name").asString()) .isEqualTo(stackTraceElements[0].getMethodName()); - assertThat(node.get("caller").get("caller_file_name").textValue()) + assertThat(node.get("caller").get("caller_file_name").asString()) .isEqualTo(stackTraceElements[0].getFileName()); assertThat(node.get("caller").get("caller_line_number").intValue()) .isEqualTo(stackTraceElements[0].getLineNumber()); } @Test - public void callerDataIsNotIncludedIfSwitchedOff() throws Exception { + public void callerDataIsNotIncludedIfSwitchedOff() { LoggingEvent event = mockBasicILoggingEvent(Level.ERROR); StackTraceElement[] stackTraceElements = { @@ -491,7 +489,7 @@ public void callerDataIsNotIncludedIfSwitchedOff() throws Exception { } @Test - public void propertiesInContextAreIncluded() throws Exception { + public void propertiesInContextAreIncluded() { Map propertyMap = new HashMap<>(); propertyMap.put("thing_one", "One"); propertyMap.put("thing_two", "Three"); @@ -507,12 +505,12 @@ public void propertiesInContextAreIncluded() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("thing_two").asString()).isEqualTo("Three"); } @Test - public void propertiesInContextAreNotIncludedIfSwitchedOff() throws Exception { + public void propertiesInContextAreNotIncludedIfSwitchedOff() { Map propertyMap = new HashMap<>(); propertyMap.put("thing_one", "One"); propertyMap.put("thing_two", "Three"); @@ -533,7 +531,7 @@ public void propertiesInContextAreNotIncludedIfSwitchedOff() throws Exception { } @Test - public void propertiesInContextAreIncludedInSubObject() throws Exception { + public void propertiesInContextAreIncludedInSubObject() { Map propertyMap = new HashMap<>(); propertyMap.put("thing_one", "One"); propertyMap.put("thing_two", "Three"); @@ -550,12 +548,12 @@ public void propertiesInContextAreIncludedInSubObject() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("context").get("thing_one").textValue()).isEqualTo("One"); - assertThat(node.get("context").get("thing_two").textValue()).isEqualTo("Three"); + assertThat(node.get("context").get("thing_one").asString()).isEqualTo("One"); + assertThat(node.get("context").get("thing_two").asString()).isEqualTo("Three"); } @Test - public void markerIncludesItselfAsTag() throws Exception { + public void markerIncludesItselfAsTag() { Marker marker = MarkerFactory.getDetachedMarker("hoosh"); LoggingEvent event = mockBasicILoggingEvent(Level.INFO); addMarker(event, marker); @@ -569,7 +567,7 @@ public void markerIncludesItselfAsTag() throws Exception { } @Test - public void markerReferencesAreIncludedAsTags() throws Exception { + public void markerReferencesAreIncludedAsTags() { Marker marker = MarkerFactory.getDetachedMarker("bees"); marker.add(MarkerFactory.getMarker("knees")); LoggingEvent event = mockBasicILoggingEvent(Level.INFO); @@ -584,7 +582,7 @@ public void markerReferencesAreIncludedAsTags() throws Exception { } @Test - public void nullMarkerIsIgnored() throws Exception { + public void nullMarkerIsIgnored() { ILoggingEvent event = mockBasicILoggingEvent(Level.INFO); encoder.start(); @@ -596,7 +594,7 @@ public void nullMarkerIsIgnored() throws Exception { } @Test - public void markerNoneIncluded() throws Exception { + public void markerNoneIncluded() { Marker marker = MarkerFactory.getDetachedMarker("bees"); marker.add(MarkerFactory.getDetachedMarker("knees")); LoggingEvent event = mockBasicILoggingEvent(Level.INFO); @@ -612,7 +610,7 @@ public void markerNoneIncluded() throws Exception { } @Test - public void testAppendJsonMessage() throws Exception { + public void testAppendJsonMessage() { Object[] argArray = new Object[] { 1, Collections.singletonMap("hello", Collections.singletonMap("hello", "world")) }; @@ -630,7 +628,7 @@ public void testAppendJsonMessage() throws Exception { } @Test - public void includeJsonChunk() throws Exception { + public void includeJsonChunk() { String customFields = "{\"appname\":\"damnGodWebservice\",\"roles\":[\"customerorder\", \"auth\"], \"buildinfo\": { \"version\" : \"Version 0.1.0-SNAPSHOT\", \"lastcommit\" : \"75473700d5befa953c45f630c6d9105413c16fe1\"} }"; ILoggingEvent event = mockBasicILoggingEvent(Level.INFO); @@ -640,14 +638,14 @@ public void includeJsonChunk() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("appname").textValue()).isEqualTo("damnGodWebservice"); + assertThat(node.get("appname").asString()).isEqualTo("damnGodWebservice"); assertThat(node.get("roles")).isEqualTo((parse("[\"customerorder\", \"auth\"]"))); assertThat(node.get("buildinfo")).isEqualTo(parse( "{ \"version\" : \"Version 0.1.0-SNAPSHOT\", \"lastcommit\" : \"75473700d5befa953c45f630c6d9105413c16fe1\"}")); } @Test - public void customTimeZone() throws Exception { + public void customTimeZone() { ILoggingEvent event = mockBasicILoggingEvent(Level.ERROR); encoder.setTimeZone("UTC"); @@ -656,22 +654,24 @@ public void customTimeZone() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("@timestamp").textValue()).isEqualTo( + assertThat(node.get("@timestamp").asString()).isEqualTo( DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId()).format(now)); - assertThat(node.get("@version").textValue()).isEqualTo("1"); - assertThat(node.get("logger_name").textValue()).isEqualTo("LoggerName"); - assertThat(node.get("thread_name").textValue()).isEqualTo("ThreadName"); - assertThat(node.get("message").textValue()).isEqualTo("My message"); - assertThat(node.get("level").textValue()).isEqualTo("ERROR"); + assertThat(node.get("@version").asString()).isEqualTo("1"); + assertThat(node.get("logger_name").asString()).isEqualTo("LoggerName"); + assertThat(node.get("thread_name").asString()).isEqualTo("ThreadName"); + assertThat(node.get("message").asString()).isEqualTo("My message"); + assertThat(node.get("level").asString()).isEqualTo("ERROR"); assertThat(node.get("level_value").intValue()).isEqualTo(40000); } - public JsonNode parse(String string) throws IOException { - return FACTORY.createParser(string).readValueAsTree(); + public JsonNode parse(String string) { + try (JsonParser parser = MAPPER.createParser(string)) { + return parser.readValueAsTree(); + } } @Test - public void testAppendEntries() throws Exception { + public void testAppendEntries() { LoggingEvent event = mockBasicILoggingEvent(Level.INFO); Map contextMap = new HashMap<>(); @@ -695,16 +695,16 @@ public void testAppendEntries() throws Exception { assertThat(node.get("duration")).isNotNull(); assertThat(node.get("duration").intValue()).isEqualTo(1200); assertThat(node.get("remoteResponse")).isNotNull(); - assertThat(node.get("remoteResponse").textValue()).isEqualTo("OK"); + assertThat(node.get("remoteResponse").asString()).isEqualTo("OK"); assertThat(node.get("extra")).isNotNull(); assertThat(node.get("extra").get("extraEntry")).isNotNull(); - assertThat(node.get("extra").get("extraEntry").textValue()).isEqualTo("extraValue"); + assertThat(node.get("extra").get("extraEntry").asString()).isEqualTo("extraValue"); assertThat(node.get("ignoredMapEntry")).as("The second map from the end should be ignored").isNull(); } @Test - public void testEncoderConfiguration() throws Exception { + public void testEncoderConfiguration() throws FileNotFoundException { Logger LOG = LoggerFactory.getLogger(LogstashEncoderTest.class); File tempFile = new File(System.getProperty("java.io.tmpdir"), "test.log"); @@ -725,17 +725,17 @@ public void testEncoderConfiguration() throws Exception { assertThat(node.get("@version")).isNull(); assertThat(node.get(LogstashCommonFieldNames.IGNORE_FIELD_INDICATOR)).isNull(); - assertThat(node.get("appname").textValue()).isEqualTo("damnGodWebservice"); - assertThat(node.get("appendedName").textValue()).isEqualTo("appendedValue"); + assertThat(node.get("appname").asString()).isEqualTo("damnGodWebservice"); + assertThat(node.get("appendedName").asString()).isEqualTo("appendedValue"); assertThat(node.get("myMdcKey")).isNull(); - assertThat(node.get("logger").textValue()).isEqualTo(LogstashEncoderTest.class.getName()); + assertThat(node.get("logger").asString()).isEqualTo(LogstashEncoderTest.class.getName()); assertThat(node.get("roles")).isEqualTo(parse("[\"customerorder\", \"auth\"]")); assertThat(node.get("buildinfo")).isEqualTo(parse( "{ \"version\" : \"Version 0.1.0-SNAPSHOT\", \"lastcommit\" : \"75473700d5befa953c45f630c6d9105413c16fe1\"}")); } @Test - public void testEncoderConfigurationOnFluentApi() throws Exception { + public void testEncoderConfigurationOnFluentApi() throws FileNotFoundException { Logger LOG = LoggerFactory.getLogger(LogstashEncoderTest.class); File tempFile = new File(System.getProperty("java.io.tmpdir"), "test.log"); @@ -757,10 +757,10 @@ public void testEncoderConfigurationOnFluentApi() throws Exception { assertThat(node.get("@version")).isNull(); assertThat(node.get(LogstashCommonFieldNames.IGNORE_FIELD_INDICATOR)).isNull(); - assertThat(node.get("appname").textValue()).isEqualTo("damnGodWebservice"); - assertThat(node.get("appendedName").textValue()).isEqualTo("appendedValue"); - assertThat(node.get("myKvpKey").textValue()).isEqualTo("myKvpValue"); - assertThat(node.get("logger").textValue()).isEqualTo(LogstashEncoderTest.class.getName()); + assertThat(node.get("appname").asString()).isEqualTo("damnGodWebservice"); + assertThat(node.get("appendedName").asString()).isEqualTo("appendedValue"); + assertThat(node.get("myKvpKey").asString()).isEqualTo("myKvpValue"); + assertThat(node.get("logger").asString()).isEqualTo(LogstashEncoderTest.class.getName()); assertThat(node.get("roles")).isEqualTo(parse("[\"customerorder\", \"auth\"]")); assertThat(node.get("buildinfo")).isEqualTo(parse( "{ \"version\" : \"Version 0.1.0-SNAPSHOT\", \"lastcommit\" : \"75473700d5befa953c45f630c6d9105413c16fe1\"}")); @@ -775,7 +775,7 @@ public void testCustomFields() { } @Test - public void unixTimestampAsNumber() throws Exception { + public void unixTimestampAsNumber() { ILoggingEvent event = mockBasicILoggingEvent(Level.ERROR); encoder.setTimestampPattern(AbstractFormattedTimestampJsonProvider.UNIX_TIMESTAMP_AS_NUMBER); @@ -788,7 +788,7 @@ public void unixTimestampAsNumber() throws Exception { } @Test - public void unixTimestampAsString() throws Exception { + public void unixTimestampAsString() { ILoggingEvent event = mockBasicILoggingEvent(Level.ERROR); encoder.setTimestampPattern(AbstractFormattedTimestampJsonProvider.UNIX_TIMESTAMP_AS_STRING); @@ -797,11 +797,11 @@ public void unixTimestampAsString() throws Exception { JsonNode node = MAPPER.readTree(encoded); - assertThat(node.get("@timestamp").textValue()).isEqualTo(Long.toString(event.getTimeStamp())); + assertThat(node.get("@timestamp").asString()).isEqualTo(Long.toString(event.getTimeStamp())); } @Test - public void testMessageSplitEnabled() throws Exception { + public void testMessageSplitEnabled() { LoggingEvent event = mockBasicILoggingEvent(Level.ERROR, buildMultiLineMessage("###")); encoder.setMessageSplitRegex("#+"); assertThat(encoder.getMessageSplitRegex()).isEqualTo("#+"); @@ -814,7 +814,7 @@ public void testMessageSplitEnabled() throws Exception { } @Test - public void testMessageSplitDisabled() throws Exception { + public void testMessageSplitDisabled() { String message = buildMultiLineMessage(System.lineSeparator()); LoggingEvent event = mockBasicILoggingEvent(Level.ERROR, message); @@ -825,12 +825,12 @@ public void testMessageSplitDisabled() throws Exception { JsonNode node = MAPPER.readTree(encoder.encode(event)); encoder.stop(); - assertThat(node.path("message").isTextual()).isTrue(); - assertThat(node.path("message").textValue()).isEqualTo(message); + assertThat(node.path("message").isString()).isTrue(); + assertThat(node.path("message").asString()).isEqualTo(message); } @Test - public void testMessageSplitDisabledByDefault() throws Exception { + public void testMessageSplitDisabledByDefault() { String message = buildMultiLineMessage(System.lineSeparator()); LoggingEvent event = mockBasicILoggingEvent(Level.ERROR, message); @@ -840,8 +840,8 @@ public void testMessageSplitDisabledByDefault() throws Exception { JsonNode node = MAPPER.readTree(encoder.encode(event)); encoder.stop(); - assertThat(node.path("message").isTextual()).isTrue(); - assertThat(node.path("message").textValue()).isEqualTo(message); + assertThat(node.path("message").isString()).isTrue(); + assertThat(node.path("message").asString()).isEqualTo(message); } @Test @@ -856,7 +856,7 @@ private void assertJsonArray(JsonNode jsonNode, String... expected) { String[] values = new String[jsonNode.size()]; for (int i = 0; i < values.length; i++) { - values[i] = jsonNode.get(i).asText(); + values[i] = jsonNode.get(i).asString(); } assertThat(values).containsExactly(expected); } diff --git a/src/test/java/net/logstash/logback/layout/CompositeJsonLayoutTest.java b/src/test/java/net/logstash/logback/layout/CompositeJsonLayoutTest.java index 3305d2a3..7bce0e07 100644 --- a/src/test/java/net/logstash/logback/layout/CompositeJsonLayoutTest.java +++ b/src/test/java/net/logstash/logback/layout/CompositeJsonLayoutTest.java @@ -18,19 +18,17 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import java.io.IOException; - import net.logstash.logback.composite.AbstractCompositeJsonFormatter; import net.logstash.logback.composite.AbstractJsonProvider; import ch.qos.logback.core.Layout; import ch.qos.logback.core.LayoutBase; import ch.qos.logback.core.spi.DeferredProcessingAware; -import com.fasterxml.jackson.core.JsonGenerator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; @ExtendWith(MockitoExtension.class) public class CompositeJsonLayoutTest { @@ -41,10 +39,10 @@ public class CompositeJsonLayoutTest { static class TesterCompositeJsonLayout extends CompositeJsonLayout { @Override protected AbstractCompositeJsonFormatter createFormatter() { - AbstractCompositeJsonFormatter formatter = new AbstractCompositeJsonFormatter(this) { }; - formatter.getProviders().addProvider(new AbstractJsonProvider() { + AbstractCompositeJsonFormatter formatter = new AbstractCompositeJsonFormatter<>(this) { }; + formatter.getProviders().addProvider(new AbstractJsonProvider<>() { @Override - public void writeTo(JsonGenerator generator, DeferredProcessingAware event) throws IOException { + public void writeTo(JsonGenerator generator, DeferredProcessingAware event) { generator.writeRaw("event"); } @Override @@ -56,20 +54,20 @@ public void prepareForDeferredProcessing(DeferredProcessingAware event) { } } - private Layout prefixLayout = new LayoutBase() { + private final Layout prefixLayout = new LayoutBase<>() { @Override public String doLayout(DeferredProcessingAware event) { return "prefix:"; } }; - private Layout suffixLayout = new LayoutBase() { + private final Layout suffixLayout = new LayoutBase<>() { public String doLayout(DeferredProcessingAware event) { return ":suffix"; - }; + } }; - @Mock(lenient = true) + @Mock(strictness = Mock.Strictness.LENIENT) private DeferredProcessingAware event; diff --git a/src/test/java/net/logstash/logback/marker/DeferredLogstashMarkerTest.java b/src/test/java/net/logstash/logback/marker/DeferredLogstashMarkerTest.java index ed6c58ad..1d605029 100644 --- a/src/test/java/net/logstash/logback/marker/DeferredLogstashMarkerTest.java +++ b/src/test/java/net/logstash/logback/marker/DeferredLogstashMarkerTest.java @@ -21,18 +21,20 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.io.IOException; import java.io.StringWriter; import java.util.function.Supplier; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class DeferredLogstashMarkerTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); public static class MyClass { private String myField; @@ -51,7 +53,7 @@ public void setMyField(String myField) { } @Test - public void testWriteTo() throws IOException { + public void testWriteTo() { @SuppressWarnings("unchecked") Supplier supplier = mock(Supplier.class); @@ -59,7 +61,7 @@ public void testWriteTo() throws IOException { when(supplier.get()).thenReturn(new MyClass("value")); StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); LogstashMarker marker = Markers.defer(() -> Markers.append("myObject", supplier.get())); @@ -93,7 +95,6 @@ public void testEquals() { LogstashMarker marker = Markers.defer(() -> Markers.append("myObject", myObject)); assertThat(marker) - .isEqualTo(marker) .isNotEqualTo(Markers.defer(() -> Markers.append("myObject", myObject))); } diff --git a/src/test/java/net/logstash/logback/marker/MapEntriesAppendingMarkerTest.java b/src/test/java/net/logstash/logback/marker/MapEntriesAppendingMarkerTest.java index fecef805..8ddb1a45 100755 --- a/src/test/java/net/logstash/logback/marker/MapEntriesAppendingMarkerTest.java +++ b/src/test/java/net/logstash/logback/marker/MapEntriesAppendingMarkerTest.java @@ -17,28 +17,30 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.IOException; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class MapEntriesAppendingMarkerTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); @Test - public void testWriteTo() throws IOException { + public void testWriteTo() { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("myField", "value"); StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); LogstashMarker marker = Markers.appendEntries(map); generator.writeStartObject(); @@ -51,22 +53,22 @@ public void testWriteTo() throws IOException { @Test public void testEquals() { - Map map = new HashMap(); + Map map = new HashMap<>(); assertThat(Markers.appendEntries(map)).isEqualTo(Markers.appendEntries(map)); - Map map2 = new HashMap(); + Map map2 = new HashMap<>(); map2.put("foo", "bar"); assertThat(Markers.appendEntries(map)).isNotEqualTo(Markers.appendEntries(map2)); } @Test public void testHashCode() { - Map map = new HashMap(); + Map map = new HashMap<>(); assertThat(Markers.appendEntries(map)).hasSameHashCodeAs(Markers.appendEntries(map)); - Map map2 = new HashMap(); + Map map2 = new HashMap<>(); map2.put("foo", "bar"); assertThat(Markers.appendEntries(map)).doesNotHaveSameHashCodeAs(Markers.appendEntries(map2)); } diff --git a/src/test/java/net/logstash/logback/marker/ObjectAppendingMarkerTest.java b/src/test/java/net/logstash/logback/marker/ObjectAppendingMarkerTest.java index 5ee928e8..9bb2aa17 100755 --- a/src/test/java/net/logstash/logback/marker/ObjectAppendingMarkerTest.java +++ b/src/test/java/net/logstash/logback/marker/ObjectAppendingMarkerTest.java @@ -17,18 +17,20 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.IOException; import java.io.StringWriter; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class ObjectAppendingMarkerTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); - + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); + public static class MyClass { private String myField; @@ -46,12 +48,12 @@ public void setMyField(String myField) { } @Test - public void testWriteTo() throws IOException { + public void testWriteTo() { MyClass myObject = new MyClass("value"); StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); LogstashMarker marker = Markers.append("myObject", myObject); generator.writeStartObject(); diff --git a/src/test/java/net/logstash/logback/marker/ObjectFieldsAppendingMarkerTest.java b/src/test/java/net/logstash/logback/marker/ObjectFieldsAppendingMarkerTest.java index e37a88a0..6d5d0abc 100755 --- a/src/test/java/net/logstash/logback/marker/ObjectFieldsAppendingMarkerTest.java +++ b/src/test/java/net/logstash/logback/marker/ObjectFieldsAppendingMarkerTest.java @@ -17,17 +17,19 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.IOException; import java.io.StringWriter; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class ObjectFieldsAppendingMarkerTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); public static class MyClass { private String myField; @@ -46,12 +48,12 @@ public void setMyField(String myField) { } @Test - public void testWriteTo() throws IOException { + public void testWriteTo() { MyClass myObject = new MyClass("value"); StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); LogstashMarker marker = Markers.appendFields(myObject); generator.writeStartObject(); @@ -63,12 +65,12 @@ public void testWriteTo() throws IOException { } @Test - public void testWriteTo_nonUnwrappable() throws IOException { + public void testWriteTo_nonUnwrappable() { StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); - LogstashMarker marker = Markers.appendFields(Long.valueOf(1L)); + LogstashMarker marker = Markers.appendFields(1L); generator.writeStartObject(); marker.writeTo(generator); generator.writeEndObject(); diff --git a/src/test/java/net/logstash/logback/marker/RawJsonAppendingMarkerTest.java b/src/test/java/net/logstash/logback/marker/RawJsonAppendingMarkerTest.java index 43f14742..7bdcff00 100755 --- a/src/test/java/net/logstash/logback/marker/RawJsonAppendingMarkerTest.java +++ b/src/test/java/net/logstash/logback/marker/RawJsonAppendingMarkerTest.java @@ -17,25 +17,27 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.IOException; import java.io.StringWriter; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.json.JsonWriteFeature; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; public class RawJsonAppendingMarkerTest { - private static final JsonFactory FACTORY = new MappingJsonFactory().enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .enable(JsonWriteFeature.ESCAPE_NON_ASCII) + .build(); @Test - public void testWriteTo() throws IOException { + public void testWriteTo() { String rawJson = "{\"myField\":\"value\"}"; StringWriter writer = new StringWriter(); - JsonGenerator generator = FACTORY.createGenerator(writer); + JsonGenerator generator = MAPPER.createGenerator(writer); LogstashMarker marker = Markers.appendRaw("rawJson", rawJson); generator.writeStartObject(); diff --git a/src/test/java/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest.java b/src/test/java/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest.java index eaf94f7d..80b8c607 100644 --- a/src/test/java/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest.java +++ b/src/test/java/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest.java @@ -34,25 +34,25 @@ import ch.qos.logback.core.ConsoleAppender; import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.spi.LifeCycle; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonStreamContext; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.JsonParser; +import tools.jackson.core.TokenStreamContext; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.node.ObjectNode; public class MaskingJsonGeneratorDecoratorTest { - private static final JsonFactory FACTORY = new MappingJsonFactory(); + private static final ObjectMapper MAPPER = JsonMapper.builder().build(); public static class TestFieldMasker implements FieldMasker { @Override - public Object mask(JsonStreamContext context) { - return context.hasCurrentName() && context.getCurrentName().equals("testfield") + public Object mask(TokenStreamContext context) { + return context.hasCurrentName() && context.currentName().equals("testfield") ? "[maskedtestfield]" : null; } @@ -60,7 +60,7 @@ public Object mask(JsonStreamContext context) { public static class TestValueMasker implements ValueMasker { @Override - public Object mask(JsonStreamContext context, Object value) { + public Object mask(TokenStreamContext context, Object value) { return "testvalue".equals(value) ? "[maskedtestvalue]" : null; @@ -99,7 +99,7 @@ private JsonGeneratorDecorator configure(String file) { } @Test - public void maskedAndUnmaskedField() throws IOException { + public void maskedAndUnmaskedField() { testMaskByPath( "{'fieldA':'valueA','fieldB':'valueB','fieldC':'valueC'}", "{'fieldA':'valueA','fieldB':'****', 'fieldC':'valueC'}", @@ -123,7 +123,7 @@ public void maskedAndUnmaskedField() throws IOException { } @Test - public void maskedSubstrings() throws IOException { + public void maskedSubstrings() { testMaskByValue( "{'fieldA':'tomask1','fieldB':'tomask2','fieldC':' tomask1-tomask2 '}", "{'fieldA':'****', 'fieldB':'****', 'fieldC':' ****-**** ' }", @@ -131,7 +131,7 @@ public void maskedSubstrings() throws IOException { } @Test - public void onlyMaskedField() throws IOException { + public void onlyMaskedField() { testMaskByPath( "{'fieldA':'valueA'}", "{'fieldA':'****' }", @@ -151,7 +151,7 @@ public void onlyMaskedField() throws IOException { } @Test - public void escapedPath() throws IOException { + public void escapedPath() { testMaskByPath( "{'fieldA':'valueA', 'field~/B':'valueB', 'fieldC':'valueC'}", "{'fieldA':'valueA', 'field~/B':'****', 'fieldC':'valueC'}", @@ -159,7 +159,7 @@ public void escapedPath() throws IOException { } @Test - public void maskEverything() throws IOException { + public void maskEverything() { testMaskByPath( "{'fieldA':{'fieldAA':'valueAA','fieldAB':{'fieldABA':'valueABA'},'fieldAC':[1]}, 'fieldB':'valueB'}", "{'fieldA':'****', 'fieldB':'****'}", @@ -167,14 +167,14 @@ public void maskEverything() throws IOException { } @Test - public void maskNothing() throws IOException { + public void maskNothing() { testMaskByPath( "{'fieldA':{'fieldAA':'valueAA','fieldAB':{'fieldABA':'valueABA'},'fieldAC':[1]},'fieldB':'valueB'}", "{'fieldA':{'fieldAA':'valueAA','fieldAB':{'fieldABA':'valueABA'},'fieldAC':[1]},'fieldB':'valueB'}"); } @Test - public void configuration() throws IOException { + public void configuration() { JsonGeneratorDecorator noMasks = configure("noMasks"); test( "{'fieldA':{'fieldAA':'valueAA','fieldAB':{'fieldABA':'valueABA'},'fieldAC':[1]},'fieldB':'valueB'}", @@ -194,7 +194,7 @@ public void configuration() throws IOException { } @Test - public void maskAllStringValues() throws IOException { + public void maskAllStringValues() { testMaskByValue( "{'fieldA':{'fieldAA':'valueAA','fieldAB':{'fieldABA':'valueABA'},'fieldAC':[1]},'fieldB':'valueB','fieldC':1}", "{'fieldA':{'fieldAA':'****', 'fieldAB':{'fieldABA':'****' },'fieldAC':[1]},'fieldB':'****', 'fieldC':1}", @@ -202,7 +202,7 @@ public void maskAllStringValues() throws IOException { } @Test - public void maskedSubObject() throws IOException { + public void maskedSubObject() { testMaskByPath( "{'fieldA':{'fieldAA':'valueAA','fieldAB':{'fieldABA':'valueABA'},'fieldAC':[1]},'fieldB':'valueB','fieldC':{'fieldA':'' }}", "{'fieldA':'****', 'fieldB':'valueB','fieldC':{'fieldA':'****'}}", @@ -234,7 +234,7 @@ public void maskedSubObject() throws IOException { } @Test - public void subObjectWithMaskedField() throws IOException { + public void subObjectWithMaskedField() { testMaskByPath( "{'fieldA':{'fieldAA':'valueAA','fieldAB':12345678,'fieldAC':'valueAC'},'fieldAB':0}", "{'fieldA':{'fieldAA':'valueAA','fieldAB':'****', 'fieldAC':'valueAC'},'fieldAB':'****'}", @@ -263,7 +263,7 @@ public void subObjectWithMaskedField() throws IOException { } @Test - public void maskedArray() throws IOException { + public void maskedArray() { testMaskByPath( "{'fieldA':['valueA0','valueA1'],'fieldB':'valueB'}", "{'fieldA':'****', 'fieldB':'valueB'}", @@ -279,7 +279,7 @@ public void maskedArray() throws IOException { } @Test - public void masedArrayByIndex() throws IOException { + public void masedArrayByIndex() { testMaskByPath( "{ 'array':[{'foo':'bar' },{'a':'b'}] }", "{ 'array':[{'foo':'****'},{'a':'b'}] }", @@ -311,7 +311,7 @@ public void masedArrayByIndex() throws IOException { } @Test - public void maskedArrayOfObjects() throws IOException { + public void maskedArrayOfObjects() { testMaskByPath( "{'fieldA':[{'fieldA0A':'valueA0A'},{'fieldA1A':'valueA1A'}],'fieldB':'valueB'}", "{'fieldA':'****', 'fieldB':'valueB'}", @@ -327,7 +327,7 @@ public void maskedArrayOfObjects() throws IOException { } @Test - public void arrayOfObjectWithMaskedField() throws IOException { + public void arrayOfObjectWithMaskedField() { testMaskByPath( "{'fieldA':[{'fieldA0A':'valueA0A','fieldA0B':12345678,'fieldA0C':'valueA0C'}]}", "{'fieldA':[{'fieldA0A':'valueA0A','fieldA0B':'****', 'fieldA0C':'valueA0C'}]}", @@ -355,7 +355,7 @@ public void arrayOfObjectWithMaskedField() throws IOException { } @Test - public void arrayOfArrayOfObjectWithMaskedFields() throws IOException { + public void arrayOfArrayOfObjectWithMaskedFields() { testMaskByPath( "{'fieldA':[[{'fieldA00A':'valueA00A','fieldA00B':true, 'fieldA00C':'valueA00C'}]]}", "{'fieldA':[[{'fieldA00A':'valueA00A','fieldA00B':'****','fieldA00C':'valueA00C'}]]}", @@ -398,7 +398,7 @@ public void arrayOfArrayOfObjectWithMaskedFields() throws IOException { "foo/fieldA/0/0/fieldA00B"); } - private void testMaskByPath(String unmasked, String masked, String... pathsToMask) throws IOException { + private void testMaskByPath(String unmasked, String masked, String... pathsToMask) { MaskingJsonGeneratorDecorator decoratorByPath = new MaskingJsonGeneratorDecorator(); Arrays.stream(pathsToMask).forEach(decoratorByPath::addPath); test(unmasked, masked, decoratorByPath); @@ -429,7 +429,7 @@ private void testMaskByPath(String unmasked, String masked, String... pathsToMas } - private void testMaskByValue(String unmasked, String masked, String... valuesToMask) throws IOException { + private void testMaskByValue(String unmasked, String masked, String... valuesToMask) { MaskingJsonGeneratorDecorator decoratorByValue = new MaskingJsonGeneratorDecorator(); Arrays.stream(valuesToMask).forEach(decoratorByValue::addValue); test(unmasked, masked, decoratorByValue); @@ -457,13 +457,13 @@ private void testMaskByValue(String unmasked, String masked, String... valuesToM } @Test - public void testReplacementGroup() throws IOException { + public void testReplacementGroup() { MaskingJsonGeneratorDecorator decorator = new MaskingJsonGeneratorDecorator(); decorator.addValueMask(new MaskingJsonGeneratorDecorator.ValueMask("(hello)? world", "$1 bob")); test("{'field':'hello world'}", "{'field':'hello bob'}", decorator); } - private void test(String unmasked, String masked, JsonGeneratorDecorator decorator) throws IOException { + private void test(String unmasked, String masked, JsonGeneratorDecorator decorator) { if (decorator instanceof LifeCycle) { ((LifeCycle) decorator).start(); } @@ -472,13 +472,13 @@ private void test(String unmasked, String masked, JsonGeneratorDecorator decorat masked = toJson(masked); StringWriter maskedWriter = new StringWriter(); - JsonGenerator maskingGenerator = decorator.decorate(FACTORY.createGenerator(maskedWriter)); + JsonGenerator maskingGenerator = decorator.decorate(MAPPER.createGenerator(maskedWriter)); /* * Read through the unmasked string, while writing to the maskedWriter * Note: replay read/parser events directly on the generator to simulate calls to the generator methods */ - try (JsonParser parser = FACTORY.createParser(unmasked)) { + try (JsonParser parser = MAPPER.createParser(unmasked)) { while (parser.nextToken() != null) { maskingGenerator.copyCurrentEvent(parser); } @@ -489,8 +489,8 @@ private void test(String unmasked, String masked, JsonGeneratorDecorator decorat * Input strings may be formatted with extra blanks for convenience in the test. * Better to convert them into ObjectNodes to compare their actual JSON structure irrespective of the "pretty printing". */ - ObjectNode expected = JsonReadingUtils.readFullyAsObjectNode(FACTORY, masked); - ObjectNode actual = JsonReadingUtils.readFullyAsObjectNode(FACTORY, maskedWriter.toString()); + ObjectNode expected = JsonReadingUtils.readFullyAsObjectNode(MAPPER, masked); + ObjectNode actual = JsonReadingUtils.readFullyAsObjectNode(MAPPER, maskedWriter.toString()); assertThat(actual).isEqualTo(expected); } diff --git a/src/test/java/net/logstash/logback/mask/RegexValueMaskerTest.java b/src/test/java/net/logstash/logback/mask/RegexValueMaskerTest.java index 3ae2e241..241a0a27 100644 --- a/src/test/java/net/logstash/logback/mask/RegexValueMaskerTest.java +++ b/src/test/java/net/logstash/logback/mask/RegexValueMaskerTest.java @@ -17,8 +17,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.fasterxml.jackson.databind.node.NullNode; import org.junit.jupiter.api.Test; +import tools.jackson.databind.node.NullNode; class RegexValueMaskerTest { diff --git a/src/test/java/net/logstash/logback/pattern/AbstractJsonPatternParserTest.java b/src/test/java/net/logstash/logback/pattern/AbstractJsonPatternParserTest.java index 1e383443..d7078c41 100644 --- a/src/test/java/net/logstash/logback/pattern/AbstractJsonPatternParserTest.java +++ b/src/test/java/net/logstash/logback/pattern/AbstractJsonPatternParserTest.java @@ -18,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import java.io.IOException; import java.io.StringWriter; import java.util.Map; @@ -26,15 +25,15 @@ import net.logstash.logback.test.AbstractLogbackTest; import ch.qos.logback.core.Context; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.MappingJsonFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.JsonParser; +import tools.jackson.core.type.TypeReference; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.json.JsonMapper; /** * @author Dmitry Andrianov @@ -42,7 +41,7 @@ @ExtendWith(MockitoExtension.class) public abstract class AbstractJsonPatternParserTest extends AbstractLogbackTest { - private JsonFactory jsonFactory = new MappingJsonFactory(); + private final JsonMapper jsonMapper = JsonMapper.builder().build(); private Event event; @@ -54,18 +53,16 @@ public void setup() throws Exception { super.setup(); this.event = createEvent(); - this.parser = createParser(context, jsonFactory); + this.parser = createParser(context, jsonMapper); } protected abstract Event createEvent(); - protected abstract AbstractJsonPatternParser createParser(Context context, JsonFactory jsonFactory); + protected abstract AbstractJsonPatternParser createParser(Context context, ObjectMapper jsonMapper); private Map parseJson(final String text) { - try (JsonParser jsonParser = jsonFactory.createParser(text)) { - return jsonParser.readValueAs(new TypeReference>() { }); - } catch (IOException e) { - throw new IllegalStateException("Unexpected IOException while writing to the JsonGenerator"); + try (JsonParser jsonParser = jsonMapper.createParser(text)) { + return jsonMapper.readValue(jsonParser, new TypeReference<>() { }); } } @@ -83,14 +80,11 @@ private String process(final String patternJson) throws JsonPatternException { StringWriter buffer = new StringWriter(); - try (JsonGenerator jsonGenerator = jsonFactory.createGenerator(buffer)) { + try (JsonGenerator jsonGenerator = jsonMapper.createGenerator(buffer)) { jsonGenerator.writeStartObject(); root.write(jsonGenerator, event); jsonGenerator.writeEndObject(); jsonGenerator.flush(); - - } catch (IOException e) { - throw new IllegalStateException("Unexpected IOException while writing to the JsonGenerator", e); } return buffer.toString(); diff --git a/src/test/java/net/logstash/logback/pattern/AccessEventJsonPatternParserTest.java b/src/test/java/net/logstash/logback/pattern/AccessEventJsonPatternParserTest.java index 536374be..dd826cb3 100644 --- a/src/test/java/net/logstash/logback/pattern/AccessEventJsonPatternParserTest.java +++ b/src/test/java/net/logstash/logback/pattern/AccessEventJsonPatternParserTest.java @@ -19,11 +19,11 @@ import ch.qos.logback.access.common.spi.IAccessEvent; import ch.qos.logback.core.Context; -import com.fasterxml.jackson.core.JsonFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.databind.ObjectMapper; /** * @author Dmitry Andrianov @@ -31,7 +31,7 @@ @ExtendWith(MockitoExtension.class) public class AccessEventJsonPatternParserTest extends AbstractJsonPatternParserTest { - @Mock(lenient = true) + @Mock(strictness = Mock.Strictness.LENIENT) private IAccessEvent event; @Override @@ -42,8 +42,8 @@ protected IAccessEvent createEvent() { } @Override - protected AbstractJsonPatternParser createParser(Context context, JsonFactory jsonFactory) { - return new AccessEventJsonPatternParser(context, jsonFactory); + protected AbstractJsonPatternParser createParser(Context context, ObjectMapper objectMapper) { + return new AccessEventJsonPatternParser(context, objectMapper); } @Test diff --git a/src/test/java/net/logstash/logback/pattern/LoggingEventJsonPatternParserTest.java b/src/test/java/net/logstash/logback/pattern/LoggingEventJsonPatternParserTest.java index 4e31ad1c..0ed41c5f 100644 --- a/src/test/java/net/logstash/logback/pattern/LoggingEventJsonPatternParserTest.java +++ b/src/test/java/net/logstash/logback/pattern/LoggingEventJsonPatternParserTest.java @@ -26,11 +26,11 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Context; -import com.fasterxml.jackson.core.JsonFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.databind.ObjectMapper; /** * @author Dmitry Andrianov @@ -38,10 +38,10 @@ @ExtendWith(MockitoExtension.class) public class LoggingEventJsonPatternParserTest extends AbstractJsonPatternParserTest { - @Mock(lenient = true) + @Mock(strictness = Mock.Strictness.LENIENT) private ILoggingEvent event; - private Map mdc = new HashMap(); + private final Map mdc = new HashMap<>(); @Override protected ILoggingEvent createEvent() { @@ -54,8 +54,8 @@ protected ILoggingEvent createEvent() { } @Override - protected AbstractJsonPatternParser createParser(Context context, JsonFactory jsonFactory) { - return new LoggingEventJsonPatternParser(context, jsonFactory); + protected AbstractJsonPatternParser createParser(Context context, ObjectMapper objectMapper) { + return new LoggingEventJsonPatternParser(context, objectMapper); } @Test @@ -153,7 +153,7 @@ public void propertyUndefined() throws JsonPatternException { @Test - public void propertyInvalid() throws JsonPatternException { + public void propertyInvalid() { assertThatThrownBy(() -> parser.parse(toJson("{ 'prop': '%property{}' }"))).isInstanceOf(JsonPatternException.class); } } diff --git a/src/test/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegateTests.java b/src/test/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegateTests.java index 10f37e4f..f4283d25 100644 --- a/src/test/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegateTests.java +++ b/src/test/java/net/logstash/logback/util/SimpleObjectJsonGeneratorDelegateTests.java @@ -20,7 +20,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import java.io.IOException; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; @@ -28,23 +27,22 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.BigIntegerNode; -import com.fasterxml.jackson.databind.node.BooleanNode; -import com.fasterxml.jackson.databind.node.DecimalNode; -import com.fasterxml.jackson.databind.node.DoubleNode; -import com.fasterxml.jackson.databind.node.FloatNode; -import com.fasterxml.jackson.databind.node.IntNode; -import com.fasterxml.jackson.databind.node.LongNode; -import com.fasterxml.jackson.databind.node.NullNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.ShortNode; -import com.fasterxml.jackson.databind.node.TextNode; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.node.ArrayNode; +import tools.jackson.databind.node.BigIntegerNode; +import tools.jackson.databind.node.BooleanNode; +import tools.jackson.databind.node.DecimalNode; +import tools.jackson.databind.node.DoubleNode; +import tools.jackson.databind.node.FloatNode; +import tools.jackson.databind.node.IntNode; +import tools.jackson.databind.node.LongNode; +import tools.jackson.databind.node.NullNode; +import tools.jackson.databind.node.ObjectNode; +import tools.jackson.databind.node.ShortNode; +import tools.jackson.databind.node.StringNode; /** * @author brenuart @@ -52,37 +50,36 @@ */ public class SimpleObjectJsonGeneratorDelegateTests { - private static final JsonFactory FACTORY = new MappingJsonFactory(); - + public static final JsonMapper MAPPER = JsonMapper.builder().build(); private JsonGenerator delegate; private SimpleObjectJsonGeneratorDelegate generator; @BeforeEach - public void setup() throws IOException { - delegate = spy(FACTORY.createGenerator(new StringWriter())); + public void setup() { + delegate = spy(MAPPER.createGenerator(new StringWriter())); generator = new SimpleObjectJsonGeneratorDelegate(delegate); } @Test - public void writeObject_Null() throws IOException { - generator.writeObject(null); + public void writePOJO_Null() { + generator.writePOJO(null); verify(delegate).writeNull(); } @Test - public void writeObject_String() throws IOException { - generator.writeObject("foo"); + public void writePOJO_String() { + generator.writePOJO("foo"); verify(delegate).writeString("foo"); } @Test - public void writeObject_Boolean() throws IOException { - generator.writeObject(Boolean.TRUE); - generator.writeObject(new AtomicBoolean(false)); + public void writePOJO_Boolean() { + generator.writePOJO(Boolean.TRUE); + generator.writePOJO(new AtomicBoolean(false)); verify(delegate).writeBoolean(true); verify(delegate).writeBoolean(false); @@ -90,57 +87,57 @@ public void writeObject_Boolean() throws IOException { @Test - public void writeObject_Numbers() throws IOException { - generator.writeObject((byte) 1); - generator.writeObject((short) 2); - generator.writeObject((int) 3); - generator.writeObject((long) 4); - generator.writeObject((double) 5); - generator.writeObject((float) 6); - generator.writeObject(BigInteger.valueOf(7)); - generator.writeObject(BigDecimal.valueOf(8)); - generator.writeObject(new AtomicInteger(9)); - generator.writeObject(new AtomicLong(10)); + public void writePOJO_Numbers() { + generator.writePOJO((byte) 1); + generator.writePOJO((short) 2); + generator.writePOJO(3); + generator.writePOJO((long) 4); + generator.writePOJO((double) 5); + generator.writePOJO((float) 6); + generator.writePOJO(BigInteger.valueOf(7)); + generator.writePOJO(BigDecimal.valueOf(8)); + generator.writePOJO(new AtomicInteger(9)); + generator.writePOJO(new AtomicLong(10)); verify(delegate).writeNumber((byte) 1); verify(delegate).writeNumber((short) 2); - verify(delegate).writeNumber((int) 3); + verify(delegate).writeNumber(3); verify(delegate).writeNumber((long) 4); verify(delegate).writeNumber((double) 5); verify(delegate).writeNumber((float) 6); verify(delegate).writeNumber(BigInteger.valueOf(7)); verify(delegate).writeNumber(BigDecimal.valueOf(8)); - verify(delegate).writeNumber((int) 9); + verify(delegate).writeNumber(9); verify(delegate).writeNumber((long) 10); } @Test - public void writeObject_byteArray() throws IOException { + public void writePOJO_byteArray() { byte[] data = new byte[] {1, 2}; - generator.writeObject(data); + generator.writePOJO(data); verify(delegate).writeBinary(any(), eq(data), eq(0), eq(2)); } @Test - public void writeObject_jsonNode_String() throws IOException { - generator.writeObject(new TextNode("foo")); + public void writePOJO_jsonNode_String() { + generator.writePOJO(new StringNode("foo")); } @Test - public void writeObject_jsonNode_Numbers() throws IOException { - generator.writeObject(new IntNode(1)); - generator.writeObject(new LongNode(2)); - generator.writeObject(new ShortNode((short) 3)); - generator.writeObject(new FloatNode(4)); - generator.writeObject(new DoubleNode(5)); - generator.writeObject(new BigIntegerNode(BigInteger.valueOf(6))); - generator.writeObject(new DecimalNode(BigDecimal.valueOf(7))); + public void writePOJO_jsonNode_Numbers() { + generator.writePOJO(new IntNode(1)); + generator.writePOJO(new LongNode(2)); + generator.writePOJO(new ShortNode((short) 3)); + generator.writePOJO(new FloatNode(4)); + generator.writePOJO(new DoubleNode(5)); + generator.writePOJO(new BigIntegerNode(BigInteger.valueOf(6))); + generator.writePOJO(new DecimalNode(BigDecimal.valueOf(7))); - verify(delegate).writeNumber((int) 1); + verify(delegate).writeNumber(1); verify(delegate).writeNumber((long) 2); verify(delegate).writeNumber((short) 3); verify(delegate).writeNumber((float) 4); @@ -151,63 +148,61 @@ public void writeObject_jsonNode_Numbers() throws IOException { @Test - public void writeObject_jsonNode_Boolean() throws IOException { - generator.writeObject(BooleanNode.TRUE); + public void writePOJO_jsonNode_Boolean() { + generator.writePOJO(BooleanNode.TRUE); verify(delegate).writeBoolean(true); } @Test - public void writeObject_jsonNode_Object() throws IOException { - ObjectNode node = (ObjectNode) generator.getCodec().createObjectNode(); + public void writePOJO_jsonNode_Object() { + ObjectNode node = MAPPER.createObjectNode(); node.put("string", "foo"); node.put("boolean", true); - generator.writeObject(node); + generator.writePOJO(node); - verify(delegate).getCodec(); verify(delegate).writeStartObject(any()); - verify(delegate).writeFieldName("string"); + verify(delegate).writeName("string"); verify(delegate).writeString("foo"); - verify(delegate).writeFieldName("boolean"); + verify(delegate).writeName("boolean"); verify(delegate).writeBoolean(true); verify(delegate).writeEndObject(); } @Test - public void writeObject_jsonNode_Array() throws IOException { - ArrayNode node = (ArrayNode) generator.getCodec().createArrayNode(); + public void writePOJO_jsonNode_Array() { + ArrayNode node = MAPPER.createArrayNode(); node.add("string"); node.add(true); node.add(1); - generator.writeObject(node); + generator.writePOJO(node); - verify(delegate).getCodec(); verify(delegate).writeStartArray(any(), eq(3)); verify(delegate).writeString("string"); verify(delegate).writeBoolean(true); - verify(delegate).writeNumber((int) 1); + verify(delegate).writeNumber(1); verify(delegate).writeEndArray(); } @Test - public void writeObject_jsonNode_Null() throws IOException { - generator.writeObject(NullNode.instance); + public void writePOJO_jsonNode_Null() { + generator.writePOJO(NullNode.instance); verify(delegate).writeNull(); } @Test - public void writeObject_POJO() throws IOException { + public void writePOJO_POJO() { MyPojo obj = new MyPojo(); - generator.writeObject(obj); + generator.writePOJO(obj); - verify(delegate).writeObject(obj); + verify(delegate).writePOJO(obj); } @SuppressWarnings("unused") diff --git a/src/test/resources/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest-masks.xml b/src/test/resources/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest-masks.xml index ce7a2e29..693960e6 100644 --- a/src/test/resources/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest-masks.xml +++ b/src/test/resources/net/logstash/logback/mask/MaskingJsonGeneratorDecoratorTest-masks.xml @@ -5,7 +5,7 @@ - + fieldA fieldB fieldC,fieldD @@ -26,7 +26,7 @@ - +