diff --git a/.readme-partials.yaml b/.readme-partials.yaml index f25287604..3a9925d33 100644 --- a/.readme-partials.yaml +++ b/.readme-partials.yaml @@ -40,6 +40,10 @@ custom_content: | com.example.enhancers.TestLoggingEnhancer com.example.enhancers.AnotherEnhancer + + + true diff --git a/CHANGELOG.md b/CHANGELOG.md index 071efc679..9d86fac82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog +## [0.127.0](https://github.com/googleapis/java-logging-logback/compare/v0.126.17...v0.127.0) (2022-10-31) + + +### Features + +* Add support for partialSuccess ([#908](https://github.com/googleapis/java-logging-logback/issues/908)) ([1699f70](https://github.com/googleapis/java-logging-logback/commit/1699f708994f462f263218ad32ca50654229e89c)) + ## [0.126.17](https://github.com/googleapis/java-logging-logback/compare/v0.126.16...v0.126.17) (2022-10-28) diff --git a/README.md b/README.md index 3ac3e8a86..e2ed25150 100644 --- a/README.md +++ b/README.md @@ -22,20 +22,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-logging-logback - 0.127.16-alpha + 0.127.17-alpha ``` If you are using Gradle without BOM, add this to your dependencies: ```Groovy -implementation 'com.google.cloud:google-cloud-logging-logback:0.127.16-alpha' +implementation 'com.google.cloud:google-cloud-logging-logback:0.127.17-alpha' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-logging-logback" % "0.127.16-alpha" +libraryDependencies += "com.google.cloud" % "google-cloud-logging-logback" % "0.127.17-alpha" ``` ## Authentication @@ -111,6 +111,10 @@ See [Logback filters](https://logback.qos.ch/manual/filters.html#thresholdFilter com.example.enhancers.TestLoggingEnhancer com.example.enhancers.AnotherEnhancer + + + true diff --git a/pom.xml b/pom.xml index 130303a91..6d64130ec 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 google-cloud-logging-logback - 0.127.17-alpha + 0.128.0-alpha jar Google Cloud Logging Logback Appender https://github.com/googleapis/java-logging-logback diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 40537c70f..363d642ba 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-logging-logback - 0.127.16-alpha + 0.127.17-alpha diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 6887f3493..c9a0eedac 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-logging-logback - 0.127.17-alpha + 0.128.0-alpha diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 58388c4bc..4084e1840 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.3 + 26.1.4 pom import diff --git a/src/main/java/com/google/cloud/logging/logback/LoggingAppender.java b/src/main/java/com/google/cloud/logging/logback/LoggingAppender.java index 2ac038058..d1a94f93b 100644 --- a/src/main/java/com/google/cloud/logging/logback/LoggingAppender.java +++ b/src/main/java/com/google/cloud/logging/logback/LoggingAppender.java @@ -88,6 +88,9 @@ * <!-- Optional: add custom labels to log entries using {@link LoggingEnhancer} classes --> * <enhancer>com.example.enhancers.TestLoggingEnhancer</enhancer> * <enhancer>com.example.enhancers.AnotherEnhancer</enhancer> + * + * <!-- Optional: specifies if a batch's valid entries should be written even if some other entry failed due to an error. Defaults to {@code true} --> + * <partialSuccess>true</partialSuccess> * </appender> * */ @@ -118,6 +121,7 @@ public class LoggingAppender extends UnsynchronizedAppenderBase { private String logDestinationProjectId; private boolean autoPopulateMetadata = true; private boolean redirectToStdout = false; + private boolean partialSuccess = true; private Synchronicity writeSyncFlag = Synchronicity.ASYNC; private final Set enhancerClassNames = new HashSet<>(); private final Set loggingEventEnhancerClassNames = new HashSet<>(); @@ -214,6 +218,18 @@ public void setRedirectToStdout(boolean flag) { redirectToStdout = flag; } + /** + * Sets the flag indicating if a batch's valid entries should be written even if some other entry + * failed due to an error. + * + *

