chore: add Google Analytics event for record app startup

This commit is contained in:
tiny-craft 2023-10-17 10:19:50 +08:00
parent 77541ed371
commit 94e352dd30
7 changed files with 126 additions and 22 deletions

View File

@ -63,7 +63,10 @@ jobs:
- name: Build wails app for Linux
shell: bash
run: CGO_ENABLED=1 wails build -platform ${{ matrix.platform }} -ldflags "-X main.version=${{ github.event.release.tag_name }}" -o tiny-rdm
run: |
CGO_ENABLED=1 wails build -platform ${{ matrix.platform }} \
-ldflags "-X main.version=${{ github.event.release.tag_name }} -X main.gaMeasurementID=${{ secrets.GA_MEASUREMENT_ID }} -X main.gaSecretKey=${{ secrets.LINUX_GA_SECRET }}" \
-o tiny-rdm
- name: Setup control template
shell: bash

View File

@ -69,7 +69,9 @@ jobs:
- name: Build wails app for macOS
shell: bash
run: CGO_ENABLED=1 wails build -platform ${{ matrix.platform }} -ldflags "-X main.version=${{ github.event.release.tag_name }}"
run: |
CGO_ENABLED=1 wails build -platform ${{ matrix.platform }} \
-ldflags "-X main.version=${{ github.event.release.tag_name }} -X main.gaMeasurementID=${{ secrets.GA_MEASUREMENT_ID }} -X main.gaSecretKey=${{ secrets.MAC_GA_SECRET }}"
# - name: Notarise macOS app + create dmg
# shell: bash

View File

@ -62,7 +62,10 @@ jobs:
- name: Build Windows portable app
shell: bash
run: CGO_ENABLED=1 wails build -clean -platform ${{ matrix.platform }} -upx -webview2 embed -ldflags "-X main.version=${{ github.event.release.tag_name }}"
run: |
CGO_ENABLED=1 wails build -clean -platform ${{ matrix.platform }} \
-upx -webview2 embed \
-ldflags "-X main.version=${{ github.event.release.tag_name }} -X main.gaMeasurementID=${{ secrets.GA_MEASUREMENT_ID }} -X main.gaSecretKey=${{ secrets.WINDOWS_GA_SECRET }}"
- name: Compress portable binary
working-directory: ./build/bin

View File

@ -0,0 +1,110 @@
package services
import (
"bytes"
"encoding/json"
"github.com/google/uuid"
"net/http"
"runtime"
"strings"
"sync"
"tinyrdm/backend/storage"
)
// google analytics service
type gaService struct {
measurementID string
secretKey string
clientID string
}
type GaDataItem struct {
ClientID string `json:"client_id"`
Events []GaEventItem `json:"events"`
}
type GaEventItem struct {
Name string `json:"name"`
Params map[string]any `json:"params"`
}
var ga *gaService
var onceGA sync.Once
func GA() *gaService {
if ga == nil {
onceGA.Do(func() {
// get or create an unique user id
st := storage.NewLocalStore("device.txt")
uidByte, err := st.Load()
if err != nil {
uidByte = []byte(strings.ReplaceAll(uuid.NewString(), "-", ""))
st.Store(uidByte)
}
ga = &gaService{
clientID: string(uidByte),
}
})
}
return ga
}
func (a *gaService) SetSecretKey(measurementID, secretKey string) {
a.measurementID = measurementID
a.secretKey = secretKey
}
func (a *gaService) isValid() bool {
return len(a.measurementID) > 0 && len(a.secretKey) > 0
}
func (a *gaService) sendEvent(events ...GaEventItem) error {
body, err := json.Marshal(GaDataItem{
ClientID: a.clientID,
Events: events,
})
if err != nil {
return err
}
//url := "https://www.google-analytics.com/debug/mp/collect"
url := "https://www.google-analytics.com/mp/collect"
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return err
}
q := req.URL.Query()
q.Add("measurement_id", a.measurementID)
q.Add("api_secret", a.secretKey)
req.URL.RawQuery = q.Encode()
response, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
//if dump, err := httputil.DumpResponse(response, true); err == nil {
// log.Println(string(dump))
//}
return nil
}
// Startup sends application startup event
func (a *gaService) Startup(version string) {
if !a.isValid() {
return
}
go a.sendEvent(GaEventItem{
Name: "startup",
Params: map[string]any{
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"version": version,
},
})
}

View File

@ -1,18 +0,0 @@
package services
import "sync"
type storageService struct {
}
var storage *storageService
var onceStorage sync.Once
func Storage() *storageService {
if storage == nil {
onceStorage.Do(func() {
storage = &storageService{}
})
}
return storage
}

2
go.mod
View File

@ -5,6 +5,7 @@ go 1.21
require (
github.com/adrg/sysfont v0.1.2
github.com/andybalholm/brotli v1.0.5
github.com/google/uuid v1.3.1
github.com/redis/go-redis/v9 v9.2.1
github.com/vrischmann/userdir v0.0.0-20151206171402-20f291cebd68
github.com/wailsapp/wails/v2 v2.6.0
@ -19,7 +20,6 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/labstack/echo/v4 v4.11.1 // indirect
github.com/labstack/gommon v0.4.0 // indirect

View File

@ -22,6 +22,7 @@ var assets embed.FS
var icon []byte
var version = "0.0.0"
var gaMeasurementID, gaSecretKey string
func main() {
// Create an instance of the app structure
@ -55,6 +56,9 @@ func main() {
OnStartup: func(ctx context.Context) {
sysSvc.Start(ctx)
connSvc.Start(ctx)
services.GA().SetSecretKey(gaMeasurementID, gaSecretKey)
services.GA().Startup(version)
},
OnShutdown: func(ctx context.Context) {
connSvc.Stop(ctx)