diff --git a/apps/sdk-contract-tests/include/definitions.hpp b/apps/sdk-contract-tests/include/definitions.hpp index deb67d1d9..7c08d367c 100644 --- a/apps/sdk-contract-tests/include/definitions.hpp +++ b/apps/sdk-contract-tests/include/definitions.hpp @@ -80,6 +80,14 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(ConfigClientSideParams, evaluationReasons, useReport); +struct ConfigTags { + std::optional applicationId; + std::optional applicationVersion; +}; +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(ConfigTags, + applicationId, + applicationVersion); + struct ConfigParams { std::string credential; std::optional startWaitTimeMs; @@ -89,6 +97,7 @@ struct ConfigParams { std::optional events; std::optional serviceEndpoints; std::optional clientSide; + std::optional tags; }; NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(ConfigParams, credential, @@ -98,7 +107,8 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(ConfigParams, polling, events, serviceEndpoints, - clientSide); + clientSide, + tags); struct ContextSingleParams { std::optional kind; diff --git a/apps/sdk-contract-tests/src/entity_manager.cpp b/apps/sdk-contract-tests/src/entity_manager.cpp index b9055f349..cf81109b3 100644 --- a/apps/sdk-contract-tests/src/entity_manager.cpp +++ b/apps/sdk-contract-tests/src/entity_manager.cpp @@ -114,6 +114,15 @@ std::optional EntityManager::create(ConfigParams const& in) { datasource.UseReport(*in.clientSide->useReport); } + if (in.tags) { + if (in.tags->applicationId) { + config_builder.AppInfo().Identifier(*in.tags->applicationId); + } + if (in.tags->applicationVersion) { + config_builder.AppInfo().Version(*in.tags->applicationVersion); + } + } + auto config = config_builder.Build(); if (!config) { LD_LOG(logger_, LogLevel::kWarn) diff --git a/apps/sdk-contract-tests/test-suppressions.txt b/apps/sdk-contract-tests/test-suppressions.txt index cfdacd3ff..882dab53b 100644 --- a/apps/sdk-contract-tests/test-suppressions.txt +++ b/apps/sdk-contract-tests/test-suppressions.txt @@ -1,6 +1,5 @@ events/summary events/basic counter behavior events/summary events/reset after each flush -tags/disallowed characters # The Client doesn't need to know how to deserialize users. context type/convert/old user to context/{"key": ""} diff --git a/libs/client-sdk/src/data_sources/polling_data_source.cpp b/libs/client-sdk/src/data_sources/polling_data_source.cpp index 5d098f7bb..b07567a41 100644 --- a/libs/client-sdk/src/data_sources/polling_data_source.cpp +++ b/libs/client-sdk/src/data_sources/polling_data_source.cpp @@ -57,6 +57,10 @@ static network::HttpRequest MakeRequest(Config const& config, builder.Header("authorization", config.SdkKey()); + if (auto app_tag = config.ApplicationTag()) { + builder.Header("x-launchdarkly-tags", *app_tag); + } + // If no URL is set, then we will fail the request. return {url.value_or(""), method, builder.Build(), body}; } diff --git a/libs/client-sdk/src/data_sources/streaming_data_source.cpp b/libs/client-sdk/src/data_sources/streaming_data_source.cpp index 3e3980bc9..1dc681082 100644 --- a/libs/client-sdk/src/data_sources/streaming_data_source.cpp +++ b/libs/client-sdk/src/data_sources/streaming_data_source.cpp @@ -33,6 +33,7 @@ StreamingDataSource::StreamingDataSource( context_(std::move(context)), http_config_(config.HttpProperties()), data_source_config_(config.DataSourceConfig()), + app_tags_(config.ApplicationTag()), sdk_key_(config.SdkKey()), streaming_endpoint_(config.ServiceEndpoints().StreamingBaseUrl()) {} @@ -108,6 +109,10 @@ void StreamingDataSource::Start() { } client_builder.header("user-agent", http_config_.UserAgent()); + if (app_tags_) { + client_builder.header("x-launchdarkly-tags", *app_tags_); + } + // TODO: Handle proxy support. auto weak_self = weak_from_this(); diff --git a/libs/client-sdk/src/data_sources/streaming_data_source.hpp b/libs/client-sdk/src/data_sources/streaming_data_source.hpp index 61ad2817c..218a86975 100644 --- a/libs/client-sdk/src/data_sources/streaming_data_source.hpp +++ b/libs/client-sdk/src/data_sources/streaming_data_source.hpp @@ -48,6 +48,8 @@ class StreamingDataSource final config::shared::built::HttpProperties http_config_; + std::optional app_tags_; + std::string sdk_key_; Logger const& logger_;