Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 2bc0371

Browse files
LaunchDarklyReleaseBoteli-darklyLaunchDarklyCIgwhelanLDssrm
authored
prepare 5.10.0 release (#273)
* misc fixes/tests * use java-sdk-common 1.0.0 * use okhttp-eventsource 2.3.0 * use okhttp-eventsource 2.3.1 for thread fix * fix flaky tests due to change in EventSource error reporting * remove support for indirect put and indirect patch * fix typo in javadoc example code * clean up polling logic, fix status updating after an outage, don't reinit store unnecessarily (#256) * slightly change semantics of boolean setters, improve tests, misc cleanup * avoid NPEs if LDUser was deserialized by Gson (#257) * avoid NPEs if LDUser was deserialized by Gson * add test * fix release metadata * prepare 4.14.1 release (#200) * Releasing version 4.14.1 * exclude Kotlin metadata from jar + fix misc Gradle problems * update CI and Gradle to test with newer JDKs (#259) * update okhttp to 3.14.9 (fixes incompatibility with OpenJDK 8.0.252) * prepare 4.14.2 release (#205) * Releasing version 4.14.2 * update okhttp to 4.8.1 (fixes incompatibility with OpenJDK 8.0.252) * gitignore * Bump SnakeYAML from 1.19 to 1.26 to address CVE-2017-18640 * prepare 4.14.3 release (#209) * Releasing version 4.14.3 * comments * only log initialization message once in polling mode * [ch89935] Correct some logging call format strings (#264) Also adds debug logs for full exception information in a couple locations. * [ch90109] Remove outdated trackMetric comment from before service support. (#265) * Fix compatibility with Java 7. * Remove import that is no longer used. * add Java 7 build (#267) * prepare 4.14.4 release (#214) * Releasing version 4.14.4 * add and use getSocketFactory * alignment * add socketFactory to builder * test socket factory builder * preserve dummy CI config file when pushing to gh-pages (#271) * fix concatenation when base URI has a context path (#270) * fix shaded jar builds to exclude Jackson classes and not modify Jackson return types (#268) * add test httpClientCanUseCustomSocketFactory for DefaultFeatureRequestor * add httpClientCanUseCustomSocketFactory() test for DefaultEventSenderTest * add httpClientCanUseCustomSocketFactory() test to StreamProcessorTest * pass URI to in customSocketFactory event test * make test less ambiguous * copy rules to new FlagBuilder instances (#273) * Bump guava version (#274) * Removed the guides link * increment versions when loading file data, so FlagTracker will work (#275) * increment versions when loading file data, so FlagTracker will work * update doc comment about flag change events with file data * add ability to ignore duplicate keys in file data (#276) * add alias events (#278) * add alias events and function * update tests for new functionality * update javadoc strings * add validation of javadoc build to CI * update commons-codec to 1.15 (#279) * Add support for experiment rollouts * add tests and use seed for allocating user to partition * test serialization and add check for isExperiment * fix PollingProcessorTest test race condition + other test issues (#282) * use launchdarkly-java-sdk-common 1.1.0-alpha-expalloc.2 * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * Update src/test/java/com/launchdarkly/sdk/server/EvaluatorTest.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * changes per code review comments * Please enter the commit message for your changes. Lines starting * fix null pointer exception * address code review comments * address more comments * missed a ! for isUntracked() * fix default boolean for json * make untracked FALSE by default * refactoring of bucketing logic to remove the need for an extra result object (#283) * add comment to enum * various JSON fixes, update common-sdk (#284) * simlpify the logic and make it match node/.Net sdks * Update src/main/java/com/launchdarkly/sdk/server/EventFactory.java Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> * add the same comment as the Node SDK * Remove outdated/meaningless doc comment. (#286) * protect against NPEs if flag/segment JSON contains a null value * use java-sdk-common 1.2.0 * fix Jackson-related build issues (again) (#288) * update to okhttp-eventsource patch for stream retry bug, improve tests (#289) * update to okhttp-eventsource patch for stream retry bug, improve test * add test for appropriate stream retry * add public builder for FeatureFlagsState (#290) * add public builder for FeatureFlagsState * javadoc fixes * clarify FileData doc comment to say you shouldn't use offline mode (#291) * improve validation of SDK key so we won't throw an exception that contains the key (#293) * fix javadoc link in FileData comment (#294) * fix PollingProcessor 401 behavior and use new HTTP test helpers (#292) * re-fix metadata to remove Jackson dependencies, also remove Class-Path from manifest (#295) * make FeatureFlagsState.Builder.build() public (#297) * clean up tests using java-test-helpers 1.1.0 (#296) * use Releaser v2 config + newer CI images (#298) * [ch123129] Fix `PollingDataSourceBuilder` example. (#299) * Updates docs URLs * always use US locale when parsing HTTP dates * use Gson 2.8.9 * don't try to send more diagnostic events after an unrecoverable HTTP error * ensure module-info file isn't copied into our jars during build * use Gradle 7 * update build for benchmarks * more Gradle 7 compatibility changes for benchmark job * test with Java 17 in CI (#307) * test with Java 17 in CI * also test in Java 17 for Windows * fix choco install command * do date comparisons as absolute times, regardless of time zone (#310) * fix suppression of nulls in JSON representations (#311) * fix suppression of nulls in JSON representations * distinguish between situations where we do or do not want to suppress nulls * fix identify/track null user key check, also don't create index event for alias * use latest java-sdk-common * fix setting of trackEvents/trackReason in allFlagsState data when there's an experiment * implement contract tests (#314) * Merge Big Segments feature branch for 5.7.0 release (#316) Includes Big Segments implementation and contract test support for the new behavior. * Fix for pom including SDK common library as a dependency. (#317) * use new logging API * update readme notes about logging * set base logger name for SDK per test * comment * javadoc fixes * revert accidental commit * Upload JUnit XML to CircleCI on failure (#320) Fix a bug in the CircleCI config that was only uploading JUnit XML on _success_, not failure. * Add application tag support (#319) * Enforce 64 character limit on application tag values (#323) * fix "wrong type" logic in evaluations when default value is null * Rename master to main in .ldrelease/config.yml (#325) * Simpler way of setting base URIs in Java (#322) Now supports the `ServiceEndpoints` config for setting custom URIs for endpoints in a single place * update logging info in readme * use 1.0.0 release of logging package * misc cleanup * remove unnecessary extra interfaces, just use default methods instead * make BigSegmentStoreWrapper.pollingDetectsStaleStatus test less timing-sensitive * make LDEndToEndClientTest.test____SpecialHttpConfigurations less timing-sensitive * make data source status tests less timing-sensitive * use streaming JSON parsing for incoming LD data * fix tests * rm unused * rm unused * use okhttp-eventsource 2.6.0 * update eventsource to 2.6.1 to fix pom/manifest problem * increase efficiency of summary event data structures (#335) * make reusable EvaluationDetail instances as part of flag preprocessing (#336) * make evaluator result object immutable and reuse instances * comment * avoid creating List iterators during evaluations * remove unnecessary copy * fix allFlagsState to not generate prereq eval events * add "...ForAll" TestData methods to replace "...ForAllUsers" * bump okhttp & okhttp-eventsource dependencies * update comment to clarify that level() doesn't apply to SLF4J * update readme to mention different logging examples in hello-java * switch to use snapshot build of java-logging, pending next release * level setting does not apply to SLF4J and JUL * use java-logging 1.1.0 release * make sure META-INF files are never mistaken for classes and relocated * update shared data store test logic to pass ClientContext with logger * enable external javadoc links for com.launchdarkly.logging types * use variable for dependency version Co-authored-by: Eli Bishop <eli@launchdarkly.com> Co-authored-by: LaunchDarklyCI <dev@launchdarkly.com> Co-authored-by: LaunchDarklyCI <LaunchDarklyCI@users.noreply.github.com> Co-authored-by: Gavin Whelan <gwhelan@launchdarkly.com> Co-authored-by: ssrm <ssrm@users.noreply.github.com> Co-authored-by: Harpo Roeder <hroeder@launchdarkly.com> Co-authored-by: Ben Woskow <48036130+bwoskow-ld@users.noreply.github.com> Co-authored-by: Elliot <35050275+Apache-HB@users.noreply.github.com> Co-authored-by: Robert J. Neal <rneal@launchdarkly.com> Co-authored-by: Robert J. Neal <robertjneal@users.noreply.github.com> Co-authored-by: Sam Stokes <sstokes@launchdarkly.com> Co-authored-by: LaunchDarklyReleaseBot <launchdarklyreleasebot@launchdarkly.com> Co-authored-by: Ember Stevens <ember.stevens@launchdarkly.com> Co-authored-by: ember-stevens <79482775+ember-stevens@users.noreply.github.com> Co-authored-by: Alex Engelberg <alex.benjamin.engelberg@gmail.com> Co-authored-by: Alex Engelberg <aengelberg@launchdarkly.com>
1 parent 9364f98 commit 2bc0371

File tree

76 files changed

+1158
-565
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1158
-565
lines changed

CONTRIBUTING.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,15 @@ The project in the `benchmarks` subdirectory uses [JMH](https://openjdk.java.net
5656

5757
### Logging
5858

59-
Currently the SDK uses SLF4J for all log output. Here some things to keep in mind for good logging behavior:
59+
The SDK uses a LaunchDarkly logging facade, [`com.launchdarkly.logging`](https://github.com/launchdarkly/java-logging). By default, this facade sends output to SLF4J.
60+
61+
Here some things to keep in mind for good logging behavior:
6062

6163
1. Stick to the standardized logger name scheme defined in `Loggers.java`, preferably for all log output, but definitely for all log output above `DEBUG` level. Logger names can be useful for filtering log output, so it is desirable for users to be able to reference a clear, stable logger name like `com.launchdarkly.sdk.server.LDClient.Events` rather than a class name like `com.launchdarkly.sdk.server.EventSummarizer` which is an implementation detail. The text of a log message should be distinctive enough that we can easily find which class generated the message.
6264

63-
2. Use parameterized messages (`Logger.MAIN.info("The value is {}", someValue)`) rather than string concatenation (`Logger.MAIN.info("The value is " + someValue)`). This avoids the overhead of string concatenation if the logger is not enabled for that level. If computing the value is an expensive operation, and it is _only_ relevant for logging, consider implementing that computation via a custom `toString()` method on some wrapper type so that it will be done lazily only if the log level is enabled.
65+
2. Use parameterized messages (`logger.info("The value is {}", someValue)`) rather than string concatenation (`logger.info("The value is " + someValue)`). This avoids the overhead of string concatenation if the logger is not enabled for that level. If computing the value is an expensive operation, and it is _only_ relevant for logging, consider implementing that computation via a custom `toString()` method on some wrapper type so that it will be done lazily only if the log level is enabled.
6466

65-
3. Exception stacktraces should only be logged at debug level. For instance: `Logger.MAIN.warn("An error happened: {}", ex.toString()); Logger.MAIN.debug(ex.toString(), ex)`. Also, consider whether the stacktrace would be at all meaningful in this particular context; for instance, in a `try` block around a network I/O operation, the stacktrace would only tell us (a) some internal location in Java standard libraries and (b) the location in our own code where we tried to do the operation; (a) is very unlikely to tell us anything that the exception's type and message doesn't already tell us, and (b) could be more clearly communicated by just writing a specific log message.
67+
3. There is a standard pattern for logging exceptions, using the `com.launchdarkly.logging.LogValues` helpers. First, log the basic description of the exception at whatever level is appropriate (`WARN` or `ERROR`): `logger.warn("An error happened: {}", LogValues.exceptionSummary(ex))`. Then, log a stack at debug level: `logger.debug(LogValues.exceptionTrace(ex))`. The `exceptionTrace` helper is lazily evaluated so that the stacktrace will only be computed if debug logging is actually enabled. However, consider whether the stacktrace would be at all meaningful in this particular context; for instance, in a `try` block around a network I/O operation, the stacktrace would only tell us (a) some internal location in Java standard libraries and (b) the location in our own code where we tried to do the operation; (a) is very unlikely to tell us anything that the exception's type and message doesn't already tell us, and (b) could be more clearly communicated by just writing a specific log message.
6668

6769
### Code coverage
6870

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ Refer to the [SDK reference guide](https://docs.launchdarkly.com/sdk/server-side
2727

2828
## Logging
2929

30-
The LaunchDarkly SDK uses [SLF4J](https://www.slf4j.org/). All loggers are namespaced under `com.launchdarkly`. For an example configuration check out the [hello-java](https://github.com/launchdarkly/hello-java) project.
30+
By default, the LaunchDarkly SDK uses [SLF4J](https://www.slf4j.org/). SLF4J has its own configuration mechanisms for determining where output will go, and filtering by level and/or logger name.
31+
32+
The SDK can also be configured to use other adapters from the [com.launchdarkly.logging](https://github.com/launchdarkly/java-logging) facade instead of SLF4J. See `LoggingConfigurationBuilder`. This allows the logging behavior to be completely determined by the application, rather than by external SLF4J configuration.
33+
34+
For an example of using the default SLF4J behavior with a simple console logging configuration, check out the [`slf4j-logging` branch](https://github.com/launchdarkly/hello-java/tree/slf4j-logging) of the [`hello-java`](https://github.com/launchdarkly/hello-java) project. The [main branch](https://github.com/launchdarkly/hello-java) of `hello-java` uses console logging that is programmatically configured without SLF4J.
35+
36+
All loggers are namespaced under `com.launchdarkly`, if you are using name-based filtering.
3137

3238
Be aware of two considerations when enabling the DEBUG log level:
3339
1. Debug-level logs can be very verbose. It is not recommended that you turn on debug logging in high-volume environments.

benchmarks/src/jmh/java/com/launchdarkly/sdk/server/LDClientEvaluationBenchmarks.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public BenchmarkInputs() {
5454
.dataStore(specificDataStore(dataStore))
5555
.events(Components.noEvents())
5656
.dataSource(Components.externalUpdatesOnly())
57+
.logging(Components.noLogging())
5758
.build();
5859
client = new LDClient(SDK_KEY, config);
5960

build.gradle

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ ext.versions = [
7373
"guava": "30.1-jre",
7474
"jackson": "2.11.2",
7575
"launchdarklyJavaSdkCommon": "1.3.0",
76+
"launchdarklyLogging": "1.1.0",
7677
"okhttp": "4.9.3", // specify this for the SDK build instead of relying on the transitive dependency from okhttp-eventsource
7778
"okhttpEventsource": "2.6.2",
7879
"slf4j": "1.7.21",
@@ -131,6 +132,7 @@ libraries.internal = [
131132
// also as package exports (i.e. it provides them if a newer version is not available
132133
// from an import).
133134
libraries.external = [
135+
"com.launchdarkly:launchdarkly-logging:${versions.launchdarklyLogging}",
134136
"org.slf4j:slf4j-api:${versions.slf4j}"
135137
]
136138

@@ -322,6 +324,14 @@ javadoc {
322324
// Use test classpath so Javadoc won't complain about java-sdk-common classes that internally
323325
// reference stuff we don't use directly, like Jackson
324326
classpath = sourceSets.test.compileClasspath
327+
328+
// The following should allow hyperlinks to com.launchdarkly.logging classes to go to
329+
// the correct external URLs
330+
if (options instanceof StandardJavadocDocletOptions) {
331+
(options as StandardJavadocDocletOptions).links(
332+
"https://javadoc.io/doc/com.launchdarkly/launchdarkly-logging/${versions.launchdarklyLogging}"
333+
)
334+
}
325335
}
326336

327337
// Force the Javadoc build to fail if there are any Javadoc warnings. See: https://discuss.gradle.org/t/javadoc-fail-on-warning/18141/3

contract-tests/service/src/main/java/sdktest/SdkClientEntity.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public SdkClientEntity(TestService owner, CreateInstanceParams params) {
4242
this.logger = LoggerFactory.getLogger(params.tag);
4343
logger.info("Starting SDK client");
4444

45-
LDConfig config = buildSdkConfig(params.configuration);
45+
LDConfig config = buildSdkConfig(params.configuration, params.tag);
4646
this.client = new LDClient(params.configuration.credential, config);
4747
if (!client.isInitialized() && !params.configuration.initCanFail) {
4848
throw new RuntimeException("client initialization failed or timed out");
@@ -184,9 +184,11 @@ public void close() {
184184
logger.info("Test ended");
185185
}
186186

187-
private LDConfig buildSdkConfig(SdkConfigParams params) {
187+
private LDConfig buildSdkConfig(SdkConfigParams params, String tag) {
188188
LDConfig.Builder builder = new LDConfig.Builder();
189189

190+
builder.logging(Components.logging().baseLoggerName(tag + ".sdk"));
191+
190192
if (params.startWaitTimeMs != null) {
191193
builder.startWait(Duration.ofMillis(params.startWaitTimeMs.longValue()));
192194
}

src/main/java/com/launchdarkly/sdk/server/BigSegmentStoreWrapper.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.google.common.cache.CacheBuilder;
66
import com.google.common.cache.CacheLoader;
77
import com.google.common.cache.LoadingCache;
8+
import com.launchdarkly.logging.LDLogger;
89
import com.launchdarkly.sdk.EvaluationReason.BigSegmentsStatus;
910
import com.launchdarkly.sdk.server.interfaces.BigSegmentStore;
1011
import com.launchdarkly.sdk.server.interfaces.BigSegmentStoreStatusProvider.Status;
@@ -15,7 +16,6 @@
1516

1617
import org.apache.commons.codec.digest.DigestUtils;
1718
import org.checkerframework.checker.nullness.qual.NonNull;
18-
import org.slf4j.Logger;
1919

2020
import java.io.Closeable;
2121
import java.io.IOException;
@@ -27,23 +27,23 @@
2727
import java.util.concurrent.TimeUnit;
2828

2929
class BigSegmentStoreWrapper implements Closeable {
30-
private static final Logger logger = Loggers.BIG_SEGMENTS;
31-
3230
private final BigSegmentStore store;
3331
private final Duration staleAfter;
3432
private final ScheduledFuture<?> pollFuture;
3533
private final LoadingCache<String, Membership> cache;
3634
private final EventBroadcasterImpl<StatusListener, Status> statusProvider;
37-
35+
private final LDLogger logger;
3836
private final Object statusLock = new Object();
3937
private Status lastStatus;
4038

4139
BigSegmentStoreWrapper(BigSegmentsConfiguration config,
4240
EventBroadcasterImpl<StatusListener, Status> statusProvider,
43-
ScheduledExecutorService sharedExecutor) {
41+
ScheduledExecutorService sharedExecutor,
42+
LDLogger logger) {
4443
this.store = config.getStore();
4544
this.staleAfter = config.getStaleAfter();
4645
this.statusProvider = statusProvider;
46+
this.logger = logger;
4747

4848
CacheLoader<String, Membership> loader = new CacheLoader<String, Membership>() {
4949
@Override

src/main/java/com/launchdarkly/sdk/server/ClientContextImpl.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.launchdarkly.sdk.server;
22

3-
import com.launchdarkly.sdk.server.interfaces.ApplicationInfo;
3+
import com.launchdarkly.logging.LDLogger;
4+
import com.launchdarkly.logging.Logs;
45
import com.launchdarkly.sdk.server.interfaces.BasicConfiguration;
56
import com.launchdarkly.sdk.server.interfaces.ClientContext;
67
import com.launchdarkly.sdk.server.interfaces.HttpConfiguration;
@@ -52,11 +53,35 @@ private ClientContextImpl(
5253
ScheduledExecutorService sharedExecutor,
5354
DiagnosticAccumulator diagnosticAccumulator
5455
) {
55-
this.basicConfiguration = new BasicConfiguration(sdkKey, configuration.offline, configuration.threadPriority, configuration.applicationInfo, configuration.serviceEndpoints);
56+
// There is some temporarily over-elaborate logic here because the component factory interfaces can't
57+
// be updated to make the dependencies more sensible till the next major version.
58+
BasicConfiguration tempBasic = new BasicConfiguration(sdkKey, configuration.offline, configuration.threadPriority,
59+
configuration.applicationInfo, configuration.serviceEndpoints, LDLogger.none());
60+
this.loggingConfiguration = configuration.loggingConfigFactory.createLoggingConfiguration(tempBasic);
61+
LDLogger baseLogger = LDLogger.withAdapter(
62+
loggingConfiguration.getLogAdapter() == null ? Logs.none() : loggingConfiguration.getLogAdapter(),
63+
loggingConfiguration.getBaseLoggerName() == null ? Loggers.BASE_LOGGER_NAME :
64+
loggingConfiguration.getBaseLoggerName()
65+
);
66+
67+
this.basicConfiguration = new BasicConfiguration(
68+
sdkKey,
69+
configuration.offline,
70+
configuration.threadPriority,
71+
configuration.applicationInfo,
72+
configuration.serviceEndpoints,
73+
baseLogger
74+
);
5675

5776
this.httpConfiguration = configuration.httpConfigFactory.createHttpConfiguration(basicConfiguration);
58-
this.loggingConfiguration = configuration.loggingConfigFactory.createLoggingConfiguration(basicConfiguration);
59-
77+
78+
79+
if (this.httpConfiguration.getProxy() != null) {
80+
baseLogger.info("Using proxy: {} {} authentication.",
81+
this.httpConfiguration.getProxy(),
82+
this.httpConfiguration.getProxyAuthentication() == null ? "without" : "with");
83+
}
84+
6085
this.sharedExecutor = sharedExecutor;
6186

6287
if (!configuration.diagnosticOptOut && diagnosticAccumulator != null) {

src/main/java/com/launchdarkly/sdk/server/Components.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import static com.launchdarkly.sdk.server.ComponentsImpl.NULL_EVENT_PROCESSOR_FACTORY;
44

5+
import com.launchdarkly.logging.LDLogAdapter;
6+
import com.launchdarkly.logging.Logs;
57
import com.launchdarkly.sdk.server.ComponentsImpl.EventProcessorBuilderImpl;
68
import com.launchdarkly.sdk.server.ComponentsImpl.HttpBasicAuthentication;
79
import com.launchdarkly.sdk.server.ComponentsImpl.HttpConfigurationBuilderImpl;
@@ -316,14 +318,63 @@ public static HttpAuthentication httpBasicAuthentication(String username, String
316318
* .build();
317319
* </code></pre>
318320
*
319-
* @return a factory object
321+
* @return a configuration builder
320322
* @since 5.0.0
321323
* @see LDConfig.Builder#logging(com.launchdarkly.sdk.server.interfaces.LoggingConfigurationFactory)
322324
*/
323325
public static LoggingConfigurationBuilder logging() {
324326
return new LoggingConfigurationBuilderImpl();
325327
}
326328

329+
/**
330+
* Returns a configuration builder for the SDK's logging configuration, specifying the
331+
* implementation of logging to use.
332+
* <p>
333+
* This is a shortcut for <code>Components.logging().adapter(logAdapter)</code>. The
334+
* <a href="https://github.com/launchdarkly/java-logging"><code>com.launchdarkly.logging</code></a>
335+
* API defines the {@link LDLogAdapter} interface to specify where log output should be sent. By default,
336+
* it is set to {@link com.launchdarkly.logging.LDSLF4J#adapter()}, meaning that output will be sent to
337+
* <a href="https://www.slf4j.org/">SLF4J</a> and controlled by the SLF4J configuration. You may use
338+
* the {@link com.launchdarkly.logging.Logs} factory methods, or a custom implementation, to handle log
339+
* output differently. For instance, you may specify {@link com.launchdarkly.logging.Logs#basic()} for
340+
* simple console output, or {@link com.launchdarkly.logging.Logs#toJavaUtilLogging()} to use the
341+
* <code>java.util.logging</code> framework.
342+
* <p>
343+
* Passing this to {@link LDConfig.Builder#logging(com.launchdarkly.sdk.server.interfaces.LoggingConfigurationFactory)},
344+
* after setting any desired properties on the builder, applies this configuration to the SDK.
345+
* <pre><code>
346+
* LDConfig config = new LDConfig.Builder()
347+
* .logging(
348+
* Components.logging(Logs.basic())
349+
* )
350+
* .build();
351+
* </code></pre>
352+
*
353+
* @param logAdapter the log adapter
354+
* @return a configuration builder
355+
* @since 5.10.0
356+
* @see LDConfig.Builder#logging(com.launchdarkly.sdk.server.interfaces.LoggingConfigurationFactory)
357+
* @see LoggingConfigurationBuilder#adapter(LDLogAdapter)
358+
*/
359+
public static LoggingConfigurationBuilder logging(LDLogAdapter logAdapter) {
360+
return logging().adapter(logAdapter);
361+
}
362+
363+
/**
364+
* Returns a configuration builder that turns off SDK logging.
365+
* <p>
366+
* Passing this to {@link LDConfig.Builder#logging(com.launchdarkly.sdk.server.interfaces.LoggingConfigurationFactory)}
367+
* applies this configuration to the SDK.
368+
* <p>
369+
* It is equivalent to <code>Components.logging(com.launchdarkly.logging.Logs.none())</code>.
370+
*
371+
* @return a configuration builder
372+
* @since 5.10.0
373+
*/
374+
public static LoggingConfigurationBuilder noLogging() {
375+
return logging().adapter(Logs.none());
376+
}
377+
327378
/**
328379
* Returns a configuration builder for the SDK's application metadata.
329380
* <p>

0 commit comments

Comments
 (0)