The following information is for the latest SDK version (6.x). The CloudBees platform requires that your installed SDK version be at least 6.x. Please install the latest SDK by following the instructions in the platform UI or in the SDK installation documentation. Any updates to version 6.x are noted in the platform changelog. |
rox_ prefix functions
All rox_
prefix functions provide an interface for the CloudBees platform to manage feature flags that control the behavior of your application.
They handle communications with the server to obtain the latest flag values, implement flag settings, and set up flag configurations.
The flag repository manages RoxStringBase
structures, which holds your application’s feature flags.
Those variants display in the platform UI once the application is run.
The rox_
prefix functions also allow you to manage custom properties.
These can be static settings of type string, Boolean, integer, or double, or you can use a generator function to provide a custom property that is dependent upon code state.
You can also use RoxOptions
to configure some aspects of feature flag management.
For example, you can set the custom platform, impression handler, and fetch handler.
rox_setup
Configures the Rox object to work with the provided application.
RoxStateCode rox_setup(const char *api_key, RoxOptions *options)
Parameter | Modifier and type | Description |
---|---|---|
apiKey |
const char * |
The environment-specific SDK key provided in the UI. |
options |
RoxOptions |
A |
Returns the following:
typedef enum RoxStateCode { RoxUninitialized = 0, RoxSettingUp = 1, RoxInitialized = 2, RoxShuttingDown = 3, RoxErrorEmptyApiKey = -1, RoxErrorInvalidApiKey = -2, RoxErrorGenericSetupFailure = -1000 } RoxStateCode
In the case of a successful call, rox_setup
returns RoxInitialized
code.
Otherwise, analyze the application logs for errors and warnings.
If rox_setup
returned failure code, it may be called again after fixing the errors from the logs.
rox_shutdown
Like everything in C, objects must be released when the application exits.
void rox_shutdown()
rox_setup may be called again after rox_shutdown .
|
Use as in the following example:
// application start rox_setup("YOUR_SDK_KEY", NULL); // application end rox_shutdown();
rox_add_flag
Use as follows:
RoxStringBase *rox_add_flag(const char *name, bool default_value)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The flag name |
default_value |
bool |
The flag default value: true/false |
rox_add_string and rox_add_string_with_options
Use as follows:
RoxStringBase *rox_add_string(const char *name, const char *default_value) RoxStringBase *rox_add_string_with_options(const char *name, const char *default_value, RoxList *options)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The variant name. |
default_value |
const char * |
The variant default value. |
options |
RoxList * |
A list of all possible values for the defined |
RoxStringBase *rox_add_int(const char *name, int default_value) RoxStringBase *rox_add_int_with_options(const char *name, int default_value, RoxList *options)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The variant name. |
default_value |
int |
The variant default value. |
options |
RoxList * |
A list of all possible values for the defined |
RoxStringBase *rox_add_double(const char *name, double default_value) RoxStringBase *rox_add_double_with_options(const char *name, double default_value, RoxList *options)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The variant name. |
default_value |
double |
The variant default value. |
options |
RoxList * |
A list of all possible values for the defined |
Use as in the following example:
RoxStringBase *videoChat = rox_add_flag("demo.video_chat", false); RoxStringBase *fontName = rox_add_string("fontName", "Arial"); RoxStringBase *titleColor = rox_add_string_with_options("titleColors", "red", ROX_LIST_COPY_STR("red", "blue", "green")); RoxStringBase *titleSize = rox_add_int_with_options("titleSize", 14, ROX_INT_LIST(14, 18, 24)); RoxStringBase *priceVariant = rox_add_double_with_options("price", 19.99, ROX_DBL_LIST(19.99, 29.99, 40.5));
Flags and variants registered to the UI have the names
demo.video_chat
, fontName
, titleColors
, titleSize
, and priceVariant
.
You can create optional namespaces, each with its own group of flags and configurations (such as demo
).
Freeze values
By default, all flags have their freeze level set to RoxFreezeNone
, meaning a new flag value is fetched each time the flag is accessed via the rox_get_xxx
or rox_is_enabled
functions.
typedef enum RoxFreeze { RoxFreezeUntilLaunch = 1, RoxFreezeUntilForeground = 2, RoxFreezeNone = 3 } RoxFreeze;
Change the freeze level by the following:
rox_add_xxx_with_freeze - add a flag with custom freeze level
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The variant name. |
default_value |
bool/string/int/double |
The variant default value. |
options |
RoxList * |
A list of all possible values for the defined |
freeze |
RoxFreeze |
Freeze level for the defined |
rox_freeze_flag - set freeze level for a flag
Sets the freeze level for the flag, if not set via the rox_add_xxx_with_freeze
constructor.
void rox_freeze_flag(RoxStringBase *flag, RoxFreeze freeze)
Override flag values
RoxFlagOverrides
is an opaque struct, and it acts as a handle for the flag overriding data.
RoxFlagOverrides *rox_get_overrides()
Flag overrides are used to override a flag values locally and must not be used in production builds. The only way to use overrides is via the code.
When you override an existing flag value using the rox_set_override
function, the SDK disregards the existing configuration from the UI and serializes the override on disk.
This value is loaded and overrides the flag right after you call rox_setup
.
To clear the override from the cache, call either the rox_clear_override
or rox_clear_overrides
function.
rox_set_override
Sets an override value on a specific flag.
void rox_set_override(RoxFlagOverrides *overrides, const char *name, const char *value)
This function also saves the override value on the local device disk, so it is recalled for the next time the SDK is loaded to production.
Parameter | Modifier and type | Description |
---|---|---|
name |
const char* |
The full flag name including the namespace, for example, |
value |
const char* |
The value of a flag.
If this is a Boolean flag, the value must be |
rox_get_override
Returns the overridden flag value (or NULL
, if not yet overridden).
const char *rox_get_override(RoxFlagOverrides *overrides, const char *name)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char* |
The full flag name including the namespace,for example, |
rox_has_override
Checks whether the flag value has been overridden.
bool rox_has_override(RoxFlagOverrides *overrides, const char *name)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char* |
The full flag name including the namespace,for example, |
rox_clear_override
Clears the overridden flag value.
void rox_clear_override(RoxFlagOverrides *overrides, const char *name)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char* |
The full flag name including the namespace,for example, |
rox_clear_overrides
Clear all overridden flag values.
void rox_clear_overrides(RoxFlagOverrides *overrides)
Custom properties
The role of a custom property is to segment the audience and apply a set of flags for target groups defined by these properties.
Custom properties are any of the following types:
-
bool
-
int
-
double
-
semver
-
string
There are simple (direct) custom properties and calculated ones, using RoxContext
to be more dynamic.
Simple (direct) custom properties
Use as in the following examples.
rox_set_custom_boolean_property
Sets a custom property representing a Boolean value.
void rox_set_custom_boolean_property(const char *name, bool value)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The name of the property to create. |
value |
bool |
The value for the custom property, either true or false. |
rox_set_custom_string_property
Sets a custom property representing a string value.
void rox_set_custom_string_property(const char *name, const char *value)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The name of the property to create. |
value |
const char * |
The value for the custom property. |
rox_set_custom_semver_property
Sets a custom property representing a semver value. Refer to the Semantic Versioning documentation for more information.
void rox_set_custom_semver_property(const char *name, const char *value)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The name of the property to create. |
value |
const char * |
The value for the custom property. |
rox_set_custom_computed_boolean_property
Sets a computed Boolean custom property on the Rox client.
This is a computable Boolean, with a function that generates the value for the property.
The generator must be of type rox_custom_property_value_generator
.
void rox_set_custom_computed_boolean_property(const char *name, void *target, rox_custom_property_value_generator generator)
Parameter | Modifier and type | Description |
---|---|---|
name |
const char * |
The name of the property to create. |
target |
void * |
Any pointer; is forwarded to the generator. |
generator |
rox_custom_property_value_generator |
A
|
rox_set_custom_computed_string_property
Sets a computed string custom property on the Rox client.
This is a computable string, with a function that generates the value for the property.
The generator must be a delegate of type
rox_custom_property_value_generator
.
void rox_set_custom_computed_string_property(const char *name, void *target, rox_custom_property_value_generator generator)
Parameter | Modifier and type | Description |
---|---|---|
name |
string |
The name of the property to create. |
target |
void * |
Any pointer; is forwarded to the generator. |
generator |
rox_custom_property_value_generator |
A
|
rox_set_custom_computed_integer_property
Sets a computed integer custom property on the Rox client.
This is a computable int, with a function that generates the value for the property.
The generator must be a delegate of type
rox_custom_property_value_generator
.
void rox_set_custom_computed_integer_property(const char *name, void *target, rox_custom_property_value_generator generator)
Parameter | Modifier and type | Description |
---|---|---|
name |
string |
The name of the property to create. |
target |
void * |
Any pointer; is forwarded to the generator. |
generator |
rox_custom_property_value_generator |
A
|
rox_set_custom_computed_semver_property
Sets a computed semantic-versioned string custom property on the Rox
client.
This is a computable semantically-versioned string, with a
function that generates the value for the property.
The generator must be a delegate of type rox_custom_property_value_generator
.
void rox_set_custom_computed_semver_property(const char *name, void *target, rox_custom_property_value_generator generator)
Parameter | Modifier and type | Description |
---|---|---|
name |
string |
The name of the property to create. |
target |
void * |
Any pointer; is forwarded to the generator. |
generator |
rox_custom_property_value_generator |
A
|
rox_set_custom_computed_double_property
Sets a computed double custom property on the Rox client.
This is a computable double, with a function that generates the value for the property.
The generator must be a delegate of type
rox_custom_property_value_generator
.
void rox_set_custom_computed_double_property(const char *name, void *target, rox_custom_property_value_generator generator)
Parameter | Modifier and type | Description |
---|---|---|
name |
string |
The name of the property to create. |
target |
void * |
Any pointer; is forwarded to the generator. |
generator |
rox_custom_property_value_generator |
A
|
rox_set_context
Sets a global context. This context is available to all flag evaluations, in addition to the specific call context.
void rox_set_context(RoxContext *context)
RoxOptions
RoxOptions
cover configuration options for the Rox client, including fetch interval and impression handler settings.
Create instances of this struct using rox_options_create
.
In the following example, a new RoxOptions
struct is set up.
This options
object sets the version, provides an impression handler, and provides a fetch handler.
rox_options_set_version
Sets the version of the service running the CloudBees platform SDK. Use this in the platform UI for targeting filtering.
void rox_options_set_version(RoxOptions *options, const char *version)
rox_options_set_fetch_interval
Sets the polling interval for fetching configurations from the CloudBees platform storage service.
void rox_options_set_fetch_interval(RoxOptions *options, int fetch_interval)
rox_options_set_configuration_fetched_handler
Sets the configuration event handler to add actions after configurations are fetched.
void rox_options_set_configuration_fetched_handler(RoxOptions *options, void *target, rox_configuration_fetched_handler handler)
rox_options_set_impression_handler
Sets the impression event handler to add actions after a flag evaluation.
void rox_options_set_impression_handler(RoxOptions *options, void *target, rox_impression_handler handler)
rox_options_set_dynamic_properties_rule
The dynamic custom property generator is called when an explicit custom property definition does not exist on the client side.
If you do not set the rox_options_set_dynamic_properties_rule
,the default method is activated, and it attempts to extract the property value from context.
void rox_options_set_dynamic_properties_rule(RoxOptions *options, void *target, rox_dynamic_properties_rule rule)
DynamicPropertiesRule
is a:
RoxDynamicValue *(*rox_dynamic_properties_rule)(const char *prop_name, void *target, RoxContext *context)
if (context != NULL) { return rox_context_get(context, prop_name); } return NULL;
RoxStringBase
RoxStringBase
is a feature flag struct.
It represents a more complex flag type, which accepts a list of all possible values and a default value.
Use this list when selecting new values for the feature, and the value can be overridden via the UI.
rox_is_enabled
Returns the current flag value (or the default, if no value is set).
bool rox_is_enabled(RoxStringBase *variant)
rox_is_enabled_ctx
Returns the current flag value, considering the given context.
bool rox_is_enabled_ctx(RoxStringBase *variant, RoxContext *context)
RoxContext
Use the context struct to pass data to the flag or variant evaluation. This struct is used by the registered custom properties to evaluate the flag and return the value.
Create a context using the rox_context_create_empty
, sending a
dictionary to its Build
function.
rox_context_create_from_map
Creates a RoxContext
from a RoxMap
.
Keys are strings, and values are of RoxDynamicValue
type.
RoxContext *rox_context_create_from_map(RoxMap *map)
Using ConfigurationFetchedHandler
Use rox_options_set_configuration_fetched_handler
to set ConfigurationFetchedHandler
.
Use as in the following example:
typedef void (*rox_configuration_fetched_handler)(void *target, RoxConfigurationFetchedArgs *args)
The additional definitions used are:
RoxConfigurationFetchedArgs
Use as follows:
typedef struct RoxConfigurationFetchedArgs { RoxFetchStatus fetcher_status; const char *creation_date; bool has_changes; RoxFetcherError error_details; } RoxConfigurationFetchedArgs
The configuration fetched handler gets the following:
Using ImpressionHandler
The impression handler delegate/function (rox_options_set_impression_handler
) has useful
parameters to help you decide on further actions.
Use as in the following example:
typedef void (*rox_impression_handler)(void *target, RoxReportingValue *value, RoxExperiment *experiment, RoxContext *context)
With the relevant additional definitions:
RoxDynamicValue
RoxDynamicValue
represents a dynamic value, which wraps a type value.
Use this when working with RoxContext
and custom properties.
rox_dynamic_value_create_int
Wraps an int value into a RoxDynamicValue
:
RoxDynamicValue *rox_dynamic_value_create_int(int value)
rox_dynamic_value_create_double
Wraps a double value into a RoxDynamicValue
:
RoxDynamicValue *rox_dynamic_value_create_double(double value)
rox_dynamic_value_create_double_ptr
Wraps a double pointer value into a RoxDynamicValue:
RoxDynamicValue *rox_dynamic_value_create_double_ptr(double *value)
rox_dynamic_value_create_boolean
Wraps a bool value into a RoxDynamicValue
:
RoxDynamicValue *rox_dynamic_value_create_boolean(bool value)
rox_dynamic_value_create_string_copy
Creates a RoxDynamicValue
by copying the value that has to be freed after use:
RoxDynamicValue *rox_dynamic_value_create_string_copy(const char *value)
rox_dynamic_value_create_string_ptr
Wraps a string value into a RoxDynamicValue
; the string is freed by calling dynamic_value_free()
:
RoxDynamicValue *rox_dynamic_value_create_string_ptr(char *value)
rox_dynamic_value_create_list
Wraps a RoxList
value into a RoxDynamicValue
; the list is freed by calling dynamic_value_free()
.
RoxDynamicValue *rox_dynamic_value_create_list(RoxList *value)
rox_dynamic_value_create_map
Wraps a RoxMap
value into a RoxDynamicValue
; the map is freed by calling dynamic_value_free()
.
RoxDynamicValue *rox_dynamic_value_create_map(RoxMap *value)
rox_dynamic_value_create_null
Creates a null value.
RoxDynamicValue *rox_dynamic_value_create_null()
rox_dynamic_value_create_copy
Creates a copy of a RoxDynamicValue:
RoxDynamicValue *rox_dynamic_value_create_copy(RoxDynamicValue *value)
rox_dynamic_value_free
Frees the RoxDynamicValue
(must be called after rox_context_get
):
RoxDynamicValue *rox_dynamic_value_free(RoxDynamicValue *value)
rox_dynamic_value_is_int
Returns true if a RoxDynamicValue
is of type int.
bool rox_dynamic_value_is_int(RoxDynamicValue *value)
rox_dynamic_value_is_double
Returns true if a RoxDynamicValue
is of type double.
bool rox_dynamic_value_is_double(RoxDynamicValue *value)
rox_dynamic_value_is_boolean
Returns true if a RoxDynamicValue
is of type bool.
bool rox_dynamic_value_is_boolean(RoxDynamicValue *value)
rox_dynamic_value_is_string
Returns true if a RoxDynamicValue
is of type string.
bool rox_dynamic_value_is_string(RoxDynamicValue *value)
rox_dynamic_value_is_list
Returns true if a RoxDynamicValue
is of type RoxList
.
bool rox_dynamic_value_is_list(RoxDynamicValue *value)
rox_dynamic_value_is_map
Returns true if a RoxDynamicValue
is of type RoxMap
.
bool rox_dynamic_value_is_map(RoxDynamicValue *value)
rox_dynamic_value_is_undefined
Returns true if a RoxDynamicValue
is undefined.
bool rox_dynamic_value_is_undefined(RoxDynamicValue *value)
rox_dynamic_value_is_null
Returns true if a RoxDynamicValue
is null.
bool rox_dynamic_value_is_null(RoxDynamicValue *value)
rox_dynamic_value_get_int
Returns the int value of the RoxDynamicValue
.
int rox_dynamic_value_get_int(RoxDynamicValue *value)
rox_dynamic_value_get_double
Returns the double value of the RoxDynamicValue
.
double rox_dynamic_value_get_double(RoxDynamicValue *value)
rox_dynamic_value_get_boolean
Returns the bool value of the RoxDynamicValue
.
bool rox_dynamic_value_get_boolean(RoxDynamicValue *value)
rox_dynamic_value_get_string
Returns the string value of the RoxDynamicValue
.
char *rox_dynamic_value_get_string(RoxDynamicValue *value)
DynamicApi
An alternative way to evaluate flags and variants by name without having a static container. The dynamic API creates flags as if they were registered, including sending them to the UI.
rox_dynamic_api
Create a RoxDynamicApi
, the proxy to all dynamic flags and variants evaluations.
RoxDynamicApi *rox_dynamic_api()
rox_dynamic_api_is_enabled
Evaluates a flag by its name and context.
If no configuration is set via the UI, the default_value
is
returned.
bool rox_dynamic_api_is_enabled(RoxDynamicApi *api, const char *name, bool default_value, RoxContext *context)
Logging
Use rox_logging_init
to set up logging.
Use logging to assist in debugging unexpected results.
If no logging is set, errors are logged to the default printing to stdout
.
rox_logging_init
Sets up logging with RoxLoggingConfig
.
void rox_logging_init(RoxLoggingConfig *config)
RoxLoggingConfig
Sets up a logging configuration.
Setting up a rox_logging_handler
overrides the default handler that uses the other properties.
Configurations can be created using ROX_LOGGING_CONFIG_INITIALIZER
, setting the log_level
, and using default for all other properties.
typedef struct RoxLoggingConfig {RoxLogLevel min_level; void *target; rox_logging_handler handler; bool print_time; } RoxLoggingConfig
ROX_LOGGING_CONFIG_INITIALIZER
Use as follows:
#define ROX_LOGGING_CONFIG_INITIALIZER(log_level) {log_level, NULL, NULL, false}
RoxLogLevel
Use as follows:
typedef enum RoxLogLevel { RoxLogLevelTrace = 1, RoxLogLevelDebug, RoxLogLevelWarning, RoxLogLevelError, RoxLogLevelNone } RoxLogLevel
Helpers
The following helper types are available:
-
RoxList: A list.
-
RoxSet: A hashset.
-
RoxMap: A hashtable.
Helper functions
Use as in the following examples.
ROX_LIST_COPY_STR
Create a RoxList
from strings, creating a copy for each string.
#define ROX_LIST_COPY_STR(...) rox_list_create_str_va(NULL, __VA_ARGS__, NULL)
ROX_INT_LIST
Create a RoxList
from integers.
#define ROX_INT_LIST(...) rox_list_create_int_va(NULL, __VA_ARGS__, INT_MIN)