Newer
Older
#!/bin/env ruby
#
# Set options here
#
OUTPUT = ENV["OUTPUT"] || "data.txt"
API_KEY = ENV["GOOGLE_API_KEY"] || "google_api_key.json"
GA_PROFILE = ENV["GOOGLE_PROFILE"] || "133342836" # Open OnDemand (beta) / Authenticated Users
START_DATE = ENV["START_DATE"] || "2016-11-29" # Server side analytics code deployed in OSC OnDemand production
END_DATE = ENV["END_DATE"] || "today" # google keyword is "today"
START_STEP = ENV["START_STEP"] || 1 # google starts with 1, NOT 0
STEP_SIZE = ENV["STEP_SIZE"] || 10000 # max google step is 10,000
# max 7 dimensions
DIMENSIONS = %w(
ga:dimension3
ga:dimension1
ga:dimension2
ga:pagePath
)
USR_COLUMN = 1 # ga:dimension1
APP_COLUMN = 3 # ga:pagePath
# at least 1 metric, max 10 metrics
METRICS = %w(
ga:hits
)
SORT = %w()
FILTERS = %w(
ga:hostname==ondemand.osc.edu;ga:dimension6==200
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
)
# Fix app token from page path
APP_BASE_URI = "/pun"
APP_TOKEN = {
%r{^/sys/vncsim/sys/bc_osc_abaqus} => "sys/abaqus_cae",
%r{^/sys/vncsim/sys/bc_osc_ansys_workbench} => "sys/ansys_workbench",
%r{^/sys/vncsim/sys/bc_osc_comsol} => "sys/comsol",
%r{^/sys/vncsim/sys/bc_osc_oakley_desktop} => "sys/oakley_desktop",
%r{^/sys/vncsim/sys/bc_osc_oakley_vdi} => "sys/oakley_vdi",
%r{^/sys/vncsim/sys/bc_osc_paraview} => "sys/paraview",
%r{^/sys/vncsim/sys/bc_osc_ruby_desktop} => "sys/ruby_desktop",
%r{^/sys/vncsim/sys/bc_osc_ruby_vdi} => "sys/ruby_vdi",
%r{^/sys/vncsim/sys/(?<app_name>[^/]+)} => "sys/vncsim/sys/%{app_name}",
%r{^/sys/vncsim/usr/(?<app_owner>[^/]+)/(?<app_name>[^/]+)} => "sys/vncsim/usr/%{app_owner}/%{app_name}",
%r{^/sys/vncsim/dev/(?<app_name>[^/]+)} => "sys/vncsim/dev/%{user}/%{app_name}",
%r{^/sys/(?<app_name>[^/]+)} => "sys/%{app_name}",
%r{^/usr/(?<app_owner>[^/]+)/(?<app_name>[^/]+)} => "usr/%{app_owner}/%{app_name}",
%r{^/dev/(?<app_name>[^/]+)} => "dev/%{user}/%{app_name}"
}
#
# Do not modify below
#
require 'rubygems'
require 'bundler/setup'
require 'googleauth'
require 'google/apis/analytics_v3'
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io: File.open(API_KEY, 'r'),
scope: Google::Apis::AnalyticsV3::AUTH_ANALYTICS_READONLY
)
analytics = Google::Apis::AnalyticsV3::AnalyticsService.new
analytics.authorization = credentials
class InvalidToken < StandardError; end
def parse_uri(str, **opts)
raise RuntimeError, "failed to parse app uri: #{str}" unless m = /^#{APP_BASE_URI}(?<app_uri>.+)$/.match(str)
parse_token m[:app_uri], **opts
end
def parse_token(str, user: "")
APP_TOKEN.each do |regex, token|
if m = regex.match(str)
return token % Hash[m.names.map(&:to_sym).zip(m.captures)].merge(user: user)
end
end
raise InvalidToken, "failed to parse app token: #{str}"
end
def gather_data(analytics, file)
target = open(file, "w")
puts "Sending request..."
start_index = START_STEP
loop do
results = analytics.get_ga_data(
"ga:#{GA_PROFILE}",
START_DATE,
END_DATE,
METRICS.join(','),
dimensions: DIMENSIONS.empty? ? nil : DIMENSIONS.join(','),
filters: FILTERS.empty? ? nil : FILTERS.join(','),
sort: SORT.empty? ? nil : SORT.join(','),
start_index: start_index,
max_results: STEP_SIZE
)
puts "Outputting #{results.rows.size} items..."
results.rows.each do |row|
begin
app = row[APP_COLUMN]
row[APP_COLUMN] = parse_uri(app, user: row[USR_COLUMN])
row << app
target.write "#{row.join(' ')}\n"
rescue InvalidToken => e
$stderr.puts "Warning: #{e.message}"
end
end
start_index += STEP_SIZE
break unless results.next_link
end
puts "Done!"
ensure
target.close
end
gather_data(analytics, OUTPUT)