keen 0.7.2 → 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -2
- data/README.md +26 -1
- data/lib/keen/client/publishing_methods.rb +40 -13
- data/lib/keen/client/querying_methods.rb +1 -1
- data/lib/keen/version.rb +1 -1
- data/lib/keen.rb +7 -6
- data/spec/integration/api_spec.rb +23 -0
- data/spec/keen/client/publishing_methods_spec.rb +52 -13
- data/spec/keen/client/querying_methods_spec.rb +13 -3
- data/spec/keen/keen_spec.rb +10 -1
- data/spec/spec_helper.rb +5 -1
- data/spec/synchrony/synchrony_spec.rb +4 -4
- metadata +2 -2
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
keen (0.7.
|
4
|
+
keen (0.7.3)
|
5
5
|
multi_json (~> 1.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -42,6 +42,7 @@ GEM
|
|
42
42
|
guard (>= 1.8)
|
43
43
|
rspec (~> 2.13)
|
44
44
|
http_parser.rb (0.5.3)
|
45
|
+
json (1.7.7)
|
45
46
|
linecache (0.46)
|
46
47
|
rbx-require-relative (> 0.0.4)
|
47
48
|
listen (1.0.3)
|
@@ -50,7 +51,7 @@ GEM
|
|
50
51
|
rb-kqueue (>= 0.2)
|
51
52
|
lumberjack (1.0.3)
|
52
53
|
method_source (0.8.1)
|
53
|
-
multi_json (1.7.
|
54
|
+
multi_json (1.7.3)
|
54
55
|
pry (0.9.12.1)
|
55
56
|
coderay (~> 1.0.5)
|
56
57
|
method_source (~> 0.8)
|
@@ -94,6 +95,7 @@ DEPENDENCIES
|
|
94
95
|
em-synchrony
|
95
96
|
guard
|
96
97
|
guard-rspec
|
98
|
+
json (~> 1.7.7)
|
97
99
|
keen!
|
98
100
|
rake
|
99
101
|
rb-fchange
|
data/README.md
CHANGED
@@ -133,6 +133,26 @@ Detailed information on available parameters for each API resource can be found
|
|
133
133
|
|
134
134
|
### Other code examples
|
135
135
|
|
136
|
+
#### Batch publishing
|
137
|
+
|
138
|
+
The keen-gem supports publishing events in batches via the `publish_batch` method. Here's an example usage:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
Keen.publish_batch(
|
142
|
+
:signups => [
|
143
|
+
{ :name => "Bob" },
|
144
|
+
{ :name => "Mary" }
|
145
|
+
],
|
146
|
+
:purchases => [
|
147
|
+
{ :price => 10 },
|
148
|
+
{ :price => 20 }
|
149
|
+
]
|
150
|
+
)
|
151
|
+
```
|
152
|
+
|
153
|
+
This call would publish 2 `signups` events and 2 `purchases` events - all in just one API call.
|
154
|
+
Batch publishing is ideal for loading historical events into Keen IO.
|
155
|
+
|
136
156
|
#### Authentication
|
137
157
|
|
138
158
|
To configure keen-gem in code, do as follows:
|
@@ -177,6 +197,10 @@ To track email opens, simply add an image to your email template that points to
|
|
177
197
|
|
178
198
|
### Changelog
|
179
199
|
|
200
|
+
##### 0.7.3
|
201
|
+
+ Add batch publishing support
|
202
|
+
+ Allow event collection names for querying methods to be symbols. Thanks to [cbartlett](https://github.com/cbartlett).
|
203
|
+
|
180
204
|
##### 0.7.2
|
181
205
|
+ Fix support for non-https API URL testing
|
182
206
|
|
@@ -223,5 +247,6 @@ Fire away with issues and pull requests!
|
|
223
247
|
+ [alexkwolfe](https://github.com/alexkwolfe)
|
224
248
|
+ [peteygao](https://github.com/peteygao)
|
225
249
|
+ [obieq](https://github.com/obieq)
|
226
|
-
|
250
|
+
+ [cbartlett](https://github.com/cbartlett)
|
251
|
+
|
227
252
|
Thanks everyone, you rock!
|
@@ -25,17 +25,27 @@ module Keen
|
|
25
25
|
ensure_project_id!
|
26
26
|
ensure_write_key!
|
27
27
|
check_event_data!(event_collection, properties)
|
28
|
+
publish_body(
|
29
|
+
api_event_collection_resource_path(event_collection),
|
30
|
+
MultiJson.encode(properties),
|
31
|
+
"publish")
|
32
|
+
end
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
# Publishes a batch of events
|
35
|
+
# See detailed documentation here
|
36
|
+
# https://keen.io/docs/api/reference/#post-request-body-example-of-batch-event-posting
|
37
|
+
#
|
38
|
+
# @param events - a hash where the keys are event collection names
|
39
|
+
# and the values are arrays of hashes (event properties)
|
40
|
+
#
|
41
|
+
# @return the JSON response from the API
|
42
|
+
def publish_batch(events)
|
43
|
+
ensure_project_id!
|
44
|
+
ensure_write_key!
|
45
|
+
publish_body(
|
46
|
+
api_events_resource_path,
|
47
|
+
MultiJson.encode(events),
|
48
|
+
"publish")
|
39
49
|
end
|
40
50
|
|
41
51
|
# Publishes an asynchronous event
|
@@ -55,7 +65,7 @@ module Keen
|
|
55
65
|
|
56
66
|
http_client = Keen::HTTP::Async.new(self.api_url)
|
57
67
|
http = http_client.post(
|
58
|
-
:path =>
|
68
|
+
:path => api_event_collection_resource_path(event_collection),
|
59
69
|
:headers => api_headers(self.write_key, "async"),
|
60
70
|
:body => MultiJson.encode(properties)
|
61
71
|
)
|
@@ -98,15 +108,32 @@ module Keen
|
|
98
108
|
def beacon_url(event_collection, properties)
|
99
109
|
json = MultiJson.encode(properties)
|
100
110
|
data = [json].pack("m0").tr("+/", "-_").gsub("\n", "")
|
101
|
-
"#{self.api_url}#{
|
111
|
+
"#{self.api_url}#{api_event_collection_resource_path(event_collection)}?api_key=#{self.write_key}&data=#{data}"
|
102
112
|
end
|
103
113
|
|
104
114
|
private
|
105
115
|
|
106
|
-
def
|
116
|
+
def publish_body(path, body, error_method)
|
117
|
+
begin
|
118
|
+
response = Keen::HTTP::Sync.new(
|
119
|
+
self.api_url).post(
|
120
|
+
:path => path,
|
121
|
+
:headers => api_headers(self.write_key, "sync"),
|
122
|
+
:body => body)
|
123
|
+
rescue Exception => http_error
|
124
|
+
raise HttpError.new("HTTP #{error_method} failure: #{http_error.message}", http_error)
|
125
|
+
end
|
126
|
+
process_response(response.code, response.body.chomp)
|
127
|
+
end
|
128
|
+
|
129
|
+
def api_event_collection_resource_path(event_collection)
|
107
130
|
"/#{api_version}/projects/#{project_id}/events/#{URI.escape(event_collection)}"
|
108
131
|
end
|
109
132
|
|
133
|
+
def api_events_resource_path
|
134
|
+
"/#{api_version}/projects/#{project_id}/events"
|
135
|
+
end
|
136
|
+
|
110
137
|
def check_event_data!(event_collection, properties)
|
111
138
|
raise ArgumentError, "Event collection can not be nil" unless event_collection
|
112
139
|
raise ArgumentError, "Event properties can not be nil" unless properties
|
data/lib/keen/version.rb
CHANGED
data/lib/keen.rb
CHANGED
@@ -25,19 +25,20 @@ module Keen
|
|
25
25
|
class << self
|
26
26
|
extend Forwardable
|
27
27
|
|
28
|
-
def_delegators :default_client,
|
29
|
-
:project_id, :project_id=,
|
30
|
-
:write_key, :write_key=,
|
31
|
-
:read_key, :read_key=,
|
28
|
+
def_delegators :default_client,
|
29
|
+
:project_id, :project_id=,
|
30
|
+
:write_key, :write_key=,
|
31
|
+
:read_key, :read_key=,
|
32
32
|
:api_url, :api_url=
|
33
33
|
|
34
34
|
def_delegators :default_client,
|
35
|
-
:publish, :publish_async,
|
35
|
+
:publish, :publish_async, :publish_batch,
|
36
36
|
:beacon_url
|
37
37
|
|
38
38
|
def_delegators :default_client,
|
39
39
|
:count, :count_unique, :minimum, :maximum,
|
40
|
-
:sum, :average, :select_unique, :funnel, :extraction
|
40
|
+
:sum, :average, :select_unique, :funnel, :extraction,
|
41
|
+
:multi_analysis
|
41
42
|
|
42
43
|
attr_writer :logger
|
43
44
|
|
@@ -60,6 +60,29 @@ describe "Keen IO API" do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
|
+
|
64
|
+
describe "batch" do
|
65
|
+
it "should publish a batch of events" do
|
66
|
+
Keen.publish_batch(
|
67
|
+
:batch_signups => [
|
68
|
+
{ :name => "bob" },
|
69
|
+
{ :name => "ted" }
|
70
|
+
],
|
71
|
+
:batch_purchases => [
|
72
|
+
{ :price => 30 },
|
73
|
+
{ :price => 40 }
|
74
|
+
]
|
75
|
+
).should == {
|
76
|
+
"batch_purchases" => [
|
77
|
+
{ "success" => true },
|
78
|
+
{ "success" => true }
|
79
|
+
],
|
80
|
+
"batch_signups" => [
|
81
|
+
{ "success" => true },
|
82
|
+
{ "success"=>true }
|
83
|
+
]}
|
84
|
+
end
|
85
|
+
end
|
63
86
|
end
|
64
87
|
|
65
88
|
describe "queries" do
|
@@ -13,14 +13,14 @@ describe Keen::Client::PublishingMethods do
|
|
13
13
|
|
14
14
|
describe "publish" do
|
15
15
|
it "should post using the collection and properties" do
|
16
|
-
stub_keen_post(
|
16
|
+
stub_keen_post(api_event_collection_resource_url(api_url, collection), 201, "")
|
17
17
|
client.publish(collection, event_properties)
|
18
|
-
expect_keen_post(
|
18
|
+
expect_keen_post(api_event_collection_resource_url(api_url, collection), event_properties, "sync", write_key)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should return the proper response" do
|
22
22
|
api_response = { "created" => true }
|
23
|
-
stub_keen_post(
|
23
|
+
stub_keen_post(api_event_collection_resource_url(api_url, collection), 201, api_response)
|
24
24
|
client.publish(collection, event_properties).should == api_response
|
25
25
|
end
|
26
26
|
|
@@ -37,13 +37,13 @@ describe Keen::Client::PublishingMethods do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should url encode the event collection" do
|
40
|
-
stub_keen_post(
|
40
|
+
stub_keen_post(api_event_collection_resource_url(api_url, "foo%20bar"), 201, "")
|
41
41
|
client.publish("foo bar", event_properties)
|
42
|
-
expect_keen_post(
|
42
|
+
expect_keen_post(api_event_collection_resource_url(api_url, "foo%20bar"), event_properties, "sync", write_key)
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should wrap exceptions" do
|
46
|
-
stub_request(:post,
|
46
|
+
stub_request(:post, api_event_collection_resource_url(api_url, collection)).to_timeout
|
47
47
|
e = nil
|
48
48
|
begin
|
49
49
|
client.publish(collection, event_properties)
|
@@ -73,6 +73,45 @@ describe Keen::Client::PublishingMethods do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
describe "publish_batch" do
|
77
|
+
let(:events) {
|
78
|
+
{
|
79
|
+
:purchases => [
|
80
|
+
{ :price => 10 },
|
81
|
+
{ :price => 11 }
|
82
|
+
],
|
83
|
+
:signups => [
|
84
|
+
{ :name => "bob" },
|
85
|
+
{ :name => "bill" }
|
86
|
+
]
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
it "should raise an exception if client has no project_id" do
|
91
|
+
expect {
|
92
|
+
Keen::Client.new(
|
93
|
+
:write_key => "abcde"
|
94
|
+
).publish_batch(events)
|
95
|
+
}.to raise_error(Keen::ConfigurationError, "Keen IO Exception: Project ID must be set")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should raise an exception if client has no write_key" do
|
99
|
+
expect {
|
100
|
+
Keen::Client.new(
|
101
|
+
:project_id => "12345"
|
102
|
+
).publish_batch(events)
|
103
|
+
}.to raise_error(Keen::ConfigurationError, "Keen IO Exception: Write Key must be set for sending events")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should publish a batch of events" do
|
107
|
+
stub_keen_post(api_event_resource_url(api_url), 201, "")
|
108
|
+
client.publish_batch(events)
|
109
|
+
expect_keen_post(
|
110
|
+
api_event_resource_url(api_url),
|
111
|
+
events, "sync", write_key)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
76
115
|
describe "publish_async" do
|
77
116
|
# no TLS support in EventMachine on jRuby
|
78
117
|
unless defined?(JRUBY_VERSION)
|
@@ -83,11 +122,11 @@ describe Keen::Client::PublishingMethods do
|
|
83
122
|
end
|
84
123
|
|
85
124
|
it "should post the event data" do
|
86
|
-
stub_keen_post(
|
125
|
+
stub_keen_post(api_event_collection_resource_url(api_url, collection), 201, api_success)
|
87
126
|
EM.run {
|
88
127
|
client.publish_async(collection, event_properties).callback {
|
89
128
|
begin
|
90
|
-
expect_keen_post(
|
129
|
+
expect_keen_post(api_event_collection_resource_url(api_url, collection), event_properties, "async", write_key)
|
91
130
|
ensure
|
92
131
|
EM.stop
|
93
132
|
end
|
@@ -99,11 +138,11 @@ describe Keen::Client::PublishingMethods do
|
|
99
138
|
end
|
100
139
|
|
101
140
|
it "should uri encode the event collection" do
|
102
|
-
stub_keen_post(
|
141
|
+
stub_keen_post(api_event_collection_resource_url(api_url, "foo%20bar"), 201, api_success)
|
103
142
|
EM.run {
|
104
143
|
client.publish_async("foo bar", event_properties).callback {
|
105
144
|
begin
|
106
|
-
expect_keen_post(
|
145
|
+
expect_keen_post(api_event_collection_resource_url(api_url, "foo%20bar"), event_properties, "async", write_key)
|
107
146
|
ensure
|
108
147
|
EM.stop
|
109
148
|
end
|
@@ -128,7 +167,7 @@ describe Keen::Client::PublishingMethods do
|
|
128
167
|
|
129
168
|
describe "deferrable callbacks" do
|
130
169
|
it "should trigger callbacks" do
|
131
|
-
stub_keen_post(
|
170
|
+
stub_keen_post(api_event_collection_resource_url(api_url, collection), 201, api_success)
|
132
171
|
EM.run {
|
133
172
|
client.publish_async(collection, event_properties).callback { |response|
|
134
173
|
begin
|
@@ -141,7 +180,7 @@ describe Keen::Client::PublishingMethods do
|
|
141
180
|
end
|
142
181
|
|
143
182
|
it "should trigger errbacks" do
|
144
|
-
stub_request(:post,
|
183
|
+
stub_request(:post, api_event_collection_resource_url(api_url, collection)).to_timeout
|
145
184
|
EM.run {
|
146
185
|
client.publish_async(collection, event_properties).errback { |error|
|
147
186
|
begin
|
@@ -155,7 +194,7 @@ describe Keen::Client::PublishingMethods do
|
|
155
194
|
end
|
156
195
|
|
157
196
|
it "should not trap exceptions in the client callback" do
|
158
|
-
stub_keen_post(
|
197
|
+
stub_keen_post(api_event_collection_resource_url(api_url, "foo%20bar"), 201, api_success)
|
159
198
|
expect {
|
160
199
|
EM.run {
|
161
200
|
client.publish_async("foo bar", event_properties).callback {
|
@@ -113,13 +113,23 @@ describe Keen::Client do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
describe "#count" do
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
let(:query_params) { "?event_collection=#{event_collection}" }
|
117
|
+
let(:url) { query_url("count", query_params) }
|
118
|
+
before do
|
119
119
|
stub_keen_get(url, 200, :result => 10)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should not require params" do
|
120
123
|
client.count(event_collection).should == 10
|
121
124
|
expect_keen_get(url, "sync", read_key)
|
122
125
|
end
|
126
|
+
|
127
|
+
context "with event collection as symbol" do
|
128
|
+
let(:event_collection) { :users }
|
129
|
+
it "should not require a string" do
|
130
|
+
client.count(event_collection).should == 10
|
131
|
+
end
|
132
|
+
end
|
123
133
|
end
|
124
134
|
|
125
135
|
describe "#extraction" do
|
data/spec/keen/keen_spec.rb
CHANGED
@@ -62,12 +62,21 @@ describe Keen do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
[:publish, :publish_async].each do |_method|
|
65
|
+
[:publish, :publish_async, :publish_batch].each do |_method|
|
66
66
|
it "should forward the #{_method} method" do
|
67
67
|
@default_client.should_receive(_method).with("users", {})
|
68
68
|
Keen.send(_method, "users", {})
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
# pull the query methods list at runtime in order to ensure
|
73
|
+
# any new methods have a corresponding delegator
|
74
|
+
Keen::Client::QueryingMethods.instance_methods.each do |_method|
|
75
|
+
it "should forward the #{_method} query method" do
|
76
|
+
@default_client.should_receive(_method).with("users", {})
|
77
|
+
Keen.send(_method, "users", {})
|
78
|
+
end
|
79
|
+
end
|
71
80
|
end
|
72
81
|
|
73
82
|
describe "logger" do
|
data/spec/spec_helper.rb
CHANGED
@@ -48,9 +48,13 @@ module Keen::SpecHelpers
|
|
48
48
|
expect_keen_request(:post, url, MultiJson.encode(event_properties), sync_or_async_ua, write_key)
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
51
|
+
def api_event_collection_resource_url(base_url, collection)
|
52
52
|
"#{base_url}/3.0/projects/#{project_id}/events/#{collection}"
|
53
53
|
end
|
54
|
+
|
55
|
+
def api_event_resource_url(base_url)
|
56
|
+
"#{base_url}/3.0/projects/#{project_id}/events"
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
RSpec.configure do |config|
|
@@ -17,16 +17,16 @@ describe Keen::HTTP::Async do
|
|
17
17
|
|
18
18
|
describe "success" do
|
19
19
|
it "should post the event data" do
|
20
|
-
stub_keen_post(
|
20
|
+
stub_keen_post(api_event_collection_resource_url(api_url, collection), 201, api_success)
|
21
21
|
EM.synchrony {
|
22
22
|
@client.publish_async(collection, event_properties)
|
23
|
-
expect_keen_post(
|
23
|
+
expect_keen_post(api_event_collection_resource_url(api_url, collection), event_properties, "async", write_key)
|
24
24
|
EM.stop
|
25
25
|
}
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should recieve the right response 'synchronously'" do
|
29
|
-
stub_keen_post(
|
29
|
+
stub_keen_post(api_event_collection_resource_url(api_url, collection), 201, api_success)
|
30
30
|
EM.synchrony {
|
31
31
|
@client.publish_async(collection, event_properties).should == api_success
|
32
32
|
EM.stop
|
@@ -36,7 +36,7 @@ describe Keen::HTTP::Async do
|
|
36
36
|
|
37
37
|
describe "failure" do
|
38
38
|
it "should raise an exception" do
|
39
|
-
stub_request(:post,
|
39
|
+
stub_request(:post, api_event_collection_resource_url(api_url, collection)).to_timeout
|
40
40
|
e = nil
|
41
41
|
EM.synchrony {
|
42
42
|
begin
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-05-
|
14
|
+
date: 2013-05-17 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: multi_json
|