keen 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|