Merge branch 'dev' of github.com:openreplay/openreplay into funnels
This commit is contained in:
commit
8c7cbbb189
48 changed files with 160 additions and 145 deletions
|
|
@ -23,7 +23,7 @@ function build_service() {
|
|||
image="$1"
|
||||
echo "BUILDING $image"
|
||||
case "$image" in
|
||||
http | db)
|
||||
http | db | sink)
|
||||
echo build http
|
||||
docker build -t ${DOCKER_REPO:-'local'}/$image:${git_sha1} --platform linux/amd64 --build-arg SERVICE_NAME=$image -f ./cmd/Dockerfile .
|
||||
[[ $PUSH_IMAGE -eq 1 ]] && {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -9,37 +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) {
|
||||
count++
|
||||
|
||||
typeID := message.TypeID()
|
||||
if !IsReplayerType(typeID) {
|
||||
return
|
||||
}
|
||||
|
||||
count++
|
||||
message = assetMessageHandler.ParseAssets(sessionID, message)
|
||||
|
||||
value := message.Encode()
|
||||
var data []byte
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
31
backend/internal/config/sink/config.go
Normal file
31
backend/internal/config/sink/config.go
Normal file
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package oswriter
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
0
backend/services/sink/build_hack
Normal file
0
backend/services/sink/build_hack
Normal file
|
|
@ -94,7 +94,7 @@ function UserForm(props: Props) {
|
|||
</label>
|
||||
</div>
|
||||
|
||||
{ !isEnterprise && (
|
||||
{ isEnterprise && (
|
||||
<div className="form-group">
|
||||
<label htmlFor="role">{ 'Role' }</label>
|
||||
<Select
|
||||
|
|
@ -115,7 +115,7 @@ function UserForm(props: Props) {
|
|||
<div className="flex items-center mr-auto">
|
||||
<Button
|
||||
onClick={ onSave }
|
||||
disabled={ !user.valid() || isSaving }
|
||||
disabled={ !user.valid(isEnterprise) || isSaving }
|
||||
loading={ isSaving }
|
||||
primary
|
||||
marginRight
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ export default class User implements IUser {
|
|||
}
|
||||
}
|
||||
|
||||
valid() {
|
||||
return validateName(this.name, { empty: false }) && validateEmail(this.email) && !!this.roleId;
|
||||
valid(isEnterprise: boolean = false) {
|
||||
return validateName(this.name, { empty: false }) && validateEmail(this.email) && (isEnterprise ? !!this.roleId : true);
|
||||
}
|
||||
|
||||
exists() {
|
||||
|
|
|
|||
62
tracker/tracker-assist/package-lock.json
generated
62
tracker/tracker-assist/package-lock.json
generated
|
|
@ -1,16 +1,16 @@
|
|||
{
|
||||
"name": "@openreplay/tracker-assist",
|
||||
"version": "3.5.7",
|
||||
"version": "3.5.8",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@openreplay/tracker-assist",
|
||||
"version": "3.5.7",
|
||||
"version": "3.5.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.10",
|
||||
"peerjs": "^1.3.2",
|
||||
"peerjs": "1.3.2",
|
||||
"socket.io-client": "^4.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"../tracker": {
|
||||
"name": "@openreplay/tracker",
|
||||
"version": "3.5.4",
|
||||
"version": "3.5.11",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -644,15 +644,19 @@
|
|||
}
|
||||
},
|
||||
"../tracker/node_modules/ajv": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"../tracker/node_modules/ansi-escapes": {
|
||||
|
|
@ -1791,12 +1795,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"../tracker/node_modules/json5/node_modules/minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
},
|
||||
"../tracker/node_modules/levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
|
|
@ -1853,9 +1851,9 @@
|
|||
}
|
||||
},
|
||||
"../tracker/node_modules/minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"../tracker/node_modules/mkdirp": {
|
||||
|
|
@ -2376,9 +2374,9 @@
|
|||
}
|
||||
},
|
||||
"../tracker/node_modules/strip-ansi/node_modules/ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
|
||||
"integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
|
@ -4444,9 +4442,9 @@
|
|||
"requires": {}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
|
|
@ -5337,14 +5335,6 @@
|
|||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"levn": {
|
||||
|
|
@ -5391,9 +5381,9 @@
|
|||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
|
|
@ -5793,9 +5783,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
|
||||
"integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker-assist",
|
||||
"description": "Tracker plugin for screen assistance through the WebRTC",
|
||||
"version": "3.5.8",
|
||||
"version": "3.5.9",
|
||||
"keywords": [
|
||||
"WebRTC",
|
||||
"assistance",
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.10",
|
||||
"peerjs": "^1.3.2",
|
||||
"peerjs": "1.3.2",
|
||||
"socket.io-client": "^4.4.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import AnnotationCanvas from './AnnotationCanvas.js';
|
|||
import ConfirmWindow, { callConfirmDefault, controlConfirmDefault } from './ConfirmWindow.js';
|
||||
import type { Options as ConfirmOptions } from './ConfirmWindow.js';
|
||||
|
||||
// TODO: fully specified strict check (everywhere)
|
||||
|
||||
//@ts-ignore peerjs hack for webpack5 (?!) TODO: ES/node modules;
|
||||
Peer = Peer.default || Peer;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default class RemoteControl {
|
|||
|
||||
reconnect(ids: string[]) {
|
||||
const storedID = sessionStorage.getItem(this.options.session_control_peer_key)
|
||||
if (storedID !== null && ids.includes(storedID)) {
|
||||
if (storedID !== null && ids.indexOf(storedID) !== -1) {
|
||||
this.grantControl(storedID)
|
||||
} else {
|
||||
sessionStorage.removeItem(this.options.session_control_peer_key)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"description": "The OpenReplay tracker main package",
|
||||
"version": "3.5.10",
|
||||
"version": "3.5.11",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"replay"
|
||||
|
|
|
|||
|
|
@ -15,31 +15,31 @@ async function main() {
|
|||
to: webworker.replace(/'/g, "\\'"),
|
||||
});
|
||||
await fs.rename('build/main', 'lib');
|
||||
await fs.rename('build/messages', 'lib/messages');
|
||||
await fs.rename('build/common', 'lib/common');
|
||||
await replaceInFiles({
|
||||
files: 'lib/*',
|
||||
from: /\.\.\/messages/g,
|
||||
to: './messages',
|
||||
from: /\.\.\/common/g,
|
||||
to: './common',
|
||||
});
|
||||
await replaceInFiles({
|
||||
files: 'lib/**/*',
|
||||
from: /\.\.\/\.\.\/messages/g,
|
||||
to: '../messages',
|
||||
from: /\.\.\/\.\.\/common/g,
|
||||
to: '../common',
|
||||
});
|
||||
|
||||
|
||||
await fs.rename('build/cjs/main', 'cjs');
|
||||
await fs.rename('build/cjs/messages', 'cjs/messages');
|
||||
await fs.rename('build/cjs/common', 'cjs/common');
|
||||
await fs.writeFile('cjs/package.json', `{ "type": "commonjs" }`);
|
||||
await replaceInFiles({
|
||||
files: 'cjs/*',
|
||||
from: /\.\.\/messages/g,
|
||||
to: './messages',
|
||||
from: /\.\.\/common/g,
|
||||
to: './common',
|
||||
});
|
||||
await replaceInFiles({
|
||||
files: 'cjs/**/*',
|
||||
from: /\.\.\/\.\.\/messages/g,
|
||||
to: '../messages',
|
||||
from: /\.\.\/\.\.\/common/g,
|
||||
to: '../common',
|
||||
});
|
||||
}
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Auto-generated, do not edit
|
||||
import Message from "./message.js";
|
||||
import Writer from "./writer.js";
|
||||
import type { Writer, Message }from "./types.js";
|
||||
export default Message
|
||||
|
||||
function bindNew<C extends { new(...args: A): T }, A extends any[], T>(
|
||||
Class: C & { new(...args: A): T }
|
||||
10
tracker/tracker/src/common/types.ts
Normal file
10
tracker/tracker/src/common/types.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export interface Writer {
|
||||
uint(n: number): boolean
|
||||
int(n: number): boolean
|
||||
string(s: string): boolean
|
||||
boolean(b: boolean): boolean
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
encode(w: Writer): boolean;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type Message from "../../common/messages.js";
|
||||
import { Timestamp, Metadata } from "../../common/messages.js";
|
||||
import { timestamp, deprecationWarn } from "../utils.js";
|
||||
import { Timestamp, Metadata } from "../../messages/index.js";
|
||||
import Message from "../../messages/message.js";
|
||||
import Nodes from "./nodes.js";
|
||||
import Observer from "./observer/top_observer.js";
|
||||
import Sanitizer from "./sanitizer.js";
|
||||
|
|
@ -13,7 +13,7 @@ import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js";
|
|||
import type { Options as ObserverOptions } from "./observer/top_observer.js";
|
||||
import type { Options as SanitizerOptions } from "./sanitizer.js";
|
||||
import type { Options as LoggerOptions } from "./logger.js"
|
||||
import type { Options as WebworkerOptions, WorkerMessageData } from "../../webworker/types.js";
|
||||
import type { Options as WebworkerOptions, WorkerMessageData } from "../../common/webworker.js";
|
||||
|
||||
|
||||
// TODO: Unify and clearly describe options logic
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Observer from "./observer.js";
|
||||
import { CreateIFrameDocument } from "../../../messages/index.js";
|
||||
import { CreateIFrameDocument } from "../../../common/messages.js";
|
||||
|
||||
export default class IFrameObserver extends Observer {
|
||||
observe(iframe: HTMLIFrameElement) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
CreateElementNode,
|
||||
MoveNode,
|
||||
RemoveNode,
|
||||
} from "../../../messages/index.js";
|
||||
} from "../../../common/messages.js";
|
||||
import App from "../index.js";
|
||||
import { isInstance, inDocument } from "../context.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Observer from "./observer.js";
|
||||
import { CreateIFrameDocument } from "../../../messages/index.js";
|
||||
import { CreateIFrameDocument } from "../../../common/messages.js";
|
||||
|
||||
export default class ShadowRootObserver extends Observer {
|
||||
observe(el: Element) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import type { Window } from "../context.js";
|
|||
import IFrameObserver from "./iframe_observer.js";
|
||||
import ShadowRootObserver from "./shadow_root_observer.js";
|
||||
|
||||
import { CreateDocument } from "../../../messages/index.js";
|
||||
import { CreateDocument } from "../../../common/messages.js";
|
||||
import App from "../index.js";
|
||||
import { IN_BROWSER, hasOpenreplayAttribute } from '../../utils.js'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import App, { StartOptions } from "./index.js";
|
||||
import { UserID, UserAnonymousID, Metadata } from "../../messages/index.js";
|
||||
import { UserID, UserAnonymousID, Metadata } from "../../common/messages.js";
|
||||
|
||||
|
||||
enum ActivityState {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import App, { DEFAULT_INGEST_POINT } from "./app/index.js";
|
||||
export { default as App } from './app/index.js';
|
||||
|
||||
import { UserID, UserAnonymousID, Metadata, RawCustomEvent, CustomIssue } from "../messages/index.js";
|
||||
import * as _Messages from "../messages/index.js";
|
||||
import { UserID, UserAnonymousID, Metadata, RawCustomEvent, CustomIssue } from "../common/messages.js";
|
||||
import * as _Messages from "../common/messages.js";
|
||||
export const Messages = _Messages;
|
||||
|
||||
import Connection from "./modules/connection.js";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import App from "../app/index.js";
|
||||
import { ConnectionInformation } from "../../messages/index.js";
|
||||
import { ConnectionInformation } from "../../common/messages.js";
|
||||
|
||||
export default function(app: App): void {
|
||||
const connection:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import App from "../app/index.js";
|
||||
import { IN_BROWSER } from "../utils.js";
|
||||
import { ConsoleLog } from "../../messages/index.js";
|
||||
import { ConsoleLog } from "../../common/messages.js";
|
||||
|
||||
const printError: (e: Error) => string =
|
||||
IN_BROWSER && 'InstallTrigger' in window // detect Firefox
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import App from "../app/index.js";
|
||||
import { CSSInsertRuleURLBased, CSSDeleteRule, TechnicalInfo } from "../../messages/index.js";
|
||||
import { CSSInsertRuleURLBased, CSSDeleteRule, TechnicalInfo } from "../../common/messages.js";
|
||||
|
||||
export default function(app: App | null) {
|
||||
if (app === null) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type Message from "../../common/messages.js";
|
||||
import App from "../app/index.js";
|
||||
import { JSException } from "../../messages/index.js";
|
||||
import Message from "../../messages/message.js";
|
||||
import { JSException } from "../../common/messages.js";
|
||||
import ErrorStackParser from 'error-stack-parser';
|
||||
|
||||
export interface Options {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { timestamp, isURL } from "../utils.js";
|
||||
import App from "../app/index.js";
|
||||
import { ResourceTiming, SetNodeAttributeURLBased, SetNodeAttribute } from "../../messages/index.js";
|
||||
import { ResourceTiming, SetNodeAttributeURLBased, SetNodeAttribute } from "../../common/messages.js";
|
||||
|
||||
const PLACEHOLDER_SRC = "https://static.openreplay.com/tracker/placeholder.jpeg";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
hasOpenreplayAttribute,
|
||||
} from "../utils.js";
|
||||
import App from "../app/index.js";
|
||||
import { SetInputTarget, SetInputValue, SetInputChecked } from "../../messages/index.js";
|
||||
import { SetInputTarget, SetInputValue, SetInputChecked } from "../../common/messages.js";
|
||||
|
||||
// TODO: take into consideration "contenteditable" attribute
|
||||
type TextEditableElement = HTMLInputElement | HTMLTextAreaElement
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import App from "../app/index.js";
|
||||
import { LongTask } from "../../messages/index.js";
|
||||
import { LongTask } from "../../common/messages.js";
|
||||
|
||||
// https://w3c.github.io/performance-timeline/#the-performanceentry-interface
|
||||
interface TaskAttributionTiming extends PerformanceEntry {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {
|
|||
getLabelAttribute,
|
||||
} from "../utils.js";
|
||||
import App from "../app/index.js";
|
||||
import { MouseMove, MouseClick } from "../../messages/index.js";
|
||||
import { MouseMove, MouseClick } from "../../common/messages.js";
|
||||
import { getInputLabel } from "./input.js";
|
||||
|
||||
function _getSelector(target: Element): string {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import App from "../app/index.js";
|
||||
import { IN_BROWSER } from "../utils.js";
|
||||
import { PerformanceTrack } from "../../messages/index.js";
|
||||
import { PerformanceTrack } from "../../common/messages.js";
|
||||
|
||||
|
||||
type Perf = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import App from "../app/index.js";
|
||||
import { SetViewportScroll, SetNodeScroll } from "../../messages/index.js";
|
||||
import { SetViewportScroll, SetNodeScroll } from "../../common/messages.js";
|
||||
|
||||
export default function (app: App): void {
|
||||
let documentScroll = false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type Message from "../../common/messages.js";
|
||||
import { isURL } from "../utils.js";
|
||||
import App from "../app/index.js";
|
||||
import { ResourceTiming, PageLoadTiming, PageRenderTiming } from "../../messages/index.js";
|
||||
import type Message from "../../messages/message.js";
|
||||
import { ResourceTiming, PageLoadTiming, PageRenderTiming } from "../../common/messages.js";
|
||||
|
||||
// Inspired by https://github.com/WPO-Foundation/RUM-SpeedIndex/blob/master/src/rum-speedindex.js
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {
|
|||
SetPageLocation,
|
||||
SetViewportSize,
|
||||
SetPageVisibility,
|
||||
} from "../../messages/index.js";
|
||||
} from "../../common/messages.js";
|
||||
|
||||
export default function (app: App): void {
|
||||
let url: string, width: number, height: number;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"lib": ["es6", "dom"],
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../messages" }
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"exclude": ["app/observer"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
import Writer from "./writer.js";
|
||||
|
||||
export default interface Message {
|
||||
encode(w: Writer): boolean;
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import Writer from "../messages/writer.js";
|
||||
import Message from "../messages/message.js";
|
||||
import type Message from "../common/messages.js";
|
||||
import PrimitiveWriter from "./PrimitiveWriter.js";
|
||||
import {
|
||||
BatchMeta,
|
||||
Timestamp,
|
||||
} from "../messages/index.js";
|
||||
} from "../common/messages.js";
|
||||
|
||||
export default class BatchWriter {
|
||||
private nextIndex = 0
|
||||
private beaconSize = 2 * 1e5 // Default 200kB
|
||||
private writer = new Writer(this.beaconSize)
|
||||
private writer = new PrimitiveWriter(this.beaconSize)
|
||||
private isEmpty = true
|
||||
|
||||
constructor(
|
||||
|
|
@ -50,7 +50,7 @@ export default class BatchWriter {
|
|||
}
|
||||
// MBTODO: tempWriter for one message?
|
||||
this.beaconSize = Math.min(this.beaconSize*2, this.beaconSizeLimit)
|
||||
this.writer = new Writer(this.beaconSize)
|
||||
this.writer = new PrimitiveWriter(this.beaconSize)
|
||||
this.prepareBatchMeta()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ const textEncoder: { encode(str: string): Uint8Array } =
|
|||
},
|
||||
};
|
||||
|
||||
export default class Writer {
|
||||
export default class PrimitiveWriter {
|
||||
private offset: number = 0;
|
||||
private checkpointOffset: number = 0;
|
||||
private readonly data: Uint8Array;
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
import Message from "../messages/message.js";
|
||||
import type Message from "../common/messages.js";
|
||||
import type { WorkerMessageData } from "../common/webworker.js";
|
||||
|
||||
import {
|
||||
classes,
|
||||
SetPageVisibility,
|
||||
MouseMove,
|
||||
} from "../messages/index.js";
|
||||
} from "../common/messages.js";
|
||||
import QueueSender from "./QueueSender.js";
|
||||
import BatchWriter from "./BatchWriter.js";
|
||||
|
||||
import type { WorkerMessageData } from "./types.js";
|
||||
|
||||
|
||||
const AUTO_SEND_INTERVAL = 10 * 1000
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
"lib": ["es6", "webworker"]
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../messages" }
|
||||
{ "path": "../common" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
|
||||
|
||||
|
||||
function getFullURL(baseURL: string, relativeURL: string) {
|
||||
if (isRelative(relativeURL)) {
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue