Skip to content

Commit

Permalink
Support cascader and getaccount logic simplify (#68)
Browse files Browse the repository at this point in the history
* support cascader

* Update dependency

* Add account summaries

* Remove get account and add getAccountSummaries

* Remove useless function and formatting

* Fix typo
  • Loading branch information
lcc3108 committed Jun 13, 2023
1 parent 0e61e1e commit e58c0d3
Show file tree
Hide file tree
Showing 20 changed files with 342 additions and 640 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.21.3
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
FROM golang:1.16-alpine as go_build
FROM golang:1.20-alpine as go_build
WORKDIR /build
COPY . .
RUN go run mage.go -v

FROM node:12-alpine as node_build
FROM node:14-alpine as node_build
WORKDIR /build
COPY package.json yarn.lock ./
RUN yarn --frozen-lockfile
COPY . .
RUN yarn build

FROM grafana/grafana:7.4.3
FROM grafana/grafana:9.4.3
ARG PLUGINS_NAME
ENV GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=${PLUGINS_NAME}
COPY --from=go_build /build/dist /var/lib/grafana/plugins
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"@types/react-dropzone": "^5.1.0"
},
"engines": {
"node": ">=12"
"node": ">=14"
}
}
5 changes: 1 addition & 4 deletions pkg/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ import (

type GoogleAnalytics interface {
Query(context.Context, *setting.DatasourceSecretSettings, backend.DataQuery) (*data.Frames, error)
GetAccounts(context.Context, *setting.DatasourceSecretSettings) (map[string]string, error)
GetWebProperties(context.Context, *setting.DatasourceSecretSettings, string) (map[string]string, error)
GetProfiles(context.Context, *setting.DatasourceSecretSettings, string, string) (map[string]string, error)
GetAccountSummaries(context.Context, *setting.DatasourceSecretSettings) ([]*model.AccountSummary, error)
GetTimezone(context.Context, *setting.DatasourceSecretSettings, string, string, string) (string, error)
GetAllProfilesList(context.Context, *setting.DatasourceSecretSettings) (map[string]string, error)
GetDimensions(context.Context, *setting.DatasourceSecretSettings, string) ([]model.MetadataItem, error)
GetMetrics(context.Context, *setting.DatasourceSecretSettings, string) ([]model.MetadataItem, error)
CheckHealth(context.Context, *setting.DatasourceSecretSettings) (*backend.CheckHealthResult, error)
Expand Down
73 changes: 17 additions & 56 deletions pkg/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,10 @@ func NewDataSource(dis backend.DataSourceInstanceSettings) (instancemgmt.Instanc
analytics: analytics,
resourceHandler: httpadapter.New(mux),
}
mux.HandleFunc("/accounts", ds.handleResourceAccounts)
mux.HandleFunc("/web-properties", ds.handleResourceWebProperties)
mux.HandleFunc("/profiles", ds.handleResourceProfiles)
mux.HandleFunc("/profile/timezone", ds.handleResourceProfileTimezone)
mux.HandleFunc("/dimensions", ds.handleResourceDimensions)
mux.HandleFunc("/metrics", ds.handleResourceMetrics)
mux.HandleFunc("/account-summaries", ds.handleResourceAccountSummaries)

return ds, nil
}
Expand Down Expand Up @@ -119,60 +117,7 @@ func writeResult(rw http.ResponseWriter, path string, val interface{}, err error
rw.WriteHeader(code)
}

func (ds *GoogleAnalyticsDataSource) handleResourceAccounts(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
return
}

ctx := req.Context()
config, err := setting.LoadSettings(httpadapter.PluginConfigFromContext(ctx))
if err != nil {
writeResult(rw, "?", nil, err)
return
}

res, err := ds.analytics.GetAccounts(ctx, config)
writeResult(rw, "accounts", res, err)
}

func (ds *GoogleAnalyticsDataSource) handleResourceWebProperties(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
return
}

ctx := req.Context()
config, err := setting.LoadSettings(httpadapter.PluginConfigFromContext(ctx))
if err != nil {
writeResult(rw, "?", nil, err)
return
}
query := req.URL.Query()
var (
accountId = query.Get("accountId")
)
res, err := ds.analytics.GetWebProperties(ctx, config, accountId)
writeResult(rw, "webProperties", res, err)
}

func (ds *GoogleAnalyticsDataSource) handleResourceProfiles(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
return
}

ctx := req.Context()
config, err := setting.LoadSettings(httpadapter.PluginConfigFromContext(ctx))
if err != nil {
writeResult(rw, "?", nil, err)
return
}
query := req.URL.Query()
var (
accountId = query.Get("accountId")
webPropertyId = query.Get("webPropertyId")
)
res, err := ds.analytics.GetProfiles(ctx, config, accountId, webPropertyId)
writeResult(rw, "profiles", res, err)
}

