diff --git a/backend/build.sh b/backend/build.sh
index 70a29c5af..e67178c8c 100755
--- a/backend/build.sh
+++ b/backend/build.sh
@@ -23,15 +23,15 @@ function build_service() {
image="$1"
echo "BUILDING $image"
case "$image" in
- http | db | ender | heuristics)
+ http | db | sink | ender | heuristics)
echo build http
- docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --build-arg SERVICE_NAME=$image -f ./cmd/Dockerfile .
+ docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --platform linux/amd64 --build-arg SERVICE_NAME=$image -f ./cmd/Dockerfile .
[[ $PUSH_IMAGE -eq 1 ]] && {
docker push ${DOCKER_REPO:-'local'}/$image:${git_sha1}
}
;;
*)
- docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --build-arg SERVICE_NAME=$image .
+ docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --platform linux/amd64 --build-arg SERVICE_NAME=$image .
[[ $PUSH_IMAGE -eq 1 ]] && {
docker push ${DOCKER_REPO:-'local'}/$image:${git_sha1}
}
diff --git a/backend/cmd/Dockerfile b/backend/cmd/Dockerfile
index e2f611afa..f36bfc99e 100644
--- a/backend/cmd/Dockerfile
+++ b/backend/cmd/Dockerfile
@@ -18,7 +18,7 @@ COPY cmd cmd
ARG SERVICE_NAME
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o service -tags musl openreplay/backend/cmd/$SERVICE_NAME
-FROM alpine
+FROM alpine AS entrypoint
RUN apk add --no-cache ca-certificates
ENV TZ=UTC \
diff --git a/backend/cmd/http/main.go b/backend/cmd/http/main.go
index 541baab62..3fdd8d34a 100644
--- a/backend/cmd/http/main.go
+++ b/backend/cmd/http/main.go
@@ -2,6 +2,10 @@ package main
import (
"log"
+ "os"
+ "os/signal"
+ "syscall"
+
"openreplay/backend/internal/config"
"openreplay/backend/internal/router"
"openreplay/backend/internal/server"
@@ -10,9 +14,6 @@ import (
"openreplay/backend/pkg/db/postgres"
"openreplay/backend/pkg/pprof"
"openreplay/backend/pkg/queue"
- "os"
- "os/signal"
- "syscall"
)
func main() {
diff --git a/backend/services/sink/main.go b/backend/cmd/sink/main.go
similarity index 67%
rename from backend/services/sink/main.go
rename to backend/cmd/sink/main.go
index a649bb6ef..269b8fab0 100644
--- a/backend/services/sink/main.go
+++ b/backend/cmd/sink/main.go
@@ -9,42 +9,48 @@ import (
"os/signal"
"syscall"
- "openreplay/backend/pkg/env"
+ "openreplay/backend/internal/assetscache"
+ "openreplay/backend/internal/config/sink"
+ "openreplay/backend/internal/oswriter"
. "openreplay/backend/pkg/messages"
"openreplay/backend/pkg/queue"
"openreplay/backend/pkg/queue/types"
+ "openreplay/backend/pkg/url/assets"
)
func main() {
log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile)
- FS_DIR := env.String("FS_DIR")
- if _, err := os.Stat(FS_DIR); os.IsNotExist(err) {
- log.Fatalf("%v doesn't exist. %v", FS_DIR, err)
+ cfg := sink.New()
+
+ if _, err := os.Stat(cfg.FsDir); os.IsNotExist(err) {
+ log.Fatalf("%v doesn't exist. %v", cfg.FsDir, err)
}
- writer := NewWriter(env.Uint16("FS_ULIMIT"), FS_DIR)
+ writer := oswriter.NewWriter(cfg.FsUlimit, cfg.FsDir)
+
+ producer := queue.NewProducer()
+ defer producer.Close(cfg.ProducerCloseTimeout)
+ rewriter := assets.NewRewriter(cfg.AssetsOrigin)
+ assetMessageHandler := assetscache.New(cfg, rewriter, producer)
count := 0
consumer := queue.NewMessageConsumer(
- env.String("GROUP_SINK"),
+ cfg.GroupSink,
[]string{
- env.String("TOPIC_RAW_WEB"),
- env.String("TOPIC_RAW_IOS"),
+ cfg.TopicRawIOS,
+ cfg.TopicRawWeb,
},
func(sessionID uint64, message Message, _ *types.Meta) {
- //typeID, err := GetMessageTypeID(value)
- // if err != nil {
- // log.Printf("Message type decoding error: %v", err)
- // return
- // }
- typeID := message.Meta().TypeID
+ count++
+
+ typeID := message.TypeID()
if !IsReplayerType(typeID) {
return
}
- count++
+ message = assetMessageHandler.ParseAssets(sessionID, message)
value := message.Encode()
var data []byte
diff --git a/backend/internal/assetscache/assets.go b/backend/internal/assetscache/assets.go
index 1ef70b56c..cf76bed8c 100644
--- a/backend/internal/assetscache/assets.go
+++ b/backend/internal/assetscache/assets.go
@@ -1,19 +1,19 @@
package assetscache
import (
- "openreplay/backend/internal/config"
+ "openreplay/backend/internal/config/sink"
"openreplay/backend/pkg/messages"
"openreplay/backend/pkg/queue/types"
"openreplay/backend/pkg/url/assets"
)
type AssetsCache struct {
- cfg *config.Config
+ cfg *sink.Config
rewriter *assets.Rewriter
producer types.Producer
}
-func New(cfg *config.Config, rewriter *assets.Rewriter, producer types.Producer) *AssetsCache {
+func New(cfg *sink.Config, rewriter *assets.Rewriter, producer types.Producer) *AssetsCache {
return &AssetsCache{
cfg: cfg,
rewriter: rewriter,
diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go
index 5b55ba346..b98f910c2 100644
--- a/backend/internal/config/config.go
+++ b/backend/internal/config/config.go
@@ -11,12 +11,9 @@ type Config struct {
HTTPTimeout time.Duration
TopicRawWeb string
TopicRawIOS string
- TopicCache string
- CacheAssets bool
BeaconSizeLimit int64
JsonSizeLimit int64
FileSizeLimit int64
- AssetsOrigin string
AWSRegion string
S3BucketIOSImages string
Postgres string
@@ -33,12 +30,9 @@ func New() *Config {
HTTPTimeout: time.Second * 60,
TopicRawWeb: env.String("TOPIC_RAW_WEB"),
TopicRawIOS: env.String("TOPIC_RAW_IOS"),
- TopicCache: env.String("TOPIC_CACHE"),
- CacheAssets: env.Bool("CACHE_ASSETS"),
BeaconSizeLimit: int64(env.Uint64("BEACON_SIZE_LIMIT")),
JsonSizeLimit: 1e3, // 1Kb
FileSizeLimit: 1e7, // 10Mb
- AssetsOrigin: env.String("ASSETS_ORIGIN"),
AWSRegion: env.String("AWS_REGION"),
S3BucketIOSImages: env.String("S3_BUCKET_IOS_IMAGES"),
Postgres: env.String("POSTGRES_STRING"),
diff --git a/backend/internal/config/sink/config.go b/backend/internal/config/sink/config.go
new file mode 100644
index 000000000..a78bfba63
--- /dev/null
+++ b/backend/internal/config/sink/config.go
@@ -0,0 +1,31 @@
+package sink
+
+import (
+ "openreplay/backend/pkg/env"
+)
+
+type Config struct {
+ FsDir string
+ FsUlimit uint16
+ GroupSink string
+ TopicRawWeb string
+ TopicRawIOS string
+ TopicCache string
+ CacheAssets bool
+ AssetsOrigin string
+ ProducerCloseTimeout int
+}
+
+func New() *Config {
+ return &Config{
+ FsDir: env.String("FS_DIR"),
+ FsUlimit: env.Uint16("FS_ULIMIT"),
+ GroupSink: env.String("GROUP_SINK"),
+ TopicRawWeb: env.String("TOPIC_RAW_WEB"),
+ TopicRawIOS: env.String("TOPIC_RAW_IOS"),
+ TopicCache: env.String("TOPIC_CACHE"),
+ CacheAssets: env.Bool("CACHE_ASSETS"),
+ AssetsOrigin: env.String("ASSETS_ORIGIN"),
+ ProducerCloseTimeout: 15000,
+ }
+}
diff --git a/backend/services/sink/writer.go b/backend/internal/oswriter/oswriter.go
similarity index 99%
rename from backend/services/sink/writer.go
rename to backend/internal/oswriter/oswriter.go
index 6fcfdddbc..839e61eba 100644
--- a/backend/services/sink/writer.go
+++ b/backend/internal/oswriter/oswriter.go
@@ -1,4 +1,4 @@
-package main
+package oswriter
import (
"math"
diff --git a/backend/internal/router/handlers-web.go b/backend/internal/router/handlers-web.go
index fc7c6421d..13301d97e 100644
--- a/backend/internal/router/handlers-web.go
+++ b/backend/internal/router/handlers-web.go
@@ -1,9 +1,9 @@
package router
import (
- "bytes"
"encoding/json"
"errors"
+ "io/ioutil"
"log"
"math/rand"
"net/http"
@@ -64,14 +64,14 @@ func (e *Router) startSessionHandlerWeb(w http.ResponseWriter, r *http.Request)
ResponseWithError(w, http.StatusForbidden, errors.New("browser not recognized"))
return
}
- sessionID, err := e.services.Flaker.Compose(uint64(startTime.UnixNano() / 1e6))
+ sessionID, err := e.services.Flaker.Compose(uint64(startTime.UnixMilli()))
if err != nil {
ResponseWithError(w, http.StatusInternalServerError, err)
return
}
// TODO: if EXPIRED => send message for two sessions association
expTime := startTime.Add(time.Duration(p.MaxSessionDuration) * time.Millisecond)
- tokenData = &token.TokenData{ID: sessionID, ExpTime: expTime.UnixNano() / 1e6}
+ tokenData = &token.TokenData{ID: sessionID, ExpTime: expTime.UnixMilli()}
e.services.Producer.Produce(e.cfg.TopicRawWeb, tokenData.ID, Encode(&SessionStart{
Timestamp: req.Timestamp,
@@ -117,20 +117,15 @@ func (e *Router) pushMessagesHandlerWeb(w http.ResponseWriter, r *http.Request)
body := http.MaxBytesReader(w, r.Body, e.cfg.BeaconSizeLimit)
defer body.Close()
- var handledMessages bytes.Buffer
-
- // Process each message in request data
- err = ReadBatchReader(body, func(msg Message) {
- msg = e.services.Assets.ParseAssets(sessionData.ID, msg)
- handledMessages.Write(msg.Encode())
- })
+ bytes, err := ioutil.ReadAll(body)
if err != nil {
- ResponseWithError(w, http.StatusForbidden, err)
+ ResponseWithError(w, http.StatusInternalServerError, err) // TODO: Split environments; send error here only on staging
return
}
// Send processed messages to queue as array of bytes
- err = e.services.Producer.Produce(e.cfg.TopicRawWeb, sessionData.ID, handledMessages.Bytes())
+ // TODO: check bytes for nonsense crap
+ err = e.services.Producer.Produce(e.cfg.TopicRawWeb, sessionData.ID, bytes)
if err != nil {
log.Printf("can't send processed messages to queue: %s", err)
}
diff --git a/backend/internal/services/services.go b/backend/internal/services/services.go
index 5b84e1dfb..c9915c78e 100644
--- a/backend/internal/services/services.go
+++ b/backend/internal/services/services.go
@@ -1,7 +1,6 @@
package services
import (
- "openreplay/backend/internal/assetscache"
"openreplay/backend/internal/config"
"openreplay/backend/internal/geoip"
"openreplay/backend/internal/uaparser"
@@ -10,13 +9,11 @@ import (
"openreplay/backend/pkg/queue/types"
"openreplay/backend/pkg/storage"
"openreplay/backend/pkg/token"
- "openreplay/backend/pkg/url/assets"
)
type ServicesBuilder struct {
Database *cache.PGCache
Producer types.Producer
- Assets *assetscache.AssetsCache
Flaker *flakeid.Flaker
UaParser *uaparser.UAParser
GeoIP *geoip.GeoIP
@@ -25,11 +22,9 @@ type ServicesBuilder struct {
}
func New(cfg *config.Config, producer types.Producer, pgconn *cache.PGCache) *ServicesBuilder {
- rewriter := assets.NewRewriter(cfg.AssetsOrigin)
return &ServicesBuilder{
Database: pgconn,
Producer: producer,
- Assets: assetscache.New(cfg, rewriter, producer),
Storage: storage.NewS3(cfg.AWSRegion, cfg.S3BucketIOSImages),
Tokenizer: token.NewTokenizer(cfg.TokenSecret),
UaParser: uaparser.NewUAParser(cfg.UAParserFile),
diff --git a/backend/pkg/messages/filters.go b/backend/pkg/messages/filters.go
index 44b2c7959..a74d49eec 100644
--- a/backend/pkg/messages/filters.go
+++ b/backend/pkg/messages/filters.go
@@ -1,10 +1,10 @@
// Auto-generated, do not edit
package messages
-func IsReplayerType(id uint64) bool {
+func IsReplayerType(id int) bool {
return 0 == id || 2 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 22 == id || 37 == id || 38 == id || 39 == id || 40 == id || 41 == id || 44 == id || 45 == id || 46 == id || 47 == id || 48 == id || 49 == id || 54 == id || 55 == id || 59 == id || 69 == id || 70 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id
}
-func IsIOSType(id uint64) bool {
+func IsIOSType(id int) bool {
return 107 == id || 90 == id || 91 == id || 92 == id || 93 == id || 94 == id || 95 == id || 96 == id || 97 == id || 98 == id || 99 == id || 100 == id || 101 == id || 102 == id || 103 == id || 104 == id || 105 == id || 110 == id || 111 == id
}
diff --git a/backend/pkg/messages/legacy-message-transform.go b/backend/pkg/messages/legacy-message-transform.go
index 6774d95b1..3a42cdab0 100644
--- a/backend/pkg/messages/legacy-message-transform.go
+++ b/backend/pkg/messages/legacy-message-transform.go
@@ -3,10 +3,7 @@ package messages
func transformDeprecated(msg Message) Message {
switch m := msg.(type) {
case *MouseClickDepricated:
- meta := m.Meta()
- meta.TypeID = 33
return &MouseClick{
- meta: meta,
ID: m.ID,
HesitationTime: m.HesitationTime,
Label: m.Label,
diff --git a/backend/pkg/messages/message.go b/backend/pkg/messages/message.go
new file mode 100644
index 000000000..d701d474f
--- /dev/null
+++ b/backend/pkg/messages/message.go
@@ -0,0 +1,16 @@
+package messages
+
+type message struct {
+ Timestamp int64
+ Index uint64
+}
+
+func (m *message) Meta() *message {
+ return m
+}
+
+type Message interface {
+ Encode() []byte
+ TypeID() int
+ Meta() *message
+}
diff --git a/backend/pkg/messages/messages.go b/backend/pkg/messages/messages.go
index 418c47342..ba10eb026 100644
--- a/backend/pkg/messages/messages.go
+++ b/backend/pkg/messages/messages.go
@@ -1,24 +1,8 @@
// Auto-generated, do not edit
package messages
-type Message interface {
- Encode() []byte
- Meta() *meta
-}
-
-type meta struct {
- Timestamp int64
- Index uint64
- TypeID uint64
-}
-
-// Might also implement Encode() here (?)
-func (m *meta) Meta() *meta {
- return m
-}
-
type BatchMeta struct {
- *meta
+ message
PageNo uint64
FirstIndex uint64
Timestamp int64
@@ -34,8 +18,12 @@ func (msg *BatchMeta) Encode() []byte {
return buf[:p]
}
+func (msg *BatchMeta) TypeID() int {
+ return 80
+}
+
type Timestamp struct {
- *meta
+ message
Timestamp uint64
}
@@ -47,8 +35,12 @@ func (msg *Timestamp) Encode() []byte {
return buf[:p]
}
+func (msg *Timestamp) TypeID() int {
+ return 0
+}
+
type SessionStart struct {
- *meta
+ message
Timestamp uint64
ProjectID uint64
TrackerVersion string
@@ -90,8 +82,12 @@ func (msg *SessionStart) Encode() []byte {
return buf[:p]
}
+func (msg *SessionStart) TypeID() int {
+ return 1
+}
+
type SessionDisconnect struct {
- *meta
+ message
Timestamp uint64
}
@@ -103,8 +99,12 @@ func (msg *SessionDisconnect) Encode() []byte {
return buf[:p]
}
+func (msg *SessionDisconnect) TypeID() int {
+ return 2
+}
+
type SessionEnd struct {
- *meta
+ message
Timestamp uint64
}
@@ -116,8 +116,12 @@ func (msg *SessionEnd) Encode() []byte {
return buf[:p]
}
+func (msg *SessionEnd) TypeID() int {
+ return 3
+}
+
type SetPageLocation struct {
- *meta
+ message
URL string
Referrer string
NavigationStart uint64
@@ -133,8 +137,12 @@ func (msg *SetPageLocation) Encode() []byte {
return buf[:p]
}
+func (msg *SetPageLocation) TypeID() int {
+ return 4
+}
+
type SetViewportSize struct {
- *meta
+ message
Width uint64
Height uint64
}
@@ -148,8 +156,12 @@ func (msg *SetViewportSize) Encode() []byte {
return buf[:p]
}
+func (msg *SetViewportSize) TypeID() int {
+ return 5
+}
+
type SetViewportScroll struct {
- *meta
+ message
X int64
Y int64
}
@@ -163,8 +175,12 @@ func (msg *SetViewportScroll) Encode() []byte {
return buf[:p]
}
+func (msg *SetViewportScroll) TypeID() int {
+ return 6
+}
+
type CreateDocument struct {
- *meta
+ message
}
func (msg *CreateDocument) Encode() []byte {
@@ -175,8 +191,12 @@ func (msg *CreateDocument) Encode() []byte {
return buf[:p]
}
+func (msg *CreateDocument) TypeID() int {
+ return 7
+}
+
type CreateElementNode struct {
- *meta
+ message
ID uint64
ParentID uint64
index uint64
@@ -196,8 +216,12 @@ func (msg *CreateElementNode) Encode() []byte {
return buf[:p]
}
+func (msg *CreateElementNode) TypeID() int {
+ return 8
+}
+
type CreateTextNode struct {
- *meta
+ message
ID uint64
ParentID uint64
Index uint64
@@ -213,8 +237,12 @@ func (msg *CreateTextNode) Encode() []byte {
return buf[:p]
}
+func (msg *CreateTextNode) TypeID() int {
+ return 9
+}
+
type MoveNode struct {
- *meta
+ message
ID uint64
ParentID uint64
Index uint64
@@ -230,8 +258,12 @@ func (msg *MoveNode) Encode() []byte {
return buf[:p]
}
+func (msg *MoveNode) TypeID() int {
+ return 10
+}
+
type RemoveNode struct {
- *meta
+ message
ID uint64
}
@@ -243,8 +275,12 @@ func (msg *RemoveNode) Encode() []byte {
return buf[:p]
}
+func (msg *RemoveNode) TypeID() int {
+ return 11
+}
+
type SetNodeAttribute struct {
- *meta
+ message
ID uint64
Name string
Value string
@@ -260,8 +296,12 @@ func (msg *SetNodeAttribute) Encode() []byte {
return buf[:p]
}
+func (msg *SetNodeAttribute) TypeID() int {
+ return 12
+}
+
type RemoveNodeAttribute struct {
- *meta
+ message
ID uint64
Name string
}
@@ -275,8 +315,12 @@ func (msg *RemoveNodeAttribute) Encode() []byte {
return buf[:p]
}
+func (msg *RemoveNodeAttribute) TypeID() int {
+ return 13
+}
+
type SetNodeData struct {
- *meta
+ message
ID uint64
Data string
}
@@ -290,8 +334,12 @@ func (msg *SetNodeData) Encode() []byte {
return buf[:p]
}
+func (msg *SetNodeData) TypeID() int {
+ return 14
+}
+
type SetCSSData struct {
- *meta
+ message
ID uint64
Data string
}
@@ -305,8 +353,12 @@ func (msg *SetCSSData) Encode() []byte {
return buf[:p]
}
+func (msg *SetCSSData) TypeID() int {
+ return 15
+}
+
type SetNodeScroll struct {
- *meta
+ message
ID uint64
X int64
Y int64
@@ -322,8 +374,12 @@ func (msg *SetNodeScroll) Encode() []byte {
return buf[:p]
}
+func (msg *SetNodeScroll) TypeID() int {
+ return 16
+}
+
type SetInputTarget struct {
- *meta
+ message
ID uint64
Label string
}
@@ -337,8 +393,12 @@ func (msg *SetInputTarget) Encode() []byte {
return buf[:p]
}
+func (msg *SetInputTarget) TypeID() int {
+ return 17
+}
+
type SetInputValue struct {
- *meta
+ message
ID uint64
Value string
Mask int64
@@ -354,8 +414,12 @@ func (msg *SetInputValue) Encode() []byte {
return buf[:p]
}
+func (msg *SetInputValue) TypeID() int {
+ return 18
+}
+
type SetInputChecked struct {
- *meta
+ message
ID uint64
Checked bool
}
@@ -369,8 +433,12 @@ func (msg *SetInputChecked) Encode() []byte {
return buf[:p]
}
+func (msg *SetInputChecked) TypeID() int {
+ return 19
+}
+
type MouseMove struct {
- *meta
+ message
X uint64
Y uint64
}
@@ -384,8 +452,12 @@ func (msg *MouseMove) Encode() []byte {
return buf[:p]
}
+func (msg *MouseMove) TypeID() int {
+ return 20
+}
+
type MouseClickDepricated struct {
- *meta
+ message
ID uint64
HesitationTime uint64
Label string
@@ -401,8 +473,12 @@ func (msg *MouseClickDepricated) Encode() []byte {
return buf[:p]
}
+func (msg *MouseClickDepricated) TypeID() int {
+ return 21
+}
+
type ConsoleLog struct {
- *meta
+ message
Level string
Value string
}
@@ -416,8 +492,12 @@ func (msg *ConsoleLog) Encode() []byte {
return buf[:p]
}
+func (msg *ConsoleLog) TypeID() int {
+ return 22
+}
+
type PageLoadTiming struct {
- *meta
+ message
RequestStart uint64
ResponseStart uint64
ResponseEnd uint64
@@ -445,8 +525,12 @@ func (msg *PageLoadTiming) Encode() []byte {
return buf[:p]
}
+func (msg *PageLoadTiming) TypeID() int {
+ return 23
+}
+
type PageRenderTiming struct {
- *meta
+ message
SpeedIndex uint64
VisuallyComplete uint64
TimeToInteractive uint64
@@ -462,8 +546,12 @@ func (msg *PageRenderTiming) Encode() []byte {
return buf[:p]
}
+func (msg *PageRenderTiming) TypeID() int {
+ return 24
+}
+
type JSException struct {
- *meta
+ message
Name string
Message string
Payload string
@@ -479,8 +567,12 @@ func (msg *JSException) Encode() []byte {
return buf[:p]
}
+func (msg *JSException) TypeID() int {
+ return 25
+}
+
type RawErrorEvent struct {
- *meta
+ message
Timestamp uint64
Source string
Name string
@@ -500,8 +592,12 @@ func (msg *RawErrorEvent) Encode() []byte {
return buf[:p]
}
+func (msg *RawErrorEvent) TypeID() int {
+ return 26
+}
+
type RawCustomEvent struct {
- *meta
+ message
Name string
Payload string
}
@@ -515,8 +611,12 @@ func (msg *RawCustomEvent) Encode() []byte {
return buf[:p]
}
+func (msg *RawCustomEvent) TypeID() int {
+ return 27
+}
+
type UserID struct {
- *meta
+ message
ID string
}
@@ -528,8 +628,12 @@ func (msg *UserID) Encode() []byte {
return buf[:p]
}
+func (msg *UserID) TypeID() int {
+ return 28
+}
+
type UserAnonymousID struct {
- *meta
+ message
ID string
}
@@ -541,8 +645,12 @@ func (msg *UserAnonymousID) Encode() []byte {
return buf[:p]
}
+func (msg *UserAnonymousID) TypeID() int {
+ return 29
+}
+
type Metadata struct {
- *meta
+ message
Key string
Value string
}
@@ -556,8 +664,12 @@ func (msg *Metadata) Encode() []byte {
return buf[:p]
}
+func (msg *Metadata) TypeID() int {
+ return 30
+}
+
type PageEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
URL string
@@ -601,8 +713,12 @@ func (msg *PageEvent) Encode() []byte {
return buf[:p]
}
+func (msg *PageEvent) TypeID() int {
+ return 31
+}
+
type InputEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Value string
@@ -622,8 +738,12 @@ func (msg *InputEvent) Encode() []byte {
return buf[:p]
}
+func (msg *InputEvent) TypeID() int {
+ return 32
+}
+
type ClickEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
HesitationTime uint64
@@ -643,8 +763,12 @@ func (msg *ClickEvent) Encode() []byte {
return buf[:p]
}
+func (msg *ClickEvent) TypeID() int {
+ return 33
+}
+
type ErrorEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Source string
@@ -666,8 +790,12 @@ func (msg *ErrorEvent) Encode() []byte {
return buf[:p]
}
+func (msg *ErrorEvent) TypeID() int {
+ return 34
+}
+
type ResourceEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Duration uint64
@@ -701,8 +829,12 @@ func (msg *ResourceEvent) Encode() []byte {
return buf[:p]
}
+func (msg *ResourceEvent) TypeID() int {
+ return 35
+}
+
type CustomEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Name string
@@ -720,8 +852,12 @@ func (msg *CustomEvent) Encode() []byte {
return buf[:p]
}
+func (msg *CustomEvent) TypeID() int {
+ return 36
+}
+
type CSSInsertRule struct {
- *meta
+ message
ID uint64
Rule string
Index uint64
@@ -737,8 +873,12 @@ func (msg *CSSInsertRule) Encode() []byte {
return buf[:p]
}
+func (msg *CSSInsertRule) TypeID() int {
+ return 37
+}
+
type CSSDeleteRule struct {
- *meta
+ message
ID uint64
Index uint64
}
@@ -752,8 +892,12 @@ func (msg *CSSDeleteRule) Encode() []byte {
return buf[:p]
}
+func (msg *CSSDeleteRule) TypeID() int {
+ return 38
+}
+
type Fetch struct {
- *meta
+ message
Method string
URL string
Request string
@@ -777,8 +921,12 @@ func (msg *Fetch) Encode() []byte {
return buf[:p]
}
+func (msg *Fetch) TypeID() int {
+ return 39
+}
+
type Profiler struct {
- *meta
+ message
Name string
Duration uint64
Args string
@@ -796,8 +944,12 @@ func (msg *Profiler) Encode() []byte {
return buf[:p]
}
+func (msg *Profiler) TypeID() int {
+ return 40
+}
+
type OTable struct {
- *meta
+ message
Key string
Value string
}
@@ -811,8 +963,12 @@ func (msg *OTable) Encode() []byte {
return buf[:p]
}
+func (msg *OTable) TypeID() int {
+ return 41
+}
+
type StateAction struct {
- *meta
+ message
Type string
}
@@ -824,8 +980,12 @@ func (msg *StateAction) Encode() []byte {
return buf[:p]
}
+func (msg *StateAction) TypeID() int {
+ return 42
+}
+
type StateActionEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Type string
@@ -841,8 +1001,12 @@ func (msg *StateActionEvent) Encode() []byte {
return buf[:p]
}
+func (msg *StateActionEvent) TypeID() int {
+ return 43
+}
+
type Redux struct {
- *meta
+ message
Action string
State string
Duration uint64
@@ -858,8 +1022,12 @@ func (msg *Redux) Encode() []byte {
return buf[:p]
}
+func (msg *Redux) TypeID() int {
+ return 44
+}
+
type Vuex struct {
- *meta
+ message
Mutation string
State string
}
@@ -873,8 +1041,12 @@ func (msg *Vuex) Encode() []byte {
return buf[:p]
}
+func (msg *Vuex) TypeID() int {
+ return 45
+}
+
type MobX struct {
- *meta
+ message
Type string
Payload string
}
@@ -888,8 +1060,12 @@ func (msg *MobX) Encode() []byte {
return buf[:p]
}
+func (msg *MobX) TypeID() int {
+ return 46
+}
+
type NgRx struct {
- *meta
+ message
Action string
State string
Duration uint64
@@ -905,8 +1081,12 @@ func (msg *NgRx) Encode() []byte {
return buf[:p]
}
+func (msg *NgRx) TypeID() int {
+ return 47
+}
+
type GraphQL struct {
- *meta
+ message
OperationKind string
OperationName string
Variables string
@@ -924,8 +1104,12 @@ func (msg *GraphQL) Encode() []byte {
return buf[:p]
}
+func (msg *GraphQL) TypeID() int {
+ return 48
+}
+
type PerformanceTrack struct {
- *meta
+ message
Frames int64
Ticks int64
TotalJSHeapSize uint64
@@ -943,8 +1127,12 @@ func (msg *PerformanceTrack) Encode() []byte {
return buf[:p]
}
+func (msg *PerformanceTrack) TypeID() int {
+ return 49
+}
+
type GraphQLEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
OperationKind string
@@ -966,8 +1154,12 @@ func (msg *GraphQLEvent) Encode() []byte {
return buf[:p]
}
+func (msg *GraphQLEvent) TypeID() int {
+ return 50
+}
+
type FetchEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Method string
@@ -993,8 +1185,12 @@ func (msg *FetchEvent) Encode() []byte {
return buf[:p]
}
+func (msg *FetchEvent) TypeID() int {
+ return 51
+}
+
type DOMDrop struct {
- *meta
+ message
Timestamp uint64
}
@@ -1006,8 +1202,12 @@ func (msg *DOMDrop) Encode() []byte {
return buf[:p]
}
+func (msg *DOMDrop) TypeID() int {
+ return 52
+}
+
type ResourceTiming struct {
- *meta
+ message
Timestamp uint64
Duration uint64
TTFB uint64
@@ -1033,8 +1233,12 @@ func (msg *ResourceTiming) Encode() []byte {
return buf[:p]
}
+func (msg *ResourceTiming) TypeID() int {
+ return 53
+}
+
type ConnectionInformation struct {
- *meta
+ message
Downlink uint64
Type string
}
@@ -1048,8 +1252,12 @@ func (msg *ConnectionInformation) Encode() []byte {
return buf[:p]
}
+func (msg *ConnectionInformation) TypeID() int {
+ return 54
+}
+
type SetPageVisibility struct {
- *meta
+ message
hidden bool
}
@@ -1061,8 +1269,12 @@ func (msg *SetPageVisibility) Encode() []byte {
return buf[:p]
}
+func (msg *SetPageVisibility) TypeID() int {
+ return 55
+}
+
type PerformanceTrackAggr struct {
- *meta
+ message
TimestampStart uint64
TimestampEnd uint64
MinFPS uint64
@@ -1100,8 +1312,12 @@ func (msg *PerformanceTrackAggr) Encode() []byte {
return buf[:p]
}
+func (msg *PerformanceTrackAggr) TypeID() int {
+ return 56
+}
+
type LongTask struct {
- *meta
+ message
Timestamp uint64
Duration uint64
Context uint64
@@ -1125,8 +1341,12 @@ func (msg *LongTask) Encode() []byte {
return buf[:p]
}
+func (msg *LongTask) TypeID() int {
+ return 59
+}
+
type SetNodeAttributeURLBased struct {
- *meta
+ message
ID uint64
Name string
Value string
@@ -1144,8 +1364,12 @@ func (msg *SetNodeAttributeURLBased) Encode() []byte {
return buf[:p]
}
+func (msg *SetNodeAttributeURLBased) TypeID() int {
+ return 60
+}
+
type SetCSSDataURLBased struct {
- *meta
+ message
ID uint64
Data string
BaseURL string
@@ -1161,8 +1385,12 @@ func (msg *SetCSSDataURLBased) Encode() []byte {
return buf[:p]
}
+func (msg *SetCSSDataURLBased) TypeID() int {
+ return 61
+}
+
type IssueEvent struct {
- *meta
+ message
MessageID uint64
Timestamp uint64
Type string
@@ -1184,8 +1412,12 @@ func (msg *IssueEvent) Encode() []byte {
return buf[:p]
}
+func (msg *IssueEvent) TypeID() int {
+ return 62
+}
+
type TechnicalInfo struct {
- *meta
+ message
Type string
Value string
}
@@ -1199,8 +1431,12 @@ func (msg *TechnicalInfo) Encode() []byte {
return buf[:p]
}
+func (msg *TechnicalInfo) TypeID() int {
+ return 63
+}
+
type CustomIssue struct {
- *meta
+ message
Name string
Payload string
}
@@ -1214,8 +1450,12 @@ func (msg *CustomIssue) Encode() []byte {
return buf[:p]
}
+func (msg *CustomIssue) TypeID() int {
+ return 64
+}
+
type PageClose struct {
- *meta
+ message
}
func (msg *PageClose) Encode() []byte {
@@ -1226,8 +1466,12 @@ func (msg *PageClose) Encode() []byte {
return buf[:p]
}
+func (msg *PageClose) TypeID() int {
+ return 65
+}
+
type AssetCache struct {
- *meta
+ message
URL string
}
@@ -1239,8 +1483,12 @@ func (msg *AssetCache) Encode() []byte {
return buf[:p]
}
+func (msg *AssetCache) TypeID() int {
+ return 66
+}
+
type CSSInsertRuleURLBased struct {
- *meta
+ message
ID uint64
Rule string
Index uint64
@@ -1258,8 +1506,12 @@ func (msg *CSSInsertRuleURLBased) Encode() []byte {
return buf[:p]
}
+func (msg *CSSInsertRuleURLBased) TypeID() int {
+ return 67
+}
+
type MouseClick struct {
- *meta
+ message
ID uint64
HesitationTime uint64
Label string
@@ -1277,8 +1529,12 @@ func (msg *MouseClick) Encode() []byte {
return buf[:p]
}
+func (msg *MouseClick) TypeID() int {
+ return 69
+}
+
type CreateIFrameDocument struct {
- *meta
+ message
FrameID uint64
ID uint64
}
@@ -1292,8 +1548,12 @@ func (msg *CreateIFrameDocument) Encode() []byte {
return buf[:p]
}
+func (msg *CreateIFrameDocument) TypeID() int {
+ return 70
+}
+
type IOSBatchMeta struct {
- *meta
+ message
Timestamp uint64
Length uint64
FirstIndex uint64
@@ -1309,8 +1569,12 @@ func (msg *IOSBatchMeta) Encode() []byte {
return buf[:p]
}
+func (msg *IOSBatchMeta) TypeID() int {
+ return 107
+}
+
type IOSSessionStart struct {
- *meta
+ message
Timestamp uint64
ProjectID uint64
TrackerVersion string
@@ -1340,8 +1604,12 @@ func (msg *IOSSessionStart) Encode() []byte {
return buf[:p]
}
+func (msg *IOSSessionStart) TypeID() int {
+ return 90
+}
+
type IOSSessionEnd struct {
- *meta
+ message
Timestamp uint64
}
@@ -1353,8 +1621,12 @@ func (msg *IOSSessionEnd) Encode() []byte {
return buf[:p]
}
+func (msg *IOSSessionEnd) TypeID() int {
+ return 91
+}
+
type IOSMetadata struct {
- *meta
+ message
Timestamp uint64
Length uint64
Key string
@@ -1372,8 +1644,12 @@ func (msg *IOSMetadata) Encode() []byte {
return buf[:p]
}
+func (msg *IOSMetadata) TypeID() int {
+ return 92
+}
+
type IOSCustomEvent struct {
- *meta
+ message
Timestamp uint64
Length uint64
Name string
@@ -1391,8 +1667,12 @@ func (msg *IOSCustomEvent) Encode() []byte {
return buf[:p]
}
+func (msg *IOSCustomEvent) TypeID() int {
+ return 93
+}
+
type IOSUserID struct {
- *meta
+ message
Timestamp uint64
Length uint64
Value string
@@ -1408,8 +1688,12 @@ func (msg *IOSUserID) Encode() []byte {
return buf[:p]
}
+func (msg *IOSUserID) TypeID() int {
+ return 94
+}
+
type IOSUserAnonymousID struct {
- *meta
+ message
Timestamp uint64
Length uint64
Value string
@@ -1425,8 +1709,12 @@ func (msg *IOSUserAnonymousID) Encode() []byte {
return buf[:p]
}
+func (msg *IOSUserAnonymousID) TypeID() int {
+ return 95
+}
+
type IOSScreenChanges struct {
- *meta
+ message
Timestamp uint64
Length uint64
X uint64
@@ -1448,8 +1736,12 @@ func (msg *IOSScreenChanges) Encode() []byte {
return buf[:p]
}
+func (msg *IOSScreenChanges) TypeID() int {
+ return 96
+}
+
type IOSCrash struct {
- *meta
+ message
Timestamp uint64
Length uint64
Name string
@@ -1469,8 +1761,12 @@ func (msg *IOSCrash) Encode() []byte {
return buf[:p]
}
+func (msg *IOSCrash) TypeID() int {
+ return 97
+}
+
type IOSScreenEnter struct {
- *meta
+ message
Timestamp uint64
Length uint64
Title string
@@ -1488,8 +1784,12 @@ func (msg *IOSScreenEnter) Encode() []byte {
return buf[:p]
}
+func (msg *IOSScreenEnter) TypeID() int {
+ return 98
+}
+
type IOSScreenLeave struct {
- *meta
+ message
Timestamp uint64
Length uint64
Title string
@@ -1507,8 +1807,12 @@ func (msg *IOSScreenLeave) Encode() []byte {
return buf[:p]
}
+func (msg *IOSScreenLeave) TypeID() int {
+ return 99
+}
+
type IOSClickEvent struct {
- *meta
+ message
Timestamp uint64
Length uint64
Label string
@@ -1528,8 +1832,12 @@ func (msg *IOSClickEvent) Encode() []byte {
return buf[:p]
}
+func (msg *IOSClickEvent) TypeID() int {
+ return 100
+}
+
type IOSInputEvent struct {
- *meta
+ message
Timestamp uint64
Length uint64
Value string
@@ -1549,8 +1857,12 @@ func (msg *IOSInputEvent) Encode() []byte {
return buf[:p]
}
+func (msg *IOSInputEvent) TypeID() int {
+ return 101
+}
+
type IOSPerformanceEvent struct {
- *meta
+ message
Timestamp uint64
Length uint64
Name string
@@ -1568,8 +1880,12 @@ func (msg *IOSPerformanceEvent) Encode() []byte {
return buf[:p]
}
+func (msg *IOSPerformanceEvent) TypeID() int {
+ return 102
+}
+
type IOSLog struct {
- *meta
+ message
Timestamp uint64
Length uint64
Severity string
@@ -1587,8 +1903,12 @@ func (msg *IOSLog) Encode() []byte {
return buf[:p]
}
+func (msg *IOSLog) TypeID() int {
+ return 103
+}
+
type IOSInternalError struct {
- *meta
+ message
Timestamp uint64
Length uint64
Content string
@@ -1604,8 +1924,12 @@ func (msg *IOSInternalError) Encode() []byte {
return buf[:p]
}
+func (msg *IOSInternalError) TypeID() int {
+ return 104
+}
+
type IOSNetworkCall struct {
- *meta
+ message
Timestamp uint64
Length uint64
Duration uint64
@@ -1633,8 +1957,12 @@ func (msg *IOSNetworkCall) Encode() []byte {
return buf[:p]
}
+func (msg *IOSNetworkCall) TypeID() int {
+ return 105
+}
+
type IOSPerformanceAggregated struct {
- *meta
+ message
TimestampStart uint64
TimestampEnd uint64
MinFPS uint64
@@ -1672,8 +2000,12 @@ func (msg *IOSPerformanceAggregated) Encode() []byte {
return buf[:p]
}
+func (msg *IOSPerformanceAggregated) TypeID() int {
+ return 110
+}
+
type IOSIssueEvent struct {
- *meta
+ message
Timestamp uint64
Type string
ContextString string
@@ -1692,3 +2024,7 @@ func (msg *IOSIssueEvent) Encode() []byte {
p = WriteString(msg.Payload, buf, p)
return buf[:p]
}
+
+func (msg *IOSIssueEvent) TypeID() int {
+ return 111
+}
diff --git a/backend/pkg/messages/read-message.go b/backend/pkg/messages/read-message.go
index 60f9c17a8..59c8e739c 100644
--- a/backend/pkg/messages/read-message.go
+++ b/backend/pkg/messages/read-message.go
@@ -14,7 +14,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
switch t {
case 80:
- msg := &BatchMeta{meta: &meta{TypeID: 80}}
+ msg := &BatchMeta{}
if msg.PageNo, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -27,14 +27,14 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 0:
- msg := &Timestamp{meta: &meta{TypeID: 0}}
+ msg := &Timestamp{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
return msg, nil
case 1:
- msg := &SessionStart{meta: &meta{TypeID: 1}}
+ msg := &SessionStart{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -86,21 +86,21 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 2:
- msg := &SessionDisconnect{meta: &meta{TypeID: 2}}
+ msg := &SessionDisconnect{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
return msg, nil
case 3:
- msg := &SessionEnd{meta: &meta{TypeID: 3}}
+ msg := &SessionEnd{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
return msg, nil
case 4:
- msg := &SetPageLocation{meta: &meta{TypeID: 4}}
+ msg := &SetPageLocation{}
if msg.URL, err = ReadString(reader); err != nil {
return nil, err
}
@@ -113,7 +113,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 5:
- msg := &SetViewportSize{meta: &meta{TypeID: 5}}
+ msg := &SetViewportSize{}
if msg.Width, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -123,7 +123,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 6:
- msg := &SetViewportScroll{meta: &meta{TypeID: 6}}
+ msg := &SetViewportScroll{}
if msg.X, err = ReadInt(reader); err != nil {
return nil, err
}
@@ -133,12 +133,12 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 7:
- msg := &CreateDocument{meta: &meta{TypeID: 7}}
+ msg := &CreateDocument{}
return msg, nil
case 8:
- msg := &CreateElementNode{meta: &meta{TypeID: 8}}
+ msg := &CreateElementNode{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -157,7 +157,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 9:
- msg := &CreateTextNode{meta: &meta{TypeID: 9}}
+ msg := &CreateTextNode{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -170,7 +170,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 10:
- msg := &MoveNode{meta: &meta{TypeID: 10}}
+ msg := &MoveNode{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -183,14 +183,14 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 11:
- msg := &RemoveNode{meta: &meta{TypeID: 11}}
+ msg := &RemoveNode{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
return msg, nil
case 12:
- msg := &SetNodeAttribute{meta: &meta{TypeID: 12}}
+ msg := &SetNodeAttribute{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -203,7 +203,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 13:
- msg := &RemoveNodeAttribute{meta: &meta{TypeID: 13}}
+ msg := &RemoveNodeAttribute{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -213,7 +213,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 14:
- msg := &SetNodeData{meta: &meta{TypeID: 14}}
+ msg := &SetNodeData{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -223,7 +223,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 15:
- msg := &SetCSSData{meta: &meta{TypeID: 15}}
+ msg := &SetCSSData{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -233,7 +233,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 16:
- msg := &SetNodeScroll{meta: &meta{TypeID: 16}}
+ msg := &SetNodeScroll{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -246,7 +246,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 17:
- msg := &SetInputTarget{meta: &meta{TypeID: 17}}
+ msg := &SetInputTarget{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -256,7 +256,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 18:
- msg := &SetInputValue{meta: &meta{TypeID: 18}}
+ msg := &SetInputValue{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -269,7 +269,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 19:
- msg := &SetInputChecked{meta: &meta{TypeID: 19}}
+ msg := &SetInputChecked{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -279,7 +279,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 20:
- msg := &MouseMove{meta: &meta{TypeID: 20}}
+ msg := &MouseMove{}
if msg.X, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -289,7 +289,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 21:
- msg := &MouseClickDepricated{meta: &meta{TypeID: 21}}
+ msg := &MouseClickDepricated{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -302,7 +302,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 22:
- msg := &ConsoleLog{meta: &meta{TypeID: 22}}
+ msg := &ConsoleLog{}
if msg.Level, err = ReadString(reader); err != nil {
return nil, err
}
@@ -312,7 +312,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 23:
- msg := &PageLoadTiming{meta: &meta{TypeID: 23}}
+ msg := &PageLoadTiming{}
if msg.RequestStart, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -343,7 +343,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 24:
- msg := &PageRenderTiming{meta: &meta{TypeID: 24}}
+ msg := &PageRenderTiming{}
if msg.SpeedIndex, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -356,7 +356,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 25:
- msg := &JSException{meta: &meta{TypeID: 25}}
+ msg := &JSException{}
if msg.Name, err = ReadString(reader); err != nil {
return nil, err
}
@@ -369,7 +369,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 26:
- msg := &RawErrorEvent{meta: &meta{TypeID: 26}}
+ msg := &RawErrorEvent{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -388,7 +388,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 27:
- msg := &RawCustomEvent{meta: &meta{TypeID: 27}}
+ msg := &RawCustomEvent{}
if msg.Name, err = ReadString(reader); err != nil {
return nil, err
}
@@ -398,21 +398,21 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 28:
- msg := &UserID{meta: &meta{TypeID: 28}}
+ msg := &UserID{}
if msg.ID, err = ReadString(reader); err != nil {
return nil, err
}
return msg, nil
case 29:
- msg := &UserAnonymousID{meta: &meta{TypeID: 29}}
+ msg := &UserAnonymousID{}
if msg.ID, err = ReadString(reader); err != nil {
return nil, err
}
return msg, nil
case 30:
- msg := &Metadata{meta: &meta{TypeID: 30}}
+ msg := &Metadata{}
if msg.Key, err = ReadString(reader); err != nil {
return nil, err
}
@@ -422,7 +422,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 31:
- msg := &PageEvent{meta: &meta{TypeID: 31}}
+ msg := &PageEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -477,7 +477,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 32:
- msg := &InputEvent{meta: &meta{TypeID: 32}}
+ msg := &InputEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -496,7 +496,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 33:
- msg := &ClickEvent{meta: &meta{TypeID: 33}}
+ msg := &ClickEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -515,7 +515,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 34:
- msg := &ErrorEvent{meta: &meta{TypeID: 34}}
+ msg := &ErrorEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -537,7 +537,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 35:
- msg := &ResourceEvent{meta: &meta{TypeID: 35}}
+ msg := &ResourceEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -577,7 +577,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 36:
- msg := &CustomEvent{meta: &meta{TypeID: 36}}
+ msg := &CustomEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -593,7 +593,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 37:
- msg := &CSSInsertRule{meta: &meta{TypeID: 37}}
+ msg := &CSSInsertRule{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -606,7 +606,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 38:
- msg := &CSSDeleteRule{meta: &meta{TypeID: 38}}
+ msg := &CSSDeleteRule{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -616,7 +616,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 39:
- msg := &Fetch{meta: &meta{TypeID: 39}}
+ msg := &Fetch{}
if msg.Method, err = ReadString(reader); err != nil {
return nil, err
}
@@ -641,7 +641,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 40:
- msg := &Profiler{meta: &meta{TypeID: 40}}
+ msg := &Profiler{}
if msg.Name, err = ReadString(reader); err != nil {
return nil, err
}
@@ -657,7 +657,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 41:
- msg := &OTable{meta: &meta{TypeID: 41}}
+ msg := &OTable{}
if msg.Key, err = ReadString(reader); err != nil {
return nil, err
}
@@ -667,14 +667,14 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 42:
- msg := &StateAction{meta: &meta{TypeID: 42}}
+ msg := &StateAction{}
if msg.Type, err = ReadString(reader); err != nil {
return nil, err
}
return msg, nil
case 43:
- msg := &StateActionEvent{meta: &meta{TypeID: 43}}
+ msg := &StateActionEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -687,7 +687,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 44:
- msg := &Redux{meta: &meta{TypeID: 44}}
+ msg := &Redux{}
if msg.Action, err = ReadString(reader); err != nil {
return nil, err
}
@@ -700,7 +700,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 45:
- msg := &Vuex{meta: &meta{TypeID: 45}}
+ msg := &Vuex{}
if msg.Mutation, err = ReadString(reader); err != nil {
return nil, err
}
@@ -710,7 +710,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 46:
- msg := &MobX{meta: &meta{TypeID: 46}}
+ msg := &MobX{}
if msg.Type, err = ReadString(reader); err != nil {
return nil, err
}
@@ -720,7 +720,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 47:
- msg := &NgRx{meta: &meta{TypeID: 47}}
+ msg := &NgRx{}
if msg.Action, err = ReadString(reader); err != nil {
return nil, err
}
@@ -733,7 +733,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 48:
- msg := &GraphQL{meta: &meta{TypeID: 48}}
+ msg := &GraphQL{}
if msg.OperationKind, err = ReadString(reader); err != nil {
return nil, err
}
@@ -749,7 +749,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 49:
- msg := &PerformanceTrack{meta: &meta{TypeID: 49}}
+ msg := &PerformanceTrack{}
if msg.Frames, err = ReadInt(reader); err != nil {
return nil, err
}
@@ -765,7 +765,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 50:
- msg := &GraphQLEvent{meta: &meta{TypeID: 50}}
+ msg := &GraphQLEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -787,7 +787,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 51:
- msg := &FetchEvent{meta: &meta{TypeID: 51}}
+ msg := &FetchEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -815,14 +815,14 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 52:
- msg := &DOMDrop{meta: &meta{TypeID: 52}}
+ msg := &DOMDrop{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
return msg, nil
case 53:
- msg := &ResourceTiming{meta: &meta{TypeID: 53}}
+ msg := &ResourceTiming{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -850,7 +850,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 54:
- msg := &ConnectionInformation{meta: &meta{TypeID: 54}}
+ msg := &ConnectionInformation{}
if msg.Downlink, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -860,14 +860,14 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 55:
- msg := &SetPageVisibility{meta: &meta{TypeID: 55}}
+ msg := &SetPageVisibility{}
if msg.hidden, err = ReadBoolean(reader); err != nil {
return nil, err
}
return msg, nil
case 56:
- msg := &PerformanceTrackAggr{meta: &meta{TypeID: 56}}
+ msg := &PerformanceTrackAggr{}
if msg.TimestampStart, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -913,7 +913,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 59:
- msg := &LongTask{meta: &meta{TypeID: 59}}
+ msg := &LongTask{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -938,7 +938,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 60:
- msg := &SetNodeAttributeURLBased{meta: &meta{TypeID: 60}}
+ msg := &SetNodeAttributeURLBased{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -954,7 +954,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 61:
- msg := &SetCSSDataURLBased{meta: &meta{TypeID: 61}}
+ msg := &SetCSSDataURLBased{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -967,7 +967,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 62:
- msg := &IssueEvent{meta: &meta{TypeID: 62}}
+ msg := &IssueEvent{}
if msg.MessageID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -989,7 +989,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 63:
- msg := &TechnicalInfo{meta: &meta{TypeID: 63}}
+ msg := &TechnicalInfo{}
if msg.Type, err = ReadString(reader); err != nil {
return nil, err
}
@@ -999,7 +999,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 64:
- msg := &CustomIssue{meta: &meta{TypeID: 64}}
+ msg := &CustomIssue{}
if msg.Name, err = ReadString(reader); err != nil {
return nil, err
}
@@ -1009,19 +1009,19 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 65:
- msg := &PageClose{meta: &meta{TypeID: 65}}
+ msg := &PageClose{}
return msg, nil
case 66:
- msg := &AssetCache{meta: &meta{TypeID: 66}}
+ msg := &AssetCache{}
if msg.URL, err = ReadString(reader); err != nil {
return nil, err
}
return msg, nil
case 67:
- msg := &CSSInsertRuleURLBased{meta: &meta{TypeID: 67}}
+ msg := &CSSInsertRuleURLBased{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1037,7 +1037,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 69:
- msg := &MouseClick{meta: &meta{TypeID: 69}}
+ msg := &MouseClick{}
if msg.ID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1053,7 +1053,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 70:
- msg := &CreateIFrameDocument{meta: &meta{TypeID: 70}}
+ msg := &CreateIFrameDocument{}
if msg.FrameID, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1063,7 +1063,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 107:
- msg := &IOSBatchMeta{meta: &meta{TypeID: 107}}
+ msg := &IOSBatchMeta{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1076,7 +1076,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 90:
- msg := &IOSSessionStart{meta: &meta{TypeID: 90}}
+ msg := &IOSSessionStart{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1110,14 +1110,14 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 91:
- msg := &IOSSessionEnd{meta: &meta{TypeID: 91}}
+ msg := &IOSSessionEnd{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
return msg, nil
case 92:
- msg := &IOSMetadata{meta: &meta{TypeID: 92}}
+ msg := &IOSMetadata{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1133,7 +1133,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 93:
- msg := &IOSCustomEvent{meta: &meta{TypeID: 93}}
+ msg := &IOSCustomEvent{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1149,7 +1149,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 94:
- msg := &IOSUserID{meta: &meta{TypeID: 94}}
+ msg := &IOSUserID{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1162,7 +1162,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 95:
- msg := &IOSUserAnonymousID{meta: &meta{TypeID: 95}}
+ msg := &IOSUserAnonymousID{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1175,7 +1175,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 96:
- msg := &IOSScreenChanges{meta: &meta{TypeID: 96}}
+ msg := &IOSScreenChanges{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1197,7 +1197,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 97:
- msg := &IOSCrash{meta: &meta{TypeID: 97}}
+ msg := &IOSCrash{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1216,7 +1216,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 98:
- msg := &IOSScreenEnter{meta: &meta{TypeID: 98}}
+ msg := &IOSScreenEnter{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1232,7 +1232,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 99:
- msg := &IOSScreenLeave{meta: &meta{TypeID: 99}}
+ msg := &IOSScreenLeave{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1248,7 +1248,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 100:
- msg := &IOSClickEvent{meta: &meta{TypeID: 100}}
+ msg := &IOSClickEvent{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1267,7 +1267,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 101:
- msg := &IOSInputEvent{meta: &meta{TypeID: 101}}
+ msg := &IOSInputEvent{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1286,7 +1286,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 102:
- msg := &IOSPerformanceEvent{meta: &meta{TypeID: 102}}
+ msg := &IOSPerformanceEvent{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1302,7 +1302,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 103:
- msg := &IOSLog{meta: &meta{TypeID: 103}}
+ msg := &IOSLog{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1318,7 +1318,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 104:
- msg := &IOSInternalError{meta: &meta{TypeID: 104}}
+ msg := &IOSInternalError{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1331,7 +1331,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 105:
- msg := &IOSNetworkCall{meta: &meta{TypeID: 105}}
+ msg := &IOSNetworkCall{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1362,7 +1362,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 110:
- msg := &IOSPerformanceAggregated{meta: &meta{TypeID: 110}}
+ msg := &IOSPerformanceAggregated{}
if msg.TimestampStart, err = ReadUint(reader); err != nil {
return nil, err
}
@@ -1408,7 +1408,7 @@ func ReadMessage(reader io.Reader) (Message, error) {
return msg, nil
case 111:
- msg := &IOSIssueEvent{meta: &meta{TypeID: 111}}
+ msg := &IOSIssueEvent{}
if msg.Timestamp, err = ReadUint(reader); err != nil {
return nil, err
}
diff --git a/backend/services/sink/build_hack b/backend/services/sink/build_hack
new file mode 100644
index 000000000..e69de29bb
diff --git a/frontend/app/api_client.js b/frontend/app/api_client.js
index 98a1f4dfd..a5fae45e7 100644
--- a/frontend/app/api_client.js
+++ b/frontend/app/api_client.js
@@ -24,7 +24,8 @@ const siteIdRequiredPaths = [
'/heatmaps',
'/custom_metrics',
'/dashboards',
- '/metrics'
+ '/metrics',
+ '/trails',
// '/custom_metrics/sessions',
];
diff --git a/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx b/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx
new file mode 100644
index 000000000..934604dbb
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditDetailModal/AuditDetailModal.tsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import { JSONTree } from 'UI';
+import { checkForRecent } from 'App/date';
+
+interface Props {
+ audit: any;
+}
+function AuditDetailModal(props: Props) {
+ const { audit } = props;
+ // const jsonResponse = typeof audit.payload === 'string' ? JSON.parse(audit.payload) : audit.payload;
+ // console.log('jsonResponse', jsonResponse)
+
+ return (
+
+
Audit Details
+
+
{ 'URL'}
+
{ audit.endPoint }
+
+
+
+
Username
+
{audit.username}
+
+
+
Created At
+
{audit.createdAt && checkForRecent(audit.createdAt, 'LLL dd, yyyy, hh:mm a')}
+
+
+
+
+
+
Action
+
{audit.action}
+
+
+
Method
+
{audit.method}
+
+
+
+ { audit.payload && (
+
+ )}
+
+
+ );
+}
+
+export default AuditDetailModal;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditDetailModal/index.ts b/frontend/app/components/Client/Audit/AuditDetailModal/index.ts
new file mode 100644
index 000000000..fcf6bb2b4
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditDetailModal/index.ts
@@ -0,0 +1 @@
+export { default } from './AuditDetailModal';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditList/AuditList.tsx b/frontend/app/components/Client/Audit/AuditList/AuditList.tsx
new file mode 100644
index 000000000..5ab4c0d3a
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditList/AuditList.tsx
@@ -0,0 +1,67 @@
+import { useModal } from 'App/components/Modal';
+import { useStore } from 'App/mstore';
+import { useObserver } from 'mobx-react-lite';
+import React, { useEffect } from 'react';
+import { Loader, Pagination, NoContent } from 'UI';
+import AuditDetailModal from '../AuditDetailModal';
+import AuditListItem from '../AuditListItem';
+
+interface Props {
+
+}
+function AuditList(props: Props) {
+ const { auditStore } = useStore();
+ const loading = useObserver(() => auditStore.isLoading);
+ const list = useObserver(() => auditStore.list);
+ const searchQuery = useObserver(() => auditStore.searchQuery);
+ const page = useObserver(() => auditStore.page);
+ const order = useObserver(() => auditStore.order);
+ const period = useObserver(() => auditStore.period);
+ const { showModal } = useModal();
+ console.log('AuditList', period.toTimestamps());
+
+ useEffect(() => {
+ const { startTimestamp, endTimestamp } = period.toTimestamps();
+ auditStore.fetchAudits({
+ page: auditStore.page,
+ limit: auditStore.pageSize,
+ query: auditStore.searchQuery,
+ order: auditStore.order,
+ startDate: startTimestamp,
+ endDate: endTimestamp,
+ });
+ }, [page, searchQuery, order, period]);
+
+ return useObserver(() => (
+
+
+
+
+ {list.map((item, index) => (
+
+
showModal(, { right: true })}
+ />
+
+ ))}
+
+
+
auditStore.updateKey('page', page)}
+ limit={auditStore.pageSize}
+ debounceRequest={200}
+ />
+
+
+
+ ));
+}
+
+export default AuditList;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditList/index.ts b/frontend/app/components/Client/Audit/AuditList/index.ts
new file mode 100644
index 000000000..2e6bc3739
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditList/index.ts
@@ -0,0 +1 @@
+export { default } from './AuditList'
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx b/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx
new file mode 100644
index 000000000..7d584bb06
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditListItem/AuditListItem.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { checkForRecent } from 'App/date';
+
+interface Props {
+ audit: any;
+ onShowDetails: () => void;
+}
+function AuditListItem(props: Props) {
+ const { audit, onShowDetails } = props;
+ return (
+
+
{audit.username}
+
{audit.action}
+
{audit.createdAt && checkForRecent(audit.createdAt, 'LLL dd, yyyy, hh:mm a')}
+
+ );
+}
+
+export default AuditListItem;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditListItem/index.ts b/frontend/app/components/Client/Audit/AuditListItem/index.ts
new file mode 100644
index 000000000..821ee9639
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditListItem/index.ts
@@ -0,0 +1 @@
+export { default } from './AuditListItem';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx b/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx
new file mode 100644
index 000000000..5574da847
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditSearchField/AuditSearchField.tsx
@@ -0,0 +1,33 @@
+import React, { useEffect } from 'react';
+import { Icon } from 'UI';
+import { debounce } from 'App/utils';
+
+let debounceUpdate: any = () => {}
+interface Props {
+ onChange: (value: string) => void;
+}
+function AuditSearchField(props: Props) {
+ const { onChange } = props;
+
+ useEffect(() => {
+ debounceUpdate = debounce((value) => onChange(value), 500);
+ }, [])
+
+ const write = ({ target: { name, value } }) => {
+ debounceUpdate(value);
+ }
+
+ return (
+
+
+
+
+ );
+}
+
+export default AuditSearchField;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditSearchField/index.ts b/frontend/app/components/Client/Audit/AuditSearchField/index.ts
new file mode 100644
index 000000000..646947095
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditSearchField/index.ts
@@ -0,0 +1 @@
+export { default } from './AuditSearchField';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditView/AuditView.tsx b/frontend/app/components/Client/Audit/AuditView/AuditView.tsx
new file mode 100644
index 000000000..41d506b11
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditView/AuditView.tsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import { PageTitle, Icon } from 'UI';
+import AuditList from '../AuditList';
+import AuditSearchField from '../AuditSearchField';
+import { useStore } from 'App/mstore';
+import { useObserver } from 'mobx-react-lite';
+import Select from 'Shared/Select';
+import SelectDateRange from 'Shared/SelectDateRange';
+
+function AuditView(props) {
+ const { auditStore } = useStore();
+ const order = useObserver(() => auditStore.order);
+ const total = useObserver(() => auditStore.total);
+
+ const exportToCsv = () => {
+ auditStore.exportToCsv();
+ }
+
+ const onChange = (data) => {
+ auditStore.setDateRange(data);
+ }
+
+ return useObserver(() => (
+
+
+
+ Audit Trail
+ {total}
+
+ } />
+
+
+
+
+
+
+
auditStore.updateKey('searchQuery', value) }/>
+
+
+
+
+
+
+
+
+ ));
+}
+
+export default AuditView;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Audit/AuditView/index.ts b/frontend/app/components/Client/Audit/AuditView/index.ts
new file mode 100644
index 000000000..ba32b1be0
--- /dev/null
+++ b/frontend/app/components/Client/Audit/AuditView/index.ts
@@ -0,0 +1 @@
+export { default } from './AuditView'
\ No newline at end of file
diff --git a/frontend/app/components/Client/Client.js b/frontend/app/components/Client/Client.js
index cb55d933d..c58056b5f 100644
--- a/frontend/app/components/Client/Client.js
+++ b/frontend/app/components/Client/Client.js
@@ -7,6 +7,8 @@ import { fetchList as fetchMemberList } from 'Duck/member';
import ProfileSettings from './ProfileSettings';
import Integrations from './Integrations';
import ManageUsers from './ManageUsers';
+import UserView from './Users/UsersView';
+import AuditView from './Audit/AuditView';
import Sites from './Sites';
import CustomFields from './CustomFields';
import Webhooks from './Webhooks';
@@ -25,7 +27,7 @@ import Roles from './Roles';
export default class Client extends React.PureComponent {
constructor(props){
super(props);
- props.fetchMemberList();
+ // props.fetchMemberList();
}
setTab = (tab) => {
@@ -36,12 +38,13 @@ export default class Client extends React.PureComponent {
-
+
+
)
diff --git a/frontend/app/components/Client/ManageUsers/ManageUsers.js b/frontend/app/components/Client/ManageUsers/ManageUsers.js
index 9071ee46b..1504a0631 100644
--- a/frontend/app/components/Client/ManageUsers/ManageUsers.js
+++ b/frontend/app/components/Client/ManageUsers/ManageUsers.js
@@ -236,7 +236,7 @@ class ManageUsers extends React.PureComponent {
title="No users are available."
size="small"
show={ members.size === 0 }
- icon
+ animatedIcon="empty-state"
>
{
diff --git a/frontend/app/components/Client/PreferencesMenu/PreferencesMenu.js b/frontend/app/components/Client/PreferencesMenu/PreferencesMenu.js
index 0c57c1ab7..682d1519a 100644
--- a/frontend/app/components/Client/PreferencesMenu/PreferencesMenu.js
+++ b/frontend/app/components/Client/PreferencesMenu/PreferencesMenu.js
@@ -78,6 +78,17 @@ function PreferencesMenu({ activeTab, appearance, history, isEnterprise }) {
/>
)}
+
+ { isEnterprise && (
+
+ setTab(CLIENT_TABS.AUDIT) }
+ />
+
+ )}
setTab(CLIENT_TABS.NOTIFICATIONS) }
/>
-
+
)
}
diff --git a/frontend/app/components/Client/Sites/NewSiteForm.js b/frontend/app/components/Client/Sites/NewSiteForm.js
index e58e95d4e..e7cd88f12 100644
--- a/frontend/app/components/Client/Sites/NewSiteForm.js
+++ b/frontend/app/components/Client/Sites/NewSiteForm.js
@@ -1,10 +1,11 @@
import { connect } from 'react-redux';
-import { Input, Button, Label } from 'UI';
-import { save, edit, update , fetchList } from 'Duck/site';
+import { Input, Button, Icon } from 'UI';
+import { save, edit, update , fetchList, remove } from 'Duck/site';
import { pushNewSite } from 'Duck/user';
import { setSiteId } from 'Duck/site';
import { withRouter } from 'react-router-dom';
import styles from './siteForm.css';
+import { confirm } from 'UI/Confirmation';
@connect(state => ({
site: state.getIn([ 'site', 'instance' ]),
@@ -13,6 +14,7 @@ import styles from './siteForm.css';
loading: state.getIn([ 'site', 'save', 'loading' ]),
}), {
save,
+ remove,
edit,
update,
pushNewSite,
@@ -52,6 +54,17 @@ export default class NewSiteForm extends React.PureComponent {
}
}
+ remove = async (site) => {
+ if (await confirm({
+ header: 'Projects',
+ confirmation: `Are you sure you want to delete this Project? We won't be able to record anymore sessions.`
+ })) {
+ this.props.remove(site.id).then(() => {
+ this.props.onClose(null)
+ });
+ }
+ };
+
edit = ({ target: { name, value } }) => {
this.setState({ existsError: false });
this.props.edit({ [ name ]: value });
@@ -72,7 +85,7 @@ export default class NewSiteForm extends React.PureComponent {
className={ styles.input }
/>
-
+
-
+
+
{ this.state.existsError &&
{ "Site exists already. Please choose another one." }
diff --git a/frontend/app/components/Client/Sites/SiteSearch/SiteSearch.tsx b/frontend/app/components/Client/Sites/SiteSearch/SiteSearch.tsx
new file mode 100644
index 000000000..1a4c2b881
--- /dev/null
+++ b/frontend/app/components/Client/Sites/SiteSearch/SiteSearch.tsx
@@ -0,0 +1,34 @@
+import React, { useEffect } from 'react';
+import { Icon } from 'UI';
+import { debounce } from 'App/utils';
+
+let debounceUpdate: any = () => {}
+interface Props {
+ onChange: (value: string) => void;
+}
+function SiteSearch(props: Props) {
+ const { onChange } = props;
+
+ useEffect(() => {
+ debounceUpdate = debounce((value) => onChange(value), 500);
+ }, [])
+
+ const write = ({ target: { name, value } }) => {
+ debounceUpdate(value);
+ }
+
+ return (
+
+
+
+
+ );
+}
+
+export default SiteSearch;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Sites/SiteSearch/index.ts b/frontend/app/components/Client/Sites/SiteSearch/index.ts
new file mode 100644
index 000000000..54376cf15
--- /dev/null
+++ b/frontend/app/components/Client/Sites/SiteSearch/index.ts
@@ -0,0 +1 @@
+export { default } from './SiteSearch';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Sites/Sites.js b/frontend/app/components/Client/Sites/Sites.js
index 4769815e5..ba3c72e6e 100644
--- a/frontend/app/components/Client/Sites/Sites.js
+++ b/frontend/app/components/Client/Sites/Sites.js
@@ -10,6 +10,7 @@ import GDPRForm from './GDPRForm';
import TrackingCodeModal from 'Shared/TrackingCodeModal';
import BlockedIps from './BlockedIps';
import { confirm } from 'UI/Confirmation';
+import SiteSearch from './SiteSearch';
const STATUS_MESSAGE_MAP = {
[ RED ]: ' There seems to be an issue (please verify your installation)',
@@ -43,6 +44,7 @@ class Sites extends React.PureComponent {
showTrackingCode: false,
modalContent: NONE,
detailContent: NONE,
+ searchQuery: '',
};
toggleBlockedIp = () => {
@@ -85,7 +87,7 @@ class Sites extends React.PureComponent {
getModalTitle() {
switch (this.state.modalContent) {
case NEW_SITE_FORM:
- return 'New Project';
+ return this.props.site.exists() ? 'Update Project' : 'New Project';
case GDPR_FORM:
return 'Project Settings';
default:
@@ -119,6 +121,7 @@ class Sites extends React.PureComponent {
const isAdmin = user.admin || user.superAdmin;
const canAddSites = isAdmin && account.limits.projects && account.limits.projects.remaining !== 0;
const canDeleteSites = sites.size > 1 && isAdmin;
+ const filteredSites = sites.filter(site => site.name.toLowerCase().includes(this.state.searchQuery.toLowerCase()));
return (
@@ -159,54 +162,71 @@ class Sites extends React.PureComponent {
position="top left"
/>
-
+
+
+ this.setState({ searchQuery: value })} />
+
+
{
- sites.map(_site => (
-
-
-
-
+ filteredSites.map(_site => (
+ //
+
+
+
+ }
+ content={ STATUS_MESSAGE_MAP[ _site.status ] }
+ inverted
+ position="top center"
+ />
+
{ _site.host }
- }
- content={ STATUS_MESSAGE_MAP[ _site.status ] }
- inverted
- position="top center"
- />
-
+
+
+ {_site.projectKey}
+
+ {/*
{ _site.host }
{_site.projectKey}
+
*/}
+
+
+ {/*
*/}
+
+ {/*
*/}
-
-
-
-
- {/*
*/}
-
-
+ //
))
}
diff --git a/frontend/app/components/Client/Users/UsersView.tsx b/frontend/app/components/Client/Users/UsersView.tsx
new file mode 100644
index 000000000..37e6fdbcd
--- /dev/null
+++ b/frontend/app/components/Client/Users/UsersView.tsx
@@ -0,0 +1,80 @@
+import React, { useEffect } from 'react';
+import UserList from './components/UserList';
+import { PageTitle, Popup, IconButton } from 'UI';
+import { useStore } from 'App/mstore';
+import { useObserver } from 'mobx-react-lite';
+import UserSearch from './components/UserSearch';
+import { useModal } from 'App/components/Modal';
+import UserForm from './components/UserForm';
+import { connect } from 'react-redux';
+
+const PERMISSION_WARNING = 'You don’t have the permissions to perform this action.';
+const LIMIT_WARNING = 'You have reached users limit.';
+interface Props {
+ account: any;
+ isEnterprise: boolean;
+ limits: any;
+}
+function UsersView(props: Props) {
+ const { account, limits, isEnterprise } = props;
+ const { userStore, roleStore } = useStore();
+ const userCount = useObserver(() => userStore.list.length);
+ const roles = useObserver(() => roleStore.list);
+ const { showModal } = useModal();
+
+ const reachedLimit = (limits.remaining + userStore.modifiedCount) <= 0;
+ const isAdmin = account.admin || account.superAdmin;
+
+ const editHandler = (user = null) => {
+ userStore.initUser(user).then(() => {
+ showModal(
, {});
+ });
+ }
+
+ useEffect(() => {
+ if (roles.length === 0 && isEnterprise) {
+ roleStore.fetchRoles();
+ }
+ }, []);
+
+ return (
+
+
}
+ actionButton={(
+
+ editHandler(null) }
+ />
+
+ }
+ content={ `${ !isAdmin ? PERMISSION_WARNING : (reachedLimit ? LIMIT_WARNING : 'Add team member') }` }
+ size="tiny"
+ inverted
+ position="top left"
+ />
+ )}
+ />
+
+
+
+
+
+
+ );
+}
+
+export default connect(state => ({
+ account: state.getIn([ 'user', 'account' ]),
+ isEnterprise: state.getIn([ 'user', 'client', 'edition' ]) === 'ee',
+ limits: state.getIn([ 'user', 'account', 'limits', 'teamMember' ]),
+}))(UsersView);
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx b/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx
new file mode 100644
index 000000000..25f35097c
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx
@@ -0,0 +1,154 @@
+import React from 'react';
+import { Input, CopyButton, Button, Icon } from 'UI'
+import cn from 'classnames';
+import { useStore } from 'App/mstore';
+import { useObserver } from 'mobx-react-lite';
+import { useModal } from 'App/components/Modal';
+import Select from 'Shared/Select';
+import { confirm } from 'UI/Confirmation';
+interface Props {
+ isSmtp?: boolean;
+ isEnterprise?: boolean;
+}
+function UserForm(props: Props) {
+ const { isSmtp = false, isEnterprise = false } = props;
+ const { hideModal } = useModal();
+ const { userStore, roleStore } = useStore();
+ const isSaving = useObserver(() => userStore.saving);
+ const user: any = useObserver(() => userStore.instance);
+ const roles = useObserver(() => roleStore.list.filter(r => r.isProtected ? user.isSuperAdmin : true).map(r => ({ label: r.name, value: r.roleId })));
+
+ const onChangeCheckbox = (e: any) => {
+ user.updateKey('isAdmin', !user.isAdmin);
+ }
+
+ const onSave = () => {
+ userStore.saveUser(user).then(() => {
+ hideModal();
+ });
+ }
+
+ const write = ({ target: { name, value } }) => {
+ user.updateKey(name, value);
+ }
+
+ const deleteHandler = async () => {
+ if (await confirm({
+ header: 'Confirm',
+ confirmButton: 'Yes, delete',
+ confirmation: `Are you sure you want to permanently delete this user?`
+ })) {
+ userStore.deleteUser(user.userId).then(() => {
+ hideModal();
+ });
+ }
+ }
+
+ return useObserver(() => (
+
+
+
{`${user.exists() ? 'Update' : 'Invite'} User`}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { !user.isJoined && user.invitationLink &&
+
+ }
+
+ ));
+}
+
+export default UserForm;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserForm/index.ts b/frontend/app/components/Client/Users/components/UserForm/index.ts
new file mode 100644
index 000000000..3a390c510
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserForm/index.ts
@@ -0,0 +1 @@
+export { default } from './UserForm';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserList/UserList.tsx b/frontend/app/components/Client/Users/components/UserList/UserList.tsx
new file mode 100644
index 000000000..b01fca57b
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserList/UserList.tsx
@@ -0,0 +1,80 @@
+import { useStore } from 'App/mstore';
+import { useObserver } from 'mobx-react-lite';
+import React, { useEffect } from 'react';
+import UserListItem from '../UserListItem';
+import { sliceListPerPage, getRE } from 'App/utils';
+import { Pagination, NoContent, Loader } from 'UI';
+import { useModal } from 'App/components/Modal';
+import UserForm from '../UserForm';
+
+interface Props {
+ isEnterprise?: boolean;
+}
+function UserList(props: Props) {
+ const { isEnterprise = false } = props;
+ const { userStore } = useStore();
+ const loading = useObserver(() => userStore.loading);
+ const users = useObserver(() => userStore.list);
+ const searchQuery = useObserver(() => userStore.searchQuery);
+ const { showModal } = useModal();
+
+ const filterList = (list) => {
+ const filterRE = getRE(searchQuery, 'i');
+ let _list = list.filter(w => {
+ return filterRE.test(w.email) || filterRE.test(w.roleName);
+ });
+ return _list
+ }
+
+ const list: any = searchQuery !== '' ? filterList(users) : users;
+ const length = list.length;
+
+ useEffect(() => {
+ userStore.fetchUsers();
+ }, []);
+
+ const editHandler = (user) => {
+ userStore.initUser(user).then(() => {
+ showModal(, { });
+ });
+ }
+
+ return useObserver(() => (
+
+
+
+
+
Name
+
Role
+
Created On
+
+
+
+ {sliceListPerPage(list, userStore.page - 1, userStore.pageSize).map((user: any) => (
+
+ editHandler(user)}
+ generateInvite={() => userStore.generateInviteCode(user.userId)}
+ copyInviteCode={() => userStore.copyInviteCode(user.userId)}
+ // isEnterprise={isEnterprise}
+ />
+
+ ))}
+
+
+
+
userStore.updateKey('page', page)}
+ limit={userStore.pageSize}
+ debounceRequest={100}
+ />
+
+
+
+ ));
+}
+
+export default UserList;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserList/index.ts b/frontend/app/components/Client/Users/components/UserList/index.ts
new file mode 100644
index 000000000..129ddae35
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserList/index.ts
@@ -0,0 +1 @@
+export { default } from './UserList'
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserListItem/UserListItem.tsx b/frontend/app/components/Client/Users/components/UserListItem/UserListItem.tsx
new file mode 100644
index 000000000..51ea43422
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserListItem/UserListItem.tsx
@@ -0,0 +1,84 @@
+//@ts-nocheck
+import React from 'react';
+import { Icon } from 'UI';
+import { checkForRecent } from 'App/date';
+import { Tooltip } from 'react-tippy';
+
+
+const AdminPrivilegeLabel = ({ user }) => {
+ return (
+ <>
+ {user.isAdmin && Admin}
+ {user.isSuperAdmin && Owner}
+ >
+ )
+}
+interface Props {
+ user: any;
+ editHandler?: any;
+ generateInvite?: any;
+ copyInviteCode?: any;
+ isEnterprise?: boolean;
+}
+function UserListItem(props: Props) {
+ const {
+ user,
+ editHandler = () => {},
+ generateInvite = () => {},
+ copyInviteCode = () => {},
+ isEnterprise = false,
+ } = props;
+ return (
+
+
+
{user.name}
+ {isEnterprise &&
}
+
+
+ {!isEnterprise &&
}
+ {isEnterprise && (
+
+ {user.roleName}
+
+ )}
+
+
+ {user.createdAt && checkForRecent(user.createdAt, 'LLL dd, yyyy, hh:mm a')}
+
+
+
+
+ {!user.isJoined && user.invitationLink ? (
+
+
+
+ ) :
}
+ {!user.isJoined && user.isExpiredInvite && (
+
+
+
+ )}
+
+
+
+
+ );
+}
+
+export default UserListItem;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserListItem/index.ts b/frontend/app/components/Client/Users/components/UserListItem/index.ts
new file mode 100644
index 000000000..f0e2ae7e3
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserListItem/index.ts
@@ -0,0 +1 @@
+export { default } from './UserListItem';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserSearch/UserSearch.tsx b/frontend/app/components/Client/Users/components/UserSearch/UserSearch.tsx
new file mode 100644
index 000000000..cc78476d8
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserSearch/UserSearch.tsx
@@ -0,0 +1,35 @@
+import { useObserver } from 'mobx-react-lite';
+import React, { useEffect, useState } from 'react';
+import { useStore } from 'App/mstore';
+import { Icon } from 'UI';
+import { debounce } from 'App/utils';
+
+let debounceUpdate: any = () => {}
+function UserSearch(props) {
+ const { userStore } = useStore();
+ const [query, setQuery] = useState(userStore.searchQuery);
+
+ useEffect(() => {
+ debounceUpdate = debounce((key, value) => userStore.updateKey(key, value), 500);
+ }, [])
+
+ const write = ({ target: { name, value } }) => {
+ setQuery(value);
+ debounceUpdate(name, value);
+ }
+
+ return useObserver(() => (
+
+
+
+
+ ));
+}
+
+export default UserSearch;
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/UserSearch/index.ts b/frontend/app/components/Client/Users/components/UserSearch/index.ts
new file mode 100644
index 000000000..3810a4030
--- /dev/null
+++ b/frontend/app/components/Client/Users/components/UserSearch/index.ts
@@ -0,0 +1 @@
+export { default } from './UserSearch';
\ No newline at end of file
diff --git a/frontend/app/components/shared/Select/Select.tsx b/frontend/app/components/shared/Select/Select.tsx
index 85418f5fc..8d963c16b 100644
--- a/frontend/app/components/shared/Select/Select.tsx
+++ b/frontend/app/components/shared/Select/Select.tsx
@@ -1,14 +1,17 @@
import React from 'react';
-import Select from 'react-select';
+import Select, { components, DropdownIndicatorProps } from 'react-select';
+import { Icon } from 'UI';
+import colors from 'App/theme/colors';
interface Props {
options: any[];
isSearchable?: boolean;
defaultValue?: string;
plain?: boolean;
+ components?: any;
[x:string]: any;
}
-export default function({ plain = false, options, isSearchable = false, defaultValue = '', ...rest }: Props) {
+export default function({ plain = false, options, isSearchable = false, components = {}, defaultValue = '', ...rest }: Props) {
const customStyles = {
option: (provided, state) => ({
...provided,
@@ -17,14 +20,26 @@ export default function({ plain = false, options, isSearchable = false, defaultV
menu: (provided, state) => ({
...provided,
top: 31,
+ minWidth: 'fit-content',
}),
control: (provided) => {
const obj = {
...provided,
- border: 'solid thin #ddd'
+ border: 'solid thin #ddd',
+ cursor: 'pointer',
}
if (plain) {
obj['border'] = '1px solid transparent'
+ obj['&:hover'] = {
+ borderColor: 'transparent',
+ backgroundColor: colors['gray-light']
+ }
+ obj['&:focus'] = {
+ borderColor: 'transparent'
+ }
+ obj['&:active'] = {
+ borderColor: 'transparent'
+ }
}
return obj;
},
@@ -39,14 +54,16 @@ export default function({ plain = false, options, isSearchable = false, defaultV
return { ...provided, opacity, transition };
}
}
- const defaultSelected = defaultValue ? options.find(x => x.value === defaultValue) : options[0];
+ const defaultSelected = defaultValue ? options.find(x => x.value === defaultValue) : null;
return (