-
Notifications
You must be signed in to change notification settings - Fork 4
feat: add X-LaunchDarkly-Instance-Id header to server SDK (SDK-2353) #532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| #include "instance_id.hpp" | ||
|
|
||
| #include <boost/uuid/uuid.hpp> | ||
| #include <boost/uuid/uuid_generators.hpp> | ||
| #include <boost/uuid/uuid_io.hpp> | ||
|
|
||
| namespace launchdarkly::server_side { | ||
|
|
||
| std::string MakeInstanceId() { | ||
| // boost::uuids::random_generator emits a version 4 (random) UUID, which is | ||
| // what the SCMP spec requires. The generator carries state (an internal RNG | ||
| // seeded from system entropy on construction), so we cache it per thread to | ||
| // avoid redundant entropy draws on repeated calls. | ||
| static thread_local boost::uuids::random_generator generator; | ||
| return boost::uuids::to_string(generator()); | ||
| } | ||
|
|
||
| } // namespace launchdarkly::server_side | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| namespace launchdarkly::server_side { | ||
|
|
||
| /** | ||
| * Name of the HTTP header used to identify this SDK instance for the purpose of | ||
| * estimating server-connection-minutes when polling. The value is a v4 UUID | ||
| * that is generated once per SDK instance and remains constant for the | ||
| * lifetime of the client. | ||
| */ | ||
| inline constexpr char const* kInstanceIdHeader = "X-LaunchDarkly-Instance-Id"; | ||
|
|
||
| /** | ||
| * Generate a fresh v4 UUID suitable for use as the value of the | ||
| * X-LaunchDarkly-Instance-Id header. Each call returns a new identifier; | ||
| * callers are expected to generate the value exactly once per SDK instance | ||
| * and reuse it for the lifetime of that instance. | ||
| * | ||
| * @return A string formatted as a lowercase v4 UUID, e.g. | ||
| * "550e8400-e29b-41d4-a716-446655440000". | ||
| */ | ||
| [[nodiscard]] std::string MakeInstanceId(); | ||
|
|
||
| } // namespace launchdarkly::server_side |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| #include <gtest/gtest.h> | ||
|
|
||
| #include "instance_id.hpp" | ||
|
|
||
| #include <launchdarkly/server_side/client.hpp> | ||
| #include <launchdarkly/server_side/config/config_builder.hpp> | ||
|
|
||
| #include <cstddef> | ||
| #include <regex> | ||
| #include <set> | ||
| #include <string> | ||
|
|
||
| using namespace launchdarkly; | ||
| using namespace launchdarkly::server_side; | ||
|
|
||
| namespace { | ||
|
|
||
| // Matches a canonical UUID v4 in lowercase hex: | ||
| // xxxxxxxx-xxxx-4xxx-Yxxx-xxxxxxxxxxxx | ||
| // where 'Y' is one of 8, 9, a, or b (RFC 4122 variant). | ||
| bool IsUuidV4(std::string const& s) { | ||
| static std::regex const re( | ||
| "^[0-9a-f]{8}-" | ||
| "[0-9a-f]{4}-" | ||
| "4[0-9a-f]{3}-" | ||
| "[89ab][0-9a-f]{3}-" | ||
| "[0-9a-f]{12}$"); | ||
| return std::regex_match(s, re); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| // Spec: SCMP-server-connection-minutes-polling section 1.1 requires the | ||
| // X-LaunchDarkly-Instance-Id value to be a v4 UUID. | ||
| TEST(InstanceIdTest, GeneratedValueIsUuidV4) { | ||
| auto id = MakeInstanceId(); | ||
| ASSERT_FALSE(id.empty()) << "MakeInstanceId returned an empty string"; | ||
| EXPECT_TRUE(IsUuidV4(id)) | ||
| << "MakeInstanceId returned " << id << " which is not a v4 UUID"; | ||
| } | ||
|
|
||
| // Each invocation must yield a different value; spec requires "the GUID MUST | ||
| // be used uniquely for this purpose". | ||
| TEST(InstanceIdTest, GeneratedValuesAreUnique) { | ||
| constexpr int kSamples = 100; | ||
| std::set<std::string> seen; | ||
| for (int i = 0; i < kSamples; ++i) { | ||
| auto id = MakeInstanceId(); | ||
| ASSERT_FALSE(id.empty()); | ||
| EXPECT_TRUE(seen.insert(id).second) | ||
| << "duplicate UUID emitted from MakeInstanceId: " << id; | ||
| } | ||
| EXPECT_EQ(seen.size(), static_cast<std::size_t>(kSamples)); | ||
| } | ||
|
|
||
| // The header name constant must match the spec verbatim. This guards against | ||
| // accidental renaming (the header name is part of the wire contract). | ||
| TEST(InstanceIdTest, HeaderNameMatchesSpec) { | ||
| EXPECT_STREQ(kInstanceIdHeader, "X-LaunchDarkly-Instance-Id"); | ||
| } | ||
|
|
||
| // Sanity-check that a Client can be constructed; the integration that the | ||
| // instance-id header actually ends up on outbound requests is covered by the | ||
| // cross-SDK contract test harness (capability: "instance-id"). | ||
| TEST(InstanceIdTest, ClientConstructsWithInstanceIdHeader) { | ||
| // Building a Client exercises the code path that stamps the instance-id | ||
| // header into the shared HttpProperties. We can't observe the header | ||
| // directly from the public API, so this test simply asserts that the | ||
| // construction succeeds; the spec-level guarantees about the header value | ||
| // are exercised by GeneratedValueIsUuidV4 and GeneratedValuesAreUnique, | ||
| // and the on-the-wire guarantee is covered by the cross-SDK contract test | ||
| // harness (capability: "instance-id"). | ||
| Client client(ConfigBuilder("sdk-123").Build().value()); | ||
| EXPECT_NE(client.Version(), nullptr); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done -- updated the comment to your wording in 9ecdc7e.