Code Monkey home page Code Monkey logo

keen-gem's Introduction

Keen IO Official Ruby Client Library

Build Status Code Climate Gem Version

keen-gem is the official Ruby Client for the Keen IO API. The Keen IO API lets developers build analytics features directly into their apps.

Installation

Add to your Gemfile:

gem 'keen'

or install from Rubygems:

gem install keen

keen is tested with Ruby 1.9.3 + and on:

  • MRI
  • Rubinius
  • jRuby (except for asynchronous methods - no TLS support for EM on jRuby)

Usage

Before making any API calls, you must supply keen-gem with a Project ID and one or more authentication keys. (If you need a Keen IO account, sign up here - it's free.)

Setting a write key is required for publishing events. Setting a read key is required for running queries. Setting a master key is required for performing deletes. You can find keys for all of your projects on keen.io.

The recommended way to set keys is via the environment. The keys you can set are KEEN_PROJECT_ID, KEEN_WRITE_KEY, KEEN_READ_KEY and KEEN_MASTER_KEY. You only need to specify the keys that correspond to the API calls you'll be performing. If you're using foreman, add this to your .env file:

KEEN_PROJECT_ID=aaaaaaaaaaaaaaa
KEEN_MASTER_KEY=xxxxxxxxxxxxxxx
KEEN_WRITE_KEY=yyyyyyyyyyyyyyy
KEEN_READ_KEY=zzzzzzzzzzzzzzz

If not, make a script to export the variables into your shell or put it before the command you use to start your server.

When you deploy, make sure your production environment variables are set. For example, set config vars on Heroku. (We recommend this environment-based approach because it keeps sensitive information out of the codebase. If you can't do this, see the alternatives below.)

Once your environment is properly configured, the Keen object is ready to go immediately.

Data Enrichment

A data enrichment is a powerful add-on to enrich the data you're already streaming to Keen IO by pre-processing the data and adding helpful data properties. To activate add-ons, you simply add some new properties within the "keen" namespace in your events. Detailed documentation for the configuration of our add-ons is available here.

Here is an example of using the URL parser:

    Keen.publish(:requests, {
        :page_url => "http://my-website.com/cool/link?source=twitter&foo=bar/#title",
        :keen => {
            :addons => [
              {
                :name => "keen:url_parser",
                :input => {
                    :url => "page_url"
                },
                :output => "parsed_page_url"
              }
            ]
        }
    })

Keen IO will parse the URL for you and that would equivalent to:

    Keen.publish(:request, {
        :page_url => "http://my-website.com/cool/link?source=twitter&foo=bar/#title",
        :parsed_page_url => {
            :protocol => "http",
            :domain => "my-website.com",
            :path => "/cool/link",
            :anchor => "title",
            :query_string => {
                :source => "twitter",
                :foo => "bar"
            }
        }
    })

Here is another example of using the Datetime parser. Let's assume you want to do a deeper analysis on the "purchases" event by day of the week (Monday, Tuesday, Wednesday, etc.) and other interesting Datetime components. You can use "keen.timestamp" property that is included in your event automatically.

    Keen.publish(:purchases, {
        :keen => {
            :addons => [
              {
                :name => "keen:date_time_parser",
                :input => {
                    :date_time => "keen.timestamp"
                },
                :output => "timestamp_info"
              }
            ]
        },
        :price => 500
    })

Other Data Enrichment add-ons are located in the API reference docs.

Synchronous Publishing

Publishing events requires that KEEN_WRITE_KEY is set. Publish an event like this:

Keen.publish(:sign_ups, { :username => "lloyd", :referred_by => "harry" })

This will publish an event to the sign_ups collection with the username and referred_by properties set. The event properties can be any valid Ruby hash. Nested properties are allowed. Lists of objects are also allowed, but not recommended because they can be difficult to query over. See alternatives to lists of objects here. You can learn more about data modeling with Keen IO with the Data Modeling Guide.

Protip: Marshalling gems like Blockhead make converting structs or objects to hashes easier.

The event collection need not exist in advance. If it doesn't exist, Keen IO will create it on the first request.

Asynchronous publishing

Publishing events shouldn't slow your application down or make users wait longer for page loads & server requests.

The Keen IO API is fast, but any synchronous network call you make will negatively impact response times. For this reason, we recommend you use the publish_async method to send events when latency is a concern. Alternatively, you can drop events into a background queue e.g. Delayed Jobs and publish synchronously from there.

To publish asynchronously, first add em-http-request to your Gemfile. Make sure it's version 1.0 or above.

gem "em-http-request", "~> 1.0"

Next, run an instance of EventMachine. If you're using an EventMachine-based web server like thin or goliath you're already doing this. Otherwise, you'll need to start an EventMachine loop manually as follows:

require 'em-http-request'

Thread.new { EventMachine.run }

The best place for this is in an initializer, or anywhere that runs when your app boots up. Here's a useful blog article that explains more about this approach - EventMachine and Passenger.

And here's a gist that shows an example of Eventmachine with Unicorn, specifically the Unicorn config for starting and stopping EventMachine after forking.

Now, in your code, replace publish with publish_async. Bind callbacks if you require them.

http = Keen.publish_async("sign_ups", { :username => "lloyd", :referred_by => "harry" })
http.callback { |response| puts "Success: #{response}"}
http.errback { puts "was a failurrr :,(" }

This will schedule the network call into the event loop and allow your request thread to resume processing immediately.

Running queries

The Keen IO API provides rich querying capabilities against your event data set. For more information, see the Data Analysis API Guide.

Running queries requires that KEEN_READ_KEY is set.

Here are some examples of querying with keen-gem. Let's assume you've added some events to the "purchases" collection.

# Various analysis types
Keen.count("purchases") # => 100
Keen.sum("purchases", :target_property => "price", :timeframe => "today")  # => 10000
Keen.minimum("purchases", :target_property => "price", :timeframe => "today")  # => 20
Keen.maximum("purchases", :target_property => "price", :timeframe => "today")  # => 100
Keen.average("purchases", :target_property => "price", :timeframe => "today")  # => 60
Keen.median("purchases", :target_property => "price", :timeframe => "today")  # => 60
Keen.percentile("purchases", :target_property => "price", :percentile => 90, :timeframe => "today")  # => 100
Keen.count_unique("purchases", :target_property => "username", :timeframe => "today")  # => 3
Keen.select_unique("purchases", :target_property => "username", :timeframe => "today")  # => ["Bob", "Linda", "Travis"]

# Group by's and filters
Keen.sum("purchases", :target_property => "price", :group_by => "item.id", :timeframe => "this_14_days")  # => [{ "item.id": 123, "result": 240 }]
Keen.count("purchases", :timeframe => "today", :filters => [{
    "property_name" => "referred_by",
    "operator" => "eq",
    "property_value" => "harry"
  }]) # => 2

# Relative timeframes
Keen.count("purchases", :timeframe => "today") # => 10

# Absolute timeframes
Keen.count("purchases", :timeframe => {
  :start => "2015-01-01T00:00:00Z",
  :end => "2015-31-01T00:00:00Z"
}) # => 5

# Extractions
Keen.extraction("purchases", :timeframe => "today")  # => [{ "keen" => { "timestamp" => "2014-01-01T00:00:00Z" }, "price" => 20 }]

# Funnels
Keen.funnel(:steps => [{
  :actor_property => "username", :event_collection => "purchases", :timeframe => "yesterday" }, {
  :actor_property => "username", :event_collection => "referrals", :timeframe => "yesterday" }]) # => [20, 15]

# Multi-analysis
Keen.multi_analysis("purchases", analyses: {
  :gross =>      { :analysis_type => "sum", :target_property => "price" },
  :customers =>  { :analysis_type => "count_unique", :target_property => "username" } },
  :timeframe => 'today', :group_by => "item.id") # => [{ "item.id" => 2, "gross" => 314.49, "customers" => 8 } }]

Many of these queries can be performed with group by, filters, series and intervals. The response is returned as a Ruby Hash or Array.

Detailed information on available parameters for each API resource can be found on the API Technical Reference.

The Query Method

You can also specify the analysis type as a parameter to a method called query:

Keen.query("median", "purchases", :target_property => "price")  # => 60

This simplifes querying code where the analysis type is dynamic.

Query Options

Each query method or alias takes an optional hash of options as an additional parameter. Possible keys are:

:response โ€“ Set to :all_keys to return the full API response (usually only the value of the "result" key is returned). :method - Set to :post to enable post body based query (https://keen.io/docs/data-analysis/post-queries/).

Query Logging

You can log all GET and POST queries automatically by setting the log_queries option.

Keen.log_queries = true
Keen.count('purchases')
# I, [2016-10-30T11:45:24.678745 #9978]  INFO -- : [KEEN] Send GET query to https://api.keen.io/3.0/projects/<YOUR_PROJECT_ID>/queries/count?event_collection=purchases with options {}

Saved and Cached Queries

You can manage your saved queries from the Keen ruby client.

Create a saved query
saved_query_attributes = {
    # NOTE : For now, refresh_rate must explicitly be set to 0 unless you
    # intend to create a Cached Query.
    refresh_rate: 0,
    query: {
        analysis_type: 'count',
        event_collection: 'purchases',
        timeframe: 'this_2_weeks',
        filters: [{
            property_name: 'price',
            operator: 'gte',
            property_value: 1.00
        }]
    }
}

Keen.saved_queries.create 'saved-query-name', saved_query_attributes
Get all saved queries
Keen.saved_queries.all
Get one saved query
Keen.saved_queries.get 'saved-query-name'
Get saved query with results
query_body = Keen.saved_queries.get('saved-query-name', true)
query_body['result']
Updating a saved query

NOTE : Updating Saved Queries through the API requires sending the entire query definition. Any attribute not sent is interpreted as being cleared/removed. This means that properties set via another client, including the Projects Explorer Web UI, would be lost this way.

The update function makes this easier by allowing client code to just specify the properties that need updating. To do this, it will retrieve the existing query definition first, which means there will be two HTTP requests. Use update_full in code that already has a full query definition that can reasonably be expected to be current.

Update a saved query to now be a cached query with the minimum refresh rate of 4 hrs

# using partial update:
Keen.saved_queries.update 'saved-query-name', refresh_rate: 14400

# using full update, if we've already fetched the query definition:
saved_query_attributes['refresh_rate'] = 14400
Keen.saved_queries.update_full('saved-query-name', update_attributes)

Update a saved query to a new resource name

# using partial update:
Keen.saved_queries.update 'saved-query-name', query_name: 'cached-query-name'

# using full update, if we've already fetched the query definition or have it lying around
# for whatever reason. We send 'refresh_rate' again, along with the entire definition, or else
# it would be reset:
saved_query_attributes['query_name'] = 'cached-query-name'
Keen.saved_queries.update_full('saved-query-name', saved_query_attributes)

Cache a query

Keen.saved_queries.cache 'saved-query-name', 14400

Uncache a query

Keen.saved_queries.uncache 'saved-query-name'

Delete a saved query (use the new resource name since we just changed it)

Keen.saved_queries.delete 'cached-query-name'
Getting Query URLs

Sometimes you just want the URL for a query, but don't actually need to run it. Maybe to paste into a dashboard, or open in your browser. In that case, use the query_url method:

Keen.query_url("median", "purchases", :target_property => "price", { :timeframe => "today" })
# => "https://api.keen.io/3.0/projects/<project-id>/queries/median?target_property=price&event_collection=purchases&api_key=<api-key>"

If you don't want the API key included, pass the :exclude_api_key option:

Keen.query_url("median", "purchases", { :target_property => "price", :timeframe => "today" }, :exclude_api_key => true)
# => "https://api.keen.io/3.0/projects/<project-id>/queries/median?target_property=price&event_collection=purchases"

Cached Datasets

You can manage your cached datasets from the Keen ruby client.

Create a cached dataset
index_by = 'userId'
query = {
  "project_id" => "PROJECT ID",
  "analysis_type" => "count",
  "event_collection" => "purchases",
  "filters" =>  [
    {
      "property_name" => "price",
      "operator" => "gte",
      "property_value" => 100
    }
  ],
  "timeframe" => "this_500_days",
  "interval" => "daily",
  "group_by" => ["ip_geo_info.country"]
}

Keen.cached_datasets.create 'cached-dataset-name', index_by, query, 'My Dataset Display Name'
Query cached dataset's results
response_json = Keen.cached_datasets.get_results('a-dataset-name', {
  start: "2012-08-13T19:00:00.000Z",
  end: "2013-09-20T19:00:00.000Z"
 }, index_by_value)
response_json['result']
Retrieve definitions of cached datasets
Keen.cached_datasets.list
Keen.cached_datasets.list(limit: 5, after_name: 'some-dataset')
Get a cached dataset's definition
Keen.cached_datasets.get_definition 'a-dataset-name'
Delete a cached dataset
Keen.cached_datasets.delete 'a-dataset-name'

Listing collections

The Keen IO API let you get the event collections for the project set, it includes properties and their type. It also returns links to the collection resource.

Keen.event_collections # => [{ "name": "purchases", "properties": { "item.id": "num", ... }, ... }]

Getting the list of event collections requires that the KEEN_MASTER_KEY is set.

Deleting events

The Keen IO API allows you to delete events from event collections, optionally supplying a filter to narrow the scope of what you would like to delete.

Deleting events requires that the KEEN_MASTER_KEY is set.

# Assume some events in the 'signups' collection

# We can delete them all
Keen.delete(:signups)  # => true

# Or just delete an event corresponding to a particular user
Keen.delete(:signups, filters: [{
  :property_name => 'username', :operator => 'eq', :property_value => "Bob"
}])  # => true

Other code examples

Overwriting event timestamps

Two time-related properties are included in your event automatically. The properties โ€œkeen.timestampโ€ and โ€œkeen.created_atโ€ are set at the time your event is recorded. You have the ability to overwrite the keen.timestamp property. This could be useful, for example, if you are backfilling historical data. Be sure to use ISO-8601 Format.

Keen stores all date and time information in UTC!

Keen.publish(:sign_ups, {
  :keen => { :timestamp => "2012-12-14T20:24:01.123000+00:00" },
  :username => "lloyd",
  :referred_by => "harry"
})

Batch publishing

The keen-gem supports publishing events in batches via the publish_batch method. Here's an example usage:

Keen.publish_batch(
  :signups => [
    { :name => "Bob" },
    { :name => "Mary" }
  ],
  :purchases => [
    { :price => 10 },
    { :price => 20 }
  ]
)

This call would publish 2 signups events and 2 purchases events - all in just one API call. Batch publishing is ideal for loading historical events into Keen IO.

Asynchronous batch publishing

Ensuring the above guidance is followed for asynchronous publishing, batch publishing logic can used asynchronously with publish_batch_async:

Keen.publish_batch_async(
  :signups => [
    { :name => "Bob" },
    { :name => "Mary" }
  ],
  :purchases => [
    { :price => 10 },
    { :price => 20 }
  ]
)

Configurable and per-client authentication

To configure keen-gem in code, do as follows:

Keen.project_id = 'xxxxxxxxxxxxxxx'
Keen.write_key = 'yyyyyyyyyyyyyyy'
Keen.read_key = 'zzzzzzzzzzzzzzz'
Keen.master_key = 'aaaaaaaaaaaaaaa'

You can also configure unique client instances as follows:

keen = Keen::Client.new(:project_id => 'xxxxxxxxxxxxxxx',
                        :write_key  => 'yyyyyyyyyyyyyyy',
                        :read_key   => 'zzzzzzzzzzzzzzz',
                        :master_key => 'aaaaaaaaaaaaaaa')

em-synchrony

keen-gem can be used with em-synchrony. If you call publish_async and EM::Synchrony is defined the method will return the response directly. (It does not return the deferrable on which to register callbacks.) Likewise, it will raise exceptions 'synchronously' should they happen.

Beacon URLs

It's possible to publish events to your Keen IO project using the HTTP GET method. This is useful for situations like tracking email opens using image beacons.

In this situation, the JSON event data is passed by encoding it base-64 and adding it as a request parameter called data. The beacon_url method found on the Keen::Client does this for you. Here's an example:

Keen.project_id = 'xxxxxx';
Keen.write_key = 'yyyyyy';
Keen.beacon_url("sign_ups", :recipient => "[email protected]")
  # => "https://api.keen.io/3.0/projects/xxxxxx/events/email_opens?api_key=yyyyyy&data=eyJyZWNpcGllbnQiOiJmb29AZm9vLmNvbSJ9"

To track email opens, simply add an image to your email template that points to this URL. For further information on how to do this, see the image beacon documentation.

Redirect URLs

Redirect URLs are just like image beacon URLs with the addition of a redirect query parameter. This parameter is used to issue a redirect to a certain URL after an event is recorded.

Keen.redirect_url("sign_ups", { :recipient => "[email protected]" }, "http://foo.com")
  # => "https://api.keen.io/3.0/projects/xxxxxx/events/email_opens?api_key=yyyyyy&data=eyJyZWNpcGllbnQiOiJmb29AZm9vLmNvbSJ9&redirect=http://foo.com"

This is helpful for tracking email clickthroughs. See the redirect documentation for further information.

Generating scoped keys

Note, Scoped Keys are now deprecated in favor of Access Keys.

A scoped key is a string, generated with your API Key, that represents some encrypted authentication and query options. Use them to control what data queries have access to.

# "my-api-key" should be your MASTER API key
scoped_key = Keen::ScopedKey.new("my-api-key", { "filters" => [{
  "property_name" => "accountId",
  "operator" => "eq",
  "property_value" => "123456"
}]}).encrypt! # "4d1982fe601b359a5cab7ac7845d3bf27026936cdbf8ce0ab4ebcb6930d6cf7f139e..."

You can use the scoped key created in Ruby for API requests from any client. Scoped keys are commonly used in JavaScript, where credentials are visible and need to be protected.

Access Keys

You can use Access Keys to restrict the functionality of a key you use with the Keen API. Access Keys can also enrich events that you send.

Create a key that automatically adds information to each event published with that key:

key_body = {
  "name" => "autofill foo",
  "is_active" => true,
  "permitted" => ["writes"],
  "options" => {
    "writes" => {
      "autofill": {
        "foo": "bar"
      }
    }
  }
}

new_key = Keen.access_keys.create(key_body)
autofill_write_key = new_key["key"]

List all keys associated with a project.

Keen.access_keys.all

Get info associated with a given key

access_key = '0000000000000000000000000000000000000000000000000000000000000000'
Keen.access_keys.get(access_key)

Update a key. Information passed to this method will overwrite existing properties.

access_key = '0000000000000000000000000000000000000000000000000000000000000000'
update_body = {
  name: 'updated key',
  is_active: false,
  permitted: ['reads']
}
Keen.access_keys.update(access_key, update_body)

Revoke a key. This will set the key's active flag to false, but keep it available to be unrevoked. If you want to permanently remove a key, use delete.

access_key = '0000000000000000000000000000000000000000000000000000000000000000'
Keen.access_keys.revoke(access_key)

Unrevoke a key. This will set a previously revoked key's active flag to true.

access_key = '0000000000000000000000000000000000000000000000000000000000000000'
Keen.access_keys.unrevoke(access_key)

Delete a key. Once deleted, a key cannot be recovered. Consider revoke if you want to keep the key around but deactivate it.

access_key = '0000000000000000000000000000000000000000000000000000000000000000'
Keen.access_keys.delete(access_key)

Additional options

HTTP Read Timeout

The default Net::HTTP timeout is 60 seconds. That's usually enough, but if you're querying over a large collection you may need to increase it. The timeout on the API side is 300 seconds, so that's as far as you'd want to go. You can configure a read timeout (in seconds) by setting a KEEN_READ_TIMEOUT environment variable, or by passing in a read_timeout option to the client constructor as follows:

keen = Keen::Client.new(:read_timeout => 300)

You can also configure the NET::HTTP open timeout, default is 60 seconds. To configure the timeout (in seconds) either set KEEN_OPEN_TIMEOUT environment variable, or by passing in a open_timeout option to the client constructor as follows:

keen = Keen::Client.new(:open_timeout => 30)
HTTP Proxy

You can set the KEEN_PROXY_TYPE and KEEN_PROXY_URL environment variables to enable HTTP proxying. KEEN_PROXY_TYPE should be set to socks5. You can also configure this on client instances by passing in proxy_type and proxy_url keys.

keen = Keen::Client.new(:proxy_type => 'socks5', :proxy_url => 'http://localhost:8888')

Troubleshooting

EventMachine

If you run into Keen::Error: Keen IO Exception: An EventMachine loop must be running to use publish_async calls or Uncaught RuntimeError: eventmachine not initialized: evma_set_pending_connect_timeout, this means that the EventMachine loop has died. This can happen for a variety of reasons, and every app is different. Issue #22 shows how to add some extra protection to avoid this situation.

publish_async in a script or worker

If you write a script that uses publish_async, you need to keep the script alive long enough for the call(s) to complete. EventMachine itself won't do this because it runs in a different thread. Here's an example gist that shows how to exit the process after the event has been recorded.

Additional Considerations

Bots

It's not just us humans that browse the web. Spiders, crawlers, and bots share the pipes too. When it comes to analytics, this can cause a mild headache. Events generated by bots can inflate your metrics and eat up your event quota.

If you want some bot protection, check out the Voight-Kampff gem. Use the gem's request.bot? method to detect bots and avoid logging events.

Changelog

1.1.1
  • Added an option to log queries
  • Added a cli option that includes the Keen code
1.1.0
  • Add support for Access Keys
  • Move saved queries into the Keen namespace
  • Deprecate scoped keys in favor of Access Keys
1.0.0
  • Remove support for ruby 1.9.3
  • Update a few dependencies
0.9.10
  • Add ability to set the open_time setting for the http client.
0.9.9
  • Added the ability to send additional optional headers.
0.9.7
  • Added a new header Keen-Sdk that sends the SDK version information on all requests.
0.9.6
0.9.5
  • Fix bug with scoped key generation not working with newer Keen projects.
0.9.4
  • Add SDK support for Saved Queries
  • Removed support for Ruby MRI 1.8.7
0.9.2
  • Added support for max_age as an integer.
0.9.1
  • Added support for setting an IV for scoped keys. Thanks @anatolydwnld
0.8.10
0.8.9
0.8.8
  • Add support for a configurable read timeout
0.8.7
  • Add support for returning all keys back from query API responses
0.8.6
  • Add support for getting query URLs
  • Make the query method public so code supporting dynamic analysis types is easier to write
0.8.4
0.8.3
0.8.2
  • Add support for median and percentile analysis
  • Support arrays for extraction property_names option
0.8.1
  • Add support for asynchronous batch publishing
0.8.0
  • UPGRADE WARNING Do you use spaces in collection names? Or other special characters? Read this post from the mailing list to make sure your collection names don't change.
  • Add support for generating scoped keys.
  • Make collection name encoding more robust. Make sure collection names are encoded identically for publishing events, running queries, and performing deletes.
  • Add support for grouping by multiple properties.
0.7.8
  • Add support for redirect URL creation.
0.7.7
  • Add support for HTTP and SOCKS proxies. Set KEEN_PROXY_URL to the proxy URL and KEEN_PROXY_TYPE to 'socks5' if you need to. These properties can also be set on the client instances as proxy_url and proxy_type.

  • Delegate the master_key fields from the Keen object.

0.7.6
  • Explicitly require CGI.
0.7.5
  • Use CGI.escape instead of URI.escape to get accurate URL encoding for certain characters
0.7.4
  • Add support for deletes (thanks again cbartlett!)
  • Allow event collection names for publishing/deleting methods to be symbols
0.7.3
  • Add batch publishing support
  • Allow event collection names for querying methods to be symbols. Thanks to cbartlett.
0.7.2
  • Fix support for non-https API URL testing
0.7.1
  • Allow configuration of the base API URL via the KEEN_API_URL environment variable. Useful for local testing and proxies.
0.7.0
  • BREAKING CHANGE! Added support for read and write scoped keys to reflect the new Keen IO security architecture. The advantage of scoped keys is finer grained permission control. Public clients that publish events (like a web browser) require a key that can write but not read. On the other hand, private dashboards and server-side querying processes require a Read key that should not be made public.
0.6.1
  • Improved logging and exception handling.
0.6.0
  • Added querying capabilities. A big thanks to ifeelgoods for contributing!
0.5.0
  • Removed API Key as a required field on Keen::Client. Only the Project ID is required to publish events.
  • You can continue to provide the API Key. Future features planned for this gem will require it. But for now, there is no keen-gem functionality that uses it.
0.4.4
  • Event collections are URI escaped to account for spaces.
  • User agent of API calls made more granular to aid in support cases.
  • Throw arguments error for nil event_collection and properties arguments.
0.4.3
  • Added beacon_url support
  • Add support for using em-synchrony with asynchronous calls

Questions & Support

For questions, bugs, or suggestions about this gem: File a Github Issue.

For other Keen-IO related technical questions: 'keen-io' on Stack Overflow

For general Keen IO discussion & feedback: 'keen-io-devs' Google Group

Contributing

keen-gem is an open source project and we welcome your contributions. Fire away with issues and pull requests!

Running Tests

bundle exec rake spec - Run unit specs. HTTP is mocked.

bundle exec rake integration - Run integration specs with the real API. Requires env variables. See .travis.yml.

bundle exec rake synchrony - Run async publishing specs with EM::Synchrony.

Similarly, you can use guard to listen for changes to files and run specs.

bundle exec guard -g unit

bundle exec guard -g integration

bundle exec guard -g synchrony

Running a Local Console

You can spawn an irb session with the local files already loaded for debugging or experimentation.

$ bundle exec rake console
2.2.6 :001 > Keen
 => Keen

Community Contributors

Thanks everyone, you rock!

keen-gem's People

Contributors

ajwharton avatar alexkwolfe avatar avlok avatar cbartlett avatar ccurtisj avatar dkador avatar dorkitude avatar dsshap avatar ea0723 avatar edgarortegaramirez avatar elof avatar hex337 avatar jakeaustwick avatar joshed-io avatar l4u avatar lukemelia avatar maxidr avatar mptap avatar myrridin avatar naudo avatar newtriks avatar nvieirafelipe avatar rebeccastandig avatar soloman1124 avatar spraetz avatar tbarn avatar terrhorn avatar vinniefranco avatar wellmatchdev avatar wetzler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keen-gem's Issues

generating scoped key

The docs say that "Our server-side SDKs (Ruby, Python, Java, Node.js) have built-in methods to make generating a Scoped Key a one-line affair." but I am having trouble finding this functionality in the Ruby gem. Am I just missing it?

README contains broken link to keen-gem-example

Hi. I just started exploring this repo and noticed the link to the keen-gem-example app points to a nonexistent app on Heroku. I was actually expecting the link to point to a repo, not a Heroku app. I looked through all your repos and didn't see one that looks like a Ruby example app, but perhaps I didn't look hard enough. Is there one?

Keen query modifes options hash

Say we have an options hash:

options = {timeframe: {start: "2014-03-3", end:"2014-04-03"}}

Then we query to event collection called 'a'

Keen.count 'a', options

If we check the options hash again, this is what we got:

{:timeframe=>"{\"start\":\"2014-03-3\",\"end\":\"2014-04-03\"}", :event_collection=>"a"}

This is quite annoying, especially if we want to reuse the options hash again after the query.

Query turn {"error_code": "RequestForbiddenError"

I've tried configuring the Keen.io Gem with only "project_id" and "read_key", and I 've tried the 3 ways, ENV variable, setting Keen.variable and creating a new client, but only get this message:

Keen::HttpError - Keen IO Exception: {"error_code": "RequestForbiddenError", "message": "You're not allowed to run this request. Check your API Key and maybe try again."}:

It works when I try calling it on the client as well as the workbench.

Add support for Cached Queries

MVP

  • Create Saved Query
  • Cache a Saved Query
  • Uncache a Saved Query
  • Delete a Saved Query
  • Retrieve Results from Saved Query

Stretch

  • Retrieve definition of a saved query
  • Update a cached query

Validate that values for unrecognized query options are strings

If a non-string is passed as an query option value for a key we don't track (not :group_by or :filters, etc) we should validate that it is a string so it can be escaped later on.

Currently passing a non-string just throws a confusing exception:

>> Keen.count("votes", :max_age => 60)
NoMethodError: undefined method `gsub' for 60:Fixnum
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/cgi/util.rb:7:in `escape'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client.rb:109:in `block in preprocess_params'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client.rb:109:in `each'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client.rb:109:in `map'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client.rb:109:in `preprocess_params'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client/querying_methods.rb:239:in `_query_url'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client/querying_methods.rb:223:in `query'
        from /Users/dzello/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.8/lib/keen/client/querying_methods.rb:19:in `count'
        from (irb):7
        from /Users/dzello/.rbenv/versions/1.9.3-p448/bin/irb:12:in `<main>'

require 'keen' takes almost a minute at run-time?

I used benchmark to measure the time of keen compared to other gems when running on iron.io:

cgi:โ€‚โ€‚ 0.000000โ€‚โ€‚ 0.000000โ€‚โ€‚ 0.000000 (โ€‚โ€‚0.005616)
iron_cache:โ€‚โ€‚ 0.070000โ€‚โ€‚ 0.030000โ€‚โ€‚ 0.100000 (โ€‚โ€‚0.107393)
keen:โ€‚โ€‚ 0.080000โ€‚โ€‚ 0.020000โ€‚โ€‚54.830000 ( 69.544284)
rollbar:โ€‚โ€‚ 0.010000โ€‚โ€‚ 0.000000โ€‚โ€‚ 0.010000 (โ€‚โ€‚0.009601)
active_spport:โ€‚โ€‚ 0.020000โ€‚โ€‚ 0.000000โ€‚โ€‚ 0.020000 (โ€‚โ€‚0.01519)

This report shows the user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time. The unit of time is seconds.

Environment initialization for noop support in dev/testing

Currently the gem is missing a method to disable publishing of events for non-production usages which means we have to wrap all our calls in environment checks. It would be great if the gem had an initializer to make all Keen calls a no-op.

Collections with spaces are sent to the API with "+" instead of space

Keen.publish("Played a Song", event)

Creates a new collection called "Played+a+Song".

Other related problems:

Say you get the list of collections for a given project and one of the Collection names is "Tooted a Flute"

Using the ruby client to run a count of "Tooted a Flue" works fine.

Keen.count("Tooted a Flute")  # => 337

However, running a delete fails.

Keen.delete("Tooted a Flute") # => "error_code": "ResourceNotFoundError"

The library doesn't properly encode the URL for the delete. Remember, when you use an event collection name in a count it is a query parameter, but when you use it in a delete request it is part of the request URL.

Logging queries

Hi,

Does the keen-gem support logging every query being sent out?

In the Java Keen Client it's pretty straight forward and documented: https://github.com/keenlabs/KeenClient-Java#logging

I have explored the official docs, issues in this repo as well as googled for it and couldn't find anything in this regard.

Perhaps it's supported but it's rather a lack of documentation?

Regards.

Add support for caching

When providing a max_age parameter to a query using the Ruby gem, it fails with:

inescape': undefined method encoding' for 300:Fixnum (NoMethodError)

It should be possible to add a caching parameter (max_age) to a query like this:

puts Keen.count("Content Engagement",
:filters => [{
"property_name" => "siteId",
"operator" => "eq",
"property_value" => 2563
}],
:max_age => 300
)

I am kind of surprised that the library doesn't work with any provided property (I thought it did). Maybe it doesn't work with this one specifically because the value is numeric?

Reference:
https://keen.io/docs/data-analysis/caching/

Generated Scoped Key fails with Invalid API Key error

Using the gem to generate a scoped key and subsequently using that key in a query throws an Invalid API Key Error.

The newly generated scoped key can be successfully encrypted/decrypted, but cannot be used.

To verify, please initialize a new Keen Client with a generated scoped key corresponding to a filter, say

data = { "filters" => [{ "property_name" => "", "operator" => "eq", "property_value" => "" }] }
scoped_key_generator = Keen::ScopedKey.new master_key, data
scoped_read_key = scoped_key_generator.encrypt!

client = Keen::Client.new( project_id: <PROJECT_ID>, read_key: scoped_read_key )

Now, perform a count query on some collection in the project
client.count(...)

Expose a method to publish strings of JSON

Databases that can output JSON (Postgres) can generate strings of JSON much quicker than getting it into a Ruby hash (most of the time by returning rows, instantiating AR objects, then serializing them into JSON). We should provide a method (#publish_json)? that allows you to send such a string instead of needing the data to be a hash.

Caching parameter max_age unit

The documentation states that the max_age parameters has seconds as units, but from what I'm seeing that's not the case:

[12] ideas ยป  Benchmark.measure { 10.times {Keen.count('page_views')} }.real
=> 15.510477650001121
[13] ideas ยป  Benchmark.measure { 10.times {Keen.count('page_views', max_age: '3000')} }.real 
=> 6.994793229001516
[14] ideas ยป  Benchmark.measure { 10.times {Keen.count('page_views', max_age: '3000')} }.real
=> 7.90146774599998
[15] ideas ยป  Benchmark.measure { 10.times {Keen.count('page_views', max_age: '300')} }.real
=> 17.010403779997432

Also a fix for #73 would be nice :)

Just a simple hash?

Is there an easy way to get People or Company data back in a simple ruby hash rather than the Hashie format?

How to initialize without environment variables?

The readme states that "the recommended way to (initialize) is to set KEEN_PROJECT_ID in your environment.".

In my environment though, it's complicated to set environment variables.

Is it already possible to use a configure block somehow? (it looks like the default_client is a private method).

Something like this would be nice and would allow any scenario, like reading from a yml file, or hard-coding to get started etc:

Keen.configure do |config|
  config.api_key = "xxxx"
  config.project_token = "yyy"
end

Environment vars not ideal for some environments

[This was shared by another developer; I'm sharing it here on their behalf]

I'm starting to use the keen.io ruby gem and I have feedback. On some hosting systems (like EngineYard), it is very complicated to configure libraries using environment variables. Instead, they recommend using a yaml file which is in a backed-up folder https://support.cloud.engineyard.com/entries/36999448-Environment-Variables-and-Why-You-Shouldn-t-Use-Them. I looked at the code (default_client specifically) and it looks like a "manual configuration" from an initializer would be a bit fragile. I would have to make sure I artificially set the env vars before bundler is loaded, so that the default client is not generated with empty credentials. That, or create my own instance of Keen::Client (which I'm probably going to do). Well - just a bit of feedback; in some case, using env vars is really not possible (which actually made me delay the use of keen.io several times already).

Unused variable - padded_data.

An RSpec warning reports:

"...keen-0.8.8/lib/keen/scoped_key.rb:30: warning: assigned but unused variable - padded_data"

Perhaps you want to check why that variable is there. :-)

Allow timeframe to accept values of 'all' or nil.

From the support email:

It would be nice if timeframe accepted a value of 'all' or '' or nil...

Sometimes I am doing

Keen.count('scheduled_campaign', group_by: 'account_id', timeframe: timeframe_var, filters: determine_filters)

timeframe_var is dynamic, and somtimes can be nil. If nil, I'd like it to get all results

Unfortunately, your endpoint does not allow this...

It would be extra effort to have something like:

if timeframe_var.present?
Keen.count('scheduled_campaign', group_by: 'account_id', timeframe: timeframe_var, filters: determine_filters)
else
Keen.count('scheduled_campaign', group_by: 'account_id', filters: determine_filters)
end

Ensure that master key is set when dealing with saved queries

Methods in SavedQueries class use client.master_key, but they don't invoke ensure_master_key! method as it's done in Keen::Client::MaintenanceMethods. If master key is not set one will obtain a cryptic error message:

NoMethodError: undefined method `strip' for nil:NilClass
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http/header.rb" line 17 in block in initialize_http_header
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http/header.rb" line 15 in each
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http/header.rb" line 15 in initialize_http_header
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http/generic_request.rb" line 43 in initialize
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http/request.rb" line 14 in initialize
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb" line 1133 in new
File "/app/vendor/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb" line 1133 in get
File "/app/vendor/bundle/ruby/2.2.0/gems/keen-0.9.5/lib/keen/http.rb" line 44 in get
File "/app/vendor/bundle/ruby/2.2.0/gems/keen-0.9.5/lib/keen/client/saved_queries.rb" line 45 in saved_query_response
File "/app/vendor/bundle/ruby/2.2.0/gems/keen-0.9.5/lib/keen/client/saved_queries.rb" line 17 in get

rails 4 secrets file

Has anyone been able to configure the keen keys via a secrets file:

KEEN_PROJECT_ID=Rails.application.secrets.keen_project_id
KEEN_MASTER_KEY=Rails.application.secrets.keen_master_key
KEEN_WRITE_KEY=Rails.application.secrets.keen_write_key
KEEN_READ_KEY=Rails.application.secrets.keen_read_key

How can I get the full response from a funnel query?

How can I get the full response from a funnel query? I would like to print out the with_actors step in addition to the Results, but I don't know how to do that.

From Funnel page for reference:
{
"result":[
200,
20,
180,
100
],
"actors":[
null,
["ef54c5bc3ab0482e393a8dc9d7b5fbc4", "44ba554fd29365868be64e42e5e8fde8", ... ],
null,
null
],
"steps":[
{
"event_collection":"tutorial_completed",
"actor_property":"user.id",
"inverted":false,
"optional":false,
"with_actors":false
},
{
"event_collection":"content_created",
"actor_property":"user.id",
"inverted":true,
"optional":true,
"with_actors":true
},
{
"event_collection":"content_created",
"actor_property":"user.id",
"inverted":false,
"optional":false,
"with_actors":false
},
{
"event_collection":"content_shared",
"actor_property":"user.id",
"inverted":false,
"optional":false,
"with_actors":false
}
]
}

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

  spec.license = 'MIT'
  # or
  spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

Uncaught RuntimeError: eventmachine not initialized: evma_set_pending_connect_timeout

Every so often, we get this RuntimeError when calling publish_async due to some as-yet unknown issue we're having with EventMachine+Passenger:

/gems/eventmachine-1.0.3/lib/em/connection.rb:619 in "set_pending_connect_timeout"
/gems/eventmachine-1.0.3/lib/em/connection.rb:619 in "pending_connect_timeout="
/gems/em-http-request-1.0.3/lib/em-http/http_connection.rb:61 in "block in activate_connection"
/gems/eventmachine-1.0.3/lib/eventmachine.rb:672 in "bind_connect"
/gems/em-http-request-1.0.3/lib/em-http/http_connection.rb:54 in "activate_connection"
/gems/em-http-request-1.0.3/lib/em-http/http_connection.rb:89 in "setup_request"
/gems/em-http-request-1.0.3/lib/em-http/http_connection.rb:8 in "post"
/gems/keen-0.7.7/lib/keen/http.rb:75 in "post"
/gems/keen-0.7.7/lib/keen/client/publishing_methods.rb:69 in "publish_async"

Sometimes the EM problem causes an error that the Keen gem catches and bubbles up as a Keen::Error:

Keen::Error: Keen IO Exception: An EventMachine loop must be running to use publish_async calls
/gems/keen-0.7.7/lib/keen/http.rb:53 in "initialize"
/gems/keen-0.7.7/lib/keen/client/publishing_methods.rb:66 in "new"
/gems/keen-0.7.7/lib/keen/client/publishing_methods.rb:66 in "publish_async"

I'd rather just catch the Keen::Error in my application code and not have to look out for the RuntimeError, too.

Is there a way to increase the HTTP timeout?

Is there any easy way to increase the time to wait for an HTTP response?
My (large) requests work OK in the Keen IO workbench but timeout after ~3 minutes when using keen gem.

rb:249:in `rescue in get_response': Keen IO Exception: Couldn't perform  on Keen IO: Net::ReadTimeout (Keen::HttpError)
``

Listing collections, KEEN_MASTER_KEY requirement.

Hi there!

Isn't too strict and probably less secure that the KEEN_MASTER_KEY is required to run Keen.event_collections?

From the documentation the general rule seems to be that for reading and querying the KEEN_READ_KEY is what's needed. While the KEEN_MASTER_KEY is required for destructive operations such as deleting.

The result of the current requirement means that in practical terms for exploratory querying among teams and/or team members one really needs to hand around the KEEN_MASTER_KEY more deliberately than one otherwise would for reading and querying data.

Isn't this requirement for Keen.event_collections something that should be re-considered?

Thank you.

Numerous threads spawned -unicorn

Im using Keen in our app in async mode. Followed the unicorn setup here - https://gist.github.com/jonkgrimes/5103321 for EventMachine.

Lately I have been seeing tons of opened database connections. Multiple postgres connections attributed to each Unicorn workers.

I kept digging and saw that the unicorn workers had numerous threads spawned under them.

screenshot from 2016-04-08 15 54 49

I then used techniques given here to find out where these threads were executing and here is what I got for one of the worker's threads -


[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] -------------------

Clearly its in EventMachine. We dont use EM for anything else other than Keen in our app.
Is this normal? Could this be leading to the leaking db connections?

Didn't work with some multi_json gem versions

I did try to use the gem and not seems to work with a version of multi_json previous to 1.3.0.

This is the error:

NoMethodError - undefined method `dump' for MultiJson:Module:
        /home/maxi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/keen-0.8.0/lib/keen/scoped_key.rb:28:in `encrypt!'

This method is introduced in the version 1.3.0 of multi_json. You can see here that the method not exists.

I upgrade the version to 1.3.0 and seems to work fine.

I suppose that you need to change the keen.gemspec file from:

s.add_dependency "multi_json", "~> 1.0"

to:

s.add_dependency "multi_json", "~> 1.3.0"

What do you think? I can clone and pull request if you think that this change is correct.

Regards,

thread safety (or issues with sidekiq?)

i'm trying to delete data in a sidekiq worker. my code is super simple:

class KeenDeleteJob < ActiveJob::Base
  include LogAndNotify
  queue_as :default

  def perform(c, id)
    Rails.logger.error "deleting old event c=#{c}, keen.id=#{id}"
    Keen.delete c, filters: [{property_name: 'keen.id', operator: 'eq', property_value: id }]
  end
end

after running through a few deletes i inevitably get this error:

11:31:00 worker.1 | 2015-07-29T18:31:00.430Z 83691 TID-oxvhyi4po ERROR: Actor crashed!
11:31:00 worker.1 | Keen::HttpError: Keen IO Exception: Couldn't perform delete of LoanApplicationFlow on Keen IO: Bad file descriptor
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/keen-0.9.2/lib/keen/client/maintenance_methods.rb:23:in `rescue in delete'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/keen-0.9.2/lib/keen/client/maintenance_methods.rb:18:in `delete'
11:31:00 worker.1 |     /Users/jon/git/vouch_api/app/jobs/keen_delete_job.rb:7:in `perform'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:32:in `block in perform_now'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:553:in `block (2 levels) in compile'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:496:in `block (2 levels) in around'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:341:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:341:in `block (2 levels) in simple'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:23:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:23:in `block (4 levels) in <module:Logging>'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications.rb:164:in `block in instrument'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications.rb:164:in `instrument'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:22:in `block (3 levels) in <module:Logging>'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:43:in `block in tag_logger'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:68:in `block in tagged'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:26:in `tagged'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:68:in `tagged'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:43:in `tag_logger'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:19:in `block (2 levels) in <module:Logging>'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:439:in `instance_exec'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:439:in `block in make_lambda'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:340:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:340:in `block in simple'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:495:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:495:in `block in around'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:88:in `run_callbacks'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:31:in `perform_now'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:21:in `execute'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/queue_adapters/sidekiq_adapter.rb:42:in `perform'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:75:in `execute_job'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:52:in `block (2 levels) in process'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/active_record.rb:6:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/retry_jobs.rb:74:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:15:in `block in call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/logging.rb:30:in `with_context'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:11:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/skylight-ruby-f53c9580dbab/lib/skylight/core.rb:70:in `trace'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/sidekiq-skylight-98b748497038/lib/sidekiq/skylight/server_middleware.rb:10:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:132:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:132:in `invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:51:in `block in process'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:98:in `stats'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:50:in `process'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'

followed by this one:

11:31:00 worker.1 | 2015-07-29T18:31:00.432Z 83691 TID-oxvhyh2t8 ERROR: Actor crashed!
11:31:00 worker.1 | Keen::HttpError: Keen IO Exception: Couldn't perform delete of LoanApplicationFlow on Keen IO: undefined method `+' for nil:NilClass
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/keen-0.9.2/lib/keen/client/maintenance_methods.rb:23:in `rescue in delete'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/keen-0.9.2/lib/keen/client/maintenance_methods.rb:18:in `delete'
11:31:00 worker.1 |     /Users/jon/git/vouch_api/app/jobs/keen_delete_job.rb:7:in `perform'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:32:in `block in perform_now'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:553:in `block (2 levels) in compile'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:496:in `block (2 levels) in around'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:341:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:341:in `block (2 levels) in simple'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:23:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:23:in `block (4 levels) in <module:Logging>'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications.rb:164:in `block in instrument'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications.rb:164:in `instrument'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:22:in `block (3 levels) in <module:Logging>'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:43:in `block in tag_logger'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:68:in `block in tagged'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:26:in `tagged'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:68:in `tagged'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:43:in `tag_logger'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:19:in `block (2 levels) in <module:Logging>'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:439:in `instance_exec'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:439:in `block in make_lambda'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:340:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:340:in `block in simple'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:495:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:495:in `block in around'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:88:in `run_callbacks'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:31:in `perform_now'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:21:in `execute'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/queue_adapters/sidekiq_adapter.rb:42:in `perform'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:75:in `execute_job'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:52:in `block (2 levels) in process'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/active_record.rb:6:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/retry_jobs.rb:74:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:15:in `block in call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/logging.rb:30:in `with_context'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:11:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/skylight-ruby-f53c9580dbab/lib/skylight/core.rb:70:in `trace'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/sidekiq-skylight-98b748497038/lib/sidekiq/skylight/server_middleware.rb:10:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:132:in `call'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:132:in `invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:51:in `block in process'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:98:in `stats'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:50:in `process'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
11:31:00 worker.1 |     /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'

and then at some point very soon after:

11:31:00 worker.1 | /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:923: [BUG] Segmentation fault at 0x000000000003f0
11:31:00 worker.1 | ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
11:31:00 worker.1 |
11:31:00 worker.1 | -- Crash Report log information --------------------------------------------
11:31:00 worker.1 |    See Crash Report log file under the one of following:
11:31:00 worker.1 |      * ~/Library/Logs/CrashReporter
11:31:00 worker.1 |      * /Library/Logs/CrashReporter
11:31:00 worker.1 |      * ~/Library/Logs/DiagnosticReports
11:31:00 worker.1 |      * /Library/Logs/DiagnosticReports
11:31:00 worker.1 |    for more details.
11:31:00 worker.1 |
11:31:00 worker.1 | -- Control frame information -----------------------------------------------
11:31:00 worker.1 | c:0074 p:---- s:0322 e:000321 CFUNC  :connect
11:31:00 worker.1 | c:0073 p:0008 s:0319 e:000318 BLOCK  /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:923
11:31:00 worker.1 | c:0072 p:0026 s:0317 e:000316 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/timeout.rb:74
11:31:00 worker.1 | c:0071 p:0551 s:0306 e:000305 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:923
11:31:00 worker.1 | c:0070 p:0007 s:0295 e:000294 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:863
11:31:00 worker.1 | c:0069 p:0036 s:0292 e:000291 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:852
11:31:00 worker.1 | c:0068 p:0017 s:0289 e:000288 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:1375
11:31:00 worker.1 | c:0067 p:0025 s:0282 e:000281 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/skylight-ruby-f53c9580dbab/lib/skylight/probes/net_http.rb:13
11:31:00 worker.1 | c:0066 p:0028 s:0269 e:000268 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/net/http.rb:1232
11:31:00 worker.1 | c:0065 p:0030 s:0264 e:000263 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/keen-0.9.2/lib/keen/http.rb:44
11:31:00 worker.1 | c:0064 p:0068 s:0258 e:000257 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/keen-0.9.2/lib/keen/client/maintenance_methods.rb:19
11:31:00 worker.1 | c:0063 p:0019 s:0249 e:000248 METHOD /Users/jon/.rvm/rubies/ruby-2.2.2/lib/ruby/2.2.0/forwardable.rb:183
11:31:00 worker.1 | c:0062 p:0057 s:0244 e:000243 METHOD /Users/jon/git/vouch_api/app/jobs/keen_delete_job.rb:7
11:31:00 worker.1 | c:0061 p:0012 s:0239 e:000238 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:32 [FINISH]
11:31:00 worker.1 | c:0060 p:---- s:0237 e:000236 CFUNC  :call
11:31:00 worker.1 | c:0059 p:0036 s:0234 e:000232 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:115
11:31:00 worker.1 | c:0058 p:0017 s:0228 e:000227 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:553 [FINISH]
11:31:00 worker.1 | c:0057 p:---- s:0225 e:000224 CFUNC  :call
11:31:00 worker.1 | c:0056 p:0021 s:0221 e:000220 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503
11:31:00 worker.1 | c:0055 p:0011 s:0216 e:000215 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:496 [FINISH]
11:31:00 worker.1 | c:0054 p:---- s:0214 e:000213 CFUNC  :call
11:31:00 worker.1 | c:0053 p:0010 s:0210 e:000209 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:341 [FINISH]
11:31:00 worker.1 | c:0052 p:---- s:0208 e:000207 CFUNC  :call
11:31:00 worker.1 | c:0051 p:0009 s:0205 e:000204 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:23
11:31:00 worker.1 | c:0050 p:0013 s:0203 e:000202 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications.rb:164
11:31:00 worker.1 | c:0049 p:0026 s:0201 e:000200 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications/instrumenter.rb:20
11:31:00 worker.1 | c:0048 p:0028 s:0195 e:000194 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/notifications.rb:164
11:31:00 worker.1 | c:0047 p:0057 s:0190 e:000189 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:22
11:31:00 worker.1 | c:0046 p:0006 s:0187 e:000186 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:43
11:31:00 worker.1 | c:0045 p:0007 s:0185 e:000184 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:68
11:31:00 worker.1 | c:0044 p:0018 s:0183 e:000182 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:26
11:31:00 worker.1 | c:0043 p:0013 s:0178 e:000177 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/tagged_logging.rb:68
11:31:00 worker.1 | c:0042 p:0046 s:0174 e:000173 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:43
11:31:00 worker.1 | c:0041 p:0017 s:0170 e:000169 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/logging.rb:19 [FINISH]
11:31:00 worker.1 | c:0040 p:---- s:0165 e:000164 CFUNC  :instance_exec
11:31:00 worker.1 | c:0039 p:0031 s:0160 e:000159 LAMBDA /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:439 [FINISH]
11:31:00 worker.1 | c:0038 p:---- s:0155 e:000154 CFUNC  :call
11:31:00 worker.1 | c:0037 p:0016 s:0150 E:0013d0 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:340 [FINISH]
11:31:00 worker.1 | c:0036 p:---- s:0146 e:000145 CFUNC  :call
11:31:00 worker.1 | c:0035 p:0012 s:0142 E:001368 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:495 [FINISH]
11:31:00 worker.1 | c:0034 p:---- s:0139 e:000138 CFUNC  :call
11:31:00 worker.1 | c:0033 p:0021 s:0135 e:000134 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:503
11:31:00 worker.1 | c:0032 p:0077 s:0130 e:000129 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:88
11:31:00 worker.1 | c:0031 p:0015 s:0122 E:001308 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:31
11:31:00 worker.1 | c:0030 p:0017 s:0118 e:000117 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/execution.rb:21
11:31:00 worker.1 | c:0029 p:0015 s:0113 e:000112 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/activejob-4.2.3/lib/active_job/queue_adapters/sidekiq_adapter.rb:42
11:31:00 worker.1 | c:0028 p:0012 s:0109 e:000108 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:75
11:31:00 worker.1 | c:0027 p:0019 s:0104 e:000103 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:52
11:31:00 worker.1 | c:0026 p:0014 s:0102 e:000101 LAMBDA /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:127
11:31:00 worker.1 | c:0025 p:0006 s:0100 e:000099 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/active_record.rb:6
11:31:00 worker.1 | c:0024 p:0030 s:0096 e:000095 LAMBDA /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129
11:31:00 worker.1 | c:0023 p:0006 s:0094 e:000093 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/retry_jobs.rb:74
11:31:00 worker.1 | c:0022 p:0030 s:0087 e:000086 LAMBDA /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129
11:31:00 worker.1 | c:0021 p:0029 s:0085 E:0011e8 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:15
11:31:00 worker.1 | c:0020 p:0056 s:0082 e:000081 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/logging.rb:30
11:31:00 worker.1 | c:0019 p:0068 s:0078 E:002350 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/server/logging.rb:11
11:31:00 worker.1 | c:0018 p:0030 s:0071 e:000070 LAMBDA /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129
11:31:00 worker.1 | c:0017 p:0038 s:0069 e:000068 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/skylight-ruby-f53c9580dbab/lib/skylight/core.rb:70
11:31:00 worker.1 | c:0016 p:0061 s:0062 e:000061 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/bundler/gems/sidekiq-skylight-98b748497038/lib/sidekiq/skylight/server_middleware.rb:
11:31:00 worker.1 | c:0015 p:0030 s:0056 e:000055 LAMBDA /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:129 [FINISH]
11:31:00 worker.1 | c:0014 p:---- s:0054 e:000053 CFUNC  :call
11:31:00 worker.1 | c:0013 p:0024 s:0051 E:002268 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/middleware/chain.rb:132
11:31:00 worker.1 | c:0012 p:0021 s:0045 E:002690 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:51
11:31:00 worker.1 | c:0011 p:0016 s:0043 E:002188 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:98
11:31:00 worker.1 | c:0010 p:0105 s:0037 E:002480 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/sidekiq-3.4.2/lib/sidekiq/processor.rb:50 [FINISH]
11:31:00 worker.1 | c:0009 p:---- s:0026 e:000025 CFUNC  :public_send
11:31:00 worker.1 | c:0008 p:0042 s:0021 e:000020 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26
11:31:00 worker.1 | c:0007 p:0031 s:0016 e:000015 METHOD /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122
11:31:00 worker.1 | c:0006 p:0011 s:0011 e:000010 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60
11:31:00 worker.1 | c:0005 p:0041 s:0009 e:000008 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71
11:31:00 worker.1 | c:0004 p:0026 s:0007 e:000006 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357
11:31:00 worker.1 | c:0003 p:0073 s:0005 e:000004 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57
11:31:00 worker.1 | c:0002 p:0060 s:0003 e:000002 BLOCK  /Users/jon/.rvm/gems/ruby-2.2.2@vouch_api/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15 [FINISH]
11:31:00 worker.1 | c:0001 p:---- s:0001 e:000000 ------

the same code runs fine in a console but as soon as i move it to a worker it fails. i also tested it via the delayed_job extensions for sidekiq with the same result.

we're using ruby-2.2.2 and keen (0.9.2). i'd love to do these async - i don't know if i can depend on eventmachine although i suppose that's the next route i'm going to go, just wanted to file this in case this was a known issue.

Doubt about relative timeframes

Is there a way, to know the attributes start and end of a timeframe, given its "code"?
Like for example, if I use this_month, I would like to know its attributes, in this case:

"timeframe" => {
  :"start" => "2015-07-01T00:00:00.000Z",
  :"end" => "2015-07-31T00:00:00.000Z"
}

Or the other way around.
Thanks!

`uninitialized constant Keen::ScopedKey`

I'm using the keen gem to give scoped keys to clients for rendering charts in JS.

In my rails model, I'm using:

  before_save :set_scoped_keen_key!, if: Proc.new{scoped_keen_key.blank?}

  def set_scoped_keen_key!
    # Locks all queries the partner can see to those involving their own content.
    self.scoped_keen_key = Keen::ScopedKey.new(ENV['KEEN_MASTER_KEY'], {
      "allowed_operations" => [ "read" ],
      "filters" => [{
        "property_name" => "Content.source.name",
        "operator" => "exists",
        "property_value" => true
        },{
        "property_name" => "Content.source.name",
        "operator" => "eq",
        "property_value" => self.partner_brand.content_source_name
    }]}).encrypt!
  end

But am getting the error:

uninitialized constant Keen::ScopedKey

Extracted source (around line #8):

  def set_scoped_keen_key!
    # Locks all queries the partner can see to those involving their own content.
    self.scoped_keen_key = Keen::ScopedKey.new(ENV['KEEN_MASTER_KEY'], {  # <== Error here
      "allowed_operations" => [ "read" ],
      "filters" => [{
        "property_name" => "Content.source.name",

I've set in .env:

KEEN_PROJECT_ID=...
KEEN_READ_KEY=...
KEEN_MASTER_KEY=...

Support array value for property_names option in Keen.extraction

Currently it is not possible to pass an array of values to the property_names params option for Keen.extraction. It does accept a string which is limiting. It breaks with an arry with the following error:

Keen.extraction(:member_subscriptions, filters: [{ property_name: :activity, operator: :in, property_value: ['subscribed']}], property_names: [:id])
NoMethodError: undefined method `encoding' for [:id]:Array

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.