keen 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +38 -8
- data/lib/keen.rb +2 -1
- data/lib/keen/client/querying_methods.rb +45 -20
- data/lib/keen/version.rb +1 -1
- data/spec/keen/client/querying_methods_spec.rb +18 -0
- data/spec/keen/keen_spec.rb +1 -0
- metadata +74 -170
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Keen IO Official Ruby Client Library
|
2
2
|
|
3
3
|
[![Build Status](https://secure.travis-ci.org/keenlabs/keen-gem.png?branch=master)](http://travis-ci.org/keenlabs/keen-gem) [![Code Climate](https://codeclimate.com/github/keenlabs/keen-gem.png)](https://codeclimate.com/github/keenlabs/keen-gem)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/keen.svg)](http://badge.fury.io/rb/keen)
|
4
5
|
|
5
6
|
keen-gem is the official Ruby Client for the [Keen IO](https://keen.io/) API. The
|
6
7
|
Keen IO API lets developers build analytics features directly into their apps.
|
@@ -48,7 +49,7 @@ environment-based approach because it keeps sensitive information out of the cod
|
|
48
49
|
|
49
50
|
Once your environment is properly configured, the `Keen` object is ready to go immediately.
|
50
51
|
|
51
|
-
### Publishing
|
52
|
+
### Synchronous Publishing
|
52
53
|
|
53
54
|
Publishing events requires that `KEEN_WRITE_KEY` is set. Publish an event like this:
|
54
55
|
|
@@ -57,18 +58,17 @@ Keen.publish(:sign_ups, { :username => "lloyd", :referred_by => "harry" })
|
|
57
58
|
```
|
58
59
|
|
59
60
|
This will publish an event to the `sign_ups` collection with the `username` and `referred_by` properties set.
|
60
|
-
The event properties can be any valid Ruby hash
|
61
|
+
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](http://stackoverflow.com/questions/24620330/nested-json-objects-in-keen-io). You can learn more about data modeling with Keen IO with the [Data Modeling Guide](https://keen.io/docs/event-data-modeling/event-data-intro/).
|
62
|
+
|
63
|
+
Protip: Marshalling gems like [Blockhead](https://github.com/vinniefranco/blockhead) make converting structs or objects to hashes easier.
|
61
64
|
|
62
65
|
The event collection need not exist in advance. If it doesn't exist, Keen IO will create it on the first request.
|
63
66
|
|
64
67
|
### Asynchronous publishing
|
65
68
|
|
66
|
-
Publishing events shouldn't slow your application down or make
|
67
|
-
users wait longer for page loads & server requests.
|
69
|
+
Publishing events shouldn't slow your application down or make users wait longer for page loads & server requests.
|
68
70
|
|
69
|
-
The Keen IO API is fast, but any synchronous network call you make will
|
70
|
-
negatively impact response times. For this reason, we recommend you use the `publish_async`
|
71
|
-
method to send events.
|
71
|
+
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.
|
72
72
|
|
73
73
|
To compare asychronous vs. synchronous performance, check out the [keen-gem-example](http://keen-gem-example.herokuapp.com/) app.
|
74
74
|
|
@@ -91,7 +91,7 @@ Thread.new { EventMachine.run }
|
|
91
91
|
The best place for this is in an initializer, or anywhere that runs when your app boots up.
|
92
92
|
Here's a useful blog article that explains more about this approach - [EventMachine and Passenger](http://railstips.org/blog/archives/2011/05/04/eventmachine-and-passenger/).
|
93
93
|
|
94
|
-
And here's
|
94
|
+
And here's a gist that shows an example of [Eventmachine with Unicorn](https://gist.github.com/jonkgrimes/5103321), specifically the Unicorn config for starting and stopping EventMachine after forking.
|
95
95
|
|
96
96
|
Now, in your code, replace `publish` with `publish_async`. Bind callbacks if you require them.
|
97
97
|
|
@@ -143,6 +143,32 @@ Many of these queries can be performed with group by, filters, series and interv
|
|
143
143
|
|
144
144
|
Detailed information on available parameters for each API resource can be found on the [API Technical Reference](https://keen.io/docs/api/reference/).
|
145
145
|
|
146
|
+
##### The Query Method
|
147
|
+
|
148
|
+
You can also specify the analysis type as a parameter to a method called `query`:
|
149
|
+
|
150
|
+
``` ruby
|
151
|
+
Keen.query("median", "purchases", :target_property => "price") # => 60
|
152
|
+
```
|
153
|
+
|
154
|
+
This simplifes querying code where the analysis type is dynamic.
|
155
|
+
|
156
|
+
##### Getting Query URLs
|
157
|
+
|
158
|
+
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:
|
159
|
+
|
160
|
+
``` ruby
|
161
|
+
Keen.query_url("median", "purchases", :target_property => "price")
|
162
|
+
# => "https://api.keen.io/3.0/projects/<project-id>/queries/median?target_property=price&event_collection=purchases&api_key=<api-key>"
|
163
|
+
```
|
164
|
+
|
165
|
+
If you don't want the API key included, pass the `:exclude_api_key` option:
|
166
|
+
|
167
|
+
``` ruby
|
168
|
+
Keen.query_url("median", "purchases", { :target_property => "price" }, :exclude_api_key => true)
|
169
|
+
# => "https://api.keen.io/3.0/projects/<project-id>/queries/median?target_property=price&event_collection=purchases"
|
170
|
+
```
|
171
|
+
|
146
172
|
### Listing collections
|
147
173
|
|
148
174
|
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.
|
@@ -297,6 +323,10 @@ EventMachine itself won't do this because it runs in a different thread. Here's
|
|
297
323
|
|
298
324
|
### Changelog
|
299
325
|
|
326
|
+
##### 0.8.5
|
327
|
+
+ Add support for getting [query URLs](https://github.com/keenlabs/keen-gem/pull/47)
|
328
|
+
+ Make the `query` method public so code supporting dynamic analysis types is easier to write
|
329
|
+
|
300
330
|
##### 0.8.4
|
301
331
|
+ Add support for getting [project details](https://keen.io/docs/api/reference/#project-row-resource)
|
302
332
|
|
data/lib/keen.rb
CHANGED
@@ -191,33 +191,58 @@ module Keen
|
|
191
191
|
query(__method__, event_collection, params)
|
192
192
|
end
|
193
193
|
|
194
|
+
# Returns the URL for a Query without running it
|
195
|
+
# @param event_colection
|
196
|
+
# @param params [Hash] (required)
|
197
|
+
# analysis_type (required)
|
198
|
+
# group_by (optional)
|
199
|
+
# timeframe (optional)
|
200
|
+
# interval (optional)
|
201
|
+
# filters (optional) [Array]
|
202
|
+
# timezone (optional)
|
203
|
+
# @param options
|
204
|
+
# exclude_api_key
|
205
|
+
def query_url(analysis_type, event_collection, params={}, options={})
|
206
|
+
str = _query_url(analysis_type, event_collection, params)
|
207
|
+
str << "&api_key=#{self.read_key}" unless options[:exclude_api_key]
|
208
|
+
str
|
209
|
+
end
|
210
|
+
|
211
|
+
# Run a query
|
212
|
+
# @param event_colection
|
213
|
+
# @param params [Hash] (required)
|
214
|
+
# analysis_type (required)
|
215
|
+
# group_by (optional)
|
216
|
+
# timeframe (optional)
|
217
|
+
# interval (optional)
|
218
|
+
# filters (optional) [Array]
|
219
|
+
# timezone (optional)
|
220
|
+
def query(analysis_type, event_collection, params={})
|
221
|
+
url = _query_url(analysis_type, event_collection, params)
|
222
|
+
response = get_response(url)
|
223
|
+
response_body = response.body.chomp
|
224
|
+
process_response(response.code, response_body)["result"]
|
225
|
+
end
|
226
|
+
|
194
227
|
private
|
195
228
|
|
196
|
-
def
|
197
|
-
query_params = clone_params(params)
|
229
|
+
def _query_url(analysis_type, event_collection, params={})
|
198
230
|
ensure_project_id!
|
199
231
|
ensure_read_key!
|
200
232
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
query_params = preprocess_params(query_params)
|
206
|
-
|
207
|
-
begin
|
208
|
-
response = Keen::HTTP::Sync.new(self.api_url, self.proxy_url).get(
|
209
|
-
:path => "#{api_query_resource_path(query_name)}?#{query_params}",
|
210
|
-
:headers => api_headers(self.read_key, "sync"))
|
211
|
-
rescue Exception => http_error
|
212
|
-
raise HttpError.new("Couldn't perform #{query_name} on Keen IO: #{http_error.message}", http_error)
|
213
|
-
end
|
214
|
-
|
215
|
-
response_body = response.body.chomp
|
216
|
-
process_response(response.code, response_body)["result"]
|
233
|
+
query_params = params.dup
|
234
|
+
query_params[:event_collection] = event_collection.to_s if event_collection
|
235
|
+
"#{self.api_url}#{api_query_resource_path(analysis_type)}?#{preprocess_params(query_params)}"
|
217
236
|
end
|
218
237
|
|
219
|
-
def
|
220
|
-
|
238
|
+
def get_response(url)
|
239
|
+
uri = URI.parse(url)
|
240
|
+
Keen::HTTP::Sync.new(self.api_url, self.proxy_url).get(
|
241
|
+
:path => "#{uri.path}?#{uri.query}",
|
242
|
+
:headers => api_headers(self.read_key, "sync")
|
243
|
+
)
|
244
|
+
rescue Exception => http_error
|
245
|
+
raise HttpError.new("Couldn't perform #{@analysis_type} on Keen IO: #{http_error.message}", http_error)
|
221
246
|
end
|
222
247
|
|
223
248
|
def api_query_resource_path(analysis_type)
|
data/lib/keen/version.rb
CHANGED
@@ -172,4 +172,22 @@ describe Keen::Client do
|
|
172
172
|
expect_keen_get(url, "sync", read_key)
|
173
173
|
end
|
174
174
|
end
|
175
|
+
|
176
|
+
describe "#query_url" do
|
177
|
+
let(:expected) { }
|
178
|
+
|
179
|
+
it "should returns the URL for a query" do
|
180
|
+
response = client.query_url('count', event_collection)
|
181
|
+
expect(response).to eq 'https://notreal.keen.io/3.0/projects/12345/queries/count?event_collection=users&api_key=abcde'
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should exclude the api key if option is passed" do
|
185
|
+
response = client.query_url('count', event_collection, {}, :exclude_api_key => true)
|
186
|
+
expect(response).to eq 'https://notreal.keen.io/3.0/projects/12345/queries/count?event_collection=users'
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should not run the query" do
|
190
|
+
Keen::HTTP::Sync.should_not receive(:new)
|
191
|
+
end
|
192
|
+
end
|
175
193
|
end
|
data/spec/keen/keen_spec.rb
CHANGED
@@ -94,6 +94,7 @@ describe Keen do
|
|
94
94
|
# pull the query methods list at runtime in order to ensure
|
95
95
|
# any new methods have a corresponding delegator
|
96
96
|
Keen::Client::QueryingMethods.instance_methods.each do |_method|
|
97
|
+
next if _method.to_sym == :query
|
97
98
|
it "should forward the #{_method} query method" do
|
98
99
|
@default_client.should_receive(_method).with("users", {})
|
99
100
|
Keen.send(_method, "users", {})
|
metadata
CHANGED
@@ -1,184 +1,79 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: keen
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 53
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 5
|
10
|
+
version: 0.8.5
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Kyle Wild
|
9
14
|
- Josh Dzielak
|
10
15
|
- Daniel Kador
|
11
16
|
autorequire:
|
12
17
|
bindir: bin
|
13
18
|
cert_chain: []
|
14
|
-
|
15
|
-
|
16
|
-
|
19
|
+
|
20
|
+
date: 2014-08-01 00:00:00 -07:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
17
24
|
name: multi_json
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
|
-
requirements:
|
21
|
-
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: '1.3'
|
24
|
-
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
|
27
|
-
none: false
|
28
|
-
requirements:
|
29
|
-
- - ~>
|
30
|
-
- !ruby/object:Gem::Version
|
31
|
-
version: '1.3'
|
32
|
-
- !ruby/object:Gem::Dependency
|
33
|
-
name: addressable
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
35
27
|
none: false
|
36
|
-
requirements:
|
28
|
+
requirements:
|
37
29
|
- - ~>
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 9
|
32
|
+
segments:
|
33
|
+
- 1
|
34
|
+
- 3
|
35
|
+
version: "1.3"
|
40
36
|
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: addressable
|
41
40
|
prerelease: false
|
42
|
-
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
42
|
none: false
|
44
|
-
requirements:
|
43
|
+
requirements:
|
45
44
|
- - ~>
|
46
|
-
- !ruby/object:Gem::Version
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 9
|
47
|
+
segments:
|
48
|
+
- 2
|
49
|
+
- 3
|
50
|
+
- 5
|
47
51
|
version: 2.3.5
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
requirements:
|
53
|
-
- - ! '>='
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '0'
|
56
|
-
type: :development
|
57
|
-
prerelease: false
|
58
|
-
version_requirements: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
|
-
requirements:
|
61
|
-
- - ! '>='
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: '0'
|
64
|
-
- !ruby/object:Gem::Dependency
|
65
|
-
name: guard-rspec
|
66
|
-
requirement: !ruby/object:Gem::Requirement
|
67
|
-
none: false
|
68
|
-
requirements:
|
69
|
-
- - ! '>='
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
version: '0'
|
72
|
-
type: :development
|
73
|
-
prerelease: false
|
74
|
-
version_requirements: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
|
-
requirements:
|
77
|
-
- - ! '>='
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '0'
|
80
|
-
- !ruby/object:Gem::Dependency
|
81
|
-
name: rb-inotify
|
82
|
-
requirement: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
|
-
requirements:
|
85
|
-
- - ! '>='
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version: '0'
|
88
|
-
type: :development
|
89
|
-
prerelease: false
|
90
|
-
version_requirements: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
|
-
requirements:
|
93
|
-
- - ! '>='
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: '0'
|
96
|
-
- !ruby/object:Gem::Dependency
|
97
|
-
name: rb-fsevent
|
98
|
-
requirement: !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
|
-
requirements:
|
101
|
-
- - ! '>='
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
none: false
|
108
|
-
requirements:
|
109
|
-
- - ! '>='
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
version: '0'
|
112
|
-
- !ruby/object:Gem::Dependency
|
113
|
-
name: rb-fchange
|
114
|
-
requirement: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
|
-
requirements:
|
117
|
-
- - ! '>='
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
version: '0'
|
120
|
-
type: :development
|
121
|
-
prerelease: false
|
122
|
-
version_requirements: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
|
-
requirements:
|
125
|
-
- - ! '>='
|
126
|
-
- !ruby/object:Gem::Version
|
127
|
-
version: '0'
|
128
|
-
- !ruby/object:Gem::Dependency
|
129
|
-
name: ruby_gntp
|
130
|
-
requirement: !ruby/object:Gem::Requirement
|
131
|
-
none: false
|
132
|
-
requirements:
|
133
|
-
- - ! '>='
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
version: '0'
|
136
|
-
type: :development
|
52
|
+
type: :runtime
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: ruby-debug
|
137
56
|
prerelease: false
|
138
|
-
|
139
|
-
none: false
|
140
|
-
requirements:
|
141
|
-
- -
|
142
|
-
- !ruby/object:Gem::Version
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
none: false
|
148
|
-
requirements:
|
149
|
-
- - ! '>='
|
150
|
-
- !ruby/object:Gem::Version
|
151
|
-
version: '0'
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
152
66
|
type: :development
|
153
|
-
|
154
|
-
version_requirements: !ruby/object:Gem::Requirement
|
155
|
-
none: false
|
156
|
-
requirements:
|
157
|
-
- - ! '>='
|
158
|
-
- !ruby/object:Gem::Version
|
159
|
-
version: '0'
|
160
|
-
- !ruby/object:Gem::Dependency
|
161
|
-
name: debugger
|
162
|
-
requirement: !ruby/object:Gem::Requirement
|
163
|
-
none: false
|
164
|
-
requirements:
|
165
|
-
- - ! '>='
|
166
|
-
- !ruby/object:Gem::Version
|
167
|
-
version: '0'
|
168
|
-
type: :development
|
169
|
-
prerelease: false
|
170
|
-
version_requirements: !ruby/object:Gem::Requirement
|
171
|
-
none: false
|
172
|
-
requirements:
|
173
|
-
- - ! '>='
|
174
|
-
- !ruby/object:Gem::Version
|
175
|
-
version: '0'
|
67
|
+
version_requirements: *id003
|
176
68
|
description: Send events and build analytics features into your Ruby applications.
|
177
69
|
email: josh@keen.io
|
178
70
|
executables: []
|
71
|
+
|
179
72
|
extensions: []
|
73
|
+
|
180
74
|
extra_rdoc_files: []
|
181
|
-
|
75
|
+
|
76
|
+
files:
|
182
77
|
- .gitignore
|
183
78
|
- .rspec
|
184
79
|
- .travis.yml
|
@@ -210,32 +105,41 @@ files:
|
|
210
105
|
- spec/spec_helper.rb
|
211
106
|
- spec/synchrony/spec_helper.rb
|
212
107
|
- spec/synchrony/synchrony_spec.rb
|
108
|
+
has_rdoc: true
|
213
109
|
homepage: https://github.com/keenlabs/keen-gem
|
214
|
-
licenses:
|
110
|
+
licenses:
|
215
111
|
- MIT
|
216
112
|
post_install_message:
|
217
113
|
rdoc_options: []
|
218
|
-
|
114
|
+
|
115
|
+
require_paths:
|
219
116
|
- lib
|
220
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
221
118
|
none: false
|
222
|
-
requirements:
|
223
|
-
- -
|
224
|
-
- !ruby/object:Gem::Version
|
225
|
-
|
226
|
-
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
hash: 3
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
227
127
|
none: false
|
228
|
-
requirements:
|
229
|
-
- -
|
230
|
-
- !ruby/object:Gem::Version
|
231
|
-
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
hash: 3
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
version: "0"
|
232
135
|
requirements: []
|
136
|
+
|
233
137
|
rubyforge_project:
|
234
|
-
rubygems_version: 1.
|
138
|
+
rubygems_version: 1.6.2
|
235
139
|
signing_key:
|
236
140
|
specification_version: 3
|
237
141
|
summary: Keen IO API Client
|
238
|
-
test_files:
|
142
|
+
test_files:
|
239
143
|
- spec/integration/api_spec.rb
|
240
144
|
- spec/integration/spec_helper.rb
|
241
145
|
- spec/keen/client/maintenance_methods_spec.rb
|