Skip to content

Commit

Permalink
add a funnel visualization type (highlight#8761)
Browse files Browse the repository at this point in the history
## Summary

* Adds initial support for event funnel charts.
Funnel applies to events, grouped by `secure_session_id`, to allow
charting sessions where a number of events happen.
Once events have additional session metadata, it should be possible to
group by user rather than by session.
Currently, some of the graph configuration is disabled when the chart is
a funnel, as it is set to the
default values that the funnel querying assumes (ie. the group by /
bucket by / metric)

The funnel loads by using the `Metrics` query, sharing the query logic
with other graph types.
Multiple steps are loaded serially to allow filtering on the group
values (sessions) from the previous bar.

Closes highlight#9098
Closes HIG-4864

## How did you test this change?

<img width="1565" alt="Screenshot 2024-10-07 at 10 21 05"
src="https://github.com/user-attachments/assets/ed122c3c-0400-4017-98fd-ac5308decb48">

- [x] Switching to a funnel chart when the selected source is `events`
- [x] Adding / removing steps using event filters, setting different
titles for various steps
- [x] Saving / reloading dashboard with event filters 
- [x] Loading state for the funnel is correct, showing funnel once all
steps are loaded
- [x] UI is using correct figma designs

## Are there any deployment considerations?

no

## Does this work require review from our design team?

will review with @julian-highlight
  • Loading branch information
Vadman97 authored Oct 10, 2024
1 parent 92e0d0b commit 7b26905
Show file tree
Hide file tree
Showing 30 changed files with 1,453 additions and 238 deletions.
5 changes: 3 additions & 2 deletions backend/clickhouse/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ type SessionEventRow struct {
UUID string
ProjectID uint32
SessionID uint64
SessionCreatedAt time.Time
Timestamp time.Time
SessionCreatedAt int64
Timestamp int64
Event string
Attributes map[string]string
}
Expand Down Expand Up @@ -115,6 +115,7 @@ func (client *Client) WriteSessionEventRows(ctx context.Context, eventRows []*Se
NewStruct(new(SessionEventRow)).
InsertInto(SessionEventsTable, chEvents...).
BuildWithFlavor(sqlbuilder.ClickHouse)
eventsSql, eventsArgs = replaceTimestampInserts(eventsSql, eventsArgs, map[int]bool{3: true, 4: true}, MicroSeconds)

return client.conn.Exec(chCtx, eventsSql, eventsArgs...)
}
Expand Down
8 changes: 3 additions & 5 deletions backend/clickhouse/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,14 +752,14 @@ func matchesQuery[TObj interface{}](row *TObj, config model.TableConfig, filters
switch filter.Operator {
case listener.OperatorAnd:
for _, childFilter := range filter.Filters {
if !matchesQuery(row, config, listener.Filters{childFilter}, filter.Operator) {
if !matchesQuery[TObj](row, config, listener.Filters{childFilter}, filter.Operator) {
return false
}
}
case listener.OperatorOr:
var anyMatch bool
for _, childFilter := range filter.Filters {
if matchesQuery(row, config, listener.Filters{childFilter}, filter.Operator) {
if matchesQuery[TObj](row, config, listener.Filters{childFilter}, filter.Operator) {
anyMatch = true
break
}
Expand All @@ -768,7 +768,7 @@ func matchesQuery[TObj interface{}](row *TObj, config model.TableConfig, filters
return false
}
case listener.OperatorNot:
return !matchesQuery(row, config, listener.Filters{filter.Filters[0]}, filter.Operator)
return !matchesQuery[TObj](row, config, listener.Filters{filter.Filters[0]}, filter.Operator)
default:
matches, err := matchFilter(row, config, filter)
if err != nil {
Expand Down Expand Up @@ -971,7 +971,6 @@ func (client *Client) ReadMetrics(ctx context.Context, input ReadMetricsInput) (
if len(input.MetricTypes) == 0 {
return nil, errors.New("no metric types provided")
}

if input.Params.DateRange == nil {
input.Params.DateRange = &modelInputs.DateRangeRequiredInput{
StartDate: time.Now().Add(-time.Hour * 24 * 30),
Expand Down Expand Up @@ -1331,7 +1330,6 @@ func (client *Client) ReadMetrics(ctx context.Context, input ReadMetricsInput) (

return metrics, err
}

func formatColumn(input string, column string) string {
base := input
if base == "" {
Expand Down
1 change: 1 addition & 0 deletions backend/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,7 @@ type Graph struct {
Limit *int
LimitFunctionType *modelInputs.MetricAggregator
LimitMetric *string
FunnelSteps *string `gorm:"type:jsonb"`
Display *string
NullHandling *string
}
Expand Down
Loading

0 comments on commit 7b26905

Please sign in to comment.