mixpanel_client 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +38 -14
- data/lib/mixpanel/client.rb +37 -4
- data/lib/mixpanel/exceptions.rb +1 -0
- data/lib/mixpanel/version.rb +1 -1
- data/manual_test/basic.rb +7 -8
- data/manual_test/parallel.rb +25 -0
- data/mixpanel_client.gemspec +2 -2
- data/spec/mixpanel_client/mixpanel_client_spec.rb +79 -0
- metadata +35 -18
data/README.md
CHANGED
@@ -21,26 +21,46 @@ or if you use a Gemfile
|
|
21
21
|
client = Mixpanel::Client.new(config)
|
22
22
|
|
23
23
|
data = client.request('events/properties', {
|
24
|
-
|
25
|
-
|
26
|
-
name: 'hello',
|
24
|
+
event: 'splash features',
|
25
|
+
name: 'feature',
|
27
26
|
values: '["uno", "dos"]',
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
interval: 24,
|
27
|
+
type: 'unique',
|
28
|
+
unit: 'day',
|
29
|
+
interval: 7,
|
32
30
|
limit: 5,
|
33
|
-
bucket: 'contents',
|
34
|
-
from_date: '2011-08-11',
|
35
|
-
to_date: '2011-08-12',
|
36
|
-
on: 'properties["product_id"]',
|
37
|
-
where: '1 in properties["product_id"]',
|
38
|
-
buckets: '5',
|
39
|
-
# etc.
|
40
31
|
})
|
41
32
|
|
42
33
|
puts data.inspect
|
43
34
|
|
35
|
+
## Parallel
|
36
|
+
|
37
|
+
require 'rubygems'
|
38
|
+
require 'mixpanel_client'
|
39
|
+
|
40
|
+
config = {api_key: 'changeme', api_secret: 'changeme', parallel: true}
|
41
|
+
client = Mixpanel::Client.new(config)
|
42
|
+
|
43
|
+
first_request = client.request('events/properties', {
|
44
|
+
...
|
45
|
+
})
|
46
|
+
|
47
|
+
second_request = client.request('events/properties', {
|
48
|
+
...
|
49
|
+
})
|
50
|
+
|
51
|
+
third_request = client.request('events/properties', {
|
52
|
+
...
|
53
|
+
})
|
54
|
+
|
55
|
+
...
|
56
|
+
|
57
|
+
client.run_parallel_requests
|
58
|
+
|
59
|
+
puts first_request.response.handled_response
|
60
|
+
puts second_request.response.handled_response
|
61
|
+
puts third_request.response.handled_response
|
62
|
+
|
63
|
+
|
44
64
|
## Development
|
45
65
|
List of rake tasks.
|
46
66
|
|
@@ -74,6 +94,10 @@ Create tag v2.0.2 and build and push mixpanel_client-2.0.2.gem to Rubygems
|
|
74
94
|
|
75
95
|
## Changelog
|
76
96
|
|
97
|
+
|
98
|
+
### v3.1.0
|
99
|
+
* Parallel requests option.
|
100
|
+
|
77
101
|
### v.3.0.0
|
78
102
|
* NOTE: This version breaks backwards compatibility.
|
79
103
|
* Use a regular ruby hash instead of metaprogramming for mixpanel options.
|
data/lib/mixpanel/client.rb
CHANGED
@@ -13,7 +13,7 @@ module Mixpanel
|
|
13
13
|
DATA_URI = 'https://data.mixpanel.com/api/2.0'
|
14
14
|
|
15
15
|
attr_reader :uri
|
16
|
-
attr_accessor :api_key, :api_secret
|
16
|
+
attr_accessor :api_key, :api_secret, :parallel
|
17
17
|
|
18
18
|
# Configure the client
|
19
19
|
#
|
@@ -25,6 +25,7 @@ module Mixpanel
|
|
25
25
|
def initialize(config)
|
26
26
|
@api_key = config[:api_key]
|
27
27
|
@api_secret = config[:api_secret]
|
28
|
+
@parallel = config[:parallel] || false
|
28
29
|
end
|
29
30
|
|
30
31
|
# Return mixpanel data as a JSON object or CSV string
|
@@ -47,9 +48,41 @@ module Mixpanel
|
|
47
48
|
def request(resource, options)
|
48
49
|
@format = options[:format] || :json
|
49
50
|
@uri = URI.mixpanel(resource, normalize_options(options))
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
if @parallel
|
52
|
+
parallel_request = prepare_parallel_request
|
53
|
+
hydra.queue parallel_request
|
54
|
+
parallel_request
|
55
|
+
else
|
56
|
+
response = URI.get(@uri)
|
57
|
+
response = %Q|[#{response.split("\n").join(',')}]| if resource == 'export'
|
58
|
+
Utils.to_hash(response, @format)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def prepare_parallel_request
|
63
|
+
request = ::Typhoeus::Request.new(@uri)
|
64
|
+
request.on_complete do |response|
|
65
|
+
if response.success?
|
66
|
+
Utils.to_hash(response.body, @format)
|
67
|
+
elsif response.timed_out?
|
68
|
+
raise TimeoutError
|
69
|
+
elsif response.code == 0
|
70
|
+
# Could not get an http response, something's wrong.
|
71
|
+
raise HTTPError, response.curl_error_message
|
72
|
+
else
|
73
|
+
# Received a non-successful http response.
|
74
|
+
raise HTTPError, response.body.present? ? JSON.parse(response.body)['error'] : response.code.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
request
|
78
|
+
end
|
79
|
+
|
80
|
+
def run_parallel_requests
|
81
|
+
hydra.run
|
82
|
+
end
|
83
|
+
|
84
|
+
def hydra
|
85
|
+
@hydra ||= ::Typhoeus::Hydra.new
|
53
86
|
end
|
54
87
|
|
55
88
|
private
|
data/lib/mixpanel/exceptions.rb
CHANGED
data/lib/mixpanel/version.rb
CHANGED
data/manual_test/basic.rb
CHANGED
@@ -6,14 +6,13 @@ require 'yaml'
|
|
6
6
|
|
7
7
|
config = YAML.load_file(File.dirname(__FILE__) + '/../config/mixpanel.yml')['mixpanel']
|
8
8
|
|
9
|
-
client = Mixpanel::Client.new(config)
|
9
|
+
client = Mixpanel::Client.new({api_key: config['api_key'], api_secret: config['api_secret']})
|
10
10
|
|
11
|
-
data = client.request
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
11
|
+
data = client.request('events/properties', {
|
12
|
+
event: '["test-event"]',
|
13
|
+
type: 'general',
|
14
|
+
unit: 'hour',
|
15
|
+
name: 'test'
|
16
|
+
})
|
18
17
|
|
19
18
|
puts data.inspect
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'mixpanel_client'
|
5
|
+
require 'yaml'
|
6
|
+
require 'typhoeus'
|
7
|
+
|
8
|
+
config = YAML.load_file(File.dirname(__FILE__) + '/../config/mixpanel.yml')['mixpanel']
|
9
|
+
|
10
|
+
client = Mixpanel::Client.new({:api_key => config['api_key'], :api_secret => config['api_secret'], :parallel => true})
|
11
|
+
|
12
|
+
f = client.request('events/top', {
|
13
|
+
:type => 'general'
|
14
|
+
})
|
15
|
+
|
16
|
+
|
17
|
+
s = client.request('events/names', {
|
18
|
+
:type => 'general'
|
19
|
+
})
|
20
|
+
|
21
|
+
client.run_parallel_requests
|
22
|
+
|
23
|
+
puts f.response.handled_response.inspect
|
24
|
+
puts s.response.handled_response.inspect
|
25
|
+
|
data/mixpanel_client.gemspec
CHANGED
@@ -18,11 +18,11 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ['lib']
|
21
|
-
|
22
21
|
s.add_runtime_dependency('json', '~> 1.6') if RUBY_VERSION < '1.9'
|
22
|
+
s.add_runtime_dependency('typhoeus', '~> 0.5.4')
|
23
23
|
s.add_development_dependency('bundler', '>=1.2')
|
24
24
|
s.add_development_dependency('rake', '>=0.9.2.2')
|
25
25
|
s.add_development_dependency('rdoc', '>=3.11')
|
26
26
|
s.add_development_dependency('rspec', '>=2.5.0')
|
27
|
-
s.add_development_dependency('webmock', '>=1.
|
27
|
+
s.add_development_dependency('webmock', '>=1.9.0')
|
28
28
|
end
|
@@ -10,6 +10,14 @@ describe Mixpanel::Client do
|
|
10
10
|
it 'should not raise an exception if a hash is given' do
|
11
11
|
Mixpanel::Client.new('api_key' => 'test_key', 'api_secret' => 'test_secret').should_not raise_error(ArgumentError)
|
12
12
|
end
|
13
|
+
|
14
|
+
it 'should set a parallel option as false by default' do
|
15
|
+
Mixpanel::Client.new(:api_key => 'test_key', :api_secret => 'test_secret').parallel.should == false
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should be able to set a parallel option when passed' do
|
19
|
+
Mixpanel::Client.new(:api_key => 'test_key', :api_secret => 'test_secret', :parallel => true).parallel.should == true
|
20
|
+
end
|
13
21
|
end
|
14
22
|
|
15
23
|
context 'when making an invalid request' do
|
@@ -50,6 +58,76 @@ describe Mixpanel::Client do
|
|
50
58
|
})
|
51
59
|
data.should == {"events"=>[], "type"=>"general"}
|
52
60
|
end
|
61
|
+
|
62
|
+
context "with parallel option enabled" do
|
63
|
+
before :all do
|
64
|
+
@parallel_client = Mixpanel::Client.new(:api_key => 'test_key', :api_secret => 'test_secret', :parallel => true)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return Typhoeus::Request" do
|
68
|
+
# Stub Mixpanel request
|
69
|
+
stub_request(:get, /^#{@uri}.*/).to_return(:body => '{"legend_size": 0, "data": {"series": [], "values": {}}}')
|
70
|
+
|
71
|
+
# No endpoint
|
72
|
+
data = @parallel_client.request('events', {
|
73
|
+
:event => '["test-event"]',
|
74
|
+
:unit => 'hour',
|
75
|
+
:interval => 24
|
76
|
+
})
|
77
|
+
data.should be_a Typhoeus::Request
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#hydra' do
|
81
|
+
it 'should return a Typhoeus::Hydra object' do
|
82
|
+
@parallel_client.hydra.should be_a Typhoeus::Hydra
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#run_parallel_requests' do
|
87
|
+
it 'should run queued requests' do
|
88
|
+
# Stub Mixpanel request
|
89
|
+
stub_request(:any, /^#{@uri}.*/).to_return(:body => '{"legend_size": 1, "data": {"series": ["2010-05-29","2010-05-30","2010-05-31"],
|
90
|
+
"values": {
|
91
|
+
"account-page": {"2010-05-30": 1},
|
92
|
+
"splash features": {"2010-05-29": 6,
|
93
|
+
"2010-05-30": 4,
|
94
|
+
"2010-05-31": 5
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}')
|
99
|
+
|
100
|
+
|
101
|
+
stub_request(:any, /^#{@uri}.*secondevent.*/).to_return(:body => '{"legend_size": 2, "data": {"series": ["2010-05-29","2010-05-30","2010-05-31"],
|
102
|
+
"values": {
|
103
|
+
"account-page": {"2010-05-30": 2},
|
104
|
+
"splash features": {"2010-05-29": 8,
|
105
|
+
"2010-05-30": 6,
|
106
|
+
"2010-05-31": 7
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}')
|
111
|
+
|
112
|
+
first_request = @parallel_client.request('events', {
|
113
|
+
:event => '["firstevent"]',
|
114
|
+
:unit => 'day'
|
115
|
+
})
|
116
|
+
|
117
|
+
|
118
|
+
second_request = @parallel_client.request('events', {
|
119
|
+
:event => '["secondevent"]',
|
120
|
+
:unit => 'day'
|
121
|
+
})
|
122
|
+
|
123
|
+
@parallel_client.run_parallel_requests
|
124
|
+
|
125
|
+
first_request.response.handled_response.should == {"data"=>{"series"=>["2010-05-29", "2010-05-30", "2010-05-31"], "values"=>{"splash features"=>{"2010-05-29"=>6, "2010-05-30"=>4, "2010-05-31"=>5}, "account-page"=>{"2010-05-30"=>1}}}, "legend_size"=>1}
|
126
|
+
|
127
|
+
second_request.response.handled_response.should == {"data"=>{"series"=>["2010-05-29", "2010-05-30", "2010-05-31"], "values"=>{"splash features"=>{"2010-05-29"=>8, "2010-05-30"=>6, "2010-05-31"=>7}, "account-page"=>{"2010-05-30"=>2}}}, "legend_size"=>2}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
53
131
|
end
|
54
132
|
|
55
133
|
describe '#hash_args' do
|
@@ -65,4 +143,5 @@ describe Mixpanel::Client do
|
|
65
143
|
Mixpanel::Client::Utils.to_hash('{"a" : "ey", "b" : "bee"}', :json).should == {'a' => 'ey', 'b' => 'bee'}
|
66
144
|
end
|
67
145
|
end
|
146
|
+
|
68
147
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixpanel_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 3
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 3.0.0
|
10
|
+
version: 3.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Keolo Keagy
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2013-02-05 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: json
|
@@ -33,9 +33,25 @@ dependencies:
|
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: typhoeus
|
37
37
|
prerelease: false
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 5
|
47
|
+
- 4
|
48
|
+
version: 0.5.4
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: bundler
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
55
|
none: false
|
40
56
|
requirements:
|
41
57
|
- - ">="
|
@@ -46,11 +62,11 @@ dependencies:
|
|
46
62
|
- 2
|
47
63
|
version: "1.2"
|
48
64
|
type: :development
|
49
|
-
version_requirements: *
|
65
|
+
version_requirements: *id003
|
50
66
|
- !ruby/object:Gem::Dependency
|
51
67
|
name: rake
|
52
68
|
prerelease: false
|
53
|
-
requirement: &
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
54
70
|
none: false
|
55
71
|
requirements:
|
56
72
|
- - ">="
|
@@ -63,11 +79,11 @@ dependencies:
|
|
63
79
|
- 2
|
64
80
|
version: 0.9.2.2
|
65
81
|
type: :development
|
66
|
-
version_requirements: *
|
82
|
+
version_requirements: *id004
|
67
83
|
- !ruby/object:Gem::Dependency
|
68
84
|
name: rdoc
|
69
85
|
prerelease: false
|
70
|
-
requirement: &
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
71
87
|
none: false
|
72
88
|
requirements:
|
73
89
|
- - ">="
|
@@ -78,11 +94,11 @@ dependencies:
|
|
78
94
|
- 11
|
79
95
|
version: "3.11"
|
80
96
|
type: :development
|
81
|
-
version_requirements: *
|
97
|
+
version_requirements: *id005
|
82
98
|
- !ruby/object:Gem::Dependency
|
83
99
|
name: rspec
|
84
100
|
prerelease: false
|
85
|
-
requirement: &
|
101
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
86
102
|
none: false
|
87
103
|
requirements:
|
88
104
|
- - ">="
|
@@ -94,23 +110,23 @@ dependencies:
|
|
94
110
|
- 0
|
95
111
|
version: 2.5.0
|
96
112
|
type: :development
|
97
|
-
version_requirements: *
|
113
|
+
version_requirements: *id006
|
98
114
|
- !ruby/object:Gem::Dependency
|
99
115
|
name: webmock
|
100
116
|
prerelease: false
|
101
|
-
requirement: &
|
117
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
102
118
|
none: false
|
103
119
|
requirements:
|
104
120
|
- - ">="
|
105
121
|
- !ruby/object:Gem::Version
|
106
|
-
hash:
|
122
|
+
hash: 51
|
107
123
|
segments:
|
108
124
|
- 1
|
109
|
-
-
|
110
|
-
-
|
111
|
-
version: 1.
|
125
|
+
- 9
|
126
|
+
- 0
|
127
|
+
version: 1.9.0
|
112
128
|
type: :development
|
113
|
-
version_requirements: *
|
129
|
+
version_requirements: *id007
|
114
130
|
description: Simple ruby client interface to the Mixpanel API.
|
115
131
|
email:
|
116
132
|
- keolo@dreampointmedia.com
|
@@ -136,6 +152,7 @@ files:
|
|
136
152
|
- lib/mixpanel/version.rb
|
137
153
|
- lib/mixpanel_client.rb
|
138
154
|
- manual_test/basic.rb
|
155
|
+
- manual_test/parallel.rb
|
139
156
|
- mixpanel_client.gemspec
|
140
157
|
- spec/mixpanel_client/events_externalspec.rb
|
141
158
|
- spec/mixpanel_client/mixpanel_client_spec.rb
|