Skip to content

Commit

Permalink
Merge pull request #970 from logfellow/drop_logback_12
Browse files Browse the repository at this point in the history
Drop support for logback 1.2
  • Loading branch information
philsttr committed Jun 17, 2023
2 parents 639c28f + ea18315 commit af9f826
Show file tree
Hide file tree
Showing 13 changed files with 53 additions and 195 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ jobs:
- name: Test Jackson 2.12.x
run: ./mvnw --batch-mode --no-transfer-progress --show-version --settings .github/maven/settings.xml -Pcompat-jackson surefire:test

# Run tests against Logback 1.2 to ensure runtime compatibility (do not recompile)
- name: Test Logback 1.2.x
run: ./mvnw --batch-mode --no-transfer-progress --show-version --settings .github/maven/settings.xml -Pcompat-logback surefire:test

- name: Upload Test Reports to Github
uses: actions/upload-artifact@v3
if: ${{ always() }}
Expand Down
32 changes: 12 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Maven style:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.5</version>
<version>1.3.7</version>
<!-- Use runtime scope if the project does not have any compile-time usage of logback,
such as implementations of Appender, Encoder, Layout, TurboFilter, etc
<scope>runtime</scope>
Expand All @@ -123,22 +123,22 @@ from the maven repository exist on the runtime classpath.
Specifically, the following need to be available on the runtime classpath:

* jackson-databind / jackson-core / jackson-annotations >= 2.12.0
* logback-core >= 1.2.0
* logback-classic >= 1.2.0 (required for logging _LoggingEvents_)
* logback-access >= 1.2.0 (required for logging _AccessEvents_)
* logback-core >= 1.3.0
* logback-classic >= 1.3.0 (required for logging _LoggingEvents_)
* logback-access >= 1.3.0 (required for logging _AccessEvents_)
* slf4j-api (usually comes as a transitive dependency of logback-classic)
* java-uuid-generator (required if the `uuid` provider is used)

Older versions than the ones specified in the pom file _might_ work, but the versions in the pom file are what testing has been performed against.
Support for logback versions prior to 1.2.0 was removed in logstash-logback-encoder 7.0.
Support for logback versions prior to 1.3.0 was removed in logstash-logback-encoder 7.4.

If you are using logstash-logback-encoder in a project (such as spring-boot) that also declares dependencies on any of the above libraries, you might need to tell maven explicitly which versions to use to avoid conflicts.
You can do so using maven's [dependencyManagement](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management) feature.
For example, to ensure that maven doesn't pick different versions of logback-core, logback-classic, and logback-access, add this to your project's pom.xml