func (ds *GoogleAnalyticsDataSource) handleResourceDimensions(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
Expand Down Expand Up @@ -224,3 +169,19 @@ func (ds *GoogleAnalyticsDataSource) handleResourceProfileTimezone(rw http.Respo
res, err := ds.analytics.GetTimezone(ctx, config, accountId, webPropertyId, profileId)
writeResult(rw, "timezone", res, err)
}

func (ds *GoogleAnalyticsDataSource) handleResourceAccountSummaries(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
return
}

ctx := req.Context()
config, err := setting.LoadSettings(httpadapter.PluginConfigFromContext(ctx))
if err != nil {
writeResult(rw, "?", nil, err)
return
}

res, err := ds.analytics.GetAccountSummaries(ctx, config)
writeResult(rw, "accountSummaries", res, err)
}
166 changes: 56 additions & 110 deletions pkg/gav3/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"time"

"github.com/blackcowmoo/grafana-google-analytics-dataSource/pkg/model"
"github.com/blackcowmoo/grafana-google-analytics-dataSource/pkg/setting"

"github.com/grafana/grafana-plugin-sdk-go/backend"
Expand Down Expand Up @@ -54,81 +55,6 @@ func (ga *GoogleAnalytics) Query(ctx context.Context, config *setting.Datasource
return transformReportsResponseToDataFrames(report, queryModel.RefID, queryModel.Timezone)
}

func (ga *GoogleAnalytics) GetAccounts(ctx context.Context, config *setting.DatasourceSecretSettings) (map[string]string, error) {
client, err := NewGoogleClient(ctx, config.JWT)
if err != nil {
return nil, fmt.Errorf("failed to create Google API client: %w", err)
}

cacheKey := fmt.Sprintf("analytics:accounts:%s", config.JWT)
if item, _, found := ga.Cache.GetWithExpiration(cacheKey); found {
return item.(map[string]string), nil
}

accounts, err := client.getAccountsList(GaDefaultIdx)
if err != nil {
return nil, err
}

accountNames := map[string]string{}
for _, i := range accounts {
accountNames[i.Id] = i.Name
}

ga.Cache.Set(cacheKey, accountNames, 60*time.Second)
return accountNames, nil
}

func (ga *GoogleAnalytics) GetWebProperties(ctx context.Context, config *setting.DatasourceSecretSettings, accountId string) (map[string]string, error) {
client, err := NewGoogleClient(ctx, config.JWT)
if err != nil {
return nil, fmt.Errorf("failed to create Google API client: %w", err)
}

cacheKey := fmt.Sprintf("analytics:account:%s:webproperties", accountId)
if item, _, found := ga.Cache.GetWithExpiration(cacheKey); found {
return item.(map[string]string), nil
}

Webproperties, err := client.getWebpropertiesList(accountId, GaDefaultIdx)
if err != nil {
return nil, err
}

WebpropertyNames := map[string]string{}
for _, i := range Webproperties {
WebpropertyNames[i.Id] = i.Name
}

ga.Cache.Set(cacheKey, WebpropertyNames, 60*time.Second)
return WebpropertyNames, nil
}

func (ga *GoogleAnalytics) GetProfiles(ctx context.Context, config *setting.DatasourceSecretSettings, accountId string, webPropertyId string) (map[string]string, error) {
client, err := NewGoogleClient(ctx, config.JWT)
if err != nil {
return nil, fmt.Errorf("failed to create Google API client: %w", err)
}

cacheKey := fmt.Sprintf("analytics:account:%s:webproperty:%s:profiles", accountId, webPropertyId)
if item, _, found := ga.Cache.GetWithExpiration(cacheKey); found {
return item.(map[string]string), nil
}

profiles, err := client.getProfilesList(accountId, webPropertyId, GaDefaultIdx)
if err != nil {
return nil, err
}

profileNames := map[string]string{}
for _, i := range profiles {
profileNames[i.Id] = i.Name
}

ga.Cache.Set(cacheKey, profileNames, 60*time.Second)
return profileNames, nil
}

