Skip to content
This repository has been archived by the owner on Feb 28, 2023. It is now read-only.

Commit

Permalink
Add more tests, missing datapoints column to events, and other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
hermanschaaf committed Jan 24, 2023
1 parent 22efa1a commit 31c37c6
Show file tree
Hide file tree
Showing 20 changed files with 773 additions and 101 deletions.
51 changes: 50 additions & 1 deletion client/spec.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package client

import (
"errors"
"fmt"
"regexp"
"strconv"
"time"
)

Expand All @@ -11,6 +14,8 @@ var DefaultStartTime = time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC)
// AllowedTimeLayout is the layout used for the start_time and end_time fields, and matches what the export API supports
var AllowedTimeLayout = "2006-01-02"

var reValidDuration = regexp.MustCompile(`^(\d+)([dmy])$`)

type Spec struct {
// UserID is the Simple Analytics API user ID.
UserID string `json:"user_id"`
Expand All @@ -33,6 +38,15 @@ type Spec struct {
// be fetched in a subsequent sync and guarantee at-least-once delivery, but can
// introduce duplicates.
WindowOverlapSeconds int `json:"window_overlap_seconds"`

// DurationStr is the duration of the time window to fetch historical data for, in days, months or years.
// Examples:
// "7d": past 7 days
// "3m": last 3 months
// "1y": last year
// It is used to calculate start_time if it is not specified. If start_time is specified,
// duration is ignored.
DurationStr string `json:"duration"`
}

type WebsiteSpec struct {
Expand Down Expand Up @@ -67,11 +81,17 @@ func (s Spec) Validate() error {
return fmt.Errorf("could not parse end_time: %v", err)
}
}
if s.DurationStr != "" {
_, err := parseDuration(s.DurationStr)
if err != nil {
return fmt.Errorf("could not validate duration: %v (should be a number followed by \"d\", \"m\" or \"y\", e.g. \"7d\", \"1m\" or \"3y\")", err)
}
}
return nil
}

