embulk-input-google_analytics 0.1.17 → 0.1.18.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/embulk-input-google_analytics.gemspec +2 -1
- data/lib/embulk/input/google_analytics/client.rb +16 -4
- data/lib/embulk/input/google_analytics/plugin.rb +22 -3
- data/test/embulk/input/google_analytics/test_client.rb +58 -0
- data/test/embulk/input/google_analytics/test_plugin.rb +84 -0
- data/test/fixtures/valid_refresh_token.yml +18 -0
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 840c722b01ba3cf337f7b5e405e8b6b07676810b
|
4
|
+
data.tar.gz: 9416098303f34773cf3df1329a8eaf84fe4594b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 736e069eb795ba331c2125df44cb5cc48525f8bb4a44f43e62bb1b0b27c2b1affbd9e8e76fd76dfeeaeb8eaa64b5b9e91cde98254d4a3c90600fb30c7534ac64
|
7
|
+
data.tar.gz: 61a3515ba0cd0c28832d39d215b5619e3e62799164155c28ace126f773c8c4c08398e040b5424d38fb775fd08414d0af20833e8c6d5d4ab038ee5cf1373d459e
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
Gem::Specification.new do |spec|
|
3
3
|
spec.name = "embulk-input-google_analytics"
|
4
|
-
spec.version = "0.1.
|
4
|
+
spec.version = "0.1.18.alpha"
|
5
5
|
spec.authors = ["uu59"]
|
6
6
|
spec.summary = "Google Analytics input plugin for Embulk"
|
7
7
|
spec.description = "Loads records from Google Analytics."
|
@@ -27,5 +27,6 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency 'simplecov'
|
28
28
|
spec.add_development_dependency "codeclimate-test-reporter"
|
29
29
|
spec.add_development_dependency "pry"
|
30
|
+
spec.add_development_dependency "pry-debugger-jruby"
|
30
31
|
spec.add_development_dependency "gem_release_helper", "~> 1.0"
|
31
32
|
end
|
@@ -208,10 +208,22 @@ module Embulk
|
|
208
208
|
|
209
209
|
def auth
|
210
210
|
retryer.with_retry do
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
211
|
+
case task['auth_method']
|
212
|
+
when Plugin::AUTH_TYPE_JSON_KEY
|
213
|
+
Google::Auth::ServiceAccountCredentials.make_creds(
|
214
|
+
json_key_io: StringIO.new(task["json_key_content"]),
|
215
|
+
scope: "https://www.googleapis.com/auth/analytics.readonly"
|
216
|
+
)
|
217
|
+
when Plugin::AUTH_TYPE_REFRESH_TOKEN
|
218
|
+
Google::Auth::UserRefreshCredentials.new(
|
219
|
+
'token_credential_uri': Google::Auth::UserRefreshCredentials::TOKEN_CRED_URI,
|
220
|
+
'client_id': task['client_id'],
|
221
|
+
'client_secret': task['client_secret'],
|
222
|
+
'refresh_token': task['refresh_token']
|
223
|
+
)
|
224
|
+
else
|
225
|
+
raise Embulk::ConfigError.new("Unknown Authentication method: '#{task['auth_method']}'.")
|
226
|
+
end
|
215
227
|
end
|
216
228
|
rescue Google::Apis::AuthorizationError => e
|
217
229
|
raise ConfigError.new(e.message)
|
@@ -3,6 +3,8 @@ module Embulk
|
|
3
3
|
module GoogleAnalytics
|
4
4
|
class Plugin < InputPlugin
|
5
5
|
::Embulk::Plugin.register_input("google_analytics", self)
|
6
|
+
AUTH_TYPE_JSON_KEY = 'json_key'.freeze
|
7
|
+
AUTH_TYPE_REFRESH_TOKEN = 'refresh_token'.freeze
|
6
8
|
|
7
9
|
# https://developers.google.com/analytics/devguides/reporting/core/dimsmets
|
8
10
|
|
@@ -11,6 +13,15 @@ module Embulk
|
|
11
13
|
unless %w(ga:date ga:dateHour).include?(task["time_series"])
|
12
14
|
raise ConfigError.new("Unknown time_series '#{task["time_series"]}'. Use 'ga:dateHour' or 'ga:date'")
|
13
15
|
end
|
16
|
+
|
17
|
+
raise ConfigError.new("Unknown Authentication method '#{task['auth_method']}'.") unless task['auth_method']
|
18
|
+
|
19
|
+
if task['auth_method'] == Plugin::AUTH_TYPE_REFRESH_TOKEN
|
20
|
+
unless task['client_id'] && task['client_secret'] && task['refresh_token']
|
21
|
+
raise ConfigError.new("client_id, client_secret and refresh_token are required when using Oauth authentication")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
14
25
|
columns_list = Client.new(task).get_columns_list
|
15
26
|
|
16
27
|
columns = columns_from_task(task).map do |col_name|
|
@@ -53,8 +64,16 @@ module Embulk
|
|
53
64
|
end
|
54
65
|
|
55
66
|
def self.task_from_config(config)
|
56
|
-
|
57
|
-
|
67
|
+
refresh_token = config.param('refresh_token', :string, default: nil)
|
68
|
+
json_key_content = config.param("json_key_content", :string, default: nil)
|
69
|
+
|
70
|
+
auth_method = Plugin::AUTH_TYPE_REFRESH_TOKEN if refresh_token
|
71
|
+
auth_method = Plugin::AUTH_TYPE_JSON_KEY if json_key_content && auth_method == nil
|
72
|
+
{
|
73
|
+
"auth_method" => auth_method,
|
74
|
+
"client_id" => config.param("client_id", :string, default: nil),
|
75
|
+
"client_secret" => config.param("client_secret", :string, default: nil),
|
76
|
+
"refresh_token" => refresh_token,
|
58
77
|
"json_key_content" => json_key_content,
|
59
78
|
"view_id" => config.param("view_id", :string),
|
60
79
|
"dimensions" => config.param("dimensions", :array, default: []),
|
@@ -98,7 +117,7 @@ module Embulk
|
|
98
117
|
client = Client.new(task, preview?)
|
99
118
|
columns = self.class.columns_from_task(task) + ["view_id"]
|
100
119
|
|
101
|
-
last_record_time = task["last_record_time"] ? Time.parse(task["last_record_time"]) : nil
|
120
|
+
last_record_time = task['incremental'] && task["last_record_time"] ? Time.parse(task["last_record_time"]) : nil
|
102
121
|
|
103
122
|
latest_time_series = nil
|
104
123
|
skip_counter, total_counter = 0, 0
|
@@ -283,6 +283,60 @@ module Embulk
|
|
283
283
|
end
|
284
284
|
end
|
285
285
|
|
286
|
+
sub_test_case "oauth_refresh_token" do
|
287
|
+
setup do
|
288
|
+
conf = valid_config_oauth["in"]
|
289
|
+
mute_logger
|
290
|
+
@client = Client.new(task(embulk_config(conf)))
|
291
|
+
end
|
292
|
+
|
293
|
+
sub_test_case "retry refresh token" do
|
294
|
+
def should_retry
|
295
|
+
mock(Google::Auth::UserRefreshCredentials).new(anything).times(retryer.config.limit + 1) { raise error }
|
296
|
+
assert_raise do
|
297
|
+
@client.auth
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def should_not_retry
|
302
|
+
mock(Google::Auth::UserRefreshCredentials).new(anything).times(1) { raise error }
|
303
|
+
assert_raise do
|
304
|
+
@client.auth
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
sub_test_case "Server respones error (5xx)" do
|
309
|
+
def error
|
310
|
+
Google::Apis::ServerError.new("error")
|
311
|
+
end
|
312
|
+
|
313
|
+
test "should retry refresh token" do
|
314
|
+
should_retry
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
sub_test_case "Refresh token reach Rate Limit" do
|
319
|
+
def error
|
320
|
+
Google::Apis::RateLimitError.new("error")
|
321
|
+
end
|
322
|
+
|
323
|
+
test "should retry refresh token" do
|
324
|
+
should_retry
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
sub_test_case "Refresh token Error" do
|
329
|
+
def error
|
330
|
+
Google::Apis::AuthorizationError.new("error")
|
331
|
+
end
|
332
|
+
|
333
|
+
test "should not retry" do
|
334
|
+
should_not_retry
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
286
340
|
sub_test_case "too_early_data?" do
|
287
341
|
def stub_timezone(client)
|
288
342
|
stub(client).get_profile { {timezone: "America/Los_Angeles" } }
|
@@ -412,6 +466,10 @@ module Embulk
|
|
412
466
|
fixture_load("valid.yml")
|
413
467
|
end
|
414
468
|
|
469
|
+
def valid_config_oauth
|
470
|
+
fixture_load("valid_refresh_token.yml")
|
471
|
+
end
|
472
|
+
|
415
473
|
def embulk_config(hash)
|
416
474
|
Embulk::DataSource.new(hash)
|
417
475
|
end
|
@@ -75,6 +75,46 @@ module Embulk
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
test "missing client_id params for oauth" do
|
79
|
+
conf = valid_config_oauth["in"]
|
80
|
+
conf.delete("client_id")
|
81
|
+
assert_raise(Embulk::ConfigError.new(oauth_expect_message)) do
|
82
|
+
Plugin.transaction(embulk_config(conf))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
test "missing client_secret params for oauth" do
|
87
|
+
conf = valid_config_oauth["in"]
|
88
|
+
conf.delete('client_secret')
|
89
|
+
assert_raise(Embulk::ConfigError.new(oauth_expect_message)) do
|
90
|
+
Plugin.transaction(embulk_config(conf))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
test "missing refresh_token params for oauth" do
|
95
|
+
conf = valid_config_oauth["in"]
|
96
|
+
conf.delete("refresh_token")
|
97
|
+
assert_raise(Embulk::ConfigError.new(unknown_auth_method_message)) do
|
98
|
+
Plugin.transaction(embulk_config(conf))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
test "missing json_key_content params for oauth" do
|
103
|
+
conf = valid_config["in"]
|
104
|
+
conf.delete("json_key_content")
|
105
|
+
assert_raise(Embulk::ConfigError.new(unknown_auth_method_message)) do
|
106
|
+
Plugin.transaction(embulk_config(conf))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def unknown_auth_method_message
|
111
|
+
"Unknown Authentication method ''."
|
112
|
+
end
|
113
|
+
|
114
|
+
def oauth_expect_message
|
115
|
+
"client_id, client_secret and refresh_token are required when using Oauth authentication"
|
116
|
+
end
|
117
|
+
|
78
118
|
def unknown_col_name
|
79
119
|
"ga:foooooo"
|
80
120
|
end
|
@@ -162,12 +202,14 @@ module Embulk
|
|
162
202
|
|
163
203
|
sub_test_case "last_record_time option" do
|
164
204
|
setup do
|
205
|
+
stub(Plugin).calculate_next_times { {} }
|
165
206
|
Time.zone = "America/Los_Angeles"
|
166
207
|
@last_record_time = Time.zone.parse("2016-06-01 12:00:00").to_time
|
167
208
|
|
168
209
|
conf = valid_config["in"]
|
169
210
|
conf["time_series"] = time_series
|
170
211
|
conf["last_record_time"] = @last_record_time.strftime("%Y-%m-%d %H:%M:%S %z")
|
212
|
+
conf['incremental'] = true
|
171
213
|
@plugin = Plugin.new(embulk_config(conf), nil, nil, @page_builder)
|
172
214
|
end
|
173
215
|
|
@@ -182,6 +224,7 @@ module Embulk
|
|
182
224
|
}
|
183
225
|
block.call row
|
184
226
|
end
|
227
|
+
stub(klass).get_profile { {timezone: "America/Los_Angeles" } }
|
185
228
|
end
|
186
229
|
|
187
230
|
mock(@page_builder).add.never
|
@@ -219,12 +262,15 @@ module Embulk
|
|
219
262
|
|
220
263
|
sub_test_case "last_record_time option" do
|
221
264
|
setup do
|
265
|
+
stub(Plugin).calculate_next_times { {} }
|
222
266
|
Time.zone = "America/Los_Angeles"
|
223
267
|
@last_record_time = Time.zone.parse("2016-06-01 12:00:00").to_time
|
224
268
|
|
225
269
|
conf = valid_config["in"]
|
226
270
|
conf["time_series"] = time_series
|
227
271
|
conf["last_record_time"] = @last_record_time.strftime("%Y-%m-%d %H:%M:%S %z")
|
272
|
+
conf['incremental'] = true
|
273
|
+
|
228
274
|
@plugin = Plugin.new(embulk_config(conf), nil, nil, @page_builder)
|
229
275
|
end
|
230
276
|
|
@@ -239,6 +285,7 @@ module Embulk
|
|
239
285
|
}
|
240
286
|
block.call row
|
241
287
|
end
|
288
|
+
stub(klass).get_profile { {timezone: "America/Los_Angeles" } }
|
242
289
|
end
|
243
290
|
|
244
291
|
mock(@page_builder).add.never
|
@@ -250,6 +297,39 @@ module Embulk
|
|
250
297
|
end
|
251
298
|
end
|
252
299
|
|
300
|
+
sub_test_case "run non-incremental" do
|
301
|
+
sub_test_case " should be added to page_builder" do
|
302
|
+
setup do
|
303
|
+
Time.zone = "America/Los_Angeles"
|
304
|
+
@last_record_time = Time.zone.parse("2016-06-01 12:00:00").to_time
|
305
|
+
|
306
|
+
conf = valid_config["in"]
|
307
|
+
conf["time_series"] = "ga:date"
|
308
|
+
conf["last_record_time"] = @last_record_time.strftime("%Y-%m-%d %H:%M:%S %z")
|
309
|
+
conf['incremental'] = false
|
310
|
+
@plugin = Plugin.new(embulk_config(conf), nil, nil, @page_builder)
|
311
|
+
end
|
312
|
+
|
313
|
+
test "should allow record to be added to page_builder" do
|
314
|
+
any_instance_of(Client) do |klass|
|
315
|
+
stub(klass).each_report_row do |block|
|
316
|
+
row = {
|
317
|
+
"ga:date" => @last_record_time,
|
318
|
+
"ga:browser" => "wget",
|
319
|
+
"ga:visits" => 3,
|
320
|
+
"ga:pageviews" => 4,
|
321
|
+
}
|
322
|
+
block.call row
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
mock(@page_builder).add(anything).at_least(1)
|
327
|
+
mock(@page_builder).finish
|
328
|
+
@plugin.run
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
253
333
|
sub_test_case "canonicalize_column_name" do
|
254
334
|
data do
|
255
335
|
[
|
@@ -457,6 +537,10 @@ module Embulk
|
|
457
537
|
def embulk_config(hash)
|
458
538
|
Embulk::DataSource.new(hash)
|
459
539
|
end
|
540
|
+
|
541
|
+
def valid_config_oauth
|
542
|
+
fixture_load("valid_refresh_token.yml")
|
543
|
+
end
|
460
544
|
end
|
461
545
|
end
|
462
546
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
in:
|
2
|
+
type: google_analytics
|
3
|
+
refresh_token: "your_refresh_token"
|
4
|
+
client_id: "your_client_id_here"
|
5
|
+
client_secret: "your_client_secret_here"
|
6
|
+
view_id: 101111111
|
7
|
+
time_series: "ga:dateHour"
|
8
|
+
|
9
|
+
dimensions:
|
10
|
+
- "ga:browser"
|
11
|
+
metrics:
|
12
|
+
- "ga:visits"
|
13
|
+
- "ga:pageviews"
|
14
|
+
retry_limit: 2
|
15
|
+
retry_initial_wait_sec: 0
|
16
|
+
|
17
|
+
out:
|
18
|
+
type: stdout
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-google_analytics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.18.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- uu59
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +192,20 @@ dependencies:
|
|
192
192
|
- - ">="
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
requirement: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
name: pry-debugger-jruby
|
202
|
+
prerelease: false
|
203
|
+
type: :development
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
210
|
requirement: !ruby/object:Gem::Requirement
|
197
211
|
requirements:
|
@@ -231,6 +245,7 @@ files:
|
|
231
245
|
- test/fixture_helper.rb
|
232
246
|
- test/fixtures/reports.json
|
233
247
|
- test/fixtures/valid.yml
|
248
|
+
- test/fixtures/valid_refresh_token.yml
|
234
249
|
- test/override_assert_raise.rb
|
235
250
|
- test/run-test.rb
|
236
251
|
homepage: https://github.com/treasure-data/embulk-input-google_analytics
|
@@ -248,9 +263,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
248
263
|
version: '0'
|
249
264
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
250
265
|
requirements:
|
251
|
-
- - "
|
266
|
+
- - ">"
|
252
267
|
- !ruby/object:Gem::Version
|
253
|
-
version:
|
268
|
+
version: 1.3.1
|
254
269
|
requirements: []
|
255
270
|
rubyforge_project:
|
256
271
|
rubygems_version: 2.6.6
|
@@ -263,5 +278,6 @@ test_files:
|
|
263
278
|
- test/fixture_helper.rb
|
264
279
|
- test/fixtures/reports.json
|
265
280
|
- test/fixtures/valid.yml
|
281
|
+
- test/fixtures/valid_refresh_token.yml
|
266
282
|
- test/override_assert_raise.rb
|
267
283
|
- test/run-test.rb
|