Ruby SDK

This guide provides detailed information about our Ruby SDK. All of our SDKs are open source. Go to our Ruby SDK GitHub repository to learn more.

Initialization

1. Import the SDK into your project

gem install splitclient-rb -v '~> 6.3.0'

gem install splitclient-rb -v '~> 6.3.0'

If using Synchronizer with Redis - Synchronizer 2.x required after SDK Version 3.x

Since version 2.0.0 of the split-synchronizer, we use a more efficient scheme to store impressions in Redis. This approach is faster and easier on your Redis instances, since it yields better throughput of impressions to the backend. If you use this SDK with the Synchronizer in Redis or Proxy mode, you will need the newest versions of our Split Synchronizer. It is recommended that once you're using SDK versions compatible with Split-Sync 2.0 on all your applications pointing to the redis instance maintained by the Split-Sync, you disable backwards compatibility (this is as easy as changing a parameter to `true` on the JSON config or an environment variable to `on` if you're using the docker image).

Coming from SDK version 4.x?

The current Split Ruby SDK 5.x breaks backward compatibility to correct an improper allocation in the 4.x version. If you are running a 4.x version, reach out to [support@split.io](mailto:support@split.io) for assistance.

2. Instantiate the SDK and create a new split client

When the SDK is instantiated, it kicks off background tasks to update an in-memory cache with small amounts of data fetched from Split servers. This process can take up to a few hundred milliseconds depending on the size of data. If the SDK is asked to evaluate which treatment to show to a customer for a specific split while its in this intermediate state, it may not have the data necessary to run the evaluation. In this case, the SDK does not fail, rather, it returns the control treatment.

To make sure the SDK is properly loaded before asking it for a treatment, block until the SDK is ready. This is done by using the .Ready parameter as part of the instantiation process of the SDK client as shown below. Do this all as a part of the startup sequence of your application.

We recommend instantiating the SDK once as a singleton and reusing it throughout your application.

Use the code snippet below and plug in your API key. The API key is available on your Organization Settings page, on the APIs tab. The API key is of type sdk. For more information, see Understanding API Keys.

To access the SDK client in your controllers, use the code snippet below.

Rails.application.config.split_client

Now you can start asking the SDK to evaluate treatments for your customers.

Compatibility

The Split Ruby SDK has been tested as a standalone app using the following web servers: * Puma * Passenger * Unicorn * Webrick * Thin For other setups, reach out to [support@split.io](mailto:support@split.io).

Server spawning method

