feat(backend): handle click selector & url for heatmaps
This commit is contained in:
parent
03919c23af
commit
c0824d34d4
8 changed files with 91 additions and 22 deletions
|
|
@ -105,11 +105,16 @@ func (conn *Conn) InsertWebClickEvent(sessionID uint64, e *ClickEvent) error {
|
|||
defer tx.rollback()
|
||||
if err = tx.exec(`
|
||||
INSERT INTO events.clicks
|
||||
(session_id, message_id, timestamp, label)
|
||||
(session_id, message_id, timestamp, label, selector, url)
|
||||
(SELECT
|
||||
$1, $2, $3, NULLIF($4, ''), $5, host || base_path
|
||||
FROM events.pages
|
||||
WHERE session_id = $1 AND timestamp <= $3 ORDER BY timestamp DESC LIMIT 1
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, NULLIF($4, ''))
|
||||
($1, $2, $3, NULLIF($4, ''), $5, SELECT)
|
||||
`,
|
||||
sessionID, e.MessageID, e.Timestamp, e.Label,
|
||||
sessionID, e.MessageID, e.Timestamp, e.Label, e.Selector,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ func ReadBatch(b []byte, callback func(Message)) error {
|
|||
} else if err != nil {
|
||||
return errors.Wrapf(err, "Batch Message decoding error on message with index %v", index)
|
||||
}
|
||||
msg = transformDepricated(msg)
|
||||
|
||||
isBatchMeta := false
|
||||
switch m := msg.(type){
|
||||
case *BatchMeta: // Is not required to be present in batch since IOS doesn't have it (though we might change it)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// Auto-generated, do not edit
|
||||
package messages
|
||||
|
||||
|
||||
|
|
|
|||
29
backend/pkg/messages/legacy_message_transform.go
Normal file
29
backend/pkg/messages/legacy_message_transform.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package messages
|
||||
|
||||
|
||||
func transformDepricated(msg Message) Message {
|
||||
switch m := msg.(type) {
|
||||
case *MouseClickDepricated:
|
||||
return &MouseClick {
|
||||
ID: m.ID,
|
||||
HesitationTime: m.HesitationTime,
|
||||
Label: m.Label,
|
||||
// Selector: '',
|
||||
}
|
||||
// case *FetchDepricated:
|
||||
// return &Fetch {
|
||||
// Method: m.Method,
|
||||
// URL: m.URL,
|
||||
// Request: m.Request,
|
||||
// Response: m.Response,
|
||||
// Status: m.Status,
|
||||
// Timestamp: m.Timestamp,
|
||||
// Duration: m.Duration,
|
||||
// // Headers: ''
|
||||
// }
|
||||
default:
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -350,13 +350,13 @@ p = WriteUint(msg.Y, buf, p)
|
|||
return buf[:p]
|
||||
}
|
||||
|
||||
type MouseClick struct {
|
||||
type MouseClickDepricated struct {
|
||||
*meta
|
||||
ID uint64
|
||||
HesitationTime uint64
|
||||
Label string
|
||||
}
|
||||
func (msg *MouseClick) Encode() []byte{
|
||||
func (msg *MouseClickDepricated) Encode() []byte{
|
||||
buf := make([]byte, 31 + len(msg.Label))
|
||||
buf[0] = 21
|
||||
p := 1
|
||||
|
|
@ -582,15 +582,17 @@ type ClickEvent struct {
|
|||
Timestamp uint64
|
||||
HesitationTime uint64
|
||||
Label string
|
||||
Selector string
|
||||
}
|
||||
func (msg *ClickEvent) Encode() []byte{
|
||||
buf := make([]byte, 41 + len(msg.Label))
|
||||
buf := make([]byte, 51 + len(msg.Label)+ len(msg.Selector))
|
||||
buf[0] = 33
|
||||
p := 1
|
||||
p = WriteUint(msg.MessageID, buf, p)
|
||||
p = WriteUint(msg.Timestamp, buf, p)
|
||||
p = WriteUint(msg.HesitationTime, buf, p)
|
||||
p = WriteString(msg.Label, buf, p)
|
||||
p = WriteString(msg.Selector, buf, p)
|
||||
return buf[:p]
|
||||
}
|
||||
|
||||
|
|
@ -1146,6 +1148,24 @@ p = WriteString(msg.BaseURL, buf, p)
|
|||
return buf[:p]
|
||||
}
|
||||
|
||||
type MouseClick struct {
|
||||
*meta
|
||||
ID uint64
|
||||
HesitationTime uint64
|
||||
Label string
|
||||
Selector string
|
||||
}
|
||||
func (msg *MouseClick) Encode() []byte{
|
||||
buf := make([]byte, 41 + len(msg.Label)+ len(msg.Selector))
|
||||
buf[0] = 69
|
||||
p := 1
|
||||
p = WriteUint(msg.ID, buf, p)
|
||||
p = WriteUint(msg.HesitationTime, buf, p)
|
||||
p = WriteString(msg.Label, buf, p)
|
||||
p = WriteString(msg.Selector, buf, p)
|
||||
return buf[:p]
|
||||
}
|
||||
|
||||
type IOSSessionStart struct {
|
||||
*meta
|
||||
Timestamp uint64
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ if msg.Y, err = ReadUint(reader); err != nil { return nil, err }
|
|||
return msg, nil
|
||||
|
||||
case 21:
|
||||
msg := &MouseClick{ meta: &meta{ TypeID: 21} }
|
||||
msg := &MouseClickDepricated{ meta: &meta{ TypeID: 21} }
|
||||
if msg.ID, err = ReadUint(reader); err != nil { return nil, err }
|
||||
if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err }
|
||||
if msg.Label, err = ReadString(reader); err != nil { return nil, err }
|
||||
|
|
@ -265,6 +265,7 @@ if msg.Label, err = ReadString(reader); err != nil { return nil, err }
|
|||
if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err }
|
||||
if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err }
|
||||
if msg.Label, err = ReadString(reader); err != nil { return nil, err }
|
||||
if msg.Selector, err = ReadString(reader); err != nil { return nil, err }
|
||||
return msg, nil
|
||||
|
||||
case 34:
|
||||
|
|
@ -512,6 +513,14 @@ if msg.Index, err = ReadUint(reader); err != nil { return nil, err }
|
|||
if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err }
|
||||
return msg, nil
|
||||
|
||||
case 69:
|
||||
msg := &MouseClick{ meta: &meta{ TypeID: 69} }
|
||||
if msg.ID, err = ReadUint(reader); err != nil { return nil, err }
|
||||
if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err }
|
||||
if msg.Label, err = ReadString(reader); err != nil { return nil, err }
|
||||
if msg.Selector, err = ReadString(reader); err != nil { return nil, err }
|
||||
return msg, nil
|
||||
|
||||
case 90:
|
||||
msg := &IOSSessionStart{ meta: &meta{ TypeID: 90} }
|
||||
if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err }
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ func (b *builder) handleMessage(message Message, messageID uint64) {
|
|||
Label: msg.Label,
|
||||
HesitationTime: msg.HesitationTime,
|
||||
Timestamp: b.timestamp,
|
||||
Selector: msg.Selector,
|
||||
})
|
||||
}
|
||||
case *JSException:
|
||||
|
|
|
|||
|
|
@ -61,62 +61,64 @@ func main() {
|
|||
Addr: ":" + HTTP_PORT,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// TODO: agree with specification
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "POST")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
// TODO: agree with specification
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "POST")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
|
||||
if r.Method == http.MethodOptions {
|
||||
w.Header().Set("Cache-Control", "max-age=86400")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.URL.Path {
|
||||
case "/":
|
||||
w.WriteHeader(http.StatusOK)
|
||||
case "/v1/web/not-started":
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
case http.MethodPost:
|
||||
notStartedHandler(w, r)
|
||||
default:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
}
|
||||
case "/v1/web/start":
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
case http.MethodPost:
|
||||
startSessionHandlerWeb(w, r)
|
||||
default:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
}
|
||||
case "/v1/web/i":
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
case http.MethodPost:
|
||||
pushMessagesSeparatelyHandler(w, r)
|
||||
default:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
}
|
||||
// case "/v1/ios/start":
|
||||
// switch r.Method {
|
||||
// case "POST":
|
||||
// case http.MethodPost:
|
||||
// startSessionHandlerIOS(w, r)
|
||||
// default:
|
||||
// w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
// }
|
||||
// case "/v1/ios/append":
|
||||
// switch r.Method {
|
||||
// case "POST":
|
||||
// case http.MethodPost:
|
||||
// pushMessagesHandler(w, r)
|
||||
// default:
|
||||
// w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
// }
|
||||
// case "/v1/ios/late":
|
||||
// switch r.Method {
|
||||
// case "POST":
|
||||
// case http.MethodPost:
|
||||
// pushLateMessagesHandler(w, r)
|
||||
// default:
|
||||
// w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
// }
|
||||
// case "/v1/ios/images":
|
||||
// switch r.Method {
|
||||
// case "POST":
|
||||
// case http.MethodPost:
|
||||
// iosImagesUploadHandler(w, r)
|
||||
// default:
|
||||
// w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue