Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

Commit

Permalink
prepare 4.0.0 release (#63)
Browse files Browse the repository at this point in the history
## [4.0.0] - 2023-10-18
### Added:
- Added Automatic Mobile Environment Attributes functionality which
makes it simpler to target your mobile customers based on application
name or version, or on device characteristics including manufacturer,
model, operating system, locale, and so on. To learn more, read
[Automatic environment
attributes](https://docs.launchdarkly.com/sdk/features/environment-attributes).

---------

Co-authored-by: Eli Bishop <[email protected]>
Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: LaunchDarklyReleaseBot <[email protected]>
Co-authored-by: Ryan Lamb <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Ember Stevens <[email protected]>
Co-authored-by: Ember Stevens <[email protected]>
Co-authored-by: Todd Anderson <[email protected]>
Co-authored-by: Casey Waldren <[email protected]>
Co-authored-by: Todd Anderson <[email protected]>
  • Loading branch information
12 people authored Oct 18, 2023
1 parent c5f0e3c commit d34b239
Show file tree
Hide file tree
Showing 37 changed files with 1,351 additions and 344 deletions.
1 change: 1 addition & 0 deletions contract-tests/Representations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class SdkClientSideParams
public Context? InitialContext { get; set; }
public User InitialUser { get; set; }
public bool? UseReport { get; set; }
public bool? IncludeEnvironmentAttributes { get; set; }
}

public class CommandParams
Expand Down
6 changes: 5 additions & 1 deletion contract-tests/SdkClientEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,11 @@ private ContextBuildResponse DoContextConvert(ContextConvertParams p)

private static Configuration BuildSdkConfig(SdkConfigParams sdkParams, ILogAdapter logAdapter, string tag)
{
var builder = Configuration.Builder(sdkParams.Credential);
var autoEnvAttributes = (sdkParams.ClientSide.IncludeEnvironmentAttributes ?? false)
? ConfigurationBuilder.AutoEnvAttributes.Enabled
: ConfigurationBuilder.AutoEnvAttributes.Disabled;

var builder = Configuration.Builder(sdkParams.Credential, autoEnvAttributes);

builder.Logging(Components.Logging(logAdapter).BaseLoggerName(tag + ".SDK"));

Expand Down
5 changes: 3 additions & 2 deletions contract-tests/TestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public class Webapp
"singleton",
"strongly-typed",
"user-type",
"tags"
"tags",
"auto-env-attributes"
};

public readonly Handler Handler;
Expand All @@ -54,7 +55,7 @@ public Webapp(EventWaitHandle quitSignal)
_quitSignal = quitSignal;

_version = LdClient.Version.ToString();

var service = new SimpleJsonService();
Handler = service.Handler;

Expand Down
57 changes: 41 additions & 16 deletions src/LaunchDarkly.ClientSdk/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
using System;
using System.Collections.Immutable;
using LaunchDarkly.Sdk.Client.Integrations;
using LaunchDarkly.Sdk.Client.Interfaces;
using LaunchDarkly.Sdk.Client.Internal.Interfaces;
using LaunchDarkly.Sdk.Client.PlatformSpecific;
using LaunchDarkly.Sdk.Client.Subsystems;

namespace LaunchDarkly.Sdk.Client
{
/// <summary>
/// Configuration options for <see cref="LdClient"/>.
/// Configuration options for <see cref="LdClient"/>.
/// </summary>
/// <remarks>
/// Instances of <see cref="Configuration"/> are immutable once created. They can be created with the factory method
/// <see cref="Configuration.Default(string)"/>, or using a builder pattern with <see cref="Configuration.Builder(string)"/>
/// or <see cref="Configuration.Builder(Configuration)"/>.
/// <see cref="Configuration.Default(string,ConfigurationBuilder.AutoEnvAttributes)"/>, or using a builder pattern
/// with <see cref="ImmutableArray{T}.Builder"/> or <see cref="Configuration.Builder(Configuration)"/>.
/// </remarks>
public sealed class Configuration
{
/// <summary>
/// ApplicationInfo configuration which contains info about the application the SDK is running in.
/// </summary>
public ApplicationInfoBuilder ApplicationInfo { get; }

/// <summary>
/// True if Auto Environment Attributes functionality is enabled. When enabled, the SDK will automatically
/// provide data about the environment where the application is running.
/// </summary>
public bool AutoEnvAttributes { get; }

/// <summary>
/// Default value for <see cref="PollingDataSourceBuilder.BackgroundPollInterval"/> and
/// <see cref="StreamingDataSourceBuilder.BackgroundPollInterval"/>.
Expand Down Expand Up @@ -83,13 +96,13 @@ public sealed class Configuration
/// <summary>
/// HTTP configuration properties for the SDK.
/// </summary>
/// <seealso cref="ConfigurationBuilder.Http(HttpConfigurationBuilder)"/>
/// <seealso cref="ConfigurationBuilder.Http(Integrations.HttpConfigurationBuilder)"/>
public HttpConfigurationBuilder HttpConfigurationBuilder { get; }

/// <summary>
/// Logging configuration properties for the SDK.
/// </summary>
/// <seealso cref="ConfigurationBuilder.Logging(LoggingConfigurationBuilder)"/>
/// <seealso cref="Logging"/>
public LoggingConfigurationBuilder LoggingConfigurationBuilder { get; }

/// <summary>
Expand All @@ -109,7 +122,7 @@ public sealed class Configuration
/// <summary>
/// Persistent storage configuration properties for the SDK.
/// </summary>
/// <seealso cref="ConfigurationBuilder.Persistence(PersistenceConfigurationBuilder)"/>
/// <seealso cref="ConfigurationBuilder.Persistence(Integrations.PersistenceConfigurationBuilder)"/>
public PersistenceConfigurationBuilder PersistenceConfigurationBuilder { get; }

/// <summary>
Expand All @@ -118,19 +131,21 @@ public sealed class Configuration
/// <seealso cref="ConfigurationBuilder.ServiceEndpoints(ServiceEndpointsBuilder)"/>
public ServiceEndpoints ServiceEndpoints { get; }

/// <summary>
/// ApplicationInfo configuration which contains info about the application the SDK is running in.
/// </summary>
public ApplicationInfoBuilder ApplicationInfo { get; }

/// <summary>
/// Creates a configuration with all parameters set to the default.
/// </summary>
/// <param name="mobileKey">the SDK key for your LaunchDarkly environment</param>
/// <param name="autoEnvAttributes">Enable / disable Auto Environment Attributes functionality. When enabled,
/// the SDK will automatically provide data about the environment where the application is running.
/// This data makes it simpler to target your mobile customers based on application name or version, or on
/// device characteristics including manufacturer, model, operating system, locale, and so on. We recommend
/// enabling this when you configure the SDK. See
/// <a href="https://docs.launchdarkly.com/sdk/features/environment-attributes">our documentation</a> for
/// more details.</param>
/// <returns>a <see cref="Configuration"/> instance</returns>
public static Configuration Default(string mobileKey)
public static Configuration Default(string mobileKey, ConfigurationBuilder.AutoEnvAttributes autoEnvAttributes)
{
return Builder(mobileKey).Build();
return Builder(mobileKey, autoEnvAttributes).Build();
}

/// <summary>
Expand All @@ -151,14 +166,23 @@ public static Configuration Default(string mobileKey)
/// </code>
/// </example>
/// <param name="mobileKey">the mobile SDK key for your LaunchDarkly environment</param>
/// <param name="autoEnvAttributes">Enable / disable Auto Environment Attributes functionality. When enabled,
/// the SDK will automatically provide data about the environment where the application is running.
/// This data makes it simpler to target your mobile customers based on application name or version, or on
/// device characteristics including manufacturer, model, operating system, locale, and so on. We recommend
/// enabling this when you configure the SDK. See
/// <a href="https://docs.launchdarkly.com/sdk/features/environment-attributes">our documentation</a> for
/// more details.</param>
/// <returns>a builder object</returns>
public static ConfigurationBuilder Builder(string mobileKey)
public static ConfigurationBuilder Builder(string mobileKey,
ConfigurationBuilder.AutoEnvAttributes autoEnvAttributes)
{
if (String.IsNullOrEmpty(mobileKey))
{
throw new ArgumentOutOfRangeException(nameof(mobileKey), "key is required");
}
return new ConfigurationBuilder(mobileKey);

return new ConfigurationBuilder(mobileKey, autoEnvAttributes);
}

/// <summary>
Expand All @@ -173,6 +197,8 @@ public static ConfigurationBuilder Builder(Configuration fromConfiguration)

internal Configuration(ConfigurationBuilder builder)
{
ApplicationInfo = builder._applicationInfo;
AutoEnvAttributes = builder._autoEnvAttributes;
DataSource = builder._dataSource;
DiagnosticOptOut = builder._diagnosticOptOut;
EnableBackgroundUpdating = builder._enableBackgroundUpdating;
Expand All @@ -185,7 +211,6 @@ internal Configuration(ConfigurationBuilder builder)
Offline = builder._offline;
PersistenceConfigurationBuilder = builder._persistenceConfigurationBuilder;
ServiceEndpoints = (builder._serviceEndpointsBuilder ?? Components.ServiceEndpoints()).Build();
ApplicationInfo = builder._applicationInfo;
BackgroundModeManager = builder._backgroundModeManager;
ConnectivityStateManager = builder._connectivityStateManager;
}
Expand Down
56 changes: 51 additions & 5 deletions src/LaunchDarkly.ClientSdk/ConfigurationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace LaunchDarkly.Sdk.Client
/// </summary>
/// <remarks>
/// <para>
/// Obtain an instance of this class by calling <see cref="Configuration.Builder(string)"/>.
/// Obtain an instance of this class by calling <see cref="Configuration.Builder(string, AutoEnvAttributes)"/>.
/// </para>
/// <para>
/// All of the builder methods for setting a configuration property return a reference to the same builder, so they can be
Expand All @@ -25,12 +25,39 @@ namespace LaunchDarkly.Sdk.Client
/// </example>
public sealed class ConfigurationBuilder
{
/// <summary>
/// Enable / disable options for Auto Environment Attributes functionality. When enabled, the SDK will automatically
/// provide data about the environment where the application is running. This data makes it simpler to target
/// your mobile customers based on application name or version, or on device characteristics including manufacturer,
/// model, operating system, locale, and so on. We recommend enabling this when you configure the SDK. See
/// <a href="https://docs.launchdarkly.com/sdk/features/environment-attributes">our documentation</a>
/// for more details.
/// For example, consider a “dark mode” feature being added to an app. Versions 10 through 14 contain early,
/// incomplete versions of the feature. These versions are available to all customers, but the “dark mode” feature is only
/// enabled for testers. With version 15, the feature is considered complete. With Auto Environment Attributes enabled,
/// you can use targeting rules to enable "dark mode" for all customers who are using version 15 or greater, and ensure
/// that customers on previous versions don't use the earlier, unfinished version of the feature.
/// </summary>
public enum AutoEnvAttributes
{
/// <summary>
/// Enables the Auto EnvironmentAttributes functionality.
/// </summary>
Enabled,

/// <summary>
/// Disables the Auto EnvironmentAttributes functionality.
/// </summary>
Disabled
}

// This exists so that we can distinguish between leaving the HttpMessageHandler property unchanged
// and explicitly setting it to null. If the property value is the exact same instance as this, we
// will replace it with a platform-specific implementation.
internal static readonly HttpMessageHandler DefaultHttpMessageHandlerInstance = new HttpClientHandler();

internal ApplicationInfoBuilder _applicationInfo;
internal bool _autoEnvAttributes = false;
internal IComponentConfigurer<IDataSource> _dataSource = null;
internal bool _diagnosticOptOut = false;
internal bool _enableBackgroundUpdating = true;
Expand All @@ -48,13 +75,16 @@ public sealed class ConfigurationBuilder
internal IBackgroundModeManager _backgroundModeManager;
internal IConnectivityStateManager _connectivityStateManager;

internal ConfigurationBuilder(string mobileKey)
internal ConfigurationBuilder(string mobileKey, AutoEnvAttributes autoEnvAttributes)
{
_mobileKey = mobileKey;
_autoEnvAttributes = autoEnvAttributes == AutoEnvAttributes.Enabled; // map enum to boolean
}

internal ConfigurationBuilder(Configuration copyFrom)
{
_applicationInfo = copyFrom.ApplicationInfo;
_autoEnvAttributes = copyFrom.AutoEnvAttributes;
_dataSource = copyFrom.DataSource;
_diagnosticOptOut = copyFrom.DiagnosticOptOut;
_enableBackgroundUpdating = copyFrom.EnableBackgroundUpdating;
Expand All @@ -66,7 +96,6 @@ internal ConfigurationBuilder(Configuration copyFrom)
_offline = copyFrom.Offline;
_persistenceConfigurationBuilder = copyFrom.PersistenceConfigurationBuilder;
_serviceEndpointsBuilder = new ServiceEndpointsBuilder(copyFrom.ServiceEndpoints);
_applicationInfo = copyFrom.ApplicationInfo;
}

/// <summary>
Expand All @@ -78,7 +107,7 @@ public Configuration Build()
{
return new Configuration(this);
}

/// <summary>
/// Sets the SDK's application metadata, which may be used in the LaunchDarkly analytics or other product
/// features. This object is normally a configuration builder obtained from <see cref="Components.ApplicationInfo"/>,
Expand All @@ -92,6 +121,23 @@ public ConfigurationBuilder ApplicationInfo(ApplicationInfoBuilder applicationIn
return this;
}

/// <summary>
/// Specifies whether the SDK will use Auto Environment Attributes functionality. When enabled,
/// the SDK will automatically provide data about the environment where the application is running.
/// This data makes it simpler to target your mobile customers based on application name or version, or on
/// device characteristics including manufacturer, model, operating system, locale, and so on. We recommend
/// enabling this when you configure the SDK. See
/// <a href="https://docs.launchdarkly.com/sdk/features/environment-attributes">our documentation</a> for
/// more details.
/// </summary>
/// <param name="autoEnvAttributes">Enable / disable Auto Environment Attributes functionality.</param>
/// <returns>the same builder</returns>
public ConfigurationBuilder AutoEnvironmentAttributes(AutoEnvAttributes autoEnvAttributes)
{
_autoEnvAttributes = autoEnvAttributes == AutoEnvAttributes.Enabled; // map enum to boolean
return this;
}

/// <summary>
/// Sets the implementation of the component that receives feature flag data from LaunchDarkly,
/// using a factory object.
Expand Down Expand Up @@ -205,7 +251,7 @@ public ConfigurationBuilder Events(IComponentConfigurer<IEventProcessor> eventsC
/// <remarks>
/// <para>
/// If enabled, this option changes the SDK's behavior whenever the <see cref="Context"/> (as given to
/// methods like <see cref="LdClient.Init(string, Context, System.TimeSpan)"/> or
/// methods like <see cref="LdClient.Init(string, AutoEnvAttributes, Context, System.TimeSpan)"/> or
/// <see cref="LdClient.Identify(Context, System.TimeSpan)"/>) has an <see cref="Context.Anonymous"/>
/// property of <see langword="true"/>, as follows:
/// </para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public HttpConfigurationBuilder Wrapper(string wrapperName, string wrapperVersio
/// <param name="authKey">Key for authenticating with LD service</param>
/// <param name="applicationInfo">Application Info for this application environment</param>
/// <returns>an <see cref="HttpConfiguration"/></returns>
public HttpConfiguration CreateHttpConfiguration(string authKey, ApplicationInfo applicationInfo) =>
public HttpConfiguration CreateHttpConfiguration(string authKey, ApplicationInfo? applicationInfo) =>
new HttpConfiguration(
MakeHttpProperties(authKey, applicationInfo),
_messageHandler,
Expand All @@ -255,7 +255,7 @@ public LdValue DescribeConfiguration(LdClientContext context) =>
// which is more correct, but we can't really set ReadTimeout in this SDK
.Build();

private HttpProperties MakeHttpProperties(string authToken, ApplicationInfo applicationInfo)
private HttpProperties MakeHttpProperties(string authToken, ApplicationInfo? applicationInfo)
{
Func<HttpProperties, HttpMessageHandler> handlerFn;
if (_messageHandler is null)
Expand All @@ -273,9 +273,13 @@ private HttpProperties MakeHttpProperties(string authToken, ApplicationInfo appl
.WithHttpMessageHandlerFactory(handlerFn)
.WithProxy(_proxy)
.WithUserAgent(SdkPackage.UserAgent)
.WithApplicationTags(applicationInfo)
.WithWrapper(_wrapperName, _wrapperVersion);

if (applicationInfo.HasValue)
{
httpProperties = httpProperties.WithApplicationTags(applicationInfo.Value);
}

foreach (var kv in _customHeaders)
{
httpProperties = httpProperties.WithHeader(kv.Key, kv.Value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public PersistenceConfigurationBuilder Storage(IComponentConfigurer<IPersistentD
/// </para>
/// </remarks>
/// <param name="maxCachedContexts"></param>
/// <returns></returns>
/// <returns>the builder</returns>
public PersistenceConfigurationBuilder MaxCachedContexts(int maxCachedContexts)
{
_maxCachedContexts = maxCachedContexts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

namespace LaunchDarkly.Sdk.Client.Internal
{
internal class ContextDecorator
internal class AnonymousKeyContextDecorator
{
private readonly PersistentDataStoreWrapper _store;
private readonly bool _generateAnonymousKeys;

private Dictionary<ContextKind, string> _cachedGeneratedKey = new Dictionary<ContextKind, string>();
private object _generatedKeyLock = new object();

public ContextDecorator(
public AnonymousKeyContextDecorator(
PersistentDataStoreWrapper store,
bool generateAnonymousKeys
)
Expand Down
Loading

0 comments on commit d34b239

Please sign in to comment.