If you are running NGINX with `thread_spawn_method = 'smart'`, use our Redis integration with the [Split Synchronizer](https://help.split.io/hc/en-us/articles/360019686092-Split-synchronizer) or contact [support@split.io](mailto:support@split.io) for alternatives to run Split.

Using the SDK

Basic use

After you instantiate the SDK client, you can start using the get_Treatment method of the SDK client to decide what version of your features your customers are served. The method requires the SPLIT_NAME attribute that you want to ask for a treatment and a unique CUSTOMER_ID attribute that corresponds to the end user that you want to serve the feature to.

From there, you simply need to use an if-else-if block as shown below and insert the code for the different treatments that you defined in the Split UI. Remember the final else branch in your code to handle the client returning the control treatment.

Shutdown

Call the .destroy method before letting a process using the SDK exit, as this method gracefully shuts down the Split SDK by stopping all background threads, clearing caches, closing connections, and flushing the remaining unpublished impressions.

client.destroy

Important!

A call to the `destroy()` method also destroys the factory object. When creating new client instance, first create a new factory instance.

Multiple evaluations at once

In some instances, you may want to evaluate treatments for multiple splits at once. Use the GetTreatments method of the split client to do this. Simply pass a list of the split names you want treatments for and the method returns the proper treatments in the format Dictionary<string, string>.

Attribute syntax

In the example below, we are rolling out a split to users. The provided attributes plan_type, registered_date, permissions, paying_customer, and deal_size are passed to the getTreatment call. These attributes are compared and evaluated against the attributes used in the rollout plan as defined in the Split Web console to decide whether to show the on or off treatment to this account.

The getTreatment method supports five types of attributes: strings, numbers, dates, booleans, and sets. The proper data type and syntax for each are:

Strings: Use type String.

Numbers: Use type long or int.

Dates: Express the value as seconds since epoch and as objects of class DateTime.

Get Treatments with Configurations

This method will return an object containing the treatment and associated configuration.

The config element will be a stringified version of the configuration JSON defined in the Split web console. If there is no configuration defined for a treatment, the SDK will return null for the config parameter. // is null correct for Ruby?

This method takes the exact same set of arguments as the standard getTreatment method. See below for examples on proper usage:

If you need to get multiple evaluations at once, you can also use the getTreatmentsWithConfig. The method takes the exact same arguments as the getTreatments method but just returns a mapping of split names to objects instead of strings. Example usage below.

Track

Use the track method to record any actions your customers perform. Each action is known as an event and corresponds to an event type. Calling track through one of our SDKs or via the API is the first step to getting experimentation data into Split and allows you to measure the impact of your splits on your users' actions and metrics.

In the examples below you can see that the .track() method can take up to four arguments. The proper data type and syntax for each are:

CUSTOMER_ID: The customer_id variable used in the getTreatment call and firing this track event. The expected data type is String.

TRAFFIC_TYPE: The traffic type of the customer ID in the track call. The expected data type is String. You can only pass values that match the names of traffic types that you have defined in your instance of Split.

EVENT_TYPE: The event type that this event should correspond to. The expected data type is String. Full requirements on this argument are:

Contains 63 characters or fewer.

Starts with a letter or number.

Contains only letters, numbers, hyphen, underscore, or period.

This is the regular expression we use to validate the value:[a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}

VALUE: (Optional) The value to be used in creating the metric. This field can be sent in as null or 0 if you intend to purely use the count function when creating a metric. The expected data type is Integer or Float.

The track method returns a boolean value of true or false to indicate whether or not the SDK was able to successfully queue the event to be sent back to Split's servers on the next event post. The SDK will return false if the current queue size is equal to the config set by eventsQueueSize or if an incorrect input to the track method has been provided.

In the case that a bad input has been provided, you can read more about our SDK's expected behavior here

# If you would like to send an event without a value
track_event = split_client.track("CUSTOMER_ID", "TRAFFIC_TYPE", "EVENT_TYPE")
# Example
track_event = split_client.track("john@doe.com", "user", "page_load_time")
# If you would like to associate a value to an event
track_event = split_client.track("CUSTOMER_ID", "TRAFFIC_TYPE", "EVENT_TYPE", VALUE)
# Example
track_event = split_client.track("john@doe.com", "user", "page_load_time", 83.334)

Configuration

The SDK has a number of knobs for configuring performance. Each knob is tuned to a reasonable default. However, you can override the value while instantiating the SDK. The parameters available for configuration are shown below.

Configuration

Description

Default value

logger

The log implementation to use for warnings and errors from the SDK.

Logs to STDOUT

debug_enabled

Enabled verbose mode.

false

transport_debug_enabled

Super verbose mode that prints network payloads among others.

false

connection_timeout

HTTP client connection timeout (in seconds).

5s

read_timeout

HTTP socket read timeout (in seconds).

5s

features_refresh_rate

The SDK polls Split servers for changes to feature splits at this period (in seconds).

segments_refresh_rate

The SDK polls Split servers for changes to segments at this period (in seconds).

60s

metrics_refresh_rate

The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds.

60s

impressions_refresh_rate

The treatment log captures which customer saw what treatment (on, off, etc.) at what time. This log is periodically flushed back to Split servers. This configuration controls how quickly does the cache expire after a write (in seconds).

60s

block_until_ready

The SDK blocks your app for this number of seconds until it is ready. If the time expires, SplitIoClient::SDKBlockerTimeoutExpiredException is thrown. If false, the SDK runs in non-blocking mode.

Sharing state: Redis integration

Configuring this Redis integration section is optional for most setups. Read below to determine if it might be useful for your project

By default, the split client stores the state it needs to compute treatments (rollout plans, segments, and so on) in memory. As a result, it is easy to get set up with Split: simply instantiate a client and start using it. Thus configurating this Redis integration section is optional for most setups.

This simplicity hides one important detail that is worth exploring. Because each split client downloads and stores state separately, a change in a split is picked up by every client on its own schedule. Thus, if a customer issues back-to-back requests that are served by two different machines behind a load balancer, the customer can see different treatments for the same split because one split client may not have picked up the latest change. This drift in clients is natural and usually ignorable as long as each client sets an aggressive value for FeaturesRefreshRate and SegmentsRefreshRate. You can learn more about setting these rates in the Configuration section.

However, if your application requires a total guarantee that split clients across your entire infrastructure pick up a change in a split at the exact same time, then the only way to ensure that is to externalize the state of the split client in a data store hosted on your infrastructure.

We currently support Redis for this external data store.

To use the Ruby SDK with Redis, set up the Split Synchronizer and instantiate the SDK in consumer mode.

Split Synchronizer

Follow the steps in our Split Synchronizer documents to get everything set to sync data to your Redis cache. After you do that, come back to set up the SDK in consumer mode!

Consumer Mode

In consumer mode, a client can be embedded in your application code and respond to calls to get_treatment by retrieving state from the data store (Redis in this case).

Here is how to configure and get treatments for a split client in consumer mode.

Redis Cluster

This functionality is currently not supported for this SDK, but is coming in a future release! Subscribe to our release notes for updates.

Localhost mode

//PLEASE ADD PROPER SYNTAX CHANGE FOR LOCALHOST MODE DUE TO DYNAMIC CONFIGS - USE PYTHON AS AN EXAMPLE

Features start their life on one developer's machine. A developer should be able to put code behind splits on their development machine without the SDK requiring network connectivity. To achieve this, the Split SDK can be started in localhost mode (aka off-the-grid mode). In this mode, the SDK neither polls nor updates Split servers. Instead, it uses an in-memory data structure to determine what treatments to show to the logged in customer for each of the features.

In this mode, the SDK loads a mapping of Split name to treatment from a file at $HOME/.split. For a given split, the treatment specified in the file is returned for every customer.

All getTreatment calls for a split only return the one treatment that you defined in the file. You can then change the treatment as necessary for your testing in the file. Any feature that is not provided in the features map returns the control treatment if the SDK is asked to evaluate them.

Here is a sample .split file. The format of this file is two columns separated by a whitespace. The left column is the split name, and the right column is the treatment name.

By default, changes in the file are not automatically picked up without restarting the client. To have the client automatically pick up changes to the file, specify reload_rate as the interval in seconds at which changes are picked up. Here is an example of specifying both path and reload_rate.

Listener

Split SDKs send impression data back to Split servers periodically when evaluating splits. To send this information to a location of your choice, define and attach an impression listener.

The SDK sends the generated impressions to the impression listener right away. However, to avoid blocking the caller thread, use the second parameter to specify the size of the queue acting as a buffer (see the snippet below).

If the impression listener is slow at processing the incoming data, the queue fills up and any subsequent impressions are dropped.