Snowplow Ruby Tracker 0.5.0 released

11 August 2015  •  Fred Blundun

We are happy to announce the release of version 0.5.0 of the Snowplow Ruby Tracker. As well as making the Tracker more robust, this release introduces several breaking API changes.

Read on for more detail on:

  1. Improved concurrency
  2. More robust error handling
  3. The SelfDescribingJson class
  4. New setFingerprint method
  5. Upgrading
  6. Getting help

1. Improved concurrency

The Ruby Tracker’s AsyncEmitter class now uses the Queue class to implement the producer-consumer pattern, where a fixed pool of threads work on sending events. Reusing threads this way performs better than the previous implementation in which a new thread was created for every network request.

You can configure the number of threads to use with the new thread_count field of the AsyncEmitter’s configuration hash like this:

my_emitter = AsyncEmitter.new(MY_ENDPOINT, {
  :thread_count => 10
})

If your application only rarely sends events, the default of 1 thread should be good enough; otherwise try experimenting with different values to determine which works best.

We have also eliminated a race condition where sending many events at once could cause events to be duplicated or skipped.

2. More robust error handling

The previous tracker version only treated requests with status code 200 as successful. This behavior has been broadened to include all 2xx and 3xx status codes.

The tracker now catches all network-related exceptions and treats the events which caused them as failed. This means that network unavailability no longer causes the tracker to throw exceptions.

3. The SelfDescribingJson class

The new SelfDescribingJson class makes it easier to build unstructured events and custom contexts.

Instead of fully specifying JSONs like this:

my_event = {
  'schema' => 'iglu:com.acme/myevent/jsonschema/1-0-0',
  'data' => {
    'color' => 'red'
  }
}
my_context = {
  'schema' => 'iglu:com.acme/mycontext/jsonschema/1-0-1',
  'data' => {
    'size' => 5
  }
}
my_tracker.track_unstruct_event(my_event, [my_context])

you would now use the SelfDescribingJson class to automatically handle the “schema” and “data” fields like this:

my_event = SnowplowTracker::SelfDescribingJson.new(
  'iglu:com.acme/myevent/jsonschema/1-0-0',
  {
    'color' => 'red'
  }
)

my_context = SnowplowTracker::SelfDescribingJson.new(
  'iglu:com.acme/mycontext/jsonschema/1-0-0',
  {
    'size' => 5
  }
)

my_tracker.track_unstruct_event(my_event, [my_context])

Note that this is a breaking change and old-style API calls which manually construct unstructured events and custom contexts will no longer work.

4. New setUserFingerprint method

Thanks to Snowplow community member Kacper Bielecki (@kazjote on GitHub), you can now set a user fingerprint for a Subject like this:

my_subject.set_fingerprint(7304597607)

Thanks a lot Kacper!

5. Upgrading

This release increases the version of the contexts schema from 1-0-0 to 1-0-1 to allow empty contexts arrays. Because of this, it is only compatible with version 0.9.14 and later of the core Snowplow platform.

You will need to update all unstructured events and contexts to use the SelfDescribingJson class mentioned above.

The tracker.flush method now takes one boolean argument, async, which defaults to false. Usage of this method is demonstrated below:

# Perform an asynchronous flush, which moves all buffered events to the work queue to be sent to the collector but doesn't block
my_tracker.flush(true)

# Perform a synchonous flush, blocking until all events have been sent
my_tracker.flush

The Emitter class’s buffer_size configuration option used to be 0-indexed, so with the following configuration the Emitter would send events in batches of 6:

my_emitter = AsyncEmitter.new(MY_ENDPOINT, {
  :buffer_size => 5
})

The buffer_size is now 1-indexed, so that with this configuration events will be sent in batches of 5.

Due to JRuby compatibility issues, we have made the Ruby Tracker’s dependency on the Contracts gem more strict: rather than allowing all Contracts versions since 0.3.0, the Gemfile now requires a Contracts version between 0.7 and 0.11 (inclusive).

6. Getting help

These links may be useful:

If you have an idea for a new feature or want help getting things set up, please get in touch. Raise an issue in the GitHub repository if you find any bugs.