96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
package charts
|
|
|
|
import (
|
|
"fmt"
|
|
"openreplay/backend/pkg/analytics/db"
|
|
"strings"
|
|
)
|
|
|
|
type HeatmapSessionResponse struct {
|
|
SessionID uint64 `json:"session_id"`
|
|
StartTs uint64 `json:"start_ts"`
|
|
Duration uint32 `json:"duration"`
|
|
EventTimestamp uint64 `json:"event_timestamp"`
|
|
}
|
|
|
|
type HeatmapSessionQueryBuilder struct{}
|
|
|
|
func (h HeatmapSessionQueryBuilder) Execute(p Payload, conn db.Connector) (interface{}, error) {
|
|
shortestQ, err := h.buildQuery(p)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var sid uint64
|
|
var startTs uint64
|
|
var duration uint32
|
|
var eventTs uint64
|
|
row, err := conn.QueryRow(shortestQ)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := row.Scan(&sid, &startTs, &duration, &eventTs); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO get mob urls
|
|
|
|
return HeatmapSessionResponse{
|
|
SessionID: sid,
|
|
StartTs: startTs,
|
|
Duration: duration,
|
|
EventTimestamp: eventTs,
|
|
}, nil
|
|
}
|
|
|
|
func (h HeatmapSessionQueryBuilder) buildQuery(p Payload) (string, error) {
|
|
if len(p.MetricPayload.Series) == 0 {
|
|
return "", fmt.Errorf("series empty")
|
|
}
|
|
s := p.MetricPayload.Series[0]
|
|
|
|
var globalFilters, eventFilters []Filter
|
|
for _, flt := range s.Filter.Filters {
|
|
if flt.IsEvent {
|
|
eventFilters = append(eventFilters, flt)
|
|
} else {
|
|
globalFilters = append(globalFilters, flt)
|
|
}
|
|
}
|
|
|
|
globalConds, _ := buildEventConditions(globalFilters, BuildConditionsOptions{
|
|
DefinedColumns: mainColumns,
|
|
MainTableAlias: "e",
|
|
})
|
|
|
|
eventConds, _ := buildEventConditions(eventFilters, BuildConditionsOptions{
|
|
DefinedColumns: mainColumns,
|
|
MainTableAlias: "e",
|
|
})
|
|
|
|
base := []string{
|
|
fmt.Sprintf("e.created_at >= toDateTime(%d/1000)", p.MetricPayload.StartTimestamp),
|
|
fmt.Sprintf("e.created_at < toDateTime(%d/1000)", p.MetricPayload.EndTimestamp+86400000),
|
|
fmt.Sprintf("e.project_id = %d", p.ProjectId),
|
|
"s.duration > 500",
|
|
"e.`$event_name` = 'LOCATION'",
|
|
}
|
|
base = append(base, eventConds...)
|
|
base = append(base, globalConds...)
|
|
|
|
where := strings.Join(base, " AND ")
|
|
|
|
q := fmt.Sprintf(`
|
|
SELECT
|
|
s.session_id,
|
|
toUnixTimestamp(s.datetime) * 1000 as startTs,
|
|
s.duration,
|
|
toUnixTimestamp(e.created_at) * 1000 as eventTs
|
|
FROM product_analytics.events AS e
|
|
JOIN experimental.sessions AS s USING(session_id)
|
|
WHERE %s
|
|
ORDER BY e.created_at ASC, s.duration ASC
|
|
LIMIT 1;`, where)
|
|
|
|
return q, nil
|
|
}
|