-
Notifications
You must be signed in to change notification settings - Fork 3
feat: Add support for hooks. #493
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
13 commits
Select commit
Hold shift + click to select a range
161efc3
feat: Add hooks support.
kinyoklion ab55f09
Add support for additional hook context.
kinyoklion 5cf0bcd
All variation method names.
kinyoklion 342550a
Minor code formatting.
kinyoklion f3433e6
Fix user-after-move in TrackInternal.
kinyoklion e99429d
Non-shallow clone for redis-plus-plus.
kinyoklion 3facf4f
feat: Add C-bindings for hooks.
kinyoklion 3e7147f
Preserve const
kinyoklion 398a48a
Memory management improvments.
kinyoklion 7060a38
Fix memory leak, use reference for track data.
kinyoklion b29163a
More lifetime documentation.
kinyoklion 61bd7c6
Remove wrappers.
kinyoklion 4773e9e
Add newline to end of file.
kinyoklion 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
106 changes: 106 additions & 0 deletions
106
libs/server-sdk/include/launchdarkly/server_side/bindings/c/evaluation_series_context.h
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,106 @@ | ||
| /** | ||
| * @file evaluation_series_context.h | ||
| * @brief C bindings for read-only evaluation context passed to hooks. | ||
| * | ||
| * EvaluationSeriesContext provides information about a flag evaluation | ||
| * to hook callbacks. All data is read-only and valid only during the | ||
| * callback execution. | ||
| * | ||
| * LIFETIME: | ||
| * - All context parameters are temporary - valid only during callback | ||
| * - Do not store pointers to context data | ||
| * - Copy any needed data (strings, values) if you need to retain it | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <launchdarkly/bindings/c/export.h> | ||
| #include <launchdarkly/server_side/bindings/c/hook_context.h> | ||
| #include <launchdarkly/bindings/c/value.h> | ||
| #include <launchdarkly/bindings/c/context.h> | ||
|
|
||
| // No effect in C++, but we want it for C. | ||
| // ReSharper disable once CppUnusedIncludeDirective | ||
| #include <stdbool.h> // NOLINT(*-deprecated-headers) | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| typedef struct p_LDServerSDKEvaluationSeriesContext* LDServerSDKEvaluationSeriesContext; | ||
|
|
||
| /** | ||
| * @brief Get the flag key being evaluated. | ||
| * | ||
| * @param eval_context Evaluation context. Must not be NULL. | ||
| * @return Flag key as null-terminated UTF-8 string. Valid only during | ||
| * the callback execution. Must not be freed. | ||
| */ | ||
| LD_EXPORT(char const*) | ||
| LDEvaluationSeriesContext_FlagKey(LDServerSDKEvaluationSeriesContext eval_context); | ||
|
|
||
| /** | ||
| * @brief Get the context (user/organization) being evaluated. | ||
| * | ||
| * @param eval_context Evaluation context. Must not be NULL. | ||
| * @return Context object. Valid only during the callback execution. | ||
| * Must not be freed. Do not call LDContext_Free() on this. | ||
| */ | ||
| LD_EXPORT(LDContext) | ||
| LDEvaluationSeriesContext_Context(LDServerSDKEvaluationSeriesContext eval_context); | ||
|
|
||
| /** | ||
| * @brief Get the default value provided to the variation call. | ||
| * | ||
| * @param eval_context Evaluation context. Must not be NULL. | ||
| * @return Default value. Valid only during the callback execution. | ||
| * Must not be freed. Do not call LDValue_Free() on this. | ||
| */ | ||
| LD_EXPORT(LDValue) | ||
| LDEvaluationSeriesContext_DefaultValue( | ||
| LDServerSDKEvaluationSeriesContext eval_context); | ||
|
|
||
| /** | ||
| * @brief Get the name of the variation method called. | ||
| * | ||
| * Examples: "BoolVariation", "StringVariationDetail", "JsonVariation" | ||
| * | ||
| * @param eval_context Evaluation context. Must not be NULL. | ||
| * @return Method name as null-terminated UTF-8 string. Valid only during | ||
| * the callback execution. Must not be freed. | ||
| */ | ||
| LD_EXPORT(char const*) | ||
| LDEvaluationSeriesContext_Method(LDServerSDKEvaluationSeriesContext eval_context); | ||
|
|
||
| /** | ||
| * @brief Get the hook context provided by the caller. | ||
| * | ||
| * This contains application-specific data passed to the variation call, | ||
| * such as OpenTelemetry span parents. | ||
| * | ||
| * @param eval_context Evaluation context. Must not be NULL. | ||
| * @return Hook context. Valid only during the callback execution. | ||
| * Must not be freed. Do not call LDHookContext_Free() on this. | ||
| */ | ||
| LD_EXPORT(LDHookContext) | ||
| LDEvaluationSeriesContext_HookContext( | ||
| LDServerSDKEvaluationSeriesContext eval_context); | ||
|
|
||
| /** | ||
| * @brief Get the environment ID, if available. | ||
| * | ||
| * The environment ID is only available after SDK initialization completes. | ||
| * Returns NULL if not yet available. | ||
| * | ||
| * @param eval_context Evaluation context. Must not be NULL. | ||
| * @return Environment ID as null-terminated UTF-8 string, or NULL if not | ||
| * available. Valid only during the callback execution. Must not | ||
| * be freed. | ||
| */ | ||
| LD_EXPORT(char const*) | ||
| LDEvaluationSeriesContext_EnvironmentId( | ||
| LDServerSDKEvaluationSeriesContext eval_context); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
210 changes: 210 additions & 0 deletions
210
libs/server-sdk/include/launchdarkly/server_side/bindings/c/evaluation_series_data.h
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,210 @@ | ||
| /** | ||
| * @file evaluation_series_data.h | ||
| * @brief C bindings for hook data passed between evaluation stages. | ||
| * | ||
| * EvaluationSeriesData is mutable data that hooks can use to pass information | ||
| * from beforeEvaluation to afterEvaluation. This is useful for: | ||
| * - Storing timing information | ||
| * - Passing span contexts for distributed tracing | ||
| * - Accumulating custom metrics | ||
| * | ||
| * LIFETIME AND OWNERSHIP: | ||
| * - Data returned from hook callbacks transfers ownership to the SDK | ||
| * - Data received in callbacks can be modified and returned (ownership transfer) | ||
| * - Keys are copied by the SDK | ||
| * - Values retrieved with GetValue() are temporary - valid only during callback | ||
| * - Do not call LDValue_Free() on values retrieved with GetValue() | ||
| * - Values stored with SetValue() are copied into the data object | ||
| * - Pointers (void*) lifetime is managed by the application | ||
| * | ||
| * BUILDER PATTERN: | ||
| * To modify data, use LDEvaluationSeriesData_NewBuilder() to create a builder, | ||
| * make changes, then build a new data object. | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <launchdarkly/bindings/c/export.h> | ||
| #include <launchdarkly/bindings/c/context.h> | ||
|
|
||
| // No effect in C++, but we want it for C. | ||
| // ReSharper disable once CppUnusedIncludeDirective | ||
| #include <stdbool.h> // NOLINT(*-deprecated-headers) | ||
| // ReSharper disable once CppUnusedIncludeDirective | ||
| #include <stddef.h> // NOLINT(*-deprecated-headers) | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| typedef struct p_LDServerSDKEvaluationSeriesData* LDServerSDKEvaluationSeriesData; | ||
| typedef struct p_LDEvaluationSeriesDataBuilder* LDServerSDKEvaluationSeriesDataBuilder; | ||
|
|
||
|
|
||
| /** | ||
| * @brief Create a new empty evaluation series data. | ||
| * | ||
| * @return New data object. Must be freed with LDEvaluationSeriesData_Free() | ||
| * or transferred to SDK via hook callback return. | ||
| */ | ||
| LD_EXPORT(LDServerSDKEvaluationSeriesData) | ||
| LDEvaluationSeriesData_New(void); | ||
|
|
||
| /** | ||
| * @brief Get a Value from the evaluation series data. | ||
| * | ||
| * LIFETIME: Returns a temporary value valid only during the callback. | ||
| * Do not call LDValue_Free() on the returned value. | ||
| * | ||
| * USAGE: | ||
| * @code | ||
| * LDValue value; | ||
| * if (LDEvaluationSeriesData_GetValue(data, "timestamp", &value)) { | ||
| * // Use value (valid only during callback) | ||
| * double timestamp = LDValue_GetNumber(value); | ||
| * // Do NOT call LDValue_Free(value) | ||
| * } | ||
| * @endcode | ||
| * | ||
| * @param data Data object. Must not be NULL. | ||
| * @param key Key to look up. Must be null-terminated UTF-8 string. | ||
| * Must not be NULL. | ||
| * @param out_value Pointer to receive the value. Must not be NULL. | ||
| * Set to a temporary LDValue (valid only during callback). | ||
| * Do not call LDValue_Free() on this value. | ||
| * @return true if key was found and contains a Value, false otherwise. | ||
| */ | ||
| LD_EXPORT(bool) | ||
| LDEvaluationSeriesData_GetValue(LDServerSDKEvaluationSeriesData data, | ||
| char const* key, | ||
| LDValue* out_value); | ||
|
|
||
| /** | ||
| * @brief Get a pointer from the evaluation series data. | ||
| * | ||
| * Retrieves a pointer previously stored with | ||
| * LDEvaluationSeriesDataBuilder_SetPointer(). | ||
| * | ||
| * USAGE - OpenTelemetry span: | ||
| * @code | ||
| * void* span; | ||
| * if (LDEvaluationSeriesData_GetPointer(data, "span", &span)) { | ||
| * // Cast and use span | ||
| * MySpan* typed_span = (MySpan*)span; | ||
| * } | ||
| * @endcode | ||
| * | ||
| * @param data Data object. Must not be NULL. | ||
| * @param key Key to look up. Must be null-terminated UTF-8 string. | ||
| * Must not be NULL. | ||
| * @param out_pointer Pointer to receive the pointer value. Must not be NULL. | ||
| * Set to NULL if key not found. | ||
| * @return true if key was found and contains a pointer, false otherwise. | ||
| */ | ||
| LD_EXPORT(bool) | ||
| LDEvaluationSeriesData_GetPointer(LDServerSDKEvaluationSeriesData data, | ||
| char const* key, | ||
| void** out_pointer); | ||
|
|
||
| /** | ||
| * @brief Create a builder from existing data. | ||
| * | ||
| * Creates a builder initialized with the contents of the data object. | ||
| * Use this to add or modify entries in the data. | ||
| * | ||
| * USAGE: | ||
| * @code | ||
| * LDServerSDKEvaluationSeriesDataBuilder builder = | ||
| * LDEvaluationSeriesData_NewBuilder(input_data); | ||
| * LDEvaluationSeriesDataBuilder_SetValue(builder, "key", value); | ||
| * return LDEvaluationSeriesDataBuilder_Build(builder); | ||
| * @endcode | ||
| * | ||
| * @param data Data to copy into builder. May be NULL (creates empty builder). | ||
| * @return Builder object. Must be freed with | ||
| * LDEvaluationSeriesDataBuilder_Free() or consumed with | ||
| * LDEvaluationSeriesDataBuilder_Build(). | ||
| */ | ||
| LD_EXPORT(LDServerSDKEvaluationSeriesDataBuilder) | ||
| LDEvaluationSeriesData_NewBuilder(LDServerSDKEvaluationSeriesData data); | ||
|
|
||
| /** | ||
| * @brief Free evaluation series data. | ||
| * | ||
| * Only call this if you created the data and are not returning it from | ||
| * a hook callback. Data returned from callbacks is owned by the SDK. | ||
| * | ||
| * @param data Data to free. May be NULL (no-op). | ||
| */ | ||
| LD_EXPORT(void) | ||
| LDEvaluationSeriesData_Free(LDServerSDKEvaluationSeriesData data); | ||
|
|
||
| /** | ||
| * @brief Set a Value in the builder. | ||
| * | ||
| * OWNERSHIP: The value is copied/moved into the builder. You are responsible | ||
| * for freeing the original value if needed. | ||
| * | ||
| * @param builder Builder object. Must not be NULL. | ||
| * @param key Key for the value. Must be null-terminated UTF-8 string. | ||
| * Must not be NULL. The key is copied. | ||
| * @param value Value to store. Must not be NULL. The value is copied/moved. | ||
| */ | ||
| LD_EXPORT(void) | ||
| LDEvaluationSeriesDataBuilder_SetValue(LDServerSDKEvaluationSeriesDataBuilder builder, | ||
| char const* key, | ||
| LDValue value); | ||
|
|
||
| /** | ||
| * @brief Set a pointer in the builder. | ||
| * | ||
| * Stores an application-specific pointer. Useful for storing objects like | ||
| * OpenTelemetry spans that need to be passed from beforeEvaluation to | ||
| * afterEvaluation. | ||
| * | ||
| * LIFETIME: The pointer lifetime must extend through the evaluation series | ||
| * (from beforeEvaluation through afterEvaluation). | ||
| * | ||
| * EXAMPLE - OpenTelemetry span: | ||
| * @code | ||
| * MySpan* span = start_span(); | ||
| * LDEvaluationSeriesDataBuilder_SetPointer(builder, "span", span); | ||
| * @endcode | ||
| * | ||
| * @param builder Builder object. Must not be NULL. | ||
| * @param key Key for the pointer. Must be null-terminated UTF-8 string. | ||
| * Must not be NULL. The key is copied. | ||
| * @param pointer Pointer to store. May be NULL. Lifetime managed by caller. | ||
| */ | ||
| LD_EXPORT(void) | ||
| LDEvaluationSeriesDataBuilder_SetPointer( | ||
| LDServerSDKEvaluationSeriesDataBuilder builder, | ||
| char const* key, | ||
| void* pointer); | ||
|
|
||
| /** | ||
| * @brief Build the evaluation series data. | ||
| * | ||
| * Consumes the builder and creates a data object. After calling this, | ||
| * do not call LDEvaluationSeriesDataBuilder_Free() on the builder. | ||
| * | ||
| * @param builder Builder to consume. Must not be NULL. | ||
| * @return Data object. Must be freed with LDEvaluationSeriesData_Free() | ||
| * or transferred to SDK via hook callback return. | ||
| */ | ||
| LD_EXPORT(LDServerSDKEvaluationSeriesData) | ||
| LDEvaluationSeriesDataBuilder_Build(LDServerSDKEvaluationSeriesDataBuilder builder); | ||
|
|
||
| /** | ||
| * @brief Free a builder without building. | ||
| * | ||
| * Only call this if you did not call LDEvaluationSeriesDataBuilder_Build(). | ||
| * | ||
| * @param builder Builder to free. May be NULL (no-op). | ||
| */ | ||
| LD_EXPORT(void) | ||
| LDEvaluationSeriesDataBuilder_Free(LDServerSDKEvaluationSeriesDataBuilder builder); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
Oops, something went wrong.
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.
So, there was a mistake with the syntax of the clang-tidy suppression in the base binding implementations. Which result in suppressing all tidy messages.
We are not doing that here, and the result is that these opaque struct definitions were encountering: https://clang.llvm.org/extra/clang-tidy/checks/bugprone/reserved-identifier.html
Which isn't going to be a problem because the compiler isn't going to spontaneously reserve these very specific names.
But to appease it here I have started with
p_. This first name isn't used by calling code, but we just want it to not look like it should be used either.