Skip to content

Commit

Permalink
feat: Add support for batching configuration (#977)
Browse files Browse the repository at this point in the history
* feat: Add support for batching configuration

* Add space

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* Remove redundant HTML appender tag

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* Add failing dependencies

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
losalex and gcf-owl-bot[bot] authored Jan 11, 2023
1 parent d93c150 commit afbe09c
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 6 deletions.
18 changes: 16 additions & 2 deletions .readme-partials.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ custom_content: |
<log>application.log</log>
<!-- Optional: defaults to "ERROR" -->
<flushLevel>WARNING</flushLevel>
<flushLevel>WARN</flushLevel>
<!-- Optional: defaults to ASYNC -->
<writeSynchronicity>SYNC</writeSynchronicity>
Expand All @@ -43,7 +43,21 @@ custom_content: |
<!-- Optional: specifies if a batch's valid entries should be written even if some other entry failed due to an error. Defaults to true
See [partial_success](https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write#body.request_body.FIELDS.partial_success) for more info -->
<partialSuccess>true</partialSuccess>
<partialSuccess>true</partialSuccess>
<!-- Optional: In the asynchronous mode the call(s) to Logging API takes place asynchronously and few calls to `write()`
method may be batched together to compose a single call to Logging API. In order to control the batching settings,
the `logbackBatchingSettings` section can be used as shown below.
See [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings)
for more info regarding parameters shown below -->
<logbackBatchingSettings>
<elementCountThreshold>100</elementCountThreshold>
<requestByteThreshold>1000</requestByteThreshold>
<delayThreshold>500</delayThreshold>
<maxOutstandingElementCount>10000</maxOutstandingElementCount>
<maxOutstandingRequestBytes>100000</maxOutstandingRequestBytes>
<limitExceededBehavior>Ignore</limitExceededBehavior>
</logbackBatchingSettings>
</appender>
<root level="info">
Expand Down
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ See [Logback filters](https://logback.qos.ch/manual/filters.html#thresholdFilter
<log>application.log</log>

<!-- Optional: defaults to "ERROR" -->
<flushLevel>WARNING</flushLevel>
<flushLevel>WARN</flushLevel>

<!-- Optional: defaults to ASYNC -->
<writeSynchronicity>SYNC</writeSynchronicity>
Expand All @@ -114,7 +114,21 @@ See [Logback filters](https://logback.qos.ch/manual/filters.html#thresholdFilter

<!-- Optional: specifies if a batch's valid entries should be written even if some other entry failed due to an error. Defaults to true
See [partial_success](https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write#body.request_body.FIELDS.partial_success) for more info -->
<partialSuccess>true</partialSuccess>
<partialSuccess>true</partialSuccess>

<!-- Optional: In the asynchronous mode the call(s) to Logging API takes place asynchronously and few calls to `write()`
method may be batched together to compose a single call to Logging API. In order to control the batching settings,
the `logbackBatchingSettings` section can be used as shown below.
See [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings)
for more info regarding parameters shown below -->
<logbackBatchingSettings>
<elementCountThreshold>100</elementCountThreshold>
<requestByteThreshold>1000</requestByteThreshold>
<delayThreshold>500</delayThreshold>
<maxOutstandingElementCount>10000</maxOutstandingElementCount>
<maxOutstandingRequestBytes>100000</maxOutstandingRequestBytes>
<limitExceededBehavior>Ignore</limitExceededBehavior>
</logbackBatchingSettings>
</appender>

<root level="info">
Expand Down
10 changes: 9 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>com.google.api</groupId>
<artifactId>gax</artifactId>
</dependency>
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
</dependency>
</dependencies>

<reporting>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2023 Google LLC
*
* 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 com.google.cloud.logging.logback;

import com.google.api.gax.batching.BatchingSettings;
import com.google.api.gax.batching.FlowControlSettings;
import com.google.api.gax.batching.FlowController.LimitExceededBehavior;
import org.threeten.bp.Duration;

/**
* This class is used only to provide batch settings configuration in logback.xml since {@link
* com.google.api.gax.batching.BatchingSettings} cannot be used as is with logback configuration
* described in https://logback.qos.ch/manual/configuration.html. All data members below are simply
* copy of {@link com.google.api.gax.batching.BatchingSettings} class, so it could be used with
* logback.xml.
*/
public class LogbackBatchingSettings {
private Long elementCountThreshold = null;
private Long requestByteThreshold = null;
private Long delayThreshold = null;
private Long maxOutstandingElementCount = null;
private Long maxOutstandingRequestBytes = null;
private LimitExceededBehavior limitExceededBehavior = null;

public void setElementCountThreshold(Long value) {
elementCountThreshold = value;
}

public void setRequestByteThreshold(Long value) {
requestByteThreshold = value;
}

public void setDelayThreshold(Long value) {
delayThreshold = value;
}

public void setMaxOutstandingElementCount(Long value) {
maxOutstandingElementCount = value;
}

public void setMaxOutstandingRequestBytes(Long value) {
maxOutstandingRequestBytes = value;
}

public void setLimitExceededBehavior(LimitExceededBehavior value) {
limitExceededBehavior = value;
}

public BatchingSettings build() {
BatchingSettings.Builder settings = BatchingSettings.newBuilder();
if (elementCountThreshold != null) {
settings.setElementCountThreshold(elementCountThreshold);
}
if (requestByteThreshold != null) {
settings.setRequestByteThreshold(requestByteThreshold);
}
if (delayThreshold != null) {
settings.setDelayThreshold(Duration.ofMillis(delayThreshold));
}
if (maxOutstandingElementCount != null
|| maxOutstandingRequestBytes != null
|| limitExceededBehavior != null) {
FlowControlSettings.Builder flowControlSettings = FlowControlSettings.newBuilder();
flowControlSettings.setMaxOutstandingElementCount(maxOutstandingElementCount);
flowControlSettings.setMaxOutstandingRequestBytes(maxOutstandingRequestBytes);
if (limitExceededBehavior != null) {
flowControlSettings.setLimitExceededBehavior(limitExceededBehavior);
}
settings.setFlowControlSettings(flowControlSettings.build());
}
return settings.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
* &lt;log&gt;application.log&lt;/log&gt;
*
* &lt;!-- Optional: defaults to {@code "ERROR"} --&gt;
* &lt;flushLevel&gt;WARNING&lt;/flushLevel&gt;
* &lt;flushLevel&gt;WARN&lt;/flushLevel&gt;
*
* &lt;!-- Optional: defaults to {@code ASYNC} --&gt;
* &lt;writeSynchronicity&gt;SYNC&lt;/writeSynchronicity&gt;
Expand Down Expand Up @@ -91,6 +91,20 @@
*
* &lt;!-- 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} --&gt;
* &lt;partialSuccess&gt;true&lt;/partialSuccess&gt;
*
* &lt;!-- Optional: In the asynchronous mode the call(s) to Logging API takes place asynchronously and few calls to `write()`
* method may be batched together to compose a single call to Logging API. In order to control the batching settings,
* the `logbackBatchingSettings` section can be used as shown below.
* See [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings)
* for more info regarding parameters shown below --&gt;
* &lt;logbackBatchingSettings&gt;
* &lt;elementCountThreshold&gt;100&lt;/elementCountThreshold&gt;
* &lt;requestByteThreshold&gt;1000&lt;/requestByteThreshold&gt;
* &lt;delayThreshold&gt;500&lt;/delayThreshold&gt;
* &lt;maxOutstandingElementCount&gt;10000&lt;/maxOutstandingElementCount&gt;
* &lt;maxOutstandingRequestBytes&gt;100000&lt;/maxOutstandingRequestBytes&gt;
* &lt;limitExceededBehavior&gt;Ignore&lt;/limitExceededBehavior&gt;
* &lt;/logbackBatchingSettings&gt;
* &lt;/appender&gt;
* </pre>
*/
Expand Down Expand Up @@ -131,6 +145,7 @@ public class LoggingAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
private Synchronicity writeSyncFlag = Synchronicity.ASYNC;
private final Set<String> enhancerClassNames = new HashSet<>();
private final Set<String> loggingEventEnhancerClassNames = new HashSet<>();
private LogbackBatchingSettings logbackBatchingSettings = null;

/**
* Sets a threshold for log severity level to flush all log entries that were batched so far.
Expand Down Expand Up @@ -224,6 +239,19 @@ public void setRedirectToStdout(boolean flag) {
redirectToStdout = flag;
}

/**
* Sets the {@link LogbackBatchingSettings} to be used for the asynchronous mode call(s) to
* Logging API
*
* <p>Default to {@code null}.
*
* @param batchingSettings the {@link LogbackBatchingSettings} to be used for asynchronous mode
* call(s) to Logging API
*/
public void setLogbackBatchingSettings(LogbackBatchingSettings batchingSettings) {
logbackBatchingSettings = batchingSettings;
}

/**
* Sets the flag indicating if a batch's valid entries should be written even if some other entry
* failed due to an error.
Expand Down Expand Up @@ -430,6 +458,8 @@ protected LoggingOptions getLoggingOptions() {
}
// opt-out metadata auto-population to control it in the appender code
builder.setAutoPopulateMetadata(false);
builder.setBatchingSettings(
this.logbackBatchingSettings != null ? this.logbackBatchingSettings.build() : null);
loggingOptions = builder.build();
}
return loggingOptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2023 Google LLC
*
* 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 com.google.cloud.logging.logback;

import static com.google.common.truth.Truth.assertThat;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import com.google.api.gax.batching.FlowController.LimitExceededBehavior;
import com.google.cloud.logging.LoggingOptions;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingAppenderLogbackTest {
@Test
public void testLoggingOptionsFromLogbackXMLFileConfig() throws JoranException {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset();
jc.doConfigure("src/test/java/com/google/cloud/logging/logback/logback.xml");
Logger logger = LoggerFactory.getLogger(LoggingAppenderLogbackTest.class);
assertThat(logger.getName())
.isEqualTo("com.google.cloud.logging.logback.LoggingAppenderLogbackTest");
LoggingAppender appender = (LoggingAppender) context.getLogger("ROOT").getAppender("CLOUD");
LoggingOptions options = appender.getLoggingOptions();
assertThat(options.getAutoPopulateMetadata()).isEqualTo(false);
assertThat(options.getBatchingSettings().getDelayThreshold().toMillis()).isEqualTo(500);
assertThat(options.getBatchingSettings().getElementCountThreshold()).isEqualTo(100);
assertThat(options.getBatchingSettings().getIsEnabled()).isEqualTo(true);
assertThat(options.getBatchingSettings().getRequestByteThreshold()).isEqualTo(1000);
assertThat(options.getBatchingSettings().getFlowControlSettings().getLimitExceededBehavior())
.isEqualTo(LimitExceededBehavior.Ignore);
assertThat(
options.getBatchingSettings().getFlowControlSettings().getMaxOutstandingElementCount())
.isEqualTo(10000);
assertThat(
options.getBatchingSettings().getFlowControlSettings().getMaxOutstandingRequestBytes())
.isEqualTo(100000);
}
}
57 changes: 57 additions & 0 deletions src/test/java/com/google/cloud/logging/logback/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<configuration>
<appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
<!-- Optional: filter logs at and above this level -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>

<!-- Optional: defaults to "java.log" -->
<log>application.log</log>

<!-- Optional: defaults to "ERROR" -->
<flushLevel>WARN</flushLevel>

<!-- Optional: defaults to ASYNC -->
<writeSynchronicity>SYNC</writeSynchronicity>

<!-- Optional: defaults to true -->
<autoPopulateMetadata>false</autoPopulateMetadata>

<!-- Optional: defaults to false -->
<redirectToStdout>true</redirectToStdout>

<!-- Optional: auto detects on App Engine Flex, Standard, GCE and GKE, defaults to "global". -->
<resourceType>global</resourceType>

<!-- Optional: defaults to the default credentials of the environment -->
<credentialsFile>src/test/java/com/google/cloud/logging/logback/dummy-credentials.json</credentialsFile>

<!-- Optional: defaults to the project id obtained during authentication process. Project id is also used to construct resource name of the log entries -->
<logDestinationProjectId>String</logDestinationProjectId>

<!-- Optional: add custom labels to log entries using LoggingEnhancer classes -->
<!-- <enhancer>com.example.logging.logback.enhancers.ExampleEnhancer</enhancer> -->

<!-- Optional: specifies if a batch's valid entries should be written even if some other entry failed due to an error. Defaults to true
See [partial_success](https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write#body.request_body.FIELDS.partial_success) for more info -->
<partialSuccess>true</partialSuccess>

<!-- Optional: In the asynchronous mode the call(s) to Logging API takes place asynchronously and few calls to `write()`
method may be batched together to compose a single call to Logging API. In order to control the batching settings,
the `logbackBatchingSettings` section can be used as shown below.
See [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings)
for more info regarding parameters shown below -->
<logbackBatchingSettings>
<elementCountThreshold>100</elementCountThreshold>
<requestByteThreshold>1000</requestByteThreshold>
<delayThreshold>500</delayThreshold>
<maxOutstandingElementCount>10000</maxOutstandingElementCount>
<maxOutstandingRequestBytes>100000</maxOutstandingRequestBytes>
<limitExceededBehavior>Ignore</limitExceededBehavior>
</logbackBatchingSettings>
</appender>

<root level="info">
<appender-ref ref="CLOUD" />
</root>
</configuration>

0 comments on commit afbe09c

Please sign in to comment.