func (ga *GoogleAnalytics) GetTimezone(ctx context.Context, config *setting.DatasourceSecretSettings, accountId string, webPropertyId string, profileId string) (string, error) {
client, err := NewGoogleClient(ctx, config.JWT)
if err != nil {
Expand All @@ -140,48 +66,17 @@ func (ga *GoogleAnalytics) GetTimezone(ctx context.Context, config *setting.Data
return item.(string), nil
}

profiles, err := client.getProfilesList(accountId, webPropertyId, GaDefaultIdx)
profile, err := client.getProfile(accountId, webPropertyId, profileId)
if err != nil {
return "", err
}

var timezone string
for _, profile := range profiles {
if profile.Id == profileId {
timezone = profile.Timezone
break
}
}
timezone := profile.Timezone

ga.Cache.Set(cacheKey, timezone, 60*time.Second)
return timezone, nil
}

func (ga *GoogleAnalytics) GetAllProfilesList(ctx context.Context, config *setting.DatasourceSecretSettings) (map[string]string, error) {
client, err := NewGoogleClient(ctx, config.JWT)
if err != nil {
return nil, fmt.Errorf("failed to create Google API client: %w", err)
}

cacheKey := fmt.Sprintf("analytics:account:*:webproperty:*:profiles")
if item, _, found := ga.Cache.GetWithExpiration(cacheKey); found {
return item.(map[string]string), nil
}

profiles, err := client.getAllProfilesList()
if err != nil {
return nil, err
}

profileNames := map[string]string{}
for _, i := range profiles {
profileNames[i.Id] = i.Name
}

ga.Cache.Set(cacheKey, profileNames, 60*time.Second)
return profileNames, nil
}

func (ga *GoogleAnalytics) CheckHealth(ctx context.Context, config *setting.DatasourceSecretSettings) (*backend.CheckHealthResult, error) {
var status = backend.HealthStatusOk
var message = "Success"
Expand All @@ -195,7 +90,7 @@ func (ga *GoogleAnalytics) CheckHealth(ctx context.Context, config *setting.Data
}, nil
}

profiles, err := client.getAllProfilesList()
accountSummaries, err := ga.GetAccountSummaries(ctx, config)
if err != nil {
log.DefaultLogger.Error("CheckHealth: Fail getAllProfilesList", "error", err.Error())
return &backend.CheckHealthResult{
Expand All @@ -204,7 +99,7 @@ func (ga *GoogleAnalytics) CheckHealth(ctx context.Context, config *setting.Data
}, nil
}

testData := QueryModel{profiles[0].AccountId, profiles[0].WebPropertyId, profiles[0].Id, "yesterday", "today", "a", []string{"ga:sessions"}, "ga:dateHour", []string{}, 1, "", false, "UTC", ""}
testData := model.QueryModel{AccountID: accountSummaries[0].Account, WebPropertyID: accountSummaries[0].PropertySummaries[0].Property, ProfileID: accountSummaries[0].PropertySummaries[0].ProfileSummaries[0].Profile, StartDate: "yesterday", EndDate: "today", RefID: "a", Metrics: []string{"ga:sessions"}, TimeDimension: "ga:dateHour", Dimensions: []string{"ga:dateHour"}, PageSize: 1, PageToken: "", UseNextPage: false, Timezone: "UTC", FiltersExpression: "", Offset: GaDefaultIdx}
res, err := client.getReport(testData)

if err != nil {
Expand All @@ -227,3 +122,54 @@ func (ga *GoogleAnalytics) CheckHealth(ctx context.Context, config *setting.Data
Message: message,
}, nil
}

func (ga *GoogleAnalytics) GetAccountSummaries(ctx context.Context, config *setting.DatasourceSecretSettings) ([]*model.AccountSummary, error) {
client, err := NewGoogleClient(ctx, config.JWT)
if err != nil {
return nil, fmt.Errorf("failed to create Google API client: %w", err)
}

cacheKey := fmt.Sprintf("analytics:accountsummaries:%s", config.JWT)
if item, _, found := ga.Cache.GetWithExpiration(cacheKey); found {
return item.([]*model.AccountSummary), nil
}

rawAccountSummaries, err := client.getAccountSummaries(GaDefaultIdx)
if err != nil {
return nil, err
}

var accounts []*model.AccountSummary
for _, rawAccountSummary := range rawAccountSummaries {
var account = &model.AccountSummary{
Account: rawAccountSummary.Id,
DisplayName: rawAccountSummary.Name,
}
var propertySummaries = make([]*model.PropertySummary, 0)
for _, rawPropertySummary := range rawAccountSummary.WebProperties {
var propertySummary = &model.PropertySummary{
Property: rawPropertySummary.Id,
DisplayName: rawPropertySummary.Name,
Parent: rawAccountSummary.Id,
}
propertySummaries = append(propertySummaries, propertySummary)

var profileSummaries = make([]*model.ProfileSummary, 0)

for _, rawProfileSummaries := range rawPropertySummary.Profiles {
var profileSummary = &model.ProfileSummary{
Profile: rawProfileSummaries.Id,
DisplayName: rawProfileSummaries.Name,
Parent: rawPropertySummary.Id,
Type: rawProfileSummaries.Type,
}
profileSummaries = append(profileSummaries, profileSummary)
}
propertySummary.ProfileSummaries = profileSummaries
}
account.PropertySummaries = propertySummaries
accounts = append(accounts, account)
}
ga.Cache.Set(cacheKey, accounts, 60*time.Second)
return accounts, nil
}

0 comments on commit e58c0d3

Please sign in to comment.