Skip to content

Commit

Permalink
fix breakdown endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
gernest committed Feb 15, 2024
1 parent 209345a commit a50f8ba
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 8 deletions.
5 changes: 4 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func New(ctx context.Context, o *v1.Config) (*API, error) {
w.Header().Add(vary, acceptEncoding)
code := &statsWriter{ResponseWriter: w, compress: acceptsGzip(r)}
defer func() {
logger.Get(r.Context()).Debug(r.URL.String(), "method", r.Method, "status", code.code)
logger.Get(r.Context()).Debug(r.URL.Path, "method", r.Method, "status", code.code)
}()
w = code
if a.config.AuthToken != "" && r.URL.Path != "/api/event" {
Expand Down Expand Up @@ -89,6 +89,9 @@ func New(ctx context.Context, o *v1.Config) (*API, error) {
case "/api/v1/stats/timeseries":
stats.TimeSeries(w, r)
return
case "/api/v1/stats/breakdown":
stats.BreakDown(w, r)
return
default:
if strings.HasPrefix(r.URL.Path, "/js/") {
w.Header().Set("x-content-type-options", "nosniff")
Expand Down
36 changes: 29 additions & 7 deletions stats/breakdown.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package stats

import (
"context"
"net/http"
"slices"
"time"
Expand All @@ -20,10 +21,11 @@ func BreakDown(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
query := r.URL.Query()
req := v1.BreakDown_Request{
SiteId: query.Get("site_id"),
Period: ParsePeriod(ctx, query),
Metrics: ParseMetrics(ctx, query),
Filters: ParseFilters(ctx, query),
SiteId: query.Get("site_id"),
Period: ParsePeriod(ctx, query),
Metrics: ParseMetrics(ctx, query),
Filters: ParseFilters(ctx, query),
Property: ParseProperty(ctx, query),
}
if !request.Validate(ctx, w, &req) {
return
Expand Down Expand Up @@ -80,10 +82,9 @@ func BreakDown(w http.ResponseWriter, r *http.Request) {
xc.visit = nil

for _, name := range selectedColumns {
a, err := compute.TakeArray(ctx, mapping[name], idx)
a, err := take(ctx, mapping[name], idx)
if err != nil {
idx.Release()
logger.Get(ctx).Error("Failed taking array for breaking down", "column", name)
logger.Get(ctx).Error("Failed taking array for breaking down", "column", name, "err", err)
request.Internal(ctx, w)
return
}
Expand Down Expand Up @@ -117,6 +118,27 @@ func BreakDown(w http.ResponseWriter, r *http.Request) {
request.Write(ctx, w, &v1.BreakDown_Response{Results: result})
}

func take(ctx context.Context, a arrow.Array, idx *array.Uint32) (arrow.Array, error) {
if a.DataType().ID() != arrow.DICTIONARY {
return compute.TakeArray(ctx, a, idx)
}
x := a.(*array.Dictionary)
xv := x.Dictionary().(*array.String)
o := array.NewDictionaryBuilder(
compute.GetAllocator(ctx),
a.DataType().(*arrow.DictionaryType),
).(*array.BinaryDictionaryBuilder)
defer o.Release()
for _, i := range idx.Uint32Values() {
if x.IsNull(int(i)) {
o.AppendNull()
continue
}
o.Append([]byte(xv.Value(x.GetValueIndex(int(i)))))
}
return o.NewArray(), nil
}

func hashProp(a arrow.Array) map[string]*roaring.Bitmap {
o := make(map[string]*roaring.Bitmap)
d := a.(*array.Dictionary)
Expand Down
13 changes: 13 additions & 0 deletions stats/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,19 @@ func ParseMetrics(ctx context.Context, query url.Values) (o []v1.Metric) {
return
}

func ParseProperty(ctx context.Context, query url.Values) (o []v1.Property) {
props := query.Get("property")
for _, m := range strings.Split(props, ",") {
v, ok := v1.Property_value[m]
if !ok {
logger.Get(ctx).Error("Skipping unexpected property name", "property", m)
continue
}
o = append(o, v1.Property(v))
}
return
}

func ParseInterval(ctx context.Context, query url.Values) v1.Interval {
i := query.Get("interval")
if i == "" {
Expand Down
1 change: 1 addition & 0 deletions tools/break
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bash -x ./tools/curl/testdata/breakdown.sh
17 changes: 17 additions & 0 deletions tools/curl/curl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"net/url"
"os"
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/require"
v1 "github.com/vinceanalytics/vince/gen/go/staples/v1"
"google.golang.org/protobuf/proto"
)

Expand All @@ -29,6 +31,21 @@ func TestAggregate(t *testing.T) {
q.Set("metrics", "visitors,visits,pageviews,views_per_visit,bounce_rate,visit_duration,events")
check(t, true, "aggregate.sh", "/api/v1/stats/aggregate?"+q.Encode(), http.MethodGet, nil, nil)
}
func TestBreakdown(t *testing.T) {
q := make(url.Values)
q.Set("site_id", "vinceanalytics.com")
var ls []string
for i := v1.Property_event; i <= v1.Property_city; i++ {
ls = append(ls, i.String())
}
q.Set("property", strings.Join(ls, ","))
ls = ls[:0]
for i := v1.Metric_visitors; i <= v1.Metric_events; i++ {
ls = append(ls, i.String())
}
q.Set("metrics", strings.Join(ls, ","))
check(t, true, "breakdown.sh", "/api/v1/stats/breakdown?"+q.Encode(), http.MethodGet, nil, nil)
}

func check(t *testing.T, write bool, file string, path, method string, headers http.Header, body proto.Message) {
t.Helper()
Expand Down
1 change: 1 addition & 0 deletions tools/curl/testdata/breakdown.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
curl -X 'GET' 'http://localhost:8080/api/v1/stats/breakdown?metrics=visitors%2Cvisits%2Cpageviews%2Cviews_per_visit%2Cbounce_rate%2Cvisit_duration%2Cevents&property=event%2C1%2Cpage%2Centry_page%2Cexit_page%2Csource%2Creferrer%2Cutm_source%2Cutm_medium%2Cutm_campaign%2Cutm_content%2Cutm_term%2Cdevice%2Cbrowser%2Cbrowser_version%2Cos%2Cos_version%2Ccountry%2Cregion%2Cdomain%2Ccity&site_id=vinceanalytics.com'

0 comments on commit a50f8ba

Please sign in to comment.