feat(tracker): add support for multi tab sessions
This commit is contained in:
parent
9cedd798be
commit
54e95e252d
24 changed files with 318 additions and 33 deletions
|
|
@ -2,7 +2,7 @@
|
|||
package messages
|
||||
|
||||
func IsReplayerType(id int) bool {
|
||||
return 1 != id && 3 != id && 17 != id && 23 != id && 24 != id && 25 != id && 26 != id && 27 != id && 28 != id && 29 != id && 30 != id && 31 != id && 32 != id && 42 != id && 56 != id && 62 != id && 63 != id && 64 != id && 66 != id && 78 != id && 80 != id && 81 != id && 82 != id && 112 != id && 115 != id && 125 != id && 126 != id && 127 != id && 107 != id && 91 != id && 92 != id && 94 != id && 95 != id && 97 != id && 98 != id && 99 != id && 101 != id && 104 != id && 110 != id && 111 != id
|
||||
return 1 != id && 3 != id && 17 != id && 23 != id && 24 != id && 25 != id && 26 != id && 27 != id && 28 != id && 29 != id && 30 != id && 31 != id && 32 != id && 42 != id && 56 != id && 62 != id && 63 != id && 64 != id && 66 != id && 78 != id && 80 != id && 81 != id && 82 != id && 112 != id && 115 != id && 117 != id && 125 != id && 126 != id && 127 != id && 107 != id && 91 != id && 92 != id && 94 != id && 95 != id && 97 != id && 98 != id && 99 != id && 101 != id && 104 != id && 110 != id && 111 != id
|
||||
}
|
||||
|
||||
func IsIOSType(id int) bool {
|
||||
|
|
@ -10,5 +10,5 @@ func IsIOSType(id int) bool {
|
|||
}
|
||||
|
||||
func IsDOMType(id int) bool {
|
||||
return 0 == 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 || 37 == id || 38 == id || 49 == id || 50 == id || 51 == id || 54 == id || 55 == id || 57 == id || 58 == id || 59 == id || 60 == id || 61 == id || 67 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 113 == id || 114 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id
|
||||
return 0 == 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 || 37 == id || 38 == id || 49 == id || 50 == id || 51 == id || 54 == id || 55 == id || 57 == id || 58 == id || 59 == id || 60 == id || 61 == id || 67 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 113 == id || 114 == id || 118 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,13 +74,15 @@ const (
|
|||
MsgJSException = 78
|
||||
MsgZustand = 79
|
||||
MsgBatchMeta = 80
|
||||
MsgBatchMetadata = 81
|
||||
MsgBatchMetadataDeprecated = 81
|
||||
MsgPartitionedMessage = 82
|
||||
MsgInputChange = 112
|
||||
MsgSelectionChange = 113
|
||||
MsgMouseThrashing = 114
|
||||
MsgUnbindNodes = 115
|
||||
MsgResourceTiming = 116
|
||||
MsgBatchMetadata = 117
|
||||
MsgTabChange = 118
|
||||
MsgIssueEvent = 125
|
||||
MsgSessionEnd = 126
|
||||
MsgSessionSearch = 127
|
||||
|
|
@ -1974,7 +1976,7 @@ func (msg *BatchMeta) TypeID() int {
|
|||
return 80
|
||||
}
|
||||
|
||||
type BatchMetadata struct {
|
||||
type BatchMetadataDeprecated struct {
|
||||
message
|
||||
Version uint64
|
||||
PageNo uint64
|
||||
|
|
@ -1983,7 +1985,7 @@ type BatchMetadata struct {
|
|||
Location string
|
||||
}
|
||||
|
||||
func (msg *BatchMetadata) Encode() []byte {
|
||||
func (msg *BatchMetadataDeprecated) Encode() []byte {
|
||||
buf := make([]byte, 51+len(msg.Location))
|
||||
buf[0] = 81
|
||||
p := 1
|
||||
|
|
@ -1995,11 +1997,11 @@ func (msg *BatchMetadata) Encode() []byte {
|
|||
return buf[:p]
|
||||
}
|
||||
|
||||
func (msg *BatchMetadata) Decode() Message {
|
||||
func (msg *BatchMetadataDeprecated) Decode() Message {
|
||||
return msg
|
||||
}
|
||||
|
||||
func (msg *BatchMetadata) TypeID() int {
|
||||
func (msg *BatchMetadataDeprecated) TypeID() int {
|
||||
return 81
|
||||
}
|
||||
|
||||
|
|
@ -2163,6 +2165,58 @@ func (msg *ResourceTiming) TypeID() int {
|
|||
return 116
|
||||
}
|
||||
|
||||
type BatchMetadata struct {
|
||||
message
|
||||
Version uint64
|
||||
PageNo uint64
|
||||
FirstIndex uint64
|
||||
Timestamp int64
|
||||
Location string
|
||||
TabId string
|
||||
}
|
||||
|
||||
func (msg *BatchMetadata) Encode() []byte {
|
||||
buf := make([]byte, 61+len(msg.Location)+len(msg.TabId))
|
||||
buf[0] = 117
|
||||
p := 1
|
||||
p = WriteUint(msg.Version, buf, p)
|
||||
p = WriteUint(msg.PageNo, buf, p)
|
||||
p = WriteUint(msg.FirstIndex, buf, p)
|
||||
p = WriteInt(msg.Timestamp, buf, p)
|
||||
p = WriteString(msg.Location, buf, p)
|
||||
p = WriteString(msg.TabId, buf, p)
|
||||
return buf[:p]
|
||||
}
|
||||
|
||||
func (msg *BatchMetadata) Decode() Message {
|
||||
return msg
|
||||
}
|
||||
|
||||
func (msg *BatchMetadata) TypeID() int {
|
||||
return 117
|
||||
}
|
||||
|
||||
type TabChange struct {
|
||||
message
|
||||
TabId string
|
||||
}
|
||||
|
||||
func (msg *TabChange) Encode() []byte {
|
||||
buf := make([]byte, 11+len(msg.TabId))
|
||||
buf[0] = 118
|
||||
p := 1
|
||||
p = WriteString(msg.TabId, buf, p)
|
||||
return buf[:p]
|
||||
}
|
||||
|
||||
func (msg *TabChange) Decode() Message {
|
||||
return msg
|
||||
}
|
||||
|
||||
func (msg *TabChange) TypeID() int {
|
||||
return 118
|
||||
}
|
||||
|
||||
type IssueEvent struct {
|
||||
message
|
||||
MessageID uint64
|
||||
|
|
|
|||
|
|
@ -1188,9 +1188,9 @@ func DecodeBatchMeta(reader BytesReader) (Message, error) {
|
|||
return msg, err
|
||||
}
|
||||
|
||||
func DecodeBatchMetadata(reader BytesReader) (Message, error) {
|
||||
func DecodeBatchMetadataDeprecated(reader BytesReader) (Message, error) {
|
||||
var err error = nil
|
||||
msg := &BatchMetadata{}
|
||||
msg := &BatchMetadataDeprecated{}
|
||||
if msg.Version, err = reader.ReadUint(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -1314,6 +1314,39 @@ func DecodeResourceTiming(reader BytesReader) (Message, error) {
|
|||
return msg, err
|
||||
}
|
||||
|
||||
func DecodeBatchMetadata(reader BytesReader) (Message, error) {
|
||||
var err error = nil
|
||||
msg := &BatchMetadata{}
|
||||
if msg.Version, err = reader.ReadUint(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if msg.PageNo, err = reader.ReadUint(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if msg.FirstIndex, err = reader.ReadUint(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if msg.Timestamp, err = reader.ReadInt(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if msg.Location, err = reader.ReadString(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if msg.TabId, err = reader.ReadString(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return msg, err
|
||||
}
|
||||
|
||||
func DecodeTabChange(reader BytesReader) (Message, error) {
|
||||
var err error = nil
|
||||
msg := &TabChange{}
|
||||
if msg.TabId, err = reader.ReadString(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return msg, err
|
||||
}
|
||||
|
||||
func DecodeIssueEvent(reader BytesReader) (Message, error) {
|
||||
var err error = nil
|
||||
msg := &IssueEvent{}
|
||||
|
|
@ -1914,7 +1947,7 @@ func ReadMessage(t uint64, reader BytesReader) (Message, error) {
|
|||
case 80:
|
||||
return DecodeBatchMeta(reader)
|
||||
case 81:
|
||||
return DecodeBatchMetadata(reader)
|
||||
return DecodeBatchMetadataDeprecated(reader)
|
||||
case 82:
|
||||
return DecodePartitionedMessage(reader)
|
||||
case 112:
|
||||
|
|
@ -1927,6 +1960,10 @@ func ReadMessage(t uint64, reader BytesReader) (Message, error) {
|
|||
return DecodeUnbindNodes(reader)
|
||||
case 116:
|
||||
return DecodeResourceTiming(reader)
|
||||
case 117:
|
||||
return DecodeBatchMetadata(reader)
|
||||
case 118:
|
||||
return DecodeTabChange(reader)
|
||||
case 125:
|
||||
return DecodeIssueEvent(reader)
|
||||
case 126:
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class CreateDocument(Message):
|
|||
__id__ = 7
|
||||
|
||||
def __init__(self, ):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class CreateElementNode(Message):
|
||||
|
|
@ -689,7 +689,7 @@ class BatchMeta(Message):
|
|||
self.timestamp = timestamp
|
||||
|
||||
|
||||
class BatchMetadata(Message):
|
||||
class BatchMetadataDeprecated(Message):
|
||||
__id__ = 81
|
||||
|
||||
def __init__(self, version, page_no, first_index, timestamp, location):
|
||||
|
|
@ -759,6 +759,25 @@ class ResourceTiming(Message):
|
|||
self.cached = cached
|
||||
|
||||
|
||||
class BatchMetadata(Message):
|
||||
__id__ = 117
|
||||
|
||||
def __init__(self, version, page_no, first_index, timestamp, location, tab_id):
|
||||
self.version = version
|
||||
self.page_no = page_no
|
||||
self.first_index = first_index
|
||||
self.timestamp = timestamp
|
||||
self.location = location
|
||||
self.tab_id = tab_id
|
||||
|
||||
|
||||
class TabChange(Message):
|
||||
__id__ = 118
|
||||
|
||||
def __init__(self, tab_id):
|
||||
self.tab_id = tab_id
|
||||
|
||||
|
||||
class IssueEvent(Message):
|
||||
__id__ = 125
|
||||
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ class MessageCodec(Codec):
|
|||
)
|
||||
|
||||
if message_id == 81:
|
||||
return BatchMetadata(
|
||||
return BatchMetadataDeprecated(
|
||||
version=self.read_uint(reader),
|
||||
page_no=self.read_uint(reader),
|
||||
first_index=self.read_uint(reader),
|
||||
|
|
@ -689,6 +689,21 @@ class MessageCodec(Codec):
|
|||
cached=self.read_boolean(reader)
|
||||
)
|
||||
|
||||
if message_id == 117:
|
||||
return BatchMetadata(
|
||||
version=self.read_uint(reader),
|
||||
page_no=self.read_uint(reader),
|
||||
first_index=self.read_uint(reader),
|
||||
timestamp=self.read_int(reader),
|
||||
location=self.read_string(reader),
|
||||
tab_id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 118:
|
||||
return TabChange(
|
||||
tab_id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 125:
|
||||
return IssueEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
|
|
|
|||
|
|
@ -673,6 +673,14 @@ export default class RawMessageReader extends PrimitiveReader {
|
|||
};
|
||||
}
|
||||
|
||||
case 118: {
|
||||
const tabId = this.readString(); if (tabId === null) { return resetPointer() }
|
||||
return {
|
||||
tp: MType.TabChange,
|
||||
tabId,
|
||||
};
|
||||
}
|
||||
|
||||
case 90: {
|
||||
const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() }
|
||||
const projectID = this.readUint(); if (projectID === null) { return resetPointer() }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { MType } from './raw.gen'
|
||||
|
||||
const DOM_TYPES = [0,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,37,38,49,50,51,54,55,57,58,59,60,61,67,69,70,71,72,73,74,75,76,77,113,114,90,93,96,100,102,103,105]
|
||||
const DOM_TYPES = [0,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,37,38,49,50,51,54,55,57,58,59,60,61,67,69,70,71,72,73,74,75,76,77,113,114,118,90,93,96,100,102,103,105]
|
||||
export function isDOMType(t: MType) {
|
||||
return DOM_TYPES.includes(t)
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ import type {
|
|||
RawSelectionChange,
|
||||
RawMouseThrashing,
|
||||
RawResourceTiming,
|
||||
RawTabChange,
|
||||
RawIosSessionStart,
|
||||
RawIosCustomEvent,
|
||||
RawIosScreenChanges,
|
||||
|
|
@ -178,6 +179,8 @@ export type MouseThrashing = RawMouseThrashing & Timed
|
|||
|
||||
export type ResourceTiming = RawResourceTiming & Timed
|
||||
|
||||
export type TabChange = RawTabChange & Timed
|
||||
|
||||
export type IosSessionStart = RawIosSessionStart & Timed
|
||||
|
||||
export type IosCustomEvent = RawIosCustomEvent & Timed
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ export const enum MType {
|
|||
SelectionChange = 113,
|
||||
MouseThrashing = 114,
|
||||
ResourceTiming = 116,
|
||||
TabChange = 118,
|
||||
IosSessionStart = 90,
|
||||
IosCustomEvent = 93,
|
||||
IosScreenChanges = 96,
|
||||
|
|
@ -447,6 +448,11 @@ export interface RawResourceTiming {
|
|||
cached: boolean,
|
||||
}
|
||||
|
||||
export interface RawTabChange {
|
||||
tp: MType.TabChange,
|
||||
tabId: string,
|
||||
}
|
||||
|
||||
export interface RawIosSessionStart {
|
||||
tp: MType.IosSessionStart,
|
||||
timestamp: number,
|
||||
|
|
@ -518,4 +524,4 @@ export interface RawIosNetworkCall {
|
|||
}
|
||||
|
||||
|
||||
export type RawMessage = RawTimestamp | RawSetPageLocation | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawNetworkRequest | RawConsoleLog | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawRedux | RawVuex | RawMobX | RawNgRx | RawGraphQl | RawPerformanceTrack | RawStringDict | RawSetNodeAttributeDict | RawResourceTimingDeprecated | RawConnectionInformation | RawSetPageVisibility | RawLoadFontFace | RawSetNodeFocus | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawSelectionChange | RawMouseThrashing | RawResourceTiming | RawIosSessionStart | RawIosCustomEvent | RawIosScreenChanges | RawIosClickEvent | RawIosPerformanceEvent | RawIosLog | RawIosNetworkCall;
|
||||
export type RawMessage = RawTimestamp | RawSetPageLocation | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawNetworkRequest | RawConsoleLog | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawRedux | RawVuex | RawMobX | RawNgRx | RawGraphQl | RawPerformanceTrack | RawStringDict | RawSetNodeAttributeDict | RawResourceTimingDeprecated | RawConnectionInformation | RawSetPageVisibility | RawLoadFontFace | RawSetNodeFocus | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawSelectionChange | RawMouseThrashing | RawResourceTiming | RawTabChange | RawIosSessionStart | RawIosCustomEvent | RawIosScreenChanges | RawIosClickEvent | RawIosPerformanceEvent | RawIosLog | RawIosNetworkCall;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ export const TP_MAP = {
|
|||
113: MType.SelectionChange,
|
||||
114: MType.MouseThrashing,
|
||||
116: MType.ResourceTiming,
|
||||
118: MType.TabChange,
|
||||
90: MType.IosSessionStart,
|
||||
93: MType.IosCustomEvent,
|
||||
96: MType.IosScreenChanges,
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ type TrZustand = [
|
|||
state: string,
|
||||
]
|
||||
|
||||
type TrBatchMetadata = [
|
||||
type TrBatchMetadataDeprecated = [
|
||||
type: 81,
|
||||
version: number,
|
||||
pageNo: number,
|
||||
|
|
@ -470,8 +470,23 @@ type TrResourceTiming = [
|
|||
cached: boolean,
|
||||
]
|
||||
|
||||
type TrBatchMetadata = [
|
||||
type: 117,
|
||||
version: number,
|
||||
pageNo: number,
|
||||
firstIndex: number,
|
||||
timestamp: number,
|
||||
location: string,
|
||||
tabId: string,
|
||||
]
|
||||
|
||||
export type TrackerMessage = TrTimestamp | TrSetPageLocation | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrNetworkRequest | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrRedux | TrVuex | TrMobX | TrNgRx | TrGraphQL | TrPerformanceTrack | TrStringDict | TrSetNodeAttributeDict | TrResourceTimingDeprecated | TrConnectionInformation | TrSetPageVisibility | TrLoadFontFace | TrSetNodeFocus | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrJSException | TrZustand | TrBatchMetadata | TrPartitionedMessage | TrInputChange | TrSelectionChange | TrMouseThrashing | TrUnbindNodes | TrResourceTiming
|
||||
type TrTabChange = [
|
||||
type: 118,
|
||||
tabId: string,
|
||||
]
|
||||
|
||||
|
||||
export type TrackerMessage = TrTimestamp | TrSetPageLocation | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrNetworkRequest | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrRedux | TrVuex | TrMobX | TrNgRx | TrGraphQL | TrPerformanceTrack | TrStringDict | TrSetNodeAttributeDict | TrResourceTimingDeprecated | TrConnectionInformation | TrSetPageVisibility | TrLoadFontFace | TrSetNodeFocus | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrJSException | TrZustand | TrBatchMetadataDeprecated | TrPartitionedMessage | TrInputChange | TrSelectionChange | TrMouseThrashing | TrUnbindNodes | TrResourceTiming | TrBatchMetadata | TrTabChange
|
||||
|
||||
export default function translate(tMsg: TrackerMessage): RawMessage | null {
|
||||
switch(tMsg[0]) {
|
||||
|
|
@ -940,6 +955,13 @@ export default function translate(tMsg: TrackerMessage): RawMessage | null {
|
|||
}
|
||||
}
|
||||
|
||||
case 118: {
|
||||
return {
|
||||
tp: MType.TabChange,
|
||||
tabId: tMsg[1],
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ message 80, 'BatchMeta', :replayer => false, :tracker => false do
|
|||
end
|
||||
|
||||
# since tracker 3.6.0 TODO: for webworker only
|
||||
message 81, 'BatchMetadata', :replayer => false do
|
||||
message 81, 'BatchMetadataDeprecated', :replayer => false do
|
||||
uint 'Version'
|
||||
uint 'PageNo'
|
||||
uint 'FirstIndex'
|
||||
|
|
@ -484,6 +484,19 @@ message 116, 'ResourceTiming', :replayer => :devtools do
|
|||
boolean 'Cached'
|
||||
end
|
||||
|
||||
message 117, 'BatchMetadata', :replayer => false do
|
||||
uint 'Version'
|
||||
uint 'PageNo'
|
||||
uint 'FirstIndex'
|
||||
int 'Timestamp'
|
||||
string 'Location'
|
||||
string 'TabId'
|
||||
end
|
||||
|
||||
message 118, 'TabChange' do
|
||||
string 'TabId'
|
||||
end
|
||||
|
||||
## Backend-only
|
||||
message 125, 'IssueEvent', :replayer => false, :tracker => false do
|
||||
uint 'MessageID'
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
# 8.0.0
|
||||
|
||||
- **[breaking]** support for multi-tab sessions
|
||||
|
||||
# 7.0.3
|
||||
|
||||
- Prevent auto restart after manual stop
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type Start = {
|
|||
pageNo: number
|
||||
timestamp: number
|
||||
url: string
|
||||
tabId: string
|
||||
} & Options
|
||||
|
||||
type Auth = {
|
||||
|
|
|
|||
|
|
@ -61,13 +61,15 @@ export declare const enum Type {
|
|||
AdoptedSSRemoveOwner = 77,
|
||||
JSException = 78,
|
||||
Zustand = 79,
|
||||
BatchMetadata = 81,
|
||||
BatchMetadataDeprecated = 81,
|
||||
PartitionedMessage = 82,
|
||||
InputChange = 112,
|
||||
SelectionChange = 113,
|
||||
MouseThrashing = 114,
|
||||
UnbindNodes = 115,
|
||||
ResourceTiming = 116,
|
||||
BatchMetadata = 117,
|
||||
TabChange = 118,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -480,8 +482,8 @@ export type Zustand = [
|
|||
/*state:*/ string,
|
||||
]
|
||||
|
||||
export type BatchMetadata = [
|
||||
/*type:*/ Type.BatchMetadata,
|
||||
export type BatchMetadataDeprecated = [
|
||||
/*type:*/ Type.BatchMetadataDeprecated,
|
||||
/*version:*/ number,
|
||||
/*pageNo:*/ number,
|
||||
/*firstIndex:*/ number,
|
||||
|
|
@ -536,6 +538,21 @@ export type ResourceTiming = [
|
|||
/*cached:*/ boolean,
|
||||
]
|
||||
|
||||
export type BatchMetadata = [
|
||||
/*type:*/ Type.BatchMetadata,
|
||||
/*version:*/ number,
|
||||
/*pageNo:*/ number,
|
||||
/*firstIndex:*/ number,
|
||||
/*timestamp:*/ number,
|
||||
/*location:*/ string,
|
||||
/*tabId:*/ string,
|
||||
]
|
||||
|
||||
type Message = Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequest | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | StringDict | SetNodeAttributeDict | ResourceTimingDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTiming
|
||||
export type TabChange = [
|
||||
/*type:*/ Type.TabChange,
|
||||
/*tabId:*/ string,
|
||||
]
|
||||
|
||||
|
||||
type Message = Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequest | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | StringDict | SetNodeAttributeDict | ResourceTimingDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadataDeprecated | PartitionedMessage | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTiming | BatchMetadata | TabChange
|
||||
export default Message
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ type AppOptions = {
|
|||
session_reset_key: string
|
||||
session_token_key: string
|
||||
session_pageno_key: string
|
||||
session_tabid_key: string
|
||||
local_uuid_key: string
|
||||
ingestPoint: string
|
||||
resourceBaseHref: string | null // resourceHref?
|
||||
|
|
@ -124,6 +125,7 @@ export default class App {
|
|||
session_token_key: '__openreplay_token',
|
||||
session_pageno_key: '__openreplay_pageno',
|
||||
session_reset_key: '__openreplay_reset',
|
||||
session_tabid_key: '__openreplay_tabid',
|
||||
local_uuid_key: '__openreplay_uuid',
|
||||
ingestPoint: DEFAULT_INGEST_POINT,
|
||||
resourceBaseHref: null,
|
||||
|
|
@ -455,6 +457,7 @@ export default class App {
|
|||
url: document.URL,
|
||||
connAttemptCount: this.options.connAttemptCount,
|
||||
connAttemptGap: this.options.connAttemptGap,
|
||||
tabId: this.session.getTabId(),
|
||||
})
|
||||
|
||||
const lsReset = this.sessionStorage.getItem(this.options.session_reset_key) !== null
|
||||
|
|
|
|||
|
|
@ -764,15 +764,15 @@ export function Zustand(
|
|||
]
|
||||
}
|
||||
|
||||
export function BatchMetadata(
|
||||
export function BatchMetadataDeprecated(
|
||||
version: number,
|
||||
pageNo: number,
|
||||
firstIndex: number,
|
||||
timestamp: number,
|
||||
location: string,
|
||||
): Messages.BatchMetadata {
|
||||
): Messages.BatchMetadataDeprecated {
|
||||
return [
|
||||
Messages.Type.BatchMetadata,
|
||||
Messages.Type.BatchMetadataDeprecated,
|
||||
version,
|
||||
pageNo,
|
||||
firstIndex,
|
||||
|
|
@ -869,3 +869,31 @@ export function ResourceTiming(
|
|||
]
|
||||
}
|
||||
|
||||
export function BatchMetadata(
|
||||
version: number,
|
||||
pageNo: number,
|
||||
firstIndex: number,
|
||||
timestamp: number,
|
||||
location: string,
|
||||
tabId: string,
|
||||
): Messages.BatchMetadata {
|
||||
return [
|
||||
Messages.Type.BatchMetadata,
|
||||
version,
|
||||
pageNo,
|
||||
firstIndex,
|
||||
timestamp,
|
||||
location,
|
||||
tabId,
|
||||
]
|
||||
}
|
||||
|
||||
export function TabChange(
|
||||
tabId: string,
|
||||
): Messages.TabChange {
|
||||
return [
|
||||
Messages.Type.TabChange,
|
||||
tabId,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type App from './index.js'
|
||||
import { generateRandomId } from '../utils.js'
|
||||
|
||||
interface SessionInfo {
|
||||
sessionID: string | undefined
|
||||
|
|
@ -12,6 +13,7 @@ type OnUpdateCallback = (i: Partial<SessionInfo>) => void
|
|||
export type Options = {
|
||||
session_token_key: string
|
||||
session_pageno_key: string
|
||||
session_tabid_key: string
|
||||
}
|
||||
|
||||
export default class Session {
|
||||
|
|
@ -21,8 +23,11 @@ export default class Session {
|
|||
private readonly callbacks: OnUpdateCallback[] = []
|
||||
private timestamp = 0
|
||||
private projectID: string | undefined
|
||||
private readonly tabId: string
|
||||
|
||||
constructor(private readonly app: App, private readonly options: Options) {}
|
||||
constructor(private readonly app: App, private readonly options: Options) {
|
||||
this.createTabId()
|
||||
}
|
||||
|
||||
attachUpdateCallback(cb: OnUpdateCallback) {
|
||||
this.callbacks.push(cb)
|
||||
|
|
@ -61,6 +66,7 @@ export default class Session {
|
|||
this.metadata[key] = value
|
||||
this.handleUpdate({ metadata: { [key]: value } })
|
||||
}
|
||||
|
||||
setUserID(userID: string) {
|
||||
this.userID = userID
|
||||
this.handleUpdate({ userID })
|
||||
|
|
@ -86,10 +92,11 @@ export default class Session {
|
|||
}
|
||||
|
||||
getSessionToken(): string | undefined {
|
||||
return this.app.sessionStorage.getItem(this.options.session_token_key) || undefined
|
||||
return this.app.localStorage.getItem(this.options.session_token_key) || undefined
|
||||
}
|
||||
|
||||
setSessionToken(token: string): void {
|
||||
this.app.sessionStorage.setItem(this.options.session_token_key, token)
|
||||
this.app.localStorage.setItem(this.options.session_token_key, token)
|
||||
}
|
||||
|
||||
applySessionHash(hash: string) {
|
||||
|
|
@ -102,7 +109,7 @@ export default class Session {
|
|||
if (!pageNoStr || !token) {
|
||||
return
|
||||
}
|
||||
this.app.sessionStorage.setItem(this.options.session_token_key, token)
|
||||
this.app.localStorage.setItem(this.options.session_token_key, token)
|
||||
this.app.sessionStorage.setItem(this.options.session_pageno_key, pageNoStr)
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +122,14 @@ export default class Session {
|
|||
return encodeURI(String(pageNo) + '&' + token)
|
||||
}
|
||||
|
||||
public getTabId(): string {
|
||||
return this.tabId
|
||||
}
|
||||
|
||||
private createTabId() {
|
||||
this.app.sessionStorage.setItem(this.options.session_tabid_key, generateRandomId(16))
|
||||
}
|
||||
|
||||
getInfo(): SessionInfo {
|
||||
return {
|
||||
sessionID: this.sessionID,
|
||||
|
|
@ -126,7 +141,7 @@ export default class Session {
|
|||
}
|
||||
|
||||
reset(): void {
|
||||
this.app.sessionStorage.removeItem(this.options.session_token_key)
|
||||
this.app.localStorage.removeItem(this.options.session_token_key)
|
||||
this.metadata = {}
|
||||
this.userID = null
|
||||
this.sessionID = undefined
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import Fonts from './modules/fonts.js'
|
|||
import Network from './modules/network.js'
|
||||
import ConstructedStyleSheets from './modules/constructedStyleSheets.js'
|
||||
import Selection from './modules/selection.js'
|
||||
import Tabs from './modules/tabs.js'
|
||||
import { IN_BROWSER, deprecationWarn, DOCS_HOST } from './utils.js'
|
||||
|
||||
import type { Options as AppOptions } from './app/index.js'
|
||||
|
|
@ -136,6 +137,7 @@ export default class API {
|
|||
Fonts(app)
|
||||
Network(app, options.network)
|
||||
Selection(app)
|
||||
Tabs(app)
|
||||
;(window as any).__OPENREPLAY__ = this
|
||||
|
||||
if (options.autoResetOnWindowOpen) {
|
||||
|
|
|
|||
12
tracker/tracker/src/main/modules/tabs.ts
Normal file
12
tracker/tracker/src/main/modules/tabs.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import type App from '../app/index.js'
|
||||
import { TabChange } from '../app/messages.gen.js'
|
||||
|
||||
export default function (app: App): void {
|
||||
function changeTab() {
|
||||
if (!document.hidden) app.safe(() => app.send(TabChange(app.session.getTabId())))
|
||||
}
|
||||
|
||||
if (document.hidden !== undefined) {
|
||||
app.attachEventListener(document, 'visibilitychange', changeTab as EventListener, false, false)
|
||||
}
|
||||
}
|
||||
|
|
@ -100,3 +100,16 @@ export function canAccessIframe(iframe: HTMLIFrameElement) {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function dec2hex(dec: number) {
|
||||
return dec.toString(16).padStart(2, '0')
|
||||
}
|
||||
|
||||
export function generateRandomId(len: number) {
|
||||
const arr: Uint8Array = new Uint8Array((len || 40) / 2)
|
||||
// msCrypto = IE11
|
||||
// @ts-ignore
|
||||
const safeCrypto = window.crypto || window.msCrypto
|
||||
safeCrypto.getRandomValues(arr)
|
||||
return Array.from(arr, dec2hex).join('')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export default class BatchWriter {
|
|||
private timestamp: number,
|
||||
private url: string,
|
||||
private readonly onBatch: (batch: Uint8Array) => void,
|
||||
private tabId: string,
|
||||
) {
|
||||
this.prepare()
|
||||
}
|
||||
|
|
@ -50,6 +51,7 @@ export default class BatchWriter {
|
|||
this.nextIndex,
|
||||
this.timestamp,
|
||||
this.url,
|
||||
this.tabId,
|
||||
]
|
||||
this.writeType(batchMetadata)
|
||||
this.writeFields(batchMetadata)
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ export default class MessageEncoder extends PrimitiveEncoder {
|
|||
return this.string(msg[1]) && this.string(msg[2])
|
||||
break
|
||||
|
||||
case Messages.Type.BatchMetadata:
|
||||
case Messages.Type.BatchMetadataDeprecated:
|
||||
return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3]) && this.int(msg[4]) && this.string(msg[5])
|
||||
break
|
||||
|
||||
|
|
@ -274,6 +274,14 @@ export default class MessageEncoder extends PrimitiveEncoder {
|
|||
return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3]) && this.uint(msg[4]) && this.uint(msg[5]) && this.uint(msg[6]) && this.string(msg[7]) && this.string(msg[8]) && this.uint(msg[9]) && this.boolean(msg[10])
|
||||
break
|
||||
|
||||
case Messages.Type.BatchMetadata:
|
||||
return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3]) && this.int(msg[4]) && this.string(msg[5]) && this.string(msg[6])
|
||||
break
|
||||
|
||||
case Messages.Type.TabChange:
|
||||
return this.string(msg[1])
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ const AUTO_SEND_INTERVAL = 10 * 1000
|
|||
|
||||
let sender: QueueSender | null = null
|
||||
let writer: BatchWriter | null = null
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
let workerStatus: WorkerStatus = WorkerStatus.NotActive
|
||||
// let afterSleepRestarts = 0
|
||||
|
||||
function finalize(): void {
|
||||
if (!writer) {
|
||||
return
|
||||
|
|
@ -73,7 +74,7 @@ let sendIntervalID: ReturnType<typeof setInterval> | null = null
|
|||
let restartTimeoutID: ReturnType<typeof setTimeout>
|
||||
|
||||
// @ts-ignore
|
||||
self.onmessage = ({ data }: any): any => {
|
||||
self.onmessage = ({ data }: { data: ToWorkerData }): any => {
|
||||
if (data == null) {
|
||||
finalize()
|
||||
return
|
||||
|
|
@ -146,6 +147,7 @@ self.onmessage = ({ data }: any): any => {
|
|||
data.timestamp,
|
||||
data.url,
|
||||
(batch) => sender && sender.push(batch),
|
||||
data.tabId,
|
||||
)
|
||||
if (sendIntervalID === null) {
|
||||
sendIntervalID = setInterval(finalize, AUTO_SEND_INTERVAL)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue