keen 0.4.2 → 0.4.3
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/.gitignore +1 -0
- data/.travis.yml +11 -5
- data/Gemfile +1 -0
- data/Guardfile +8 -0
- data/README.md +29 -8
- data/Rakefile +10 -0
- data/lib/keen.rb +2 -2
- data/lib/keen/client.rb +34 -15
- data/lib/keen/version.rb +1 -1
- data/spec/keen/client_spec.rb +8 -18
- data/spec/keen/keen_spec.rb +1 -5
- data/spec/spec_helper.rb +22 -2
- data/spec/synchrony/spec_helper.rb +7 -0
- data/spec/synchrony/synchrony_spec.rb +53 -0
- metadata +6 -2
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -8,10 +8,16 @@ rvm:
|
|
8
8
|
- rbx-19mode
|
9
9
|
|
10
10
|
env:
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
- PATTERN=keen
|
12
|
+
- PATTERN=integration KEEN_API_KEY=f806128f31c349fda124b62d1f4cf4b2 KEEN_PROJECT_ID=50e5ffa6897a2c319b000000
|
13
|
+
- PATTERN=synchrony
|
14
|
+
|
15
|
+
matrix:
|
16
|
+
exclude:
|
17
|
+
- rvm: 1.8.7
|
18
|
+
env: PATTERN=synchrony
|
19
|
+
- rvm: jruby-19mode
|
20
|
+
env: PATTERN=synchrony
|
14
21
|
|
15
22
|
script:
|
16
|
-
- bundle exec rake
|
17
|
-
- bundle exec rake integration
|
23
|
+
- bundle exec rake pattern
|
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -14,3 +14,11 @@ group :integration do
|
|
14
14
|
watch(%r{^spec/integration/.+_spec\.rb$})
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
group :synchrony do
|
19
|
+
guard 'rspec', :spec_paths => "spec/synchrony" do
|
20
|
+
watch('spec/spec_helper.rb') { "spec" }
|
21
|
+
watch('spec/synchrony/spec_helper.rb') { "spec" }
|
22
|
+
watch(%r{^spec/synchrony/.+_spec\.rb$})
|
23
|
+
end
|
24
|
+
end
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ keen is tested with Ruby 1.8 and 1.9 on:
|
|
23
23
|
|
24
24
|
### Usage
|
25
25
|
|
26
|
-
Before making any API calls, you must supply
|
26
|
+
Before making any API calls, you must supply keen-gem with a Project ID and an API Key.
|
27
27
|
(If you need a Keen IO account, [sign up here](https://keen.io/) - it's free.)
|
28
28
|
|
29
29
|
The recommended way to do this is to set `KEEN_PROJECT_ID` and `KEEN_API_KEY` in your
|
@@ -80,22 +80,40 @@ to resume processing immediately.
|
|
80
80
|
|
81
81
|
### Other code examples
|
82
82
|
|
83
|
-
|
83
|
+
#### Authentication
|
84
84
|
|
85
|
-
To configure
|
85
|
+
To configure keen-gem credentials in code, do as follows:
|
86
86
|
|
87
87
|
Keen.project_id = 'your-project-id'
|
88
88
|
Keen.api_key = 'your-api-key'
|
89
89
|
|
90
90
|
You can also configure individual client instances as follows:
|
91
91
|
|
92
|
-
keen =
|
93
|
-
|
92
|
+
keen = Keen::Client.new(:project_id => 'your-project-id',
|
93
|
+
:api_key => 'your-api-key')
|
94
94
|
|
95
|
-
|
95
|
+
#### em-synchrony
|
96
|
+
keen-gem can be used with [em-synchrony](https://github.com/igrigorik/em-synchrony).
|
97
|
+
If you call `publish_async` and `EM::Synchrony` is defined the method will return the response
|
98
|
+
directly. (It does not return the deferrable on which to register callbacks.) Likewise, it will raise
|
99
|
+
exceptions 'synchronously' should they happen.
|
96
100
|
|
97
|
-
|
98
|
-
|
101
|
+
#### Beacon URL's
|
102
|
+
|
103
|
+
It's possible to publish events to your Keen IO project using the HTTP GET method.
|
104
|
+
This is useful for situations like tracking email opens using [image beacons](http://en.wikipedia.org/wiki/Web_bug).
|
105
|
+
|
106
|
+
In this situation, the JSON event data is passed by encoding it base-64 and adding it as a request parameter called `data`.
|
107
|
+
The `beacon_url` method found on the `Keen::Client` does this for you. Here's an example:
|
108
|
+
|
109
|
+
keen = Keen::Client.new(:project_id => '12345',
|
110
|
+
:api_key => 'abcde')
|
111
|
+
|
112
|
+
keen.beacon_url("sign_ups", :recipient => "foo@foo.com")
|
113
|
+
# => "https://api.keen.io/3.0/projects/50e5ffa6897a2c319b000000/events/ \
|
114
|
+
email_opens?api_key=f806128f31c349fda124b62d1f4cf4b2&data=eyJyZWNpcGllbnQiOiJmb29AZm9vLmNvbSJ9"
|
115
|
+
|
116
|
+
To track email opens, simply add an image to your email template that points to this URL.
|
99
117
|
|
100
118
|
### Questions & Support
|
101
119
|
|
@@ -103,3 +121,6 @@ If you have any questions, bugs, or suggestions, please
|
|
103
121
|
report them via Github Issues. Or, come chat with us anytime
|
104
122
|
at [users.keen.io](http://users.keen.io). We'd love to hear your feedback and ideas!
|
105
123
|
|
124
|
+
### Contributing
|
125
|
+
keen-gem is an open source project and we welcome your contributions.
|
126
|
+
Fire away with issues and pull requests!
|
data/Rakefile
CHANGED
@@ -11,5 +11,15 @@ RSpec::Core::RakeTask.new(:integration) do |t|
|
|
11
11
|
t.pattern = "spec/integration/**/*_spec.rb"
|
12
12
|
end
|
13
13
|
|
14
|
+
desc "Run Rspec synchrony tests"
|
15
|
+
RSpec::Core::RakeTask.new(:synchrony) do |t|
|
16
|
+
t.pattern = "spec/synchrony/**/*_spec.rb"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Run Rspec pattern"
|
20
|
+
RSpec::Core::RakeTask.new(:pattern) do |t|
|
21
|
+
t.pattern = "spec/#{ENV['PATTERN']}/**/*_spec.rb"
|
22
|
+
end
|
23
|
+
|
14
24
|
task :default => :spec
|
15
25
|
task :test => [:spec]
|
data/lib/keen.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'forwardable'
|
3
|
-
require 'multi_json'
|
4
3
|
|
5
4
|
require 'keen/client'
|
6
5
|
|
@@ -23,7 +22,8 @@ module Keen
|
|
23
22
|
extend Forwardable
|
24
23
|
|
25
24
|
def_delegators :default_client, :project_id, :api_key,
|
26
|
-
:project_id=, :api_key=, :publish, :publish_async
|
25
|
+
:project_id=, :api_key=, :publish, :publish_async,
|
26
|
+
:beacon_url
|
27
27
|
|
28
28
|
attr_writer :logger
|
29
29
|
|
data/lib/keen/client.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
require 'keen/version'
|
2
1
|
require 'keen/http'
|
2
|
+
require 'keen/version'
|
3
|
+
require 'openssl'
|
4
|
+
require 'multi_json'
|
5
|
+
require 'base64'
|
3
6
|
|
4
7
|
module Keen
|
5
8
|
class Client
|
@@ -8,6 +11,7 @@ module Keen
|
|
8
11
|
CONFIG = {
|
9
12
|
:api_host => "api.keen.io",
|
10
13
|
:api_port => 443,
|
14
|
+
:api_version => "3.0",
|
11
15
|
:api_sync_http_options => {
|
12
16
|
:use_ssl => true,
|
13
17
|
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
@@ -20,6 +24,12 @@ module Keen
|
|
20
24
|
}
|
21
25
|
}
|
22
26
|
|
27
|
+
def beacon_url(event_name, properties)
|
28
|
+
json = MultiJson.encode(properties)
|
29
|
+
data = [json].pack("m0").tr("+/", "-_").gsub("\n", "")
|
30
|
+
"https://#{api_host}/#{api_version}/projects/#{@project_id}/events/#{event_name}?api_key=#{@api_key}&data=#{data}"
|
31
|
+
end
|
32
|
+
|
23
33
|
def initialize(*args)
|
24
34
|
options = args[0]
|
25
35
|
unless options.is_a?(Hash)
|
@@ -59,20 +69,29 @@ module Keen
|
|
59
69
|
:headers => api_headers_with_auth,
|
60
70
|
:body => MultiJson.encode(properties)
|
61
71
|
})
|
62
|
-
http.callback {
|
63
|
-
begin
|
64
|
-
response = process_response(http.response_header.status, http.response.chomp)
|
65
|
-
deferrable.succeed(response)
|
66
|
-
rescue Exception => e
|
67
|
-
deferrable.fail(e)
|
68
|
-
end
|
69
|
-
}
|
70
|
-
http.errback {
|
71
|
-
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
72
|
-
deferrable.fail(Error.new("Couldn't connect to Keen IO: #{http.error}"))
|
73
|
-
}
|
74
72
|
|
75
|
-
|
73
|
+
if defined?(EM::Synchrony)
|
74
|
+
if http.error
|
75
|
+
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
76
|
+
raise HttpError.new("Couldn't connect to Keen IO: #{http.error}")
|
77
|
+
else
|
78
|
+
process_response(http.response_header.status, http.response.chomp)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
http.callback {
|
82
|
+
begin
|
83
|
+
response = process_response(http.response_header.status, http.response.chomp)
|
84
|
+
deferrable.succeed(response)
|
85
|
+
rescue Exception => e
|
86
|
+
deferrable.fail(e)
|
87
|
+
end
|
88
|
+
}
|
89
|
+
http.errback {
|
90
|
+
Keen.logger.warn("Couldn't connect to Keen IO: #{http.error}")
|
91
|
+
deferrable.fail(Error.new("Couldn't connect to Keen IO: #{http.error}"))
|
92
|
+
}
|
93
|
+
deferrable
|
94
|
+
end
|
76
95
|
end
|
77
96
|
|
78
97
|
# deprecated
|
@@ -99,7 +118,7 @@ module Keen
|
|
99
118
|
end
|
100
119
|
|
101
120
|
def api_path(collection)
|
102
|
-
"/
|
121
|
+
"/#{api_version}/projects/#{project_id}/events/#{collection}"
|
103
122
|
end
|
104
123
|
|
105
124
|
def api_headers_with_auth
|
data/lib/keen/version.rb
CHANGED
data/spec/keen/client_spec.rb
CHANGED
@@ -7,24 +7,6 @@ describe Keen::Client do
|
|
7
7
|
let(:event_properties) { { "name" => "Bob" } }
|
8
8
|
let(:api_success) { { "created" => true } }
|
9
9
|
|
10
|
-
def stub_api(url, status, json_body)
|
11
|
-
stub_request(:post, url).to_return(
|
12
|
-
:status => status,
|
13
|
-
:body => MultiJson.encode(json_body))
|
14
|
-
end
|
15
|
-
|
16
|
-
def expect_post(url, event_properties, api_key)
|
17
|
-
WebMock.should have_requested(:post, url).with(
|
18
|
-
:body => MultiJson.encode(event_properties),
|
19
|
-
:headers => { "Content-Type" => "application/json",
|
20
|
-
"User-Agent" => "keen-gem v#{Keen::VERSION}",
|
21
|
-
"Authorization" => api_key })
|
22
|
-
end
|
23
|
-
|
24
|
-
def api_url(collection)
|
25
|
-
"https://api.keen.io/3.0/projects/#{project_id}/events/#{collection}"
|
26
|
-
end
|
27
|
-
|
28
10
|
describe "#initialize" do
|
29
11
|
context "deprecated" do
|
30
12
|
it "should allow created via project_id and api_key args" do
|
@@ -188,4 +170,12 @@ describe Keen::Client do
|
|
188
170
|
end
|
189
171
|
end
|
190
172
|
end
|
173
|
+
|
174
|
+
describe "beacon_url" do
|
175
|
+
it "should return a url with a base-64 encoded json param" do
|
176
|
+
client = Keen::Client.new(project_id, api_key)
|
177
|
+
client.beacon_url("sign_ups", { :name => "Bob" }).should ==
|
178
|
+
"https://api.keen.io/3.0/projects/12345/events/sign_ups?api_key=abcde&data=eyJuYW1lIjoiQm9iIn0="
|
179
|
+
end
|
180
|
+
end
|
191
181
|
end
|
data/spec/keen/keen_spec.rb
CHANGED
@@ -4,6 +4,7 @@ describe Keen do
|
|
4
4
|
describe "default client" do
|
5
5
|
describe "configuring from the environment" do
|
6
6
|
before do
|
7
|
+
Keen.instance_variable_set(:@default_client, nil)
|
7
8
|
ENV["KEEN_PROJECT_ID"] = "12345"
|
8
9
|
ENV["KEEN_API_KEY"] = "abcde"
|
9
10
|
end
|
@@ -17,11 +18,6 @@ describe Keen do
|
|
17
18
|
it "should set an api key from the environment" do
|
18
19
|
client.api_key.should == "abcde"
|
19
20
|
end
|
20
|
-
|
21
|
-
after do
|
22
|
-
ENV["KEEN_PROJECT_ID"] = nil
|
23
|
-
ENV["KEEN_API_KEY"] = nil
|
24
|
-
end
|
25
21
|
end
|
26
22
|
end
|
27
23
|
|
data/spec/spec_helper.rb
CHANGED
@@ -10,7 +10,27 @@ require 'em-http'
|
|
10
10
|
|
11
11
|
require File.expand_path("../../lib/keen", __FILE__)
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
module Keen::SpecHelpers
|
14
|
+
def stub_api(url, status, json_body)
|
15
|
+
stub_request(:post, url).to_return(
|
16
|
+
:status => status,
|
17
|
+
:body => MultiJson.encode(json_body))
|
18
|
+
end
|
19
|
+
|
20
|
+
def expect_post(url, event_properties, api_key)
|
21
|
+
WebMock.should have_requested(:post, url).with(
|
22
|
+
:body => MultiJson.encode(event_properties),
|
23
|
+
:headers => { "Content-Type" => "application/json",
|
24
|
+
"User-Agent" => "keen-gem v#{Keen::VERSION}",
|
25
|
+
"Authorization" => api_key })
|
26
|
+
end
|
27
|
+
|
28
|
+
def api_url(collection)
|
29
|
+
"https://api.keen.io/3.0/projects/#{project_id}/events/#{collection}"
|
15
30
|
end
|
16
31
|
end
|
32
|
+
|
33
|
+
RSpec.configure do |config|
|
34
|
+
config.include(Keen::SpecHelpers)
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
describe Keen::HTTP::Async do
|
4
|
+
let(:project_id) { "12345" }
|
5
|
+
let(:api_key) { "abcde" }
|
6
|
+
let(:collection) { "users" }
|
7
|
+
let(:event_properties) { { "name" => "Bob" } }
|
8
|
+
let(:api_success) { { "created" => true } }
|
9
|
+
|
10
|
+
describe "synchrony" do
|
11
|
+
before do
|
12
|
+
@client = Keen::Client.new(
|
13
|
+
:project_id => project_id,
|
14
|
+
:api_key => api_key)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "success" do
|
18
|
+
it "should post the event data" do
|
19
|
+
stub_api(api_url(collection), 201, api_success)
|
20
|
+
EM.synchrony {
|
21
|
+
@client.publish_async(collection, event_properties)
|
22
|
+
expect_post(api_url(collection), event_properties, api_key)
|
23
|
+
EM.stop
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should recieve the right response 'synchronously'" do
|
28
|
+
stub_api(api_url(collection), 201, api_success)
|
29
|
+
EM.synchrony {
|
30
|
+
@client.publish_async(collection, event_properties).should == api_success
|
31
|
+
EM.stop
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "failure" do
|
37
|
+
it "should raise an exception" do
|
38
|
+
stub_request(:post, api_url(collection)).to_timeout
|
39
|
+
e = nil
|
40
|
+
EM.synchrony {
|
41
|
+
begin
|
42
|
+
@client.publish_async(collection, event_properties).should == api_success
|
43
|
+
rescue Exception => exception
|
44
|
+
e = exception
|
45
|
+
end
|
46
|
+
e.class.should == Keen::HttpError
|
47
|
+
e.message.should == "Couldn't connect to Keen IO: WebMock timeout error"
|
48
|
+
EM.stop
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
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.4.
|
4
|
+
version: 0.4.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-01-
|
13
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: multi_json
|
@@ -54,6 +54,8 @@ files:
|
|
54
54
|
- spec/keen/keen_spec.rb
|
55
55
|
- spec/keen/spec_helper.rb
|
56
56
|
- spec/spec_helper.rb
|
57
|
+
- spec/synchrony/spec_helper.rb
|
58
|
+
- spec/synchrony/synchrony_spec.rb
|
57
59
|
homepage: https://github.com/keenlabs/keen-gem
|
58
60
|
licenses: []
|
59
61
|
post_install_message:
|
@@ -85,3 +87,5 @@ test_files:
|
|
85
87
|
- spec/keen/keen_spec.rb
|
86
88
|
- spec/keen/spec_helper.rb
|
87
89
|
- spec/spec_helper.rb
|
90
|
+
- spec/synchrony/spec_helper.rb
|
91
|
+
- spec/synchrony/synchrony_spec.rb
|