Skip to content

feat: foundation of an event processor #16

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 37 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b45bbb2
Add event definitions
cwaldren-ld Apr 4, 2023
75d23e6
Add IEventProcessor
cwaldren-ld Apr 4, 2023
048552d
add test
cwaldren-ld Apr 4, 2023
0ae641d
Refactor directory structure
cwaldren-ld Apr 5, 2023
3a084c4
fix test
cwaldren-ld Apr 5, 2023
aa89779
many ideas, many failures, maybe a successful design
cwaldren-ld Apr 6, 2023
b2b249a
Merge branch 'main' into cw/sc-194812/event-processor
cwaldren-ld Apr 6, 2023
6deaebe
Merge branch 'main' into cw/sc-194812/event-processor
cwaldren-ld Apr 6, 2023
d812d24
tests
cwaldren-ld Apr 6, 2023
f1e1c9b
add the config builders for events
cwaldren-ld Apr 7, 2023
a33c457
Rename ServiceEndpoints to ServiceHosts
cwaldren-ld Apr 7, 2023
e8b0c34
refactoring flush method
cwaldren-ld Apr 7, 2023
83983cd
beginnings of event JSON serialization
cwaldren-ld Apr 7, 2023
5f449e1
add tag_invoke for EvaluationReason
cwaldren-ld Apr 7, 2023
ca0bbaa
add contextKeys
cwaldren-ld Apr 7, 2023
61a095d
add debug event serialization
cwaldren-ld Apr 7, 2023
6ad708a
Add IdentifyEvent serialization
cwaldren-ld Apr 7, 2023
c6765d0
Add a helper type for dates
cwaldren-ld Apr 7, 2023
8ee293f
Add variant dispatch for all OutputEvent types
cwaldren-ld Apr 7, 2023
35e324b
Add private attributes builders to event processor config
cwaldren-ld Apr 10, 2023
ecc7e2f
Fix serialization of identify event
cwaldren-ld Apr 10, 2023
b6cd25f
refactor event classes into common and client namespaces
cwaldren-ld Apr 10, 2023
d1b1f43
Get rid of AsioEventProcessor wrapper
cwaldren-ld Apr 10, 2023
41425af
add identify event sanity check
cwaldren-ld Apr 10, 2023
69c1ece
fix a failure to rename
cwaldren-ld Apr 10, 2023
431c519
more docs
cwaldren-ld Apr 10, 2023
731d7a5
renamings for the style guide
cwaldren-ld Apr 10, 2023
15629a3
Fix some doc comments that were accidentally changed in a renaming
cwaldren-ld Apr 10, 2023
d7d3f77
Revert "Rename ServiceEndpoints to ServiceHosts"
cwaldren-ld Apr 10, 2023
d48ca6d
remove TLS setter for event config
cwaldren-ld Apr 10, 2023
e23988f
Establish upper bound on number of input events using mutex
cwaldren-ld Apr 11, 2023
aff2575
fix a couple lints
cwaldren-ld Apr 11, 2023
057881f
Make Debug/Feature events inherit from base class
cwaldren-ld Apr 12, 2023
f62c250
Merge branch 'main' into cw/sc-194283/event-processor
cwaldren-ld Apr 12, 2023
762ead5
fix compilation due to unknown header in backoff.hpp
cwaldren-ld Apr 12, 2023
994c276
Delete constructors of IEventProcessor
cwaldren-ld Apr 12, 2023
d58a6cb
add missing <functional> header to backoff.hpp
cwaldren-ld Apr 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/common/include/config/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ using SDK = config::detail::ClientSDK;
using ApplicationInfo = config::detail::ApplicationInfo;
using Endpoints = config::detail::EndpointsBuilder<SDK>;
using ConfigBuilder = config::detail::ConfigBuilder<SDK>;
using EventsBuilder = config::detail::EventsBuilder<SDK>;
using Config = config::detail::Config<SDK>;

} // namespace launchdarkly::client
3 changes: 3 additions & 0 deletions libs/common/include/config/detail/config.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "config/detail/endpoints_builder.hpp"
#include "config/detail/events_builder.hpp"

