This repository has been archived by the owner on Dec 5, 2020. It is now read-only.
forked from ticketmaster/googleanalytics_exporter
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathganalytics.go
129 lines (111 loc) · 3.13 KB
/
ganalytics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
119
120
121
122
123
124
125
126
127
128
129
/*
Obtains Google Analytics RealTime API metrics, and presents them to
prometheus for scraping.
*/
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/oauth2"
"golang.org/x/oauth2/jwt"
"google.golang.org/api/analytics/v3"
"gopkg.in/yaml.v2"
)
var (
credsfile = "./config/ga_creds.json"
conffile = "./config/conf.yaml"
promGauge = make(map[string]prometheus.Gauge)
config = new(conf)
)
// conf defines configuration parameters
type conf struct {
Interval int `yaml:"interval"`
Metrics []string `yaml:"metrics"`
ViewID string `yaml:"viewid"`
PromPort string `yaml:"port"`
}
func init() {
config.getConf(conffile)
// All metrics are registered as Prometheus Gauge
for _, metric := range config.Metrics {
promGauge[metric] = prometheus.NewGauge(prometheus.GaugeOpts{
Name: fmt.Sprintf("ga_%s", strings.Replace(metric, ":", "_", 1)),
Help: fmt.Sprintf("Google Analytics %s", metric),
ConstLabels: map[string]string{"job": "googleAnalytics"},
})
prometheus.MustRegister(promGauge[metric])
}
}
func main() {
creds := getCreds(credsfile)
// JSON web token configuration
jwtc := jwt.Config{
Email: creds["client_email"],
PrivateKey: []byte(creds["private_key"]),
PrivateKeyID: creds["private_key_id"],
Scopes: []string{analytics.AnalyticsReadonlyScope},
TokenURL: creds["token_uri"],
// Expires: time.Duration(1) * time.Hour, // Expire in 1 hour
}
httpClient := jwtc.Client(oauth2.NoContext)
as, err := analytics.New(httpClient)
if err != nil {
panic(err)
}
// Authenticated RealTime Google Analytics API service
rts := analytics.NewDataRealtimeService(as)
// Expose the registered metrics via HTTP.
http.Handle("/metrics", promhttp.Handler())
go http.ListenAndServe(fmt.Sprintf(":%s", config.PromPort), nil)
for {
for _, metric := range config.Metrics {
// Go routine per mertic
go func(metric string) {
val := getMetric(rts, metric)
// Gauge value to float64
valf, _ := strconv.ParseFloat(val, 64)
promGauge[metric].Set(valf)
}(metric)
}
time.Sleep(time.Second * time.Duration(config.Interval))
}
}
// getMetric queries GA RealTime API for a specific metric.
func getMetric(rts *analytics.DataRealtimeService, metric string) string {
getc := rts.Get(config.ViewID, metric)
m, err := getc.Do()
if err != nil {
panic(err)
}
return m.Rows[0][0]
}
// conf.getConf reads yaml configuration file
func (c *conf) getConf(filename string) {
data, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
if err = yaml.Unmarshal(data, &c); err != nil {
panic(err)
}
}
// https://console.developers.google.com/apis/credentials
// 'Service account keys' creds formated file is expected.
// NOTE: the email from the creds has to be added to the Analytics permissions
func getCreds(filename string) (r map[string]string) {
data, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
if err = json.Unmarshal(data, &r); err != nil {
panic(err)
}
return r
}