```xml
<properties>
<logback.version>1.3.0</logback.version>
<logback.version>1.3.7</logback.version>
</properties>
<dependencyManagement>
<dependencies>
Expand All @@ -164,10 +164,10 @@ For example, to ensure that maven doesn't pick different versions of logback-cor
## Java Version Requirements

| logstash-logback-encoder | Minimum Java Version supported |
| ------------------------ | -------------------------------|
| &gt;= 6.0 | 1.8 |
| 5.x | 1.7 |
| &lt;= 4.x | 1.6 |
|--------------------------|--------------------------------|
| &gt;= 6.0 | 8 |
| 5.x | 7 |
| &lt;= 4.x | 6 |


## Usage
Expand Down Expand Up @@ -1705,11 +1705,7 @@ The provider uses a standard Java DateTimeFormatter under the hood. However, spe
* `[ISO_INSTANT]`


Note that the precision of the timestamp depends on the Logback version being used:
- versions before `1.3.0` have a timestamp with millisecond precision
- nanosecond precision is available starting from Logback `1.3.0`
The standard `[...]` formats will therefore output millis or nanos depending on which version of Logback is on the runtime classpath.

With logback 1.3+ the timestamp will have millisecond precision.

The formatter uses the default TimeZone of the host Java platform by default. You can change it like this:

Expand Down Expand Up @@ -2328,8 +2324,6 @@ When using the `LogstashEncoder`, `LogstashAccessEncoder` or a composite encoder

Note that logback's xml configuration reader will [trim whitespace from xml element values](https://github.com/qos-ch/logback/blob/c2dcbfcfb4048d11d7e81cd9220efbaaccf931fa/logback-core/src/main/java/ch/qos/logback/core/joran/event/BodyEvent.java#L27-L37). Therefore, if you want to end the prefix or suffix pattern with whitespace, first add the whitespace, and then add something like `%mdc{keyThatDoesNotExist}` after it. For example `<pattern>your pattern %mdc{keyThatDoesNotExist}</pattern>`. This will cause logback to output the whitespace as desired, and then a blank string for the MDC key that does not exist.

> :warning: If you encounter the following warning: `A "net.logstash.logback.encoder.LogstashEncoder" object is not assignable to a "ch.qos.logback.core.Appender" variable.`, you are encountering a backwards incompatibilility introduced in logback 1.2.1. Please vote for [LOGBACK-1326](https://jira.qos.ch/browse/LOGBACK-1326) and add a thumbs up to [PR#383](https://github.com/qos-ch/logback/pull/383) to try to get this addressed in logback. In the meantime, the only solution is to downgrade logback-classic and logback-core to 1.2.0
The line separator, which is written after the suffix, can be specified as:
* `SYSTEM` (uses the system default)
* `UNIX` (uses `\n`)
Expand Down Expand Up @@ -2446,10 +2440,8 @@ The provider name is the xml element name to use when configuring.
<td>
<p>Event sequence number.
</p>
<p>With Logback 1.3 the sequence number is obtained from the event itself as long as the LoggerContext is configured with a `SequenceNumberGenerator` (which is not by default).
<p>With Logback 1.3+ the sequence number is obtained from the event itself as long as the LoggerContext is configured with a `SequenceNumberGenerator` (which is not by default).
If no SequenceNumberGenerator is configured, the provider emits a warning and reverts to a locally generated incrementing number starting at 1.
</p>
<p>With Logback versions prior to 1.3 the sequence number is generated locally by the provider itself.
</p>
<ul>
<li><tt>fieldName</tt> - Output field name (<tt>sequence</tt>)</li>
Expand Down
11 changes: 0 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -761,17 +761,6 @@
</build>
</profile>

<!--
Profile used to run backward compatibility tests against logback 1.2
-->
<profile>
<id>compat-logback</id>
<properties>
<logback.version>1.2.11</logback.version>
<surefire.reportsSubDir>logback-${logback.version}</surefire.reportsSubDir>
</properties>
</profile>

<!--
Profile used to run backward compatibility tests against jackson 2.12
-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;

import net.logstash.logback.util.LogbackUtils;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import ch.qos.logback.core.spi.SequenceNumberGenerator;
Expand All @@ -31,13 +29,11 @@
* Outputs an incrementing sequence number.
* Useful for determining if log events get lost along the transport chain.
*
* <p>With Logback 1.3 the sequence number is obtained from {@link ILoggingEvent#getSequenceNumber()} provided the
* <p>With Logback 1.3+ the sequence number is obtained from {@link ILoggingEvent#getSequenceNumber()} provided the
* LoggerContext is configured with a {@link SequenceNumberGenerator} (which is not by default).
* If no SequenceNumberGenerator is configured, the provider issues a warning and reverts to a locally generated
* incrementing number.
*
* <p>With Logback versions prior to 1.3 the sequence number is generated locally by the provider itself.
*
* <p>If needed, a different strategy can be used by setting a custom provider with {@link #setSequenceProvider(Function)}.
*/
public abstract class AbstractSequenceJsonProvider<Event extends DeferredProcessingAware> extends AbstractFieldJsonProvider<Event> {
Expand Down Expand Up @@ -100,36 +96,32 @@ public Function<Event, Long> getSequenceProvider() {
return sequenceProvider;
}


/**
* Create a default sequence provider depending on the current Logback version.
*
* <p>With Logback 1.3 the sequence number is obtained for {@link ILoggingEvent#getSequenceNumber()} provided the
* <p>With Logback 1.3+ the sequence number is obtained for {@link ILoggingEvent#getSequenceNumber()} provided the
* LoggerContext is configured with a {@link SequenceNumberGenerator} (which is not by default).
* If no SequenceNumberGenerator is configured, the provider issues a warning and reverts to a locally generated
* incrementing number.
*
* <p>With Logback versions prior to 1.3 the sequence number is generated locally by the provider itself.
*
* @return a sequence provider
*/
protected Function<Event, Long> createSequenceProvider() {
if (LogbackUtils.isVersion13()) {
if (getContext() == null || getContext().getSequenceNumberGenerator() == null) {
this.addWarn("No <sequenceNumberGenerator> defined in Logback configuration - revert to using a local incrementing sequence number.");
}
else {
return createNativeSequenceNumberFieldAccessor();
}
if (getContext() == null || getContext().getSequenceNumberGenerator() == null) {
this.addWarn("No <sequenceNumberGenerator> defined in Logback configuration - revert to using a local incrementing sequence number.");

return new Function<Event, Long>() {
private final AtomicLong sequence = new AtomicLong(0L);

@Override
public Long apply(Event t) {
return sequence.incrementAndGet();
}
};
}
else {
return createNativeSequenceNumberFieldAccessor();
}
return new Function<Event, Long>() {
private final AtomicLong sequence = new AtomicLong(0L);

@Override
public Long apply(Event t) {
return sequence.incrementAndGet();
}
};
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,14 @@

import net.logstash.logback.composite.AbstractFormattedTimestampJsonProvider;
import net.logstash.logback.fieldnames.LogstashFieldNames;
import net.logstash.logback.util.LogbackUtils;

import ch.qos.logback.classic.spi.ILoggingEvent;

public class LoggingEventFormattedTimestampJsonProvider extends AbstractFormattedTimestampJsonProvider<ILoggingEvent, LogstashFieldNames> {

@Override
protected Instant getTimestampAsInstant(ILoggingEvent event) {
if (LogbackUtils.isVersion13()) {
return event.getInstant();
}
else {
return Instant.ofEpochMilli(event.getTimeStamp());
}
return event.getInstant();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import net.logstash.logback.composite.JsonProvider;
import net.logstash.logback.marker.LogstashMarker;
import net.logstash.logback.marker.Markers;
import net.logstash.logback.util.LogbackUtils;

import ch.qos.logback.classic.spi.ILoggingEvent;
import com.fasterxml.jackson.core.JsonGenerator;
Expand All @@ -35,15 +34,9 @@
*/
public class LogstashMarkersJsonProvider extends AbstractJsonProvider<ILoggingEvent> {

@SuppressWarnings("deprecation")
@Override
public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
if (LogbackUtils.isVersion13()) {
writeLogstashMarkerIfNecessary(generator, event.getMarkerList());
}
else {
writeLogstashMarkerIfNecessary(generator, event.getMarker());
}
writeLogstashMarkerIfNecessary(generator, event.getMarkerList());
}

private void writeLogstashMarkerIfNecessary(JsonGenerator generator, List<Marker> markers) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import net.logstash.logback.composite.FieldNamesAware;
import net.logstash.logback.fieldnames.LogstashFieldNames;
import net.logstash.logback.marker.LogstashMarker;
import net.logstash.logback.util.LogbackUtils;

import ch.qos.logback.classic.spi.ILoggingEvent;
import com.fasterxml.jackson.core.JsonGenerator;
Expand All @@ -32,8 +31,8 @@
/**
* Writes {@link Marker} names as an array to the 'tags' field.
*
* Does not write any special {@link LogstashMarker}s
* (Those are handled by {@link LogstashMarkersJsonProvider}).
* <p>Does not write any special {@link LogstashMarker}s
* (Those are handled by {@link LogstashMarkersJsonProvider}).</p>
*/
public class TagsJsonProvider extends AbstractFieldJsonProvider<ILoggingEvent> implements FieldNamesAware<LogstashFieldNames> {

Expand All @@ -43,21 +42,15 @@ public TagsJsonProvider() {
setFieldName(FIELD_TAGS);
}

@SuppressWarnings("deprecation")
@Override
public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
/*
* Don't write the tags field unless we actually have a tag to write.
*/
boolean hasWrittenStart = false;

if (LogbackUtils.isVersion13()) {
hasWrittenStart = writeTagIfNecessary(generator, hasWrittenStart, event.getMarkerList());
}
else {
hasWrittenStart = writeTagIfNecessary(generator, hasWrittenStart, event.getMarker());
}


hasWrittenStart = writeTagIfNecessary(generator, hasWrittenStart, event.getMarkerList());

if (hasWrittenStart) {
generator.writeEndArray();
}
Expand Down
21 changes: 0 additions & 21 deletions src/main/java/net/logstash/logback/util/LogbackUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,16 @@
*/
package net.logstash.logback.util;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.LifeCycle;

public abstract class LogbackUtils {

private static final boolean IS_VERSION_13 = hasMethod(LoggerContext.class, "getSequenceNumberGenerator");

private LogbackUtils() {
// utility class
}

private static boolean hasMethod(Class<?> clazz, String name, Class<?>... args) {
try {
return clazz.getMethod(name, args) != null;
}
catch (NoSuchMethodException e) {
return false;
}
}

/**
* Indicate if Logback is at least version 1.3
*
* @return {@code true} if Logback is at least version 1.3.0, {@code false} otherwise.
*/
public static boolean isVersion13() {
return IS_VERSION_13;
}

public static void start(Object component) {
if (component instanceof LifeCycle) {
((LifeCycle) component).start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.util.TimeZone;

import net.logstash.logback.composite.AbstractFormattedTimestampJsonProvider;
import net.logstash.logback.util.LogbackUtils;

import ch.qos.logback.classic.spi.ILoggingEvent;
import com.fasterxml.jackson.core.JsonGenerator;
Expand All @@ -42,23 +41,16 @@ public class LoggingEventFormattedTimestampJsonProviderTest {
@Mock
private JsonGenerator generator;

@Mock(lenient = true)
@Mock(strictness = Mock.Strictness.LENIENT)
private ILoggingEvent event;

private Instant now;

@BeforeEach
public void setup() {
// Logback has nano precision since version 1.3
if (LogbackUtils.isVersion13()) {
now = Instant.now();
when(event.getTimeStamp()).thenReturn(now.toEpochMilli());
when(event.getInstant()).thenReturn(now);
}
else {
now = Instant.ofEpochMilli(System.currentTimeMillis());
when(event.getTimeStamp()).thenReturn(now.toEpochMilli());
}
now = Instant.now();
when(event.getTimeStamp()).thenReturn(now.toEpochMilli());
when(event.getInstant()).thenReturn(now);
}


Expand Down
Loading

0 comments on commit af9f826

Please sign in to comment.