namespace launchdarkly::config::detail {

Expand All @@ -15,9 +16,11 @@ struct Config {
bool offline;
detail::EndpointsBuilder<SDK> service_endpoints_builder;
std::optional<std::string> application_tag;
detail::EventsBuilder<SDK> events_builder;
Config(std::string sdk_key,
bool offline,
detail::EndpointsBuilder<SDK> service_endpoints_builder,
detail::EventsBuilder<SDK> events_builder,
std::optional<std::string> application_tag);
};

Expand Down
13 changes: 12 additions & 1 deletion libs/common/include/config/detail/config_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "config/detail/application_info.hpp"
#include "config/detail/config.hpp"
#include "config/detail/endpoints_builder.hpp"
#include "config/detail/events_builder.hpp"
#include "logger.hpp"

namespace launchdarkly::config::detail {
Expand All @@ -18,6 +19,7 @@ template <typename SDK>
class ConfigBuilder {
public:
using EndpointsBuilder = detail::EndpointsBuilder<SDK>;
using EventsBuilder = detail::EventsBuilder<SDK>;
using ConfigType = detail::Config<SDK>;
/**
* A minimal configuration consists of a LaunchDarkly SDK Key.
Expand All @@ -31,7 +33,7 @@ class ConfigBuilder {
* @param builder An EndpointsBuilder.
* @return Reference to this builder.
*/
ConfigBuilder& service_endpoints(detail::EndpointsBuilder<SDK> builder);
ConfigBuilder& service_endpoints(EndpointsBuilder builder);

/**
* To include metadata about the application that is utilizing the SDK,
Expand All @@ -49,6 +51,14 @@ class ConfigBuilder {
*/
ConfigBuilder& offline(bool offline);

/**
* To tune settings related to event generation and delivery, pass an
* EventsBuilder.
* @param builder An EventsBuilder.
* @return Reference to this builder.
*/
ConfigBuilder& events(EventsBuilder builder);

/**
* Builds a Configuration, suitable for passing into an instance of Client.
* @return
Expand All @@ -60,6 +70,7 @@ class ConfigBuilder {
std::optional<bool> offline_;
std::optional<EndpointsBuilder> service_endpoints_builder_;
std::optional<ApplicationInfo> application_info_builder_;
std::optional<EventsBuilder> events_builder_;
};

} // namespace launchdarkly::config::detail
13 changes: 12 additions & 1 deletion libs/common/include/config/detail/defaults.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

#include "config/detail/events.hpp"
#include "config/detail/http_properties.hpp"
#include "config/detail/sdks.hpp"
#include "service_endpoints.hpp"
#include "config/detail/service_endpoints.hpp"

namespace launchdarkly::config::detail {

Expand Down Expand Up @@ -30,6 +31,11 @@ struct Defaults<ClientSDK> {
"https://mobile.launchdarkly.com"};
}

static Events events() {
return {100, std::chrono::seconds(30), "/mobile", false,
AttributeReference::SetType()};
}

static HttpProperties http_properties() {
return {std::chrono::milliseconds{10000},
std::chrono::milliseconds{10000},
Expand All @@ -48,6 +54,11 @@ struct Defaults<ServerSDK> {
"https://events.launchdarkly.com"};
}

static Events events() {
return {10000, std::chrono::seconds(5), "/bulk", false,
AttributeReference::SetType()};
}

static HttpProperties http_properties() {
return {std::chrono::milliseconds{2000},
std::chrono::milliseconds{10000},
Expand Down
4 changes: 2 additions & 2 deletions libs/common/include/config/detail/endpoints_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ class EndpointsBuilder {

/**
* Builds a ServiceEndpoints if the configuration is valid. If not,
* returns nullptr.
* @return Unique pointer to ServiceEndpoints, or nullptr.
* returns an error.
* @return Unique pointer to ServiceEndpoints, or error.
*/
[[nodiscard]] tl::expected<ServiceEndpoints, Error> build();

Expand Down
70 changes: 70 additions & 0 deletions libs/common/include/config/detail/events.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#pragma once

#include <chrono>
#include <cstddef>
#include <string>
#include <unordered_map>
#include "attribute_reference.hpp"
namespace launchdarkly::config::detail {

struct Events {
public:
template <typename SDK>
friend class EventsBuilder;
/**
* Constructs configuration for the event subsystem.
* @param capacity How many events can queue in memory before new events
* are dropped.
* @param flush_interval How often events are automatically flushed to
* LaunchDarkly.
* @param path The path component of the LaunchDarkly event delivery
* endpoint.
* @param all_attributes_private Whether all attributes should be treated as
* private or not.
* @param private_attrs Which attributes should be treated as private, if
* all_attributes_private is false.
* @param security Whether a plaintext or encrypted client should be used
* for event delivery.
*/
Events(std::size_t capacity,
std::chrono::milliseconds flush_interval,
std::string path,
bool all_attributes_private,
AttributeReference::SetType private_attrs);

/**
* Capacity of the event processor.
*/
[[nodiscard]] std::size_t capacity() const;

/**
* Flush interval of the event processor, in milliseconds.
*/
[[nodiscard]] std::chrono::milliseconds flush_interval() const;

/**
* Path component of the LaunchDarkly event delivery endpoint.
*/
[[nodiscard]] std::string const& path() const;

/**
* Whether all attributes should be considered private or not.
*/
[[nodiscard]] bool all_attributes_private() const;

/**
* Set of individual attributes that should be considered private.
*/
[[nodiscard]] AttributeReference::SetType const& private_attributes() const;

private:
std::size_t capacity_;
std::chrono::milliseconds flush_interval_;
std::string path_;
bool all_attributes_private_;
AttributeReference::SetType private_attributes_;
};

bool operator==(Events const& lhs, Events const& rhs);

} // namespace launchdarkly::config::detail
97 changes: 97 additions & 0 deletions libs/common/include/config/detail/events_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#pragma once

#include <tl/expected.hpp>
#include "attribute_reference.hpp"
#include "config/detail/events.hpp"
#include "error.hpp"

#include <memory>
#include <optional>
#include <string>
#include <unordered_map>

namespace launchdarkly::config::detail {

template <typename SDK>
class EventsBuilder;

template <typename SDK>
bool operator==(EventsBuilder<SDK> const& lhs, EventsBuilder<SDK> const& rhs);

/**
* EventsBuilder allows for specification of parameters related to the
* SDK's event processor.
*
* @tparam SDK Type of SDK, such as ClientSDK or ServerSDK.
*/
template <typename SDK>
class EventsBuilder {
public:
friend bool operator==
<SDK>(EventsBuilder<SDK> const& lhs, EventsBuilder<SDK> const& rhs);
/**
* Constructs an EventsBuilder.
*/
EventsBuilder();

/**
* Sets the capacity of the event processor. When more events are generated
* within the processor's flush interval than this value, events will be
* dropped.
* @param capacity Event queue capacity.
* @return Reference to this builder.
*/
EventsBuilder& capacity(std::size_t capacity);

/**
* Sets the flush interval of the event processor. The processor queues
* outgoing events based on the capacity parameter; these events are then
* delivered based on the flush interval.
* @param interval Interval between automatic flushes.
* @return Reference to this builder.
*/
EventsBuilder& flush_interval(std::chrono::milliseconds interval);

/**
* Attribute privacy indicates whether or not attributes should be
* retained by LaunchDarkly after being sent upon initialization,
* and if attributes should later be sent in events.
*
* Attribute privacy may be specified in 3 ways:
*
* (1) To specify that all attributes should be considered private - not
* just those designated private on a per-context basis - call this method
* with true as the parameter.
*
* (2) To specify that a specific set of attributes should be considered
* private - in addition to those designated private on a per-context basis
* - call @ref private_attributes.
*
* (3) To specify private attributes on a per-context basis, it is not
* necessary to call either of these methods, as the default behavior is to
* treat all attributes as non-private unless otherwise specified.
*
* @param value True for behavior of (1), false for default behavior of (2)
* or (3).
* @return Reference to this builder.
*/
EventsBuilder& all_attributes_private(bool);

/**
* Specify that a set of attributes are private.
* @return Reference to this builder.
*/
EventsBuilder& private_attributes(
AttributeReference::SetType private_attrs);

/**
* Builds Events configuration, if the configuration is valid.
* @return Events config, or error.
*/
[[nodiscard]] tl::expected<Events, Error> build();

private:
Events config_;
};

} // namespace launchdarkly::config::detail
1 change: 1 addition & 0 deletions libs/common/include/config/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ using SDK = config::detail::ServerSDK;
using ApplicationInfo = config::detail::ApplicationInfo;
using Endpoints = config::detail::EndpointsBuilder<SDK>;
using ConfigBuilder = config::detail::ConfigBuilder<SDK>;
using EventsBuilder = config::detail::EventsBuilder<SDK>;
using Config = config::detail::Config<SDK>;

} // namespace launchdarkly::server
7 changes: 3 additions & 4 deletions libs/common/include/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ class Context final {
*
* @return Returns a map of kinds to keys.
*/
[[nodiscard]] std::map<std::string, std::string> const&
keys_and_kinds() const;
[[nodiscard]] std::map<std::string, std::string> const& kinds_to_keys()
const;

/**
* Get a string containing errors the context encountered during
Expand Down Expand Up @@ -114,7 +114,6 @@ class Context final {
Context& operator=(Context const&) = default;
Context& operator=(Context&&) = default;


private:
/**
* Create an invalid context with the given error message.
Expand All @@ -129,7 +128,7 @@ class Context final {

std::map<std::string, Attributes> attributes_;
std::vector<std::string> kinds_;
std::map<std::string, std::string> keys_and_kinds_;
std::map<std::string, std::string> kinds_to_keys_;
bool valid_ = false;
std::string errors_;
std::string canonical_key_;
Expand Down
2 changes: 1 addition & 1 deletion libs/common/include/data/evaluation_result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class EvaluationResult {

/**
* A timestamp, which if the current time is before, a client SDK
* should send debug events for the flag.
* should AsyncSend debug events for the flag.
* @return
*/
[[nodiscard]] std::optional<
Expand Down
2 changes: 2 additions & 0 deletions libs/common/include/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ enum class Error : std::uint32_t {
kConfig_ApplicationInfo_InvalidKeyCharacters = 202,
kConfig_ApplicationInfo_InvalidValueCharacters = 203,

kConfig_Events_ZeroCapacity = 300,

/* Client-side errors: 10000-19999 */
/* Server-side errors: 20000-29999 */

Expand Down
42 changes: 42 additions & 0 deletions libs/common/include/events/client_events.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "events/common_events.hpp"

namespace launchdarkly::events::client {

struct IdentifyEventParams {
Date creation_date;
Context context;
};

struct IdentifyEvent {
Date creation_date;
EventContext context;
};

struct FeatureEventParams {
Date creation_date;
std::string key;
Context context;
EvaluationResult eval_result;
};

struct FeatureEventBase {
Date creation_date;
std::string key;
Version version;
std::optional<VariationIndex> variation;
Value value;
std::optional<Reason> reason;
Value default_;
};

struct FeatureEvent : public FeatureEventBase {
ContextKeys context_keys;
};

struct DebugEvent : public FeatureEventBase {
EventContext context;
};

} // namespace launchdarkly::events::client
Loading