embulk-input-mixpanel 0.5.14 → 0.5.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/CHANGELOG.md +5 -1
- data/README.md +0 -3
- data/embulk-input-mixpanel.gemspec +2 -2
- data/lib/embulk/input/mixpanel.rb +2 -7
- data/lib/embulk/input/mixpanel_api/client.rb +5 -23
- data/test/embulk/input/mixpanel_api/test_client.rb +27 -31
- data/test/embulk/input/test_mixpanel.rb +0 -15
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c2a00332d19da50d63a726cac679e745206ccab
|
4
|
+
data.tar.gz: f2810c25272ee6b001f206dd0ddd93895c247ab6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 062a5d9d8948ba9efe802b477756484f03add6ce542d9bdbf40ee3988c2c943f5f6445fc32b15d05dfd0b909761fbf4f47f530e0e2d1357b1a57ca0c20074c55
|
7
|
+
data.tar.gz: df58ccf3ab6acad568681d57c39e97258849dc6e3946f5367ccdf31d64265d8c6d6afbb724259b66d21003b670b1763b6e097a0e871ff9bdaeb9e396f5e1b0cc
|
data/.travis.yml
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
|
-
|
3
|
+
dist: trusty
|
4
|
+
|
5
|
+
jdk: openjdk8
|
6
|
+
|
4
7
|
sudo: false
|
5
8
|
|
6
9
|
addons:
|
@@ -15,9 +18,9 @@ before_install:
|
|
15
18
|
ruby -v
|
16
19
|
rvm get head
|
17
20
|
rvm use jruby-9.0.5.0 --install
|
18
|
-
gem install bundler
|
21
|
+
gem install bundler -v '< 2'
|
19
22
|
ruby -v
|
20
|
-
- gem
|
23
|
+
- gem install bundler -v '< 2'
|
21
24
|
|
22
25
|
rvm:
|
23
26
|
- jruby-9.0.5.0
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
## 0.5.15 - 2020-01-22
|
2
|
+
|
3
|
+
* [enhancement] Update the authentication method to latest [#63](https://github.com/treasure-data/embulk-input-mixpanel/pull/63)
|
4
|
+
|
1
5
|
## 0.5.14 - 2018-10-22
|
2
6
|
|
3
|
-
* [enhancement] Handle the wrong period during transition from standard to daylight saving time exception [#
|
7
|
+
* [enhancement] Handle the wrong period during transition from standard to daylight saving time exception [#62](https://github.com/treasure-data/embulk-input-mixpanel/pull/62)
|
4
8
|
|
5
9
|
## 0.5.13 - 2018-10-04
|
6
10
|
|
data/README.md
CHANGED
@@ -31,7 +31,6 @@ To get it, you should log in mixpanel website, and click gear icon at the lower
|
|
31
31
|
|
32
32
|
### Configuration
|
33
33
|
|
34
|
-
- **api_key**: project API Key (string, required)
|
35
34
|
- **api_secret**: project API Secret (string, required)
|
36
35
|
- **export_endpoint**: the Data Export API's endpoint (string, default to "http://data.mixpanel.com/api/2.0/export")
|
37
36
|
- **timezone**: project timezone(string, required)
|
@@ -69,7 +68,6 @@ If you have such data and set config.yml as below.
|
|
69
68
|
```yaml
|
70
69
|
in:
|
71
70
|
type: mixpanel
|
72
|
-
api_key: "API_KEY"
|
73
71
|
api_secret: "API_SECRET"
|
74
72
|
timezone: "US/Pacific"
|
75
73
|
from_date: "2015-07-19"
|
@@ -102,7 +100,6 @@ in:
|
|
102
100
|
```yaml
|
103
101
|
in:
|
104
102
|
type: mixpanel
|
105
|
-
api_key: "API_KEY"
|
106
103
|
api_secret: "API_SECRET"
|
107
104
|
timezone: "US/Pacific"
|
108
105
|
from_date: "2015-07-19"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "embulk-input-mixpanel"
|
3
|
-
spec.version = "0.5.
|
3
|
+
spec.version = "0.5.15"
|
4
4
|
spec.authors = ["yoshihara", "uu59"]
|
5
5
|
spec.summary = "Mixpanel input plugin for Embulk"
|
6
6
|
spec.description = "Loads records from Mixpanel."
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.require_paths = ["lib"]
|
14
14
|
|
15
15
|
spec.add_dependency 'httpclient', '>= 2.8.3' # To use tcp_keepalive
|
16
|
-
spec.add_dependency 'tzinfo'
|
16
|
+
spec.add_dependency 'tzinfo', '1.2.5' # to avoid failure in when upgrade to 1.2.6 https://github.com/tzinfo/tzinfo/issues/114
|
17
17
|
spec.add_dependency 'perfect_retry', ["~> 0.5"]
|
18
18
|
spec.add_dependency 'activesupport'
|
19
19
|
spec.add_development_dependency 'bundler', ['~> 1.0']
|
@@ -61,7 +61,6 @@ module Embulk
|
|
61
61
|
dates: range,
|
62
62
|
timezone: timezone,
|
63
63
|
export_endpoint: export_endpoint(config),
|
64
|
-
api_key: config.param(:api_key, :string),
|
65
64
|
api_secret: config.param(:api_secret, :string),
|
66
65
|
schema: config.param(:columns, :array),
|
67
66
|
fetch_unknown_columns: fetch_unknown_columns,
|
@@ -129,8 +128,7 @@ module Embulk
|
|
129
128
|
retry_initial_wait_sec: config.param(:retry_initial_wait_sec, :integer, default: 1),
|
130
129
|
retry_limit: config.param(:retry_limit, :integer, default: 5),
|
131
130
|
})
|
132
|
-
client = MixpanelApi::Client.new(config.param(:
|
133
|
-
config.param(:api_secret, :string),
|
131
|
+
client = MixpanelApi::Client.new(config.param(:api_secret, :string),
|
134
132
|
retryer,
|
135
133
|
export_endpoint(config))
|
136
134
|
|
@@ -162,7 +160,6 @@ module Embulk
|
|
162
160
|
|
163
161
|
def init
|
164
162
|
@export_endpoint = task[:export_endpoint]
|
165
|
-
@api_key = task[:api_key]
|
166
163
|
@api_secret = task[:api_secret]
|
167
164
|
@params = task[:params]
|
168
165
|
@timezone = task[:timezone]
|
@@ -310,7 +307,7 @@ module Embulk
|
|
310
307
|
)
|
311
308
|
end
|
312
309
|
Embulk.logger.info "Where params is #{params["where"]}"
|
313
|
-
client = MixpanelApi::Client.new(@
|
310
|
+
client = MixpanelApi::Client.new(@api_secret, self.class.perfect_retry(task), @export_endpoint)
|
314
311
|
|
315
312
|
if preview?
|
316
313
|
client.export_for_small_dataset(params)
|
@@ -342,9 +339,7 @@ module Embulk
|
|
342
339
|
def self.export_params(config)
|
343
340
|
event = config.param(:event, :array, default: nil)
|
344
341
|
event = event.nil? ? nil : event.to_json
|
345
|
-
|
346
342
|
{
|
347
|
-
api_key: config.param(:api_key, :string),
|
348
343
|
event: event,
|
349
344
|
where: config.param(:where, :string, default: nil),
|
350
345
|
bucket: config.param(:bucket, :string, default: nil),
|
@@ -29,7 +29,9 @@ module Embulk
|
|
29
29
|
begin
|
30
30
|
retryer.with_retry do
|
31
31
|
client = HTTPClient.new
|
32
|
+
client.force_basic_auth = true
|
32
33
|
client.connect_timeout = PING_TIMEOUT_SECONDS
|
34
|
+
client.set_auth(nil, @api_secret, nil)
|
33
35
|
client.get(URI.join(endpoint, '/'))
|
34
36
|
end
|
35
37
|
true
|
@@ -38,9 +40,8 @@ module Embulk
|
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
def initialize(
|
43
|
+
def initialize(api_secret, retryer = nil, endpoint = DEFAULT_EXPORT_ENDPOINT)
|
42
44
|
@endpoint = endpoint
|
43
|
-
@api_key = api_key
|
44
45
|
@api_secret = api_secret
|
45
46
|
@retryer = retryer || PerfectRetry.new do |config|
|
46
47
|
# for test
|
@@ -100,7 +101,6 @@ module Embulk
|
|
100
101
|
def request(params, &block)
|
101
102
|
# https://mixpanel.com/docs/api-documentation/exporting-raw-data-you-inserted-into-mixpanel
|
102
103
|
Embulk.logger.debug "Export param: #{params.to_s}"
|
103
|
-
set_signatures(params)
|
104
104
|
|
105
105
|
buf = ""
|
106
106
|
error_response = ''
|
@@ -133,7 +133,6 @@ module Embulk
|
|
133
133
|
# guess/preview
|
134
134
|
# Try to fetch first number of records
|
135
135
|
params["limit"] = num_of_records
|
136
|
-
set_signatures(params)
|
137
136
|
Embulk.logger.info "Sending request to #{@endpoint}"
|
138
137
|
res = httpclient.get(@endpoint, params)
|
139
138
|
handle_error(res,res.body)
|
@@ -154,25 +153,6 @@ module Embulk
|
|
154
153
|
end
|
155
154
|
end
|
156
155
|
|
157
|
-
def set_signatures(params)
|
158
|
-
params[:expire] ||= Time.now.to_i + TIMEOUT_SECONDS
|
159
|
-
params[:sig] = signature(params)
|
160
|
-
params
|
161
|
-
end
|
162
|
-
|
163
|
-
def signature(params)
|
164
|
-
# https://mixpanel.com/docs/api-documentation/data-export-api#auth-implementation
|
165
|
-
params.delete(:sig)
|
166
|
-
sorted_keys = params.keys.map(&:to_s).sort
|
167
|
-
signature = sorted_keys.inject("") do |sig, key|
|
168
|
-
value = params[key] || params[key.to_sym]
|
169
|
-
next sig unless value
|
170
|
-
sig << "#{key}=#{value}"
|
171
|
-
end
|
172
|
-
|
173
|
-
Digest::MD5.hexdigest(signature + @api_secret)
|
174
|
-
end
|
175
|
-
|
176
156
|
def httpclient
|
177
157
|
@client ||=
|
178
158
|
begin
|
@@ -181,6 +161,8 @@ module Embulk
|
|
181
161
|
client.tcp_keepalive = true
|
182
162
|
client.default_header = {Accept: "application/json; charset=UTF-8"}
|
183
163
|
# client.debug_dev = STDERR
|
164
|
+
client.force_basic_auth = true
|
165
|
+
client.set_auth(nil, @api_secret, nil);
|
184
166
|
client
|
185
167
|
end
|
186
168
|
end
|
@@ -8,49 +8,28 @@ module Embulk
|
|
8
8
|
class ClientTest < Test::Unit::TestCase
|
9
9
|
include OverrideAssertRaise
|
10
10
|
|
11
|
-
API_KEY = "api_key".freeze
|
12
11
|
API_SECRET = "api_secret".freeze
|
13
12
|
|
14
13
|
def setup
|
15
|
-
@client = Client.new(
|
14
|
+
@client = Client.new(API_SECRET)
|
16
15
|
stub(Embulk).logger { ::Logger.new(IO::NULL) }
|
17
16
|
end
|
18
17
|
|
19
|
-
# NOTE: Client#signature is private method but this value
|
20
|
-
# can't be checked via other methods.
|
21
|
-
def test_signature
|
22
|
-
now = Time.parse("2015-07-22 00:00:00")
|
23
|
-
stub(Time).now { now }
|
24
|
-
|
25
|
-
params = {
|
26
|
-
string: "string",
|
27
|
-
array: ["elem1", "elem2"],
|
28
|
-
}
|
29
|
-
expected = "4be4a4f92f57e12b543a2a5f2f5897b6"
|
30
|
-
|
31
|
-
assert_equal(expected, @client.__send__(:signature, params))
|
32
|
-
end
|
33
|
-
|
34
18
|
class TestKeepAlive < self
|
35
19
|
def test_tcp_keepalive_enabled
|
36
|
-
client = Client.new(
|
20
|
+
client = Client.new(API_SECRET)
|
37
21
|
assert client.send(:httpclient).tcp_keepalive
|
38
22
|
end
|
39
23
|
end
|
40
24
|
|
41
25
|
class TryToDatesTest < self
|
42
26
|
def setup
|
43
|
-
@client = Client.new(
|
27
|
+
@client = Client.new(API_SECRET)
|
44
28
|
end
|
45
29
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
["2010-01-01", "2010-01-01"],
|
50
|
-
["3 days ago", (Date.today - 3).to_s],
|
51
|
-
]
|
52
|
-
end
|
53
|
-
def test_candidates(from_str)
|
30
|
+
|
31
|
+
def test_candidates_case1
|
32
|
+
from_str = "2000-01-01"
|
54
33
|
from = Date.parse(from_str)
|
55
34
|
yesterday = Date.today - 1
|
56
35
|
dates = @client.try_to_dates(from.to_s)
|
@@ -66,6 +45,24 @@ module Embulk
|
|
66
45
|
assert_equal expect, dates
|
67
46
|
assert dates.all?{|d| d <= yesterday}
|
68
47
|
end
|
48
|
+
|
49
|
+
def test_candidates_case2
|
50
|
+
from_str = (Date.today - 3).to_s
|
51
|
+
from = Date.parse(from_str)
|
52
|
+
yesterday = Date.today - 1
|
53
|
+
dates = @client.try_to_dates(from.to_s)
|
54
|
+
expect = [
|
55
|
+
from + 1,
|
56
|
+
from + 10,
|
57
|
+
from + 100,
|
58
|
+
from + 1000,
|
59
|
+
from + 10000,
|
60
|
+
yesterday,
|
61
|
+
].find_all{|d| d <= yesterday}
|
62
|
+
|
63
|
+
assert_equal expect, dates
|
64
|
+
assert dates.all?{|d| d <= yesterday}
|
65
|
+
end
|
69
66
|
end
|
70
67
|
|
71
68
|
class ExportTest < self
|
@@ -77,7 +74,7 @@ module Embulk
|
|
77
74
|
|
78
75
|
def test_success
|
79
76
|
stub_client
|
80
|
-
stub(@client).set_signatures(anything) {}
|
77
|
+
# stub(@client).set_signatures(anything) {}
|
81
78
|
stub_response(success_response)
|
82
79
|
|
83
80
|
records = []
|
@@ -90,7 +87,7 @@ module Embulk
|
|
90
87
|
|
91
88
|
def test_export_partial_with_export_terminated_early
|
92
89
|
stub_client
|
93
|
-
stub(@client).set_signatures(anything) {}
|
90
|
+
# stub(@client).set_signatures(anything) {}
|
94
91
|
stub_response(Struct.new(:code, :body).new(200, jsonl_dummy_responses+"\nexport terminated early"))
|
95
92
|
|
96
93
|
records = []
|
@@ -104,7 +101,7 @@ module Embulk
|
|
104
101
|
|
105
102
|
def test_export_partial_with_error_json
|
106
103
|
stub_client
|
107
|
-
stub(@client).set_signatures(anything) {}
|
104
|
+
# stub(@client).set_signatures(anything) {}
|
108
105
|
stub_response(Struct.new(:code, :body).new(200, jsonl_dummy_responses+"\n{\"error\":"))
|
109
106
|
records = []
|
110
107
|
assert_raise MixpanelApi::IncompleteExportResponseError do
|
@@ -203,7 +200,6 @@ module Embulk
|
|
203
200
|
|
204
201
|
def params
|
205
202
|
{
|
206
|
-
"api_key" => API_KEY,
|
207
203
|
"api_secret" => API_SECRET,
|
208
204
|
"from_date" => "2015-01-01",
|
209
205
|
"to_date" => "2015-03-02",
|
@@ -9,7 +9,6 @@ module Embulk
|
|
9
9
|
class MixpanelTest < Test::Unit::TestCase
|
10
10
|
include OverrideAssertRaise
|
11
11
|
|
12
|
-
API_KEY = "api_key".freeze
|
13
12
|
API_SECRET = "api_secret".freeze
|
14
13
|
FROM_DATE = "2015-02-22".freeze
|
15
14
|
TO_DATE = "2015-03-02".freeze
|
@@ -31,7 +30,6 @@ module Embulk
|
|
31
30
|
|
32
31
|
def setup_client
|
33
32
|
params = {
|
34
|
-
api_key: API_KEY,
|
35
33
|
event: nil,
|
36
34
|
where: nil,
|
37
35
|
bucket: nil,
|
@@ -72,7 +70,6 @@ module Embulk
|
|
72
70
|
def test_from_date_old_date
|
73
71
|
config = {
|
74
72
|
type: "mixpanel",
|
75
|
-
api_key: API_KEY,
|
76
73
|
api_secret: API_SECRET,
|
77
74
|
from_date: FROM_DATE,
|
78
75
|
}
|
@@ -87,7 +84,6 @@ module Embulk
|
|
87
84
|
def test_from_date_future
|
88
85
|
config = {
|
89
86
|
type: "mixpanel",
|
90
|
-
api_key: API_KEY,
|
91
87
|
api_secret: API_SECRET,
|
92
88
|
timezone: TIMEZONE,
|
93
89
|
from_date: (today + 1).to_s
|
@@ -103,7 +99,6 @@ module Embulk
|
|
103
99
|
from_date = (today - 1).to_s
|
104
100
|
config = {
|
105
101
|
type: "mixpanel",
|
106
|
-
api_key: API_KEY,
|
107
102
|
api_secret: API_SECRET,
|
108
103
|
from_date: from_date,
|
109
104
|
}
|
@@ -117,7 +112,6 @@ module Embulk
|
|
117
112
|
def test_no_from_date
|
118
113
|
config = {
|
119
114
|
type: "mixpanel",
|
120
|
-
api_key: API_KEY,
|
121
115
|
api_secret: API_SECRET,
|
122
116
|
timezone: TIMEZONE
|
123
117
|
}
|
@@ -141,7 +135,6 @@ module Embulk
|
|
141
135
|
stub(Embulk::Input::MixpanelApi::Client).mixpanel_available? { false }
|
142
136
|
config = {
|
143
137
|
type: "mixpanel",
|
144
|
-
api_key: API_KEY,
|
145
138
|
api_secret: API_SECRET,
|
146
139
|
}
|
147
140
|
|
@@ -300,7 +293,6 @@ module Embulk
|
|
300
293
|
def transaction_task(timezone)
|
301
294
|
task.merge(
|
302
295
|
dates: DATES.map {|date| date.to_s},
|
303
|
-
api_key: API_KEY,
|
304
296
|
api_secret: API_SECRET,
|
305
297
|
incremental: true,
|
306
298
|
incremental_column: nil,
|
@@ -366,7 +358,6 @@ module Embulk
|
|
366
358
|
from_date = Date.parse(FROM_DATE)
|
367
359
|
task.merge(
|
368
360
|
dates: (from_date..(from_date + days - 1)).map {|date| date.to_s},
|
369
|
-
api_key: API_KEY,
|
370
361
|
api_secret: API_SECRET,
|
371
362
|
timezone: TIMEZONE,
|
372
363
|
schema: schema
|
@@ -434,7 +425,6 @@ module Embulk
|
|
434
425
|
def transaction_task
|
435
426
|
task.merge(
|
436
427
|
dates: DATES.map {|date| date.to_s},
|
437
|
-
api_key: API_KEY,
|
438
428
|
api_secret: API_SECRET,
|
439
429
|
timezone: TIMEZONE,
|
440
430
|
schema: schema
|
@@ -451,7 +441,6 @@ module Embulk
|
|
451
441
|
def test_export_params
|
452
442
|
config_params = [
|
453
443
|
:type, "mixpanel",
|
454
|
-
:api_key, API_KEY,
|
455
444
|
:api_secret, API_SECRET,
|
456
445
|
:from_date, FROM_DATE,
|
457
446
|
:to_date, TO_DATE,
|
@@ -463,7 +452,6 @@ module Embulk
|
|
463
452
|
config = DataSource[*config_params]
|
464
453
|
|
465
454
|
expected = {
|
466
|
-
api_key: API_KEY,
|
467
455
|
event: "[\"ViewHoge\",\"ViewFuga\"]",
|
468
456
|
where: 'properties["$os"] == "Windows"',
|
469
457
|
bucket: "987",
|
@@ -541,7 +529,6 @@ module Embulk
|
|
541
529
|
|
542
530
|
def task
|
543
531
|
{
|
544
|
-
api_key: API_KEY,
|
545
532
|
api_secret: API_SECRET,
|
546
533
|
export_endpoint: "https://data.mixpanel.com/api/2.0/export/",
|
547
534
|
timezone: TIMEZONE,
|
@@ -846,7 +833,6 @@ module Embulk
|
|
846
833
|
|
847
834
|
def task
|
848
835
|
{
|
849
|
-
api_key: API_KEY,
|
850
836
|
api_secret: API_SECRET,
|
851
837
|
export_endpoint: "https://data.mixpanel.com/api/2.0/export/",
|
852
838
|
timezone: TIMEZONE,
|
@@ -891,7 +877,6 @@ module Embulk
|
|
891
877
|
def config
|
892
878
|
{
|
893
879
|
type: "mixpanel",
|
894
|
-
api_key: API_KEY,
|
895
880
|
api_secret: API_SECRET,
|
896
881
|
from_date: FROM_DATE,
|
897
882
|
fetch_days: DAYS,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-mixpanel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yoshihara
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-02-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -28,17 +28,17 @@ dependencies:
|
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.2.5
|
34
34
|
name: tzinfo
|
35
35
|
prerelease: false
|
36
36
|
type: :runtime
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - '='
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 1.2.5
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|