mixpanel_client 3.0.0 → 3.1.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/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
|