Default to {@code true}. + * + * @param flag the partialSuccess flag. + */ + public void setPartialSuccess(boolean flag) { + partialSuccess = flag; + } + /** Add extra labels using classes that implement {@link LoggingEnhancer}. */ public void addEnhancer(String enhancerClassName) { this.enhancerClassNames.add(enhancerClassName); @@ -298,7 +314,9 @@ public synchronized void start() { defaultWriteOptions = new WriteOption[] { - WriteOption.logName(getLogName()), WriteOption.resource(monitoredResource) + WriteOption.logName(getLogName()), + WriteOption.resource(monitoredResource), + WriteOption.partialSuccess(partialSuccess) }; Level flushLevel = getFlushLevel(); if (flushLevel != Level.OFF) { diff --git a/src/test/java/com/google/cloud/logging/logback/LoggingAppenderTest.java b/src/test/java/com/google/cloud/logging/logback/LoggingAppenderTest.java index f1bdbebf4..ac97cbc3f 100644 --- a/src/test/java/com/google/cloud/logging/logback/LoggingAppenderTest.java +++ b/src/test/java/com/google/cloud/logging/logback/LoggingAppenderTest.java @@ -160,7 +160,8 @@ public void setUp() { new ImmutableMap.Builder() .put("project_id", PROJECT_ID) .build()) - .build()) + .build()), + WriteOption.partialSuccess(true), }; @Test @@ -168,7 +169,10 @@ public void testFlushLevelConfigUpdatesLoggingFlushSeverity() { logging.setFlushSeverity(Severity.WARNING); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); replay(logging); Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); LoggingEvent loggingEvent = createLoggingEvent(Level.WARN, timestamp.getSeconds()); @@ -194,7 +198,10 @@ public void testFilterLogsOnlyLogsAtOrAboveLogLevel() { logging.setFlushSeverity(Severity.ERROR); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); expectLastCall().once(); replay(logging); Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); @@ -215,12 +222,16 @@ public void testFilterLogsOnlyLogsAtOrAboveLogLevel() { } @Test - public void testDefaultWriteOptionsHasExpectedDefaults() { + public void testPartialSuccessOverrideHasExpectedValue() { logging.setFlushSeverity(Severity.ERROR); Capture logNameArg = Capture.newInstance(); Capture resourceArg = Capture.newInstance(); + Capture partialSuccessArg = Capture.newInstance(); logging.write( - EasyMock.>anyObject(), capture(logNameArg), capture(resourceArg)); + EasyMock.>anyObject(), + capture(logNameArg), + capture(resourceArg), + capture(partialSuccessArg)); expectLastCall().once(); replay(logging); loggingAppender.start(); @@ -231,6 +242,26 @@ public void testDefaultWriteOptionsHasExpectedDefaults() { assertThat(logNameArg.getValue()).isEqualTo(defaultWriteOptions[0]); // TODO(chingor): Fix this test to work on GCE and locally // assertThat(resourceArg.getValue()).isEqualTo(defaultWriteOptions[1]); + assertThat(partialSuccessArg.getValue()).isEqualTo(defaultWriteOptions[2]); + } + + @Test + public void testDefaultWriteOptionsHasExpectedDefaults() { + logging.setFlushSeverity(Severity.ERROR); + Capture partialSuccessArg = Capture.newInstance(); + logging.write( + EasyMock.>anyObject(), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + capture(partialSuccessArg)); + expectLastCall().once(); + replay(logging); + loggingAppender.setPartialSuccess(false); + loggingAppender.start(); + Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); + LoggingEvent loggingEvent = createLoggingEvent(Level.ERROR, timestamp.getSeconds()); + loggingAppender.doAppend(loggingEvent); + assertThat(partialSuccessArg.getValue()).isEqualTo(WriteOption.partialSuccess(false)); } @Test @@ -238,7 +269,10 @@ public void testMdcValuesAreConvertedToLabels() { logging.setFlushSeverity(Severity.ERROR); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); expectLastCall().once(); replay(logging); Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); @@ -294,7 +328,10 @@ public void testMdcValuesAreConvertedToLabelsWithPassingNullValues() { logging.setFlushSeverity(Severity.ERROR); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); expectLastCall().once(); replay(logging); Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); @@ -317,7 +354,10 @@ public void testAddCustomLoggingEventEnhancers() { logging.setFlushSeverity(Severity.ERROR); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); expectLastCall().once(); replay(logging); Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); @@ -338,7 +378,10 @@ public void testAddCustomLoggingEnhancer() { logging.setFlushSeverity(Severity.ERROR); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); expectLastCall().once(); replay(logging); loggingAppender.addEnhancer(CustomLoggingEnhancer.class.getName()); @@ -359,6 +402,7 @@ public void testFlush() { logging.write( EasyMock.>anyObject(), anyObject(WriteOption.class), + anyObject(WriteOption.class), anyObject(WriteOption.class)); expectLastCall().times(2); logging.flush(); @@ -395,6 +439,7 @@ public void testAutoPopulationEnabled() { logging.write( EasyMock.>anyObject(), anyObject(WriteOption.class), + anyObject(WriteOption.class), anyObject(WriteOption.class)); expectLastCall().once(); replay(logging); @@ -460,7 +505,10 @@ public void testFDiagnosticInfoAdded() { Capture> capturedArgument = Capture.newInstance(); logging.setFlushSeverity(Severity.ERROR); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); replay(logging); LoggingEvent loggingEvent = createLoggingEvent(Level.ERROR, Timestamp.ofTimeSecondsAndNanos(100000, 0).getSeconds()); @@ -502,7 +550,10 @@ public void testFDiagnosticInfoNotAdded() { logging.setFlushSeverity(Severity.ERROR); Capture> capturedArgument = Capture.newInstance(); logging.write( - capture(capturedArgument), anyObject(WriteOption.class), anyObject(WriteOption.class)); + capture(capturedArgument), + anyObject(WriteOption.class), + anyObject(WriteOption.class), + anyObject(WriteOption.class)); replay(logging); LoggingEvent loggingEvent = createLoggingEvent(Level.WARN, Timestamp.ofTimeSecondsAndNanos(100000, 0).getSeconds()); diff --git a/versions.txt b/versions.txt index 1eb668e7e..6b78553ef 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-logging-logback:0.127.17-alpha:0.127.17-alpha +google-cloud-logging-logback:0.128.0-alpha:0.128.0-alpha