keen 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -0
- data/README.md +61 -11
- data/lib/keen.rb +2 -1
- data/lib/keen/client.rb +10 -77
- data/lib/keen/client/publishing_methods.rb +111 -0
- data/lib/keen/client/querying_methods.rb +199 -0
- data/lib/keen/http.rb +6 -0
- data/lib/keen/version.rb +1 -1
- data/spec/integration/api_spec.rb +112 -34
- data/spec/keen/client/publishing_methods_spec.rb +161 -0
- data/spec/keen/client/querying_methods_spec.rb +132 -0
- data/spec/keen/client_spec.rb +22 -188
- data/spec/spec_helper.rb +23 -8
- data/spec/synchrony/synchrony_spec.rb +4 -4
- metadata +17 -7
- checksums.yaml +0 -7
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -37,7 +37,9 @@ environment-based approach because it keeps sensitive information out of the cod
|
|
37
37
|
|
38
38
|
If your environment is set up property, `Keen` is ready go immediately. Publish an event like this:
|
39
39
|
|
40
|
-
|
40
|
+
```ruby
|
41
|
+
Keen.publish("sign_ups", { :username => "lloyd", :referred_by => "harry" })
|
42
|
+
```
|
41
43
|
|
42
44
|
This will publish an event to the 'sign_ups' collection with the `username` and `referred_by` properties set.
|
43
45
|
|
@@ -63,33 +65,78 @@ To publish asynchronously, first add
|
|
63
65
|
Next, run an instance of EventMachine. If you're using an EventMachine-based web server like
|
64
66
|
thin or goliath you're already doing this. Otherwise, you'll need to start an EventMachine loop manually as follows:
|
65
67
|
|
66
|
-
|
68
|
+
```ruby
|
69
|
+
Thread.new { EventMachine.run }
|
70
|
+
```
|
67
71
|
|
68
72
|
The best place for this is in an initializer, or anywhere that runs when your app boots up.
|
69
73
|
Here's a good blog article that explains more about this approach - [EventMachine and Passenger](http://railstips.org/blog/archives/2011/05/04/eventmachine-and-passenger/).
|
70
74
|
|
75
|
+
And here's a gist that shows an example of [Eventmachine with Unicorn](https://gist.github.com/jonkgrimes/5103321). Thanks to [jonkgrimes](https://github.com/jonkgrimes) for sharing this with us!
|
76
|
+
|
71
77
|
Now, in your code, replace `publish` with `publish_async`. Bind callbacks if you require them.
|
72
78
|
|
73
|
-
|
74
|
-
|
75
|
-
|
79
|
+
```ruby
|
80
|
+
http = Keen.publish_async("sign_ups", { :username => "lloyd", :referred_by => "harry" })
|
81
|
+
http.callback { |response| puts "Success: #{response}"}
|
82
|
+
http.errback { puts "was a failurrr :,(" }
|
83
|
+
```
|
76
84
|
|
77
85
|
This will schedule the network call into the event loop and allow your request thread
|
78
86
|
to resume processing immediately.
|
79
87
|
|
88
|
+
### Running queries
|
89
|
+
|
90
|
+
The Keen IO API provides rich querying capabilities against your event data set. For more information, see the [Data Analysis API Guide](https://keen.io/docs/data-analysis/).
|
91
|
+
|
92
|
+
Unlike event publishing, queries require that an API Key is provided. Just like project ID, we encourage that you set this as an environment variable:
|
93
|
+
|
94
|
+
KEEN_API_KEY=your-api-key
|
95
|
+
|
96
|
+
Here's are some examples of querying with the Ruby gem. Let's assume you've added some events to the "purchases" collection.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
Keen.count("purchases") # => 100
|
100
|
+
Keen.sum("purchases", :target_property => "price") # => 10000
|
101
|
+
Keen.minimum("purchases", :target_property => "price") # => 20
|
102
|
+
Keen.maximum("purchases", :target_property => "price") # => 100
|
103
|
+
Keen.average("purchases", :target_property => "price") # => 60
|
104
|
+
|
105
|
+
Keen.sum("purchases", :target_property => "price", :group_by => "item.id") # => [{ "item.id": 123, "result": 240 }, { ... }]
|
106
|
+
|
107
|
+
Keen.count_unique("purchases", :target_property => "username") # => 3
|
108
|
+
Keen.select_unique("purchases", :target_property => "username") # => ["bob", "linda", "travis"]
|
109
|
+
|
110
|
+
Keen.extraction("purchases") # => [{ "price" => 20, ... }, { ... }]
|
111
|
+
|
112
|
+
Keen.funnel(:steps => [
|
113
|
+
{ :actor_property => "username", "event_collection" => "purchases" },
|
114
|
+
{ :actor_property => "username", "event_collection" => "referrals" },
|
115
|
+
{ ... }]) # => [20, 15 ...]
|
116
|
+
```
|
117
|
+
|
118
|
+
Many of there queries can be performed with group by, filters, series and intervals. The API response for these is converted directly into Ruby Hash or Array.
|
119
|
+
|
120
|
+
Detailed information on available parameters for each API resource can be found on the [API Technical Reference](https://keen.io/docs/api/reference/).
|
121
|
+
|
80
122
|
### Other code examples
|
81
123
|
|
82
124
|
#### Authentication
|
83
125
|
|
84
126
|
To configure keen-gem in code, do as follows:
|
85
127
|
|
86
|
-
|
128
|
+
```ruby
|
129
|
+
Keen.project_id = 'your-project-id'
|
130
|
+
```
|
87
131
|
|
88
132
|
You can also configure individual client instances as follows:
|
89
133
|
|
90
|
-
|
134
|
+
```ruby
|
135
|
+
keen = Keen::Client.new(:project_id => 'your-project-id')
|
136
|
+
```
|
91
137
|
|
92
138
|
#### em-synchrony
|
139
|
+
|
93
140
|
keen-gem can be used with [em-synchrony](https://github.com/igrigorik/em-synchrony).
|
94
141
|
If you call `publish_async` and `EM::Synchrony` is defined the method will return the response
|
95
142
|
directly. (It does not return the deferrable on which to register callbacks.) Likewise, it will raise
|
@@ -103,15 +150,18 @@ This is useful for situations like tracking email opens using [image beacons](ht
|
|
103
150
|
In this situation, the JSON event data is passed by encoding it base-64 and adding it as a request parameter called `data`.
|
104
151
|
The `beacon_url` method found on the `Keen::Client` does this for you. Here's an example:
|
105
152
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
153
|
+
```ruby
|
154
|
+
Keen.beacon_url("sign_ups", :recipient => "foo@foo.com")
|
155
|
+
# => "https://api.keen.io/3.0/projects/12345/events/email_opens?data=eyJyZWNpcGllbnQiOiJmb29AZm9vLmNvbSJ9"
|
156
|
+
```
|
110
157
|
|
111
158
|
To track email opens, simply add an image to your email template that points to this URL.
|
112
159
|
|
113
160
|
### Changelog
|
114
161
|
|
162
|
+
##### 0.6.0
|
163
|
+
+ Added querying capabilities. A big thanks to [ifeelgoods](http://www.ifeelgoods.com/) for contributing!
|
164
|
+
|
115
165
|
##### 0.5.0
|
116
166
|
+ Removed API Key as a required field on Keen::Client. Only the Project ID is required to publish events.
|
117
167
|
+ You can continue to provide the API Key. Future features planned for this gem will require it. But for now,
|
data/lib/keen.rb
CHANGED
@@ -23,7 +23,8 @@ module Keen
|
|
23
23
|
|
24
24
|
def_delegators :default_client, :project_id, :api_key,
|
25
25
|
:project_id=, :api_key=, :publish, :publish_async,
|
26
|
-
:beacon_url
|
26
|
+
:beacon_url, :count, :count_unique, :minimum, :maximum,
|
27
|
+
:sum, :average, :select_unique, :funnel, :extraction
|
27
28
|
|
28
29
|
attr_writer :logger
|
29
30
|
|
data/lib/keen/client.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'keen/http'
|
2
2
|
require 'keen/version'
|
3
|
+
require 'keen/client/publishing_methods'
|
4
|
+
require 'keen/client/querying_methods'
|
5
|
+
|
3
6
|
require 'openssl'
|
4
7
|
require 'multi_json'
|
5
8
|
require 'base64'
|
@@ -7,6 +10,9 @@ require 'uri'
|
|
7
10
|
|
8
11
|
module Keen
|
9
12
|
class Client
|
13
|
+
include Keen::Client::PublishingMethods
|
14
|
+
include Keen::Client::QueryingMethods
|
15
|
+
|
10
16
|
attr_accessor :project_id, :api_key
|
11
17
|
|
12
18
|
CONFIG = {
|
@@ -30,12 +36,6 @@ module Keen
|
|
30
36
|
}
|
31
37
|
}
|
32
38
|
|
33
|
-
def beacon_url(event_collection, properties)
|
34
|
-
json = MultiJson.encode(properties)
|
35
|
-
data = [json].pack("m0").tr("+/", "-_").gsub("\n", "")
|
36
|
-
"https://#{api_host}#{api_path(event_collection)}?data=#{data}"
|
37
|
-
end
|
38
|
-
|
39
39
|
def initialize(*args)
|
40
40
|
options = args[0]
|
41
41
|
unless options.is_a?(Hash)
|
@@ -50,64 +50,6 @@ module Keen
|
|
50
50
|
:project_id, :api_key)
|
51
51
|
end
|
52
52
|
|
53
|
-
def publish(event_collection, properties)
|
54
|
-
check_configuration!
|
55
|
-
check_event_data!(event_collection, properties)
|
56
|
-
|
57
|
-
begin
|
58
|
-
response = Keen::HTTP::Sync.new(
|
59
|
-
api_host, api_port, api_sync_http_options).post(
|
60
|
-
:path => api_path(event_collection),
|
61
|
-
:headers => api_headers_with_auth("sync"),
|
62
|
-
:body => MultiJson.encode(properties))
|
63
|
-
rescue Exception => http_error
|
64
|
-
raise HttpError.new("Couldn't connect to Keen IO: #{http_error.message}", http_error)
|
65
|
-
end
|
66
|
-
process_response(response.code, response.body.chomp)
|
67
|
-
end
|
68
|
-
|
69
|
-
def publish_async(event_collection, properties)
|
70
|
-
check_configuration!
|
71
|
-
check_event_data!(event_collection, properties)
|
72
|
-
|
73
|
-
deferrable = EventMachine::DefaultDeferrable.new
|
74
|
-
|
75
|
-
http_client = Keen::HTTP::Async.new(api_host, api_port, api_async_http_options)
|
76
|
-
http = http_client.post({
|
77
|
-
:path => api_path(event_collection),
|
78
|
-
:headers => api_headers_with_auth("async"),
|
79
|
-
:body => MultiJson.encode(properties)
|
80
|
-
})
|
81
|
-
|
82
|
-
if defined?(EM::Synchrony)
|
83
|
-
if http.error
|
84
|
-
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
85
|
-
raise HttpError.new("Couldn't connect to Keen IO: #{http.error}")
|
86
|
-
else
|
87
|
-
process_response(http.response_header.status, http.response.chomp)
|
88
|
-
end
|
89
|
-
else
|
90
|
-
http.callback {
|
91
|
-
begin
|
92
|
-
response = process_response(http.response_header.status, http.response.chomp)
|
93
|
-
deferrable.succeed(response)
|
94
|
-
rescue Exception => e
|
95
|
-
deferrable.fail(e)
|
96
|
-
end
|
97
|
-
}
|
98
|
-
http.errback {
|
99
|
-
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
100
|
-
deferrable.fail(Error.new("Couldn't connect to Keen IO: #{http.error}"))
|
101
|
-
}
|
102
|
-
deferrable
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# deprecated
|
107
|
-
def add_event(event_collection, properties, options={})
|
108
|
-
self.publish(event_collection, properties, options)
|
109
|
-
end
|
110
|
-
|
111
53
|
private
|
112
54
|
|
113
55
|
def process_response(status_code, response_body)
|
@@ -126,21 +68,12 @@ module Keen
|
|
126
68
|
end
|
127
69
|
end
|
128
70
|
|
129
|
-
def
|
130
|
-
"
|
131
|
-
end
|
132
|
-
|
133
|
-
def api_headers_with_auth(sync_or_async)
|
134
|
-
api_headers(sync_or_async)
|
135
|
-
end
|
136
|
-
|
137
|
-
def check_configuration!
|
138
|
-
raise ConfigurationError, "Project ID must be set" unless project_id
|
71
|
+
def ensure_project_id!
|
72
|
+
raise ConfigurationError, "Project ID must be set" unless self.project_id
|
139
73
|
end
|
140
74
|
|
141
|
-
def
|
142
|
-
raise
|
143
|
-
raise ArgumentError, "Event properties can not be nil" unless properties
|
75
|
+
def ensure_api_key!
|
76
|
+
raise ConfigurationError, "API Key must be set for queries" unless self.api_key
|
144
77
|
end
|
145
78
|
|
146
79
|
def method_missing(_method, *args, &block)
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Keen
|
2
|
+
class Client
|
3
|
+
module PublishingMethods
|
4
|
+
|
5
|
+
# @deprecated
|
6
|
+
#
|
7
|
+
# Publishes a synchronous event
|
8
|
+
# @param event_collection
|
9
|
+
# @param [Hash] event properties
|
10
|
+
#
|
11
|
+
# @return the JSON response from the API
|
12
|
+
def add_event(event_collection, properties, options={})
|
13
|
+
self.publish(event_collection, properties, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Publishes a synchronous event
|
17
|
+
# See detailed documentation here
|
18
|
+
# https://keen.io/docs/api/reference/#event-collection-resource
|
19
|
+
#
|
20
|
+
# @param event_collection
|
21
|
+
# @param [Hash] event properties
|
22
|
+
#
|
23
|
+
# @return the JSON response from the API
|
24
|
+
def publish(event_collection, properties)
|
25
|
+
ensure_project_id!
|
26
|
+
check_event_data!(event_collection, properties)
|
27
|
+
|
28
|
+
begin
|
29
|
+
response = Keen::HTTP::Sync.new(
|
30
|
+
api_host, api_port, api_sync_http_options).post(
|
31
|
+
:path => api_event_resource_path(event_collection),
|
32
|
+
:headers => api_headers("sync"),
|
33
|
+
:body => MultiJson.encode(properties))
|
34
|
+
rescue Exception => http_error
|
35
|
+
raise HttpError.new("Couldn't connect to Keen IO: #{http_error.message}", http_error)
|
36
|
+
end
|
37
|
+
process_response(response.code, response.body.chomp)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Publishes an asynchronous event
|
41
|
+
# See detailed documentation here
|
42
|
+
# https://keen.io/docs/api/reference/#event-collection-resource
|
43
|
+
#
|
44
|
+
# @param event_collection
|
45
|
+
# @param [Hash] event properties
|
46
|
+
#
|
47
|
+
# @return a deferrable to apply callbacks to
|
48
|
+
def publish_async(event_collection, properties)
|
49
|
+
ensure_project_id!
|
50
|
+
check_event_data!(event_collection, properties)
|
51
|
+
|
52
|
+
deferrable = EventMachine::DefaultDeferrable.new
|
53
|
+
|
54
|
+
http_client = Keen::HTTP::Async.new(api_host, api_port, api_async_http_options)
|
55
|
+
http = http_client.post({
|
56
|
+
:path => api_event_resource_path(event_collection),
|
57
|
+
:headers => api_headers("async"),
|
58
|
+
:body => MultiJson.encode(properties)
|
59
|
+
})
|
60
|
+
|
61
|
+
if defined?(EM::Synchrony)
|
62
|
+
if http.error
|
63
|
+
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
64
|
+
raise HttpError.new("Couldn't connect to Keen IO: #{http.error}")
|
65
|
+
else
|
66
|
+
process_response(http.response_header.status, http.response.chomp)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
http.callback {
|
70
|
+
begin
|
71
|
+
response = process_response(http.response_header.status, http.response.chomp)
|
72
|
+
deferrable.succeed(response)
|
73
|
+
rescue Exception => e
|
74
|
+
deferrable.fail(e)
|
75
|
+
end
|
76
|
+
}
|
77
|
+
http.errback {
|
78
|
+
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
79
|
+
deferrable.fail(Error.new("Couldn't connect to Keen IO: #{http.error}"))
|
80
|
+
}
|
81
|
+
deferrable
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns an encoded URL that will record an event. Useful in email situations.
|
86
|
+
# See detailed documentation here
|
87
|
+
# https://keen.io/docs/api/reference/#event-collection-resource
|
88
|
+
#
|
89
|
+
# @param event_collection
|
90
|
+
# @param [Hash] event properties
|
91
|
+
#
|
92
|
+
# @return a URL that will track an event when hit
|
93
|
+
def beacon_url(event_collection, properties)
|
94
|
+
json = MultiJson.encode(properties)
|
95
|
+
data = [json].pack("m0").tr("+/", "-_").gsub("\n", "")
|
96
|
+
"https://#{api_host}#{api_event_resource_path(event_collection)}?data=#{data}"
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def api_event_resource_path(event_collection)
|
102
|
+
"/#{api_version}/projects/#{project_id}/events/#{URI.escape(event_collection)}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def check_event_data!(event_collection, properties)
|
106
|
+
raise ArgumentError, "Event collection can not be nil" unless event_collection
|
107
|
+
raise ArgumentError, "Event properties can not be nil" unless properties
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
module Keen
|
2
|
+
class Client
|
3
|
+
module QueryingMethods
|
4
|
+
|
5
|
+
# Runs a count query.
|
6
|
+
# See detailed documentation here:
|
7
|
+
# https://keen.io/docs/api/reference/#count-resource
|
8
|
+
#
|
9
|
+
# @param event_collection
|
10
|
+
# @param params [Hash] (optional)
|
11
|
+
# group_by (optional)
|
12
|
+
# timeframe (optional)
|
13
|
+
# interval (optional)
|
14
|
+
# filters (optional) [Array]
|
15
|
+
# timezone (optional)
|
16
|
+
def count(event_collection, params={})
|
17
|
+
query(__method__, event_collection, params)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Runs a count unique query.
|
21
|
+
# See detailed documentation here:
|
22
|
+
# https://keen.io/docs/api/reference/#count-unique-resource
|
23
|
+
#
|
24
|
+
# @param event_collection
|
25
|
+
# @param params [Hash] (optional)
|
26
|
+
# target_property (required)
|
27
|
+
# group_by (optional)
|
28
|
+
# timeframe (optional)
|
29
|
+
# interval (optional)
|
30
|
+
# filters (optional) [Array]
|
31
|
+
# timezone (optional)
|
32
|
+
def count_unique(event_collection, params)
|
33
|
+
query(__method__, event_collection, params)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Runs a minimum query.
|
37
|
+
# See detailed documentation here:
|
38
|
+
# https://keen.io/docs/api/reference/#minimum-resource
|
39
|
+
#
|
40
|
+
# @param event_collection
|
41
|
+
# @param params [Hash] (optional)
|
42
|
+
# target_property (required)
|
43
|
+
# group_by (optional)
|
44
|
+
# timeframe (optional)
|
45
|
+
# interval (optional)
|
46
|
+
# filters (optional) [Array]
|
47
|
+
# timezone (optional)
|
48
|
+
def minimum(event_collection, params)
|
49
|
+
query(__method__, event_collection, params)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Runs a maximum query.
|
53
|
+
# See detailed documentation here:
|
54
|
+
# https://keen.io/docs/api/reference/#maximum-resource
|
55
|
+
#
|
56
|
+
# @param event_collection
|
57
|
+
# @param params [Hash] (optional)
|
58
|
+
# target_property (required)
|
59
|
+
# group_by (optional)
|
60
|
+
# timeframe (optional)
|
61
|
+
# interval (optional)
|
62
|
+
# filters (optional) [Array]
|
63
|
+
# timezone (optional)
|
64
|
+
def maximum(event_collection, params)
|
65
|
+
query(__method__, event_collection, params)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Runs a sum query.
|
69
|
+
# See detailed documentation here:
|
70
|
+
# https://keen.io/docs/api/reference/#sum-resource
|
71
|
+
#
|
72
|
+
# @param event_collection
|
73
|
+
# @param params [Hash] (optional)
|
74
|
+
# target_property (required)
|
75
|
+
# group_by (optional)
|
76
|
+
# timeframe (optional)
|
77
|
+
# interval (optional)
|
78
|
+
# filters (optional) [Array]
|
79
|
+
# timezone (optional)
|
80
|
+
def sum(event_collection, params)
|
81
|
+
query(__method__, event_collection, params)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Runs a average query.
|
85
|
+
# See detailed documentation here:
|
86
|
+
# https://keen.io/docs/api/reference/#average-resource
|
87
|
+
#
|
88
|
+
# @param event_collection
|
89
|
+
# @param params [Hash] (optional)
|
90
|
+
# target_property (required)
|
91
|
+
# group_by (optional)
|
92
|
+
# timeframe (optional)
|
93
|
+
# interval (optional)
|
94
|
+
# filters (optional) [Array]
|
95
|
+
# timezone (optional)
|
96
|
+
def average(event_collection, params)
|
97
|
+
query(__method__, event_collection, params)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Runs a select_unique query.
|
101
|
+
# See detailed documentation here:
|
102
|
+
# https://keen.io/docs/api/reference/#select-unique-resource
|
103
|
+
#
|
104
|
+
# @param event_collection
|
105
|
+
# @param params [Hash] (optional)
|
106
|
+
# target_property (required)
|
107
|
+
# group_by (optional)
|
108
|
+
# timeframe (optional)
|
109
|
+
# interval (optional)
|
110
|
+
# filters (optional) [Array]
|
111
|
+
# timezone (optional)
|
112
|
+
def select_unique(event_collection, params)
|
113
|
+
query(__method__, event_collection, params)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Runs a extraction query.
|
117
|
+
# See detailed documentation here:
|
118
|
+
# https://keen.io/docs/api/reference/#extraction-resource
|
119
|
+
#
|
120
|
+
# @param event_collection
|
121
|
+
# @param params [Hash] (optional)
|
122
|
+
# target_property (required)
|
123
|
+
# group_by (optional)
|
124
|
+
# timeframe (optional)
|
125
|
+
# interval (optional)
|
126
|
+
# filters (optional) [Array]
|
127
|
+
# timezone (optional)
|
128
|
+
# latest (optional)
|
129
|
+
def extraction(event_collection, params={})
|
130
|
+
query(__method__, event_collection, params)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Runs a funnel query.
|
134
|
+
# See detailed documentation here:
|
135
|
+
# https://keen.io/docs/api/reference/#funnel-resource
|
136
|
+
#
|
137
|
+
# @param event_collection
|
138
|
+
# @param params [Hash] (optional)
|
139
|
+
# steps (required)
|
140
|
+
def funnel(params)
|
141
|
+
query(__method__, nil, params)
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def query(query_name, event_collection, params)
|
147
|
+
ensure_project_id!
|
148
|
+
ensure_api_key!
|
149
|
+
|
150
|
+
params[:api_key] = self.api_key
|
151
|
+
|
152
|
+
if event_collection
|
153
|
+
params[:event_collection] = event_collection
|
154
|
+
end
|
155
|
+
|
156
|
+
query_params = preprocess_params(params)
|
157
|
+
|
158
|
+
begin
|
159
|
+
response = Keen::HTTP::Sync.new(
|
160
|
+
api_host, api_port, api_sync_http_options).get(
|
161
|
+
:path => "#{api_query_resource_path(query_name)}?#{query_params}",
|
162
|
+
:headers => api_headers("sync"))
|
163
|
+
rescue Exception => http_error
|
164
|
+
raise HttpError.new("Couldn't perform #{query_name} on Keen IO: #{http_error.message}", http_error)
|
165
|
+
end
|
166
|
+
|
167
|
+
response_body = response.body.chomp
|
168
|
+
process_response(response.code, response_body)["result"]
|
169
|
+
end
|
170
|
+
|
171
|
+
def preprocess_params(params)
|
172
|
+
if params.key?(:filters)
|
173
|
+
params[:filters] = MultiJson.encode(params[:filters])
|
174
|
+
end
|
175
|
+
|
176
|
+
if params.key?(:steps)
|
177
|
+
params[:steps] = MultiJson.encode(params[:steps])
|
178
|
+
end
|
179
|
+
|
180
|
+
if params.key?(:timeframe) && params[:timeframe].is_a?(Hash)
|
181
|
+
params[:timeframe] = MultiJson.encode(params[:timeframe])
|
182
|
+
end
|
183
|
+
|
184
|
+
query_params = ""
|
185
|
+
params.each do |param, value|
|
186
|
+
query_params << "#{param}=#{URI.escape(value)}&"
|
187
|
+
end
|
188
|
+
|
189
|
+
query_params.chop!
|
190
|
+
query_params
|
191
|
+
end
|
192
|
+
|
193
|
+
def api_query_resource_path(analysis_type)
|
194
|
+
"/#{self.api_version}/projects/#{self.project_id}/queries/#{analysis_type}"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|