func (s *Spec) SetDefaults() {
if s.StartTimeStr == "" {
if s.StartTimeStr == "" && s.DurationStr == "" {
s.StartTimeStr = DefaultStartTime.Format(AllowedTimeLayout)
}
if s.EndTimeStr == "" {
Expand All @@ -83,6 +103,9 @@ func (s *Spec) SetDefaults() {
}

func (s Spec) StartTime() time.Time {
if s.StartTimeStr == "" && s.DurationStr != "" {
return time.Now().Add(-s.Duration())
}
t, _ := time.Parse(AllowedTimeLayout, s.StartTimeStr) // any error should be caught by Validate()
return t
}
Expand All @@ -91,3 +114,29 @@ func (s Spec) EndTime() time.Time {
t, _ := time.Parse(AllowedTimeLayout, s.EndTimeStr) // any error should be caught by Validate()
return t
}

func (s Spec) Duration() time.Duration {
d, _ := parseDuration(s.DurationStr) // any error should be caught by Validate()
return d
}

func parseDuration(s string) (time.Duration, error) {
m := reValidDuration.FindStringSubmatch(s)
if m == nil {
return 0, errors.New("invalid duration")
}
n, err := strconv.Atoi(m[1])
if err != nil {
return 0, err
}
switch m[2] {
case "d":
return time.Duration(n) * 24 * time.Hour, nil
case "m":
return time.Duration(n) * 30 * 24 * time.Hour, nil
case "y":
return time.Duration(n) * 365 * 24 * time.Hour, nil
}
// should never happen, we already validated using regex
panic("unhandled duration unit")
}
63 changes: 63 additions & 0 deletions client/testing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package client

import (
"context"
"net/http/httptest"
"os"
"testing"
"time"

"github.com/cloudquery/cq-source-simple-analytics/internal/simpleanalytics"
"github.com/cloudquery/plugin-sdk/plugins/source"
"github.com/cloudquery/plugin-sdk/schema"
"github.com/cloudquery/plugin-sdk/specs"
"github.com/rs/zerolog"
)

func TestHelper(t *testing.T, table *schema.Table, ts *httptest.Server) {
version := "vDev"
table.IgnoreInTests = false
t.Helper()
l := zerolog.New(zerolog.NewTestWriter(t)).Output(
zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.StampMicro},
).Level(zerolog.DebugLevel).With().Timestamp().Logger()
newTestExecutionClient := func(ctx context.Context, logger zerolog.Logger, spec specs.Source, opts source.Options) (schema.ClientMeta, error) {
saClient := simpleanalytics.NewClient("test", "test", simpleanalytics.WithBaseURL(ts.URL), simpleanalytics.WithHTTPClient(ts.Client()))
s := Spec{
UserID: "test",
APIKey: "test",
Websites: []WebsiteSpec{
{
Hostname: "test.com",
MetadataFields: []string{"metadata_text", "metadata_int"},
},
},
}
s.SetDefaults()
err := s.Validate()
if err != nil {
return nil, err
}
return &Client{
Logger: l,
SAClient: saClient,
Backend: opts.Backend,
Spec: s,
}, nil
}
p := source.NewPlugin(
table.Name,
version,
[]*schema.Table{
table,
},
newTestExecutionClient)
p.SetLogger(l)
source.TestPluginSync(t, p, specs.Source{
Name: "dev",
Path: "cloudquery/dev",
Version: version,
Tables: []string{table.Name},
Destinations: []string{"mock-destination"},
})
}
3 changes: 2 additions & 1 deletion docs/tables/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

## Tables

- [simple_analytics_data_points](simple_analytics_data_points.md) (Incremental)
- [simple_analytics_events](simple_analytics_events.md) (Incremental)
- [simple_analytics_page_views](simple_analytics_page_views.md) (Incremental)
45 changes: 45 additions & 0 deletions docs/tables/simple_analytics_events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Table: simple_analytics_events

https://docs.simpleanalytics.com/api/export-data-points

The primary key for this table is **_cq_id**.
It supports incremental syncs.

## Columns

| Name | Type |
| ------------- | ------------- |
|_cq_source_name|String|
|_cq_sync_time|Timestamp|
|_cq_id (PK)|UUID|
|_cq_parent_id|UUID|
|metadata|JSON|
|added_iso|Timestamp|
|added_unix|Int|
|browser_name|String|
|browser_version|String|
|country_code|String|
|device_type|String|
|document_referrer|String|
|hostname|String|
|hostname_original|String|
|is_robot|Bool|
|lang_language|String|
|lang_region|String|
|os_name|String|
|os_version|String|
|path|String|
|path_and_query|String|
|query|String|
|screen_height|Int|
|screen_width|Int|
|session_id|String|
|utm_campaign|String|
|utm_content|String|
|utm_medium|String|
|utm_source|String|
|utm_term|String|
|uuid|String|
|user_agent|String|
|viewport_height|Int|
|viewport_width|Int|
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Table: simple_analytics_data_points
# Table: simple_analytics_page_views

https://docs.simpleanalytics.com/api/export-data-points

Expand All @@ -14,33 +14,35 @@ It supports incremental syncs.
|_cq_id|UUID|
|_cq_parent_id|UUID|
|metadata|JSON|
|added_unix|Int|
|added_iso|Timestamp|
|added_unix|Int|
|browser_name|String|
|browser_version|String|
|country_code|String|
|device_type|String|
|document_referrer|String|
|hostname (PK)|String|
|hostname_original|String|
|is_robot|Bool|
|lang_language|String|
|lang_region|String|
|os_name|String|
|os_version|String|
|path|String|
|path_and_query|String|
|query|String|
|is_unique|Bool|
|is_robot|Bool|
|document_referrer|String|
|utm_source|String|
|utm_medium|String|
|screen_height|Int|
|screen_width|Int|
|session_id|String|
|utm_campaign|String|
|utm_content|String|
|utm_medium|String|
|utm_source|String|
|utm_term|String|
|scrolled_percentage|Float|
|duration_seconds|Float|
|viewport_width|Int|
|viewport_height|Int|
|screen_width|Int|
|screen_height|Int|
|uuid (PK)|String|
|user_agent|String|
|device_type|String|
|country_code|String|
|browser_name|String|
|browser_version|String|
|os_name|String|
|os_version|String|
|lang_region|String|
|lang_language|String|
|uuid (PK)|String|
|viewport_height|Int|
|viewport_width|Int|
|duration_seconds|Float|
|is_unique|Bool|
|scrolled_percentage|Float|
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ go 1.19

require (
github.com/cloudquery/plugin-sdk v1.27.0
github.com/google/go-cmp v0.5.9
github.com/rs/zerolog v1.28.0
golang.org/x/sync v0.1.0
)

require (
Expand All @@ -23,7 +25,6 @@ require (
github.com/thoas/go-funk v0.9.3 // indirect
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30 // indirect
golang.org/x/net v0.4.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
Expand Down
3 changes: 1 addition & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudquery/plugin-sdk v1.25.0 h1:LnKWhX94AF8Y/GASzLCTlMF4rZX85KXcA4CjB2vERtc=
github.com/cloudquery/plugin-sdk v1.25.0/go.mod h1:teMPyCON3uPdMsHvzpSiOg+IK2sOR5Tf9dYLreoURzI=
github.com/cloudquery/plugin-sdk v1.27.0 h1:DXuvnBt1gOB98umBZU6jltZEV6oxfsdEBIAbQXFcIx4=
github.com/cloudquery/plugin-sdk v1.27.0/go.mod h1:teMPyCON3uPdMsHvzpSiOg+IK2sOR5Tf9dYLreoURzI=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
Expand Down Expand Up @@ -105,6 +103,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
Expand Down
7 changes: 5 additions & 2 deletions internal/simpleanalytics/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ func NewClient(userId, apiKey string, opts ...Option) *Client {
}

type HTTPError struct {
Code int
Code int
Message string
}

func (e HTTPError) Error() string {
Expand All @@ -68,7 +69,9 @@ func (c *Client) get(ctx context.Context, path string, query url.Values) (io.Rea
return nil, err
}
if r.StatusCode != http.StatusOK {
return nil, HTTPError{Code: r.StatusCode}
body, _ := io.ReadAll(r.Body)
r.Body.Close()
return nil, HTTPError{Code: r.StatusCode, Message: string(body)}
}
return r.Body, nil
}

0 comments on commit 31c37c6

Please sign in to comment.