Merge remote-tracking branch 'origin/api-dev-v1.8.0' into api-v1.8.0
This commit is contained in:
commit
264df362d0
153 changed files with 5198 additions and 2792 deletions
|
|
@ -3,6 +3,7 @@ LABEL Maintainer="Rajesh Rajendran<rjshrjndrn@gmail.com>"
|
|||
LABEL Maintainer="KRAIEM Taha Yassine<tahayk2@gmail.com>"
|
||||
RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
||||
RUN apk add --no-cache build-base nodejs npm tini
|
||||
RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
||||
ARG envarg
|
||||
# Add Tini
|
||||
# Startup daemon
|
||||
|
|
|
|||
|
|
@ -35,9 +35,10 @@ def get_live_sessions_ws(project_id, body: schemas.LiveSessionsSearchPayloadSche
|
|||
}
|
||||
for f in body.filters:
|
||||
if f.type == schemas.LiveFilterType.metadata:
|
||||
data["filter"][f.source] = f.value
|
||||
data["filter"][f.source] = {"values": f.value, "operator": f.operator}
|
||||
|
||||
else:
|
||||
data["filter"][f.type.value] = f.value
|
||||
data["filter"][f.type.value] = {"values": f.value, "operator": f.operator}
|
||||
return __get_live_sessions_ws(project_id=project_id, data=data)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import schemas
|
||||
from chalicelib.core import integration_base
|
||||
from chalicelib.core.integration_github_issue import GithubIntegrationIssue
|
||||
from chalicelib.utils import pg_client, helper
|
||||
|
||||
PROVIDER = "GITHUB"
|
||||
PROVIDER = schemas.IntegrationType.github
|
||||
|
||||
|
||||
class GitHubIntegration(integration_base.BaseIntegration):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import schemas
|
||||
from chalicelib.core import integration_base
|
||||
from chalicelib.core.integration_jira_cloud_issue import JIRACloudIntegrationIssue
|
||||
from chalicelib.utils import pg_client, helper
|
||||
|
||||
PROVIDER = "JIRA"
|
||||
PROVIDER = schemas.IntegrationType.jira
|
||||
|
||||
|
||||
def obfuscate_string(string):
|
||||
|
|
|
|||
61
api/chalicelib/core/integrations_global.py
Normal file
61
api/chalicelib/core/integrations_global.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import schemas
|
||||
from chalicelib.utils import pg_client
|
||||
|
||||
|
||||
def get_global_integrations_status(tenant_id, user_id, project_id):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
cur.mogrify(f"""\
|
||||
SELECT EXISTS((SELECT 1
|
||||
FROM public.oauth_authentication
|
||||
WHERE user_id = %(user_id)s
|
||||
AND provider = 'github')) AS {schemas.IntegrationType.github},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.jira_cloud
|
||||
WHERE user_id = %(user_id)s)) AS {schemas.IntegrationType.jira},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='bugsnag')) AS {schemas.IntegrationType.bugsnag},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='cloudwatch')) AS {schemas.IntegrationType.cloudwatch},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='datadog')) AS {schemas.IntegrationType.datadog},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='newrelic')) AS {schemas.IntegrationType.newrelic},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='rollbar')) AS {schemas.IntegrationType.rollbar},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='sentry')) AS {schemas.IntegrationType.sentry},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='stackdriver')) AS {schemas.IntegrationType.stackdriver},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='sumologic')) AS {schemas.IntegrationType.sumologic},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='elasticsearch')) AS {schemas.IntegrationType.elasticsearch},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.webhooks
|
||||
WHERE type='slack')) AS {schemas.IntegrationType.slack};""",
|
||||
{"user_id": user_id, "tenant_id": tenant_id, "project_id": project_id})
|
||||
)
|
||||
current_integrations = cur.fetchone()
|
||||
result = []
|
||||
for k in current_integrations.keys():
|
||||
result.append({"name": k, "integrated": current_integrations[k]})
|
||||
return result
|
||||
|
|
@ -12,7 +12,7 @@ from chalicelib.core import log_tool_rollbar, sourcemaps, events, sessions_assig
|
|||
log_tool_cloudwatch, log_tool_sentry, log_tool_sumologic, log_tools, errors, sessions, \
|
||||
log_tool_newrelic, announcements, log_tool_bugsnag, weekly_report, integration_jira_cloud, integration_github, \
|
||||
assist, heatmaps, mobile, signup, tenants, errors_favorite_viewed, boarding, notifications, webhook, users, \
|
||||
custom_metrics, saved_search
|
||||
custom_metrics, saved_search, integrations_global
|
||||
from chalicelib.core.collaboration_slack import Slack
|
||||
from chalicelib.utils import email_helper, helper, captcha
|
||||
from chalicelib.utils.TimeUTC import TimeUTC
|
||||
|
|
@ -173,6 +173,14 @@ def session_top_filter_values(projectId: int, context: schemas.CurrentContext =
|
|||
return {'data': sessions_metas.get_top_key_values(projectId)}
|
||||
|
||||
|
||||
@app.get('/{projectId}/integrations', tags=["integrations"])
|
||||
def get_integrations_status(projectId: int, context: schemas.CurrentContext = Depends(OR_context)):
|
||||
data = integrations_global.get_global_integrations_status(tenant_id=context.tenant_id,
|
||||
user_id=context.user_id,
|
||||
project_id=projectId)
|
||||
return {"data": data}
|
||||
|
||||
|
||||
@app.post('/{projectId}/integrations/{integration}/notify/{integrationId}/{source}/{sourceId}', tags=["integrations"])
|
||||
@app.put('/{projectId}/integrations/{integration}/notify/{integrationId}/{source}/{sourceId}', tags=["integrations"])
|
||||
def integration_notify(projectId: int, integration: str, integrationId: int, source: str, sourceId: str,
|
||||
|
|
|
|||
|
|
@ -1026,13 +1026,15 @@ class LiveFilterType(str, Enum):
|
|||
user_UUID = "USERUUID"
|
||||
tracker_version = "TRACKERVERSION"
|
||||
user_browser_version = "USERBROWSERVERSION"
|
||||
user_device_type = "USERDEVICETYPE",
|
||||
user_device_type = "USERDEVICETYPE"
|
||||
|
||||
|
||||
class LiveSessionSearchFilterSchema(BaseModel):
|
||||
value: Union[List[str], str] = Field(...)
|
||||
type: LiveFilterType = Field(...)
|
||||
source: Optional[str] = Field(None)
|
||||
operator: Literal[SearchEventOperator._is.value,
|
||||
SearchEventOperator._contains.value] = Field(SearchEventOperator._contains.value)
|
||||
|
||||
@root_validator
|
||||
def validator(cls, values):
|
||||
|
|
@ -1068,3 +1070,18 @@ class LiveSessionsSearchPayloadSchema(_PaginatedSchema):
|
|||
|
||||
class Config:
|
||||
alias_generator = attribute_to_camel_case
|
||||
|
||||
|
||||
class IntegrationType(str, Enum):
|
||||
github = "GITHUB"
|
||||
jira = "JIRA"
|
||||
slack = "SLACK"
|
||||
sentry = "SENTRY"
|
||||
bugsnag = "BUGSNAG"
|
||||
rollbar = "ROLLBAR"
|
||||
elasticsearch = "ELASTICSEARCH"
|
||||
datadog = "DATADOG"
|
||||
sumologic = "SUMOLOGIC"
|
||||
stackdriver = "STACKDRIVER"
|
||||
cloudwatch = "CLOUDWATCH"
|
||||
newrelic = "NEWRELIC"
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ ENV TZ=UTC \
|
|||
ASSETS_SIZE_LIMIT=6291456 \
|
||||
ASSETS_HEADERS="{ \"Cookie\": \"ABv=3;\" }" \
|
||||
FS_CLEAN_HRS=72 \
|
||||
FILE_SPLIT_SIZE=500000 \
|
||||
FILE_SPLIT_SIZE=1000000 \
|
||||
LOG_QUEUE_STATS_INTERVAL_SEC=60 \
|
||||
DB_BATCH_QUEUE_LIMIT=20 \
|
||||
DB_BATCH_SIZE_LIMIT=10000000 \
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ LABEL Maintainer="Rajesh Rajendran<rjshrjndrn@gmail.com>"
|
|||
LABEL Maintainer="KRAIEM Taha Yassine<tahayk2@gmail.com>"
|
||||
RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
||||
RUN apk add --no-cache build-base libressl libffi-dev libressl-dev libxslt-dev libxml2-dev xmlsec-dev xmlsec nodejs npm tini
|
||||
RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
||||
ARG envarg
|
||||
ENV SOURCE_MAP_VERSION=0.7.4 \
|
||||
APP_NAME=chalice \
|
||||
|
|
|
|||
61
ee/api/chalicelib/core/integrations_global.py
Normal file
61
ee/api/chalicelib/core/integrations_global.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import schemas
|
||||
from chalicelib.utils import pg_client
|
||||
|
||||
|
||||
def get_global_integrations_status(tenant_id, user_id, project_id):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
cur.mogrify(f"""\
|
||||
SELECT EXISTS((SELECT 1
|
||||
FROM public.oauth_authentication
|
||||
WHERE user_id = %(user_id)s
|
||||
AND provider = 'github')) AS {schemas.IntegrationType.github},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.jira_cloud
|
||||
WHERE user_id = %(user_id)s)) AS {schemas.IntegrationType.jira},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='bugsnag')) AS {schemas.IntegrationType.bugsnag},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='cloudwatch')) AS {schemas.IntegrationType.cloudwatch},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='datadog')) AS {schemas.IntegrationType.datadog},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='newrelic')) AS {schemas.IntegrationType.newrelic},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='rollbar')) AS {schemas.IntegrationType.rollbar},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='sentry')) AS {schemas.IntegrationType.sentry},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='stackdriver')) AS {schemas.IntegrationType.stackdriver},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='sumologic')) AS {schemas.IntegrationType.sumologic},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.integrations
|
||||
WHERE project_id=%(project_id)s
|
||||
AND provider='elasticsearch')) AS {schemas.IntegrationType.elasticsearch},
|
||||
EXISTS((SELECT 1
|
||||
FROM public.webhooks
|
||||
WHERE type='slack' AND tenant_id=%(tenant_id)s)) AS {schemas.IntegrationType.slack};""",
|
||||
{"user_id": user_id, "tenant_id": tenant_id, "project_id": project_id})
|
||||
)
|
||||
current_integrations = cur.fetchone()
|
||||
result = []
|
||||
for k in current_integrations.keys():
|
||||
result.append({"name": k, "integrated": current_integrations[k]})
|
||||
return result
|
||||
|
|
@ -49,7 +49,7 @@ def main():
|
|||
elif LEVEL == 'normal':
|
||||
n = handle_normal_message(message)
|
||||
|
||||
session_id = codec.decode_key(msg.key)
|
||||
session_id = decode_key(msg.key)
|
||||
sessions[session_id] = handle_session(sessions[session_id], message)
|
||||
if sessions[session_id]:
|
||||
sessions[session_id].sessionid = session_id
|
||||
|
|
@ -116,6 +116,15 @@ def attempt_batch_insert(batch):
|
|||
except Exception as e:
|
||||
print(repr(e))
|
||||
|
||||
def decode_key(b) -> int:
|
||||
"""
|
||||
Decode the message key (encoded with little endian)
|
||||
"""
|
||||
try:
|
||||
decoded = int.from_bytes(b, "little", signed=False)
|
||||
except Exception as e:
|
||||
raise UnicodeDecodeError(f"Error while decoding message key (SessionID) from {b}\n{e}")
|
||||
return decoded
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ def main():
|
|||
elif LEVEL == 'normal':
|
||||
n = handle_normal_message(message)
|
||||
|
||||
session_id = codec.decode_key(msg.key)
|
||||
session_id = decode_key(msg.key)
|
||||
sessions[session_id] = handle_session(sessions[session_id], message)
|
||||
if sessions[session_id]:
|
||||
sessions[session_id].sessionid = session_id
|
||||
|
|
@ -116,6 +116,15 @@ def attempt_batch_insert(batch):
|
|||
except Exception as e:
|
||||
print(repr(e))
|
||||
|
||||
def decode_key(b) -> int:
|
||||
"""
|
||||
Decode the message key (encoded with little endian)
|
||||
"""
|
||||
try:
|
||||
decoded = int.from_bytes(b, "little", signed=False)
|
||||
except Exception as e:
|
||||
raise UnicodeDecodeError(f"Error while decoding message key (SessionID) from {b}\n{e}")
|
||||
return decoded
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import io
|
||||
|
||||
from msgcodec.messages import *
|
||||
|
||||
|
||||
class Codec:
|
||||
"""
|
||||
Implements encode/decode primitives
|
||||
|
|
@ -63,608 +60,3 @@ class Codec:
|
|||
return s.decode("utf-8", errors="replace").replace("\x00", "\uFFFD")
|
||||
except UnicodeDecodeError:
|
||||
return None
|
||||
|
||||
|
||||
class MessageCodec(Codec):
|
||||
|
||||
def encode(self, m: Message) -> bytes:
|
||||
...
|
||||
|
||||
def decode(self, b: bytes) -> Message:
|
||||
reader = io.BytesIO(b)
|
||||
message_id = self.read_message_id(reader)
|
||||
|
||||
if message_id == 0:
|
||||
return Timestamp(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
if message_id == 1:
|
||||
return SessionStart(
|
||||
timestamp=self.read_uint(reader),
|
||||
project_id=self.read_uint(reader),
|
||||
tracker_version=self.read_string(reader),
|
||||
rev_id=self.read_string(reader),
|
||||
user_uuid=self.read_string(reader),
|
||||
user_agent=self.read_string(reader),
|
||||
user_os=self.read_string(reader),
|
||||
user_os_version=self.read_string(reader),
|
||||
user_browser=self.read_string(reader),
|
||||
user_browser_version=self.read_string(reader),
|
||||
user_device=self.read_string(reader),
|
||||
user_device_type=self.read_string(reader),
|
||||
user_device_memory_size=self.read_uint(reader),
|
||||
user_device_heap_size=self.read_uint(reader),
|
||||
user_country=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 2:
|
||||
return SessionDisconnect(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 3:
|
||||
return SessionEnd(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 4:
|
||||
return SetPageLocation(
|
||||
url=self.read_string(reader),
|
||||
referrer=self.read_string(reader),
|
||||
navigation_start=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 5:
|
||||
return SetViewportSize(
|
||||
width=self.read_uint(reader),
|
||||
height=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 6:
|
||||
return SetViewportScroll(
|
||||
x=self.read_int(reader),
|
||||
y=self.read_int(reader)
|
||||
)
|
||||
|
||||
if message_id == 7:
|
||||
return CreateDocument()
|
||||
|
||||
if message_id == 8:
|
||||
return CreateElementNode(
|
||||
id=self.read_uint(reader),
|
||||
parent_id=self.read_uint(reader),
|
||||
index=self.read_uint(reader),
|
||||
tag=self.read_string(reader),
|
||||
svg=self.read_boolean(reader),
|
||||
)
|
||||
|
||||
if message_id == 9:
|
||||
return CreateTextNode(
|
||||
id=self.read_uint(reader),
|
||||
parent_id=self.read_uint(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 10:
|
||||
return MoveNode(
|
||||
id=self.read_uint(reader),
|
||||
parent_id=self.read_uint(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 11:
|
||||
return RemoveNode(
|
||||
id=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 12:
|
||||
return SetNodeAttribute(
|
||||
id=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 13:
|
||||
return RemoveNodeAttribute(
|
||||
id=self.read_uint(reader),
|
||||
name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 14:
|
||||
return SetNodeData(
|
||||
id=self.read_uint(reader),
|
||||
data=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 15:
|
||||
return SetCSSData(
|
||||
id=self.read_uint(reader),
|
||||
data=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 16:
|
||||
return SetNodeScroll(
|
||||
id=self.read_uint(reader),
|
||||
x=self.read_int(reader),
|
||||
y=self.read_int(reader),
|
||||
)
|
||||
|
||||
if message_id == 17:
|
||||
return SetInputTarget(
|
||||
id=self.read_uint(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 18:
|
||||
return SetInputValue(
|
||||
id=self.read_uint(reader),
|
||||
value=self.read_string(reader),
|
||||
mask=self.read_int(reader),
|
||||
)
|
||||
|
||||
if message_id == 19:
|
||||
return SetInputChecked(
|
||||
id=self.read_uint(reader),
|
||||
checked=self.read_boolean(reader)
|
||||
)
|
||||
|
||||
if message_id == 20:
|
||||
return MouseMove(
|
||||
x=self.read_uint(reader),
|
||||
y=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 21:
|
||||
return MouseClick(
|
||||
id=self.read_uint(reader),
|
||||
hesitation_time=self.read_uint(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 22:
|
||||
return ConsoleLog(
|
||||
level=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 23:
|
||||
return PageLoadTiming(
|
||||
request_start=self.read_uint(reader),
|
||||
response_start=self.read_uint(reader),
|
||||
response_end=self.read_uint(reader),
|
||||
dom_content_loaded_event_start=self.read_uint(reader),
|
||||
dom_content_loaded_event_end=self.read_uint(reader),
|
||||
load_event_start=self.read_uint(reader),
|
||||
load_event_end=self.read_uint(reader),
|
||||
first_paint=self.read_uint(reader),
|
||||
first_contentful_paint=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 24:
|
||||
return PageRenderTiming(
|
||||
speed_index=self.read_uint(reader),
|
||||
visually_complete=self.read_uint(reader),
|
||||
time_to_interactive=self.read_uint(reader),
|
||||
)
|
||||
|
||||
if message_id == 25:
|
||||
return JSException(
|
||||
name=self.read_string(reader),
|
||||
message=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 26:
|
||||
return RawErrorEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
source=self.read_string(reader),
|
||||
name=self.read_string(reader),
|
||||
message=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 27:
|
||||
return RawCustomEvent(
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 28:
|
||||
return UserID(
|
||||
id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 29:
|
||||
return UserAnonymousID(
|
||||
id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 30:
|
||||
return Metadata(
|
||||
key=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 31:
|
||||
return PageEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
url=self.read_string(reader),
|
||||
referrer=self.read_string(reader),
|
||||
loaded=self.read_boolean(reader),
|
||||
request_start=self.read_uint(reader),
|
||||
response_start=self.read_uint(reader),
|
||||
response_end=self.read_uint(reader),
|
||||
dom_content_loaded_event_start=self.read_uint(reader),
|
||||
dom_content_loaded_event_end=self.read_uint(reader),
|
||||
load_event_start=self.read_uint(reader),
|
||||
load_event_end=self.read_uint(reader),
|
||||
first_paint=self.read_uint(reader),
|
||||
first_contentful_paint=self.read_uint(reader),
|
||||
speed_index=self.read_uint(reader),
|
||||
visually_complete=self.read_uint(reader),
|
||||
time_to_interactive=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 32:
|
||||
return InputEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
value=self.read_string(reader),
|
||||
value_masked=self.read_boolean(reader),
|
||||
label=self.read_string(reader),
|
||||
)
|
||||
|
||||
if message_id == 33:
|
||||
return ClickEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
hesitation_time=self.read_uint(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 34:
|
||||
return ErrorEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
source=self.read_string(reader),
|
||||
name=self.read_string(reader),
|
||||
message=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 35:
|
||||
|
||||
message_id = self.read_uint(reader)
|
||||
ts = self.read_uint(reader)
|
||||
if ts > 9999999999999:
|
||||
ts = None
|
||||
return ResourceEvent(
|
||||
message_id=message_id,
|
||||
timestamp=ts,
|
||||
duration=self.read_uint(reader),
|
||||
ttfb=self.read_uint(reader),
|
||||
header_size=self.read_uint(reader),
|
||||
encoded_body_size=self.read_uint(reader),
|
||||
decoded_body_size=self.read_uint(reader),
|
||||
url=self.read_string(reader),
|
||||
type=self.read_string(reader),
|
||||
success=self.read_boolean(reader),
|
||||
method=self.read_string(reader),
|
||||
status=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 36:
|
||||
return CustomEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 37:
|
||||
return CSSInsertRule(
|
||||
id=self.read_uint(reader),
|
||||
rule=self.read_string(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 38:
|
||||
return CSSDeleteRule(
|
||||
id=self.read_uint(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 39:
|
||||
return Fetch(
|
||||
method=self.read_string(reader),
|
||||
url=self.read_string(reader),
|
||||
request=self.read_string(reader),
|
||||
response=self.read_string(reader),
|
||||
status=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 40:
|
||||
return Profiler(
|
||||
name=self.read_string(reader),
|
||||
duration=self.read_uint(reader),
|
||||
args=self.read_string(reader),
|
||||
result=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 41:
|
||||
return OTable(
|
||||
key=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 42:
|
||||
return StateAction(
|
||||
type=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 43:
|
||||
return StateActionEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
type=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 44:
|
||||
return Redux(
|
||||
action=self.read_string(reader),
|
||||
state=self.read_string(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 45:
|
||||
return Vuex(
|
||||
mutation=self.read_string(reader),
|
||||
state=self.read_string(reader),
|
||||
)
|
||||
|
||||
if message_id == 46:
|
||||
return MobX(
|
||||
type=self.read_string(reader),
|
||||
payload=self.read_string(reader),
|
||||
)
|
||||
|
||||
if message_id == 47:
|
||||
return NgRx(
|
||||
action=self.read_string(reader),
|
||||
state=self.read_string(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 48:
|
||||
return GraphQL(
|
||||
operation_kind=self.read_string(reader),
|
||||
operation_name=self.read_string(reader),
|
||||
variables=self.read_string(reader),
|
||||
response=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 49:
|
||||
return PerformanceTrack(
|
||||
frames=self.read_int(reader),
|
||||
ticks=self.read_int(reader),
|
||||
total_js_heap_size=self.read_uint(reader),
|
||||
used_js_heap_size=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 50:
|
||||
return GraphQLEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 52:
|
||||
return DomDrop(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 53:
|
||||
return ResourceTiming(
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader),
|
||||
ttfb=self.read_uint(reader),
|
||||
header_size=self.read_uint(reader),
|
||||
encoded_body_size=self.read_uint(reader),
|
||||
decoded_body_size=self.read_uint(reader),
|
||||
url=self.read_string(reader),
|
||||
initiator=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 54:
|
||||
return ConnectionInformation(
|
||||
downlink=self.read_uint(reader),
|
||||
type=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 55:
|
||||
return SetPageVisibility(
|
||||
hidden=self.read_boolean(reader)
|
||||
)
|
||||
|
||||
if message_id == 56:
|
||||
return PerformanceTrackAggr(
|
||||
timestamp_start=self.read_uint(reader),
|
||||
timestamp_end=self.read_uint(reader),
|
||||
min_fps=self.read_uint(reader),
|
||||
avg_fps=self.read_uint(reader),
|
||||
max_fps=self.read_uint(reader),
|
||||
min_cpu=self.read_uint(reader),
|
||||
avg_cpu=self.read_uint(reader),
|
||||
max_cpu=self.read_uint(reader),
|
||||
min_total_js_heap_size=self.read_uint(reader),
|
||||
avg_total_js_heap_size=self.read_uint(reader),
|
||||
max_total_js_heap_size=self.read_uint(reader),
|
||||
min_used_js_heap_size=self.read_uint(reader),
|
||||
avg_used_js_heap_size=self.read_uint(reader),
|
||||
max_used_js_heap_size=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 59:
|
||||
return LongTask(
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader),
|
||||
context=self.read_uint(reader),
|
||||
container_type=self.read_uint(reader),
|
||||
container_src=self.read_string(reader),
|
||||
container_id=self.read_string(reader),
|
||||
container_name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 60:
|
||||
return SetNodeURLBasedAttribute(
|
||||
id=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
value=self.read_string(reader),
|
||||
base_url=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 61:
|
||||
return SetStyleData(
|
||||
id=self.read_uint(reader),
|
||||
data=self.read_string(reader),
|
||||
base_url=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 62:
|
||||
return IssueEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
type=self.read_string(reader),
|
||||
context_string=self.read_string(reader),
|
||||
context=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 63:
|
||||
return TechnicalInfo(
|
||||
type=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 64:
|
||||
return CustomIssue(
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 65:
|
||||
return PageClose()
|
||||
|
||||
if message_id == 90:
|
||||
return IOSSessionStart(
|
||||
timestamp=self.read_uint(reader),
|
||||
project_id=self.read_uint(reader),
|
||||
tracker_version=self.read_string(reader),
|
||||
rev_id=self.read_string(reader),
|
||||
user_uuid=self.read_string(reader),
|
||||
user_os=self.read_string(reader),
|
||||
user_os_version=self.read_string(reader),
|
||||
user_device=self.read_string(reader),
|
||||
user_device_type=self.read_string(reader),
|
||||
user_country=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 91:
|
||||
return IOSSessionEnd(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 92:
|
||||
return IOSMetadata(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
key=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 94:
|
||||
return IOSUserID(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 95:
|
||||
return IOSUserAnonymousID(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 99:
|
||||
return IOSScreenLeave(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
title=self.read_string(reader),
|
||||
view_name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 103:
|
||||
return IOSLog(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
severity=self.read_string(reader),
|
||||
content=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 104:
|
||||
return IOSInternalError(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
content=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 110:
|
||||
return IOSPerformanceAggregated(
|
||||
timestamp_start=self.read_uint(reader),
|
||||
timestamp_end=self.read_uint(reader),
|
||||
min_fps=self.read_uint(reader),
|
||||
avg_fps=self.read_uint(reader),
|
||||
max_fps=self.read_uint(reader),
|
||||
min_cpu=self.read_uint(reader),
|
||||
avg_cpu=self.read_uint(reader),
|
||||
max_cpu=self.read_uint(reader),
|
||||
min_memory=self.read_uint(reader),
|
||||
avg_memory=self.read_uint(reader),
|
||||
max_memory=self.read_uint(reader),
|
||||
min_battery=self.read_uint(reader),
|
||||
avg_battery=self.read_uint(reader),
|
||||
max_battery=self.read_uint(reader)
|
||||
)
|
||||
|
||||
def read_message_id(self, reader: io.BytesIO) -> int:
|
||||
"""
|
||||
Read and return the first byte where the message id is encoded
|
||||
"""
|
||||
id_ = self.read_uint(reader)
|
||||
return id_
|
||||
|
||||
@staticmethod
|
||||
def check_message_id(b: bytes) -> int:
|
||||
"""
|
||||
todo: make it static and without reader. It's just the first byte
|
||||
Read and return the first byte where the message id is encoded
|
||||
"""
|
||||
reader = io.BytesIO(b)
|
||||
id_ = Codec.read_uint(reader)
|
||||
|
||||
return id_
|
||||
|
||||
@staticmethod
|
||||
def decode_key(b) -> int:
|
||||
"""
|
||||
Decode the message key (encoded with little endian)
|
||||
"""
|
||||
try:
|
||||
decoded = int.from_bytes(b, "little", signed=False)
|
||||
except Exception as e:
|
||||
raise UnicodeDecodeError(f"Error while decoding message key (SessionID) from {b}\n{e}")
|
||||
return decoded
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
"""
|
||||
Representations of Kafka messages
|
||||
"""
|
||||
from abc import ABC
|
||||
# Auto-generated, do not edit
|
||||
|
||||
from abc import ABC
|
||||
|
||||
class Message(ABC):
|
||||
pass
|
||||
|
||||
|
||||
class BatchMeta(Message):
|
||||
__id__ = 80
|
||||
|
||||
def __init__(self, page_no, first_index, timestamp):
|
||||
self.page_no = page_no
|
||||
self.first_index = first_index
|
||||
self.timestamp = timestamp
|
||||
|
||||
|
||||
class Timestamp(Message):
|
||||
__id__ = 0
|
||||
|
||||
|
|
@ -18,10 +25,7 @@ class Timestamp(Message):
|
|||
class SessionStart(Message):
|
||||
__id__ = 1
|
||||
|
||||
def __init__(self, timestamp, project_id, tracker_version, rev_id, user_uuid,
|
||||
user_agent, user_os, user_os_version, user_browser, user_browser_version,
|
||||
user_device, user_device_type, user_device_memory_size, user_device_heap_size,
|
||||
user_country):
|
||||
def __init__(self, timestamp, project_id, tracker_version, rev_id, user_uuid, user_agent, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_device_memory_size, user_device_heap_size, user_country, user_id):
|
||||
self.timestamp = timestamp
|
||||
self.project_id = project_id
|
||||
self.tracker_version = tracker_version
|
||||
|
|
@ -37,6 +41,7 @@ class SessionStart(Message):
|
|||
self.user_device_memory_size = user_device_memory_size
|
||||
self.user_device_heap_size = user_device_heap_size
|
||||
self.user_country = user_country
|
||||
self.user_id = user_id
|
||||
|
||||
|
||||
class SessionDisconnect(Message):
|
||||
|
|
@ -48,7 +53,6 @@ class SessionDisconnect(Message):
|
|||
|
||||
class SessionEnd(Message):
|
||||
__id__ = 3
|
||||
__name__ = 'SessionEnd'
|
||||
|
||||
def __init__(self, timestamp):
|
||||
self.timestamp = timestamp
|
||||
|
|
@ -82,13 +86,16 @@ class SetViewportScroll(Message):
|
|||
class CreateDocument(Message):
|
||||
__id__ = 7
|
||||
|
||||
def __init__(self, ):
|
||||
|
||||
|
||||
|
||||
class CreateElementNode(Message):
|
||||
__id__ = 8
|
||||
|
||||
def __init__(self, id, parent_id, index, tag, svg):
|
||||
self.id = id
|
||||
self.parent_id = parent_id,
|
||||
self.parent_id = parent_id
|
||||
self.index = index
|
||||
self.tag = tag
|
||||
self.svg = svg
|
||||
|
|
@ -122,7 +129,7 @@ class RemoveNode(Message):
|
|||
class SetNodeAttribute(Message):
|
||||
__id__ = 12
|
||||
|
||||
def __init__(self, id, name: str, value: str):
|
||||
def __init__(self, id, name, value):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
|
@ -131,7 +138,7 @@ class SetNodeAttribute(Message):
|
|||
class RemoveNodeAttribute(Message):
|
||||
__id__ = 13
|
||||
|
||||
def __init__(self, id, name: str):
|
||||
def __init__(self, id, name):
|
||||
self.id = id
|
||||
self.name = name
|
||||
|
||||
|
|
@ -139,7 +146,7 @@ class RemoveNodeAttribute(Message):
|
|||
class SetNodeData(Message):
|
||||
__id__ = 14
|
||||
|
||||
def __init__(self, id, data: str):
|
||||
def __init__(self, id, data):
|
||||
self.id = id
|
||||
self.data = data
|
||||
|
||||
|
|
@ -147,7 +154,7 @@ class SetNodeData(Message):
|
|||
class SetCSSData(Message):
|
||||
__id__ = 15
|
||||
|
||||
def __init__(self, id, data: str):
|
||||
def __init__(self, id, data):
|
||||
self.id = id
|
||||
self.data = data
|
||||
|
||||
|
|
@ -155,7 +162,7 @@ class SetCSSData(Message):
|
|||
class SetNodeScroll(Message):
|
||||
__id__ = 16
|
||||
|
||||
def __init__(self, id, x: int, y: int):
|
||||
def __init__(self, id, x, y):
|
||||
self.id = id
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
|
@ -164,7 +171,7 @@ class SetNodeScroll(Message):
|
|||
class SetInputTarget(Message):
|
||||
__id__ = 17
|
||||
|
||||
def __init__(self, id, label: str):
|
||||
def __init__(self, id, label):
|
||||
self.id = id
|
||||
self.label = label
|
||||
|
||||
|
|
@ -172,7 +179,7 @@ class SetInputTarget(Message):
|
|||
class SetInputValue(Message):
|
||||
__id__ = 18
|
||||
|
||||
def __init__(self, id, value: str, mask: int):
|
||||
def __init__(self, id, value, mask):
|
||||
self.id = id
|
||||
self.value = value
|
||||
self.mask = mask
|
||||
|
|
@ -181,7 +188,7 @@ class SetInputValue(Message):
|
|||
class SetInputChecked(Message):
|
||||
__id__ = 19
|
||||
|
||||
def __init__(self, id, checked: bool):
|
||||
def __init__(self, id, checked):
|
||||
self.id = id
|
||||
self.checked = checked
|
||||
|
||||
|
|
@ -194,10 +201,10 @@ class MouseMove(Message):
|
|||
self.y = y
|
||||
|
||||
|
||||
class MouseClick(Message):
|
||||
class MouseClickDepricated(Message):
|
||||
__id__ = 21
|
||||
|
||||
def __init__(self, id, hesitation_time, label: str):
|
||||
def __init__(self, id, hesitation_time, label):
|
||||
self.id = id
|
||||
self.hesitation_time = hesitation_time
|
||||
self.label = label
|
||||
|
|
@ -206,7 +213,7 @@ class MouseClick(Message):
|
|||
class ConsoleLog(Message):
|
||||
__id__ = 22
|
||||
|
||||
def __init__(self, level: str, value: str):
|
||||
def __init__(self, level, value):
|
||||
self.level = level
|
||||
self.value = value
|
||||
|
||||
|
|
@ -214,9 +221,7 @@ class ConsoleLog(Message):
|
|||
class PageLoadTiming(Message):
|
||||
__id__ = 23
|
||||
|
||||
def __init__(self, request_start, response_start, response_end, dom_content_loaded_event_start,
|
||||
dom_content_loaded_event_end, load_event_start, load_event_end,
|
||||
first_paint, first_contentful_paint):
|
||||
def __init__(self, request_start, response_start, response_end, dom_content_loaded_event_start, dom_content_loaded_event_end, load_event_start, load_event_end, first_paint, first_contentful_paint):
|
||||
self.request_start = request_start
|
||||
self.response_start = response_start
|
||||
self.response_end = response_end
|
||||
|
|
@ -236,20 +241,20 @@ class PageRenderTiming(Message):
|
|||
self.visually_complete = visually_complete
|
||||
self.time_to_interactive = time_to_interactive
|
||||
|
||||
|
||||
class JSException(Message):
|
||||
__id__ = 25
|
||||
|
||||
def __init__(self, name: str, message: str, payload: str):
|
||||
def __init__(self, name, message, payload):
|
||||
self.name = name
|
||||
self.message = message
|
||||
self.payload = payload
|
||||
|
||||
|
||||
class RawErrorEvent(Message):
|
||||
class IntegrationEvent(Message):
|
||||
__id__ = 26
|
||||
|
||||
def __init__(self, timestamp, source: str, name: str, message: str,
|
||||
payload: str):
|
||||
def __init__(self, timestamp, source, name, message, payload):
|
||||
self.timestamp = timestamp
|
||||
self.source = source
|
||||
self.name = name
|
||||
|
|
@ -260,7 +265,7 @@ class RawErrorEvent(Message):
|
|||
class RawCustomEvent(Message):
|
||||
__id__ = 27
|
||||
|
||||
def __init__(self, name: str, payload: str):
|
||||
def __init__(self, name, payload):
|
||||
self.name = name
|
||||
self.payload = payload
|
||||
|
||||
|
|
@ -268,44 +273,29 @@ class RawCustomEvent(Message):
|
|||
class UserID(Message):
|
||||
__id__ = 28
|
||||
|
||||
def __init__(self, id: str):
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
|
||||
|
||||
class UserAnonymousID(Message):
|
||||
__id__ = 29
|
||||
|
||||
def __init__(self, id: str):
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
|
||||
|
||||
class Metadata(Message):
|
||||
__id__ = 30
|
||||
|
||||
def __init__(self, key: str, value: str):
|
||||
def __init__(self, key, value):
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
||||
class PerformanceTrack(Message):
|
||||
__id__ = 49
|
||||
|
||||
def __init__(self, frames: int, ticks: int, total_js_heap_size,
|
||||
used_js_heap_size):
|
||||
self.frames = frames
|
||||
self.ticks = ticks
|
||||
self.total_js_heap_size = total_js_heap_size
|
||||
self.used_js_heap_size = used_js_heap_size
|
||||
|
||||
|
||||
class PageEvent(Message):
|
||||
__id__ = 31
|
||||
|
||||
def __init__(self, message_id, timestamp, url: str, referrer: str,
|
||||
loaded: bool, request_start, response_start, response_end,
|
||||
dom_content_loaded_event_start, dom_content_loaded_event_end,
|
||||
load_event_start, load_event_end, first_paint, first_contentful_paint,
|
||||
speed_index, visually_complete, time_to_interactive):
|
||||
def __init__(self, message_id, timestamp, url, referrer, loaded, request_start, response_start, response_end, dom_content_loaded_event_start, dom_content_loaded_event_end, load_event_start, load_event_end, first_paint, first_contentful_paint, speed_index, visually_complete, time_to_interactive):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.url = url
|
||||
|
|
@ -328,7 +318,7 @@ class PageEvent(Message):
|
|||
class InputEvent(Message):
|
||||
__id__ = 32
|
||||
|
||||
def __init__(self, message_id, timestamp, value: str, value_masked: bool, label: str):
|
||||
def __init__(self, message_id, timestamp, value, value_masked, label):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.value = value
|
||||
|
|
@ -339,18 +329,18 @@ class InputEvent(Message):
|
|||
class ClickEvent(Message):
|
||||
__id__ = 33
|
||||
|
||||
def __init__(self, message_id, timestamp, hesitation_time, label: str):
|
||||
def __init__(self, message_id, timestamp, hesitation_time, label, selector):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.hesitation_time = hesitation_time
|
||||
self.label = label
|
||||
self.selector = selector
|
||||
|
||||
|
||||
class ErrorEvent(Message):
|
||||
__id__ = 34
|
||||
|
||||
def __init__(self, message_id, timestamp, source: str, name: str, message: str,
|
||||
payload: str):
|
||||
def __init__(self, message_id, timestamp, source, name, message, payload):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.source = source
|
||||
|
|
@ -362,8 +352,7 @@ class ErrorEvent(Message):
|
|||
class ResourceEvent(Message):
|
||||
__id__ = 35
|
||||
|
||||
def __init__(self, message_id, timestamp, duration, ttfb, header_size, encoded_body_size,
|
||||
decoded_body_size, url: str, type: str, success: bool, method: str, status):
|
||||
def __init__(self, message_id, timestamp, duration, ttfb, header_size, encoded_body_size, decoded_body_size, url, type, success, method, status):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.duration = duration
|
||||
|
|
@ -381,7 +370,7 @@ class ResourceEvent(Message):
|
|||
class CustomEvent(Message):
|
||||
__id__ = 36
|
||||
|
||||
def __init__(self, message_id, timestamp, name: str, payload: str):
|
||||
def __init__(self, message_id, timestamp, name, payload):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.name = name
|
||||
|
|
@ -391,7 +380,7 @@ class CustomEvent(Message):
|
|||
class CSSInsertRule(Message):
|
||||
__id__ = 37
|
||||
|
||||
def __init__(self, id, rule: str, index):
|
||||
def __init__(self, id, rule, index):
|
||||
self.id = id
|
||||
self.rule = rule
|
||||
self.index = index
|
||||
|
|
@ -408,8 +397,7 @@ class CSSDeleteRule(Message):
|
|||
class Fetch(Message):
|
||||
__id__ = 39
|
||||
|
||||
def __init__(self, method: str, url: str, request: str, response: str, status,
|
||||
timestamp, duration):
|
||||
def __init__(self, method, url, request, response, status, timestamp, duration):
|
||||
self.method = method
|
||||
self.url = url
|
||||
self.request = request
|
||||
|
|
@ -422,7 +410,7 @@ class Fetch(Message):
|
|||
class Profiler(Message):
|
||||
__id__ = 40
|
||||
|
||||
def __init__(self, name: str, duration, args: str, result: str):
|
||||
def __init__(self, name, duration, args, result):
|
||||
self.name = name
|
||||
self.duration = duration
|
||||
self.args = args
|
||||
|
|
@ -432,7 +420,7 @@ class Profiler(Message):
|
|||
class OTable(Message):
|
||||
__id__ = 41
|
||||
|
||||
def __init__(self, key: str, value: str):
|
||||
def __init__(self, key, value):
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
|
@ -440,14 +428,14 @@ class OTable(Message):
|
|||
class StateAction(Message):
|
||||
__id__ = 42
|
||||
|
||||
def __init__(self, type: str):
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
||||
|
||||
class StateActionEvent(Message):
|
||||
__id__ = 43
|
||||
|
||||
def __init__(self, message_id, timestamp, type: str):
|
||||
def __init__(self, message_id, timestamp, type):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.type = type
|
||||
|
|
@ -456,7 +444,7 @@ class StateActionEvent(Message):
|
|||
class Redux(Message):
|
||||
__id__ = 44
|
||||
|
||||
def __init__(self, action: str, state: str, duration):
|
||||
def __init__(self, action, state, duration):
|
||||
self.action = action
|
||||
self.state = state
|
||||
self.duration = duration
|
||||
|
|
@ -465,7 +453,7 @@ class Redux(Message):
|
|||
class Vuex(Message):
|
||||
__id__ = 45
|
||||
|
||||
def __init__(self, mutation: str, state: str):
|
||||
def __init__(self, mutation, state):
|
||||
self.mutation = mutation
|
||||
self.state = state
|
||||
|
||||
|
|
@ -473,7 +461,7 @@ class Vuex(Message):
|
|||
class MobX(Message):
|
||||
__id__ = 46
|
||||
|
||||
def __init__(self, type: str, payload: str):
|
||||
def __init__(self, type, payload):
|
||||
self.type = type
|
||||
self.payload = payload
|
||||
|
||||
|
|
@ -481,7 +469,7 @@ class MobX(Message):
|
|||
class NgRx(Message):
|
||||
__id__ = 47
|
||||
|
||||
def __init__(self, action: str, state: str, duration):
|
||||
def __init__(self, action, state, duration):
|
||||
self.action = action
|
||||
self.state = state
|
||||
self.duration = duration
|
||||
|
|
@ -490,8 +478,7 @@ class NgRx(Message):
|
|||
class GraphQL(Message):
|
||||
__id__ = 48
|
||||
|
||||
def __init__(self, operation_kind: str, operation_name: str,
|
||||
variables: str, response: str):
|
||||
def __init__(self, operation_kind, operation_name, variables, response):
|
||||
self.operation_kind = operation_kind
|
||||
self.operation_name = operation_name
|
||||
self.variables = variables
|
||||
|
|
@ -501,8 +488,7 @@ class GraphQL(Message):
|
|||
class PerformanceTrack(Message):
|
||||
__id__ = 49
|
||||
|
||||
def __init__(self, frames: int, ticks: int,
|
||||
total_js_heap_size, used_js_heap_size):
|
||||
def __init__(self, frames, ticks, total_js_heap_size, used_js_heap_size):
|
||||
self.frames = frames
|
||||
self.ticks = ticks
|
||||
self.total_js_heap_size = total_js_heap_size
|
||||
|
|
@ -512,13 +498,30 @@ class PerformanceTrack(Message):
|
|||
class GraphQLEvent(Message):
|
||||
__id__ = 50
|
||||
|
||||
def __init__(self, message_id, timestamp, name: str):
|
||||
def __init__(self, message_id, timestamp, operation_kind, operation_name, variables, response):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.name = name
|
||||
self.operation_kind = operation_kind
|
||||
self.operation_name = operation_name
|
||||
self.variables = variables
|
||||
self.response = response
|
||||
|
||||
|
||||
class DomDrop(Message):
|
||||
class FetchEvent(Message):
|
||||
__id__ = 51
|
||||
|
||||
def __init__(self, message_id, timestamp, method, url, request, response, status, duration):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.method = method
|
||||
self.url = url
|
||||
self.request = request
|
||||
self.response = response
|
||||
self.status = status
|
||||
self.duration = duration
|
||||
|
||||
|
||||
class DOMDrop(Message):
|
||||
__id__ = 52
|
||||
|
||||
def __init__(self, timestamp):
|
||||
|
|
@ -528,8 +531,7 @@ class DomDrop(Message):
|
|||
class ResourceTiming(Message):
|
||||
__id__ = 53
|
||||
|
||||
def __init__(self, timestamp, duration, ttfb, header_size, encoded_body_size,
|
||||
decoded_body_size, url, initiator):
|
||||
def __init__(self, timestamp, duration, ttfb, header_size, encoded_body_size, decoded_body_size, url, initiator):
|
||||
self.timestamp = timestamp
|
||||
self.duration = duration
|
||||
self.ttfb = ttfb
|
||||
|
|
@ -543,7 +545,7 @@ class ResourceTiming(Message):
|
|||
class ConnectionInformation(Message):
|
||||
__id__ = 54
|
||||
|
||||
def __init__(self, downlink, type: str):
|
||||
def __init__(self, downlink, type):
|
||||
self.downlink = downlink
|
||||
self.type = type
|
||||
|
||||
|
|
@ -551,19 +553,14 @@ class ConnectionInformation(Message):
|
|||
class SetPageVisibility(Message):
|
||||
__id__ = 55
|
||||
|
||||
def __init__(self, hidden: bool):
|
||||
def __init__(self, hidden):
|
||||
self.hidden = hidden
|
||||
|
||||
|
||||
class PerformanceTrackAggr(Message):
|
||||
__id__ = 56
|
||||
|
||||
def __init__(self, timestamp_start, timestamp_end, min_fps, avg_fps,
|
||||
max_fps, min_cpu, avg_cpu, max_cpu,
|
||||
min_total_js_heap_size, avg_total_js_heap_size,
|
||||
max_total_js_heap_size, min_used_js_heap_size,
|
||||
avg_used_js_heap_size, max_used_js_heap_size
|
||||
):
|
||||
def __init__(self, timestamp_start, timestamp_end, min_fps, avg_fps, max_fps, min_cpu, avg_cpu, max_cpu, min_total_js_heap_size, avg_total_js_heap_size, max_total_js_heap_size, min_used_js_heap_size, avg_used_js_heap_size, max_used_js_heap_size):
|
||||
self.timestamp_start = timestamp_start
|
||||
self.timestamp_end = timestamp_end
|
||||
self.min_fps = min_fps
|
||||
|
|
@ -583,8 +580,7 @@ class PerformanceTrackAggr(Message):
|
|||
class LongTask(Message):
|
||||
__id__ = 59
|
||||
|
||||
def __init__(self, timestamp, duration, context, container_type, container_src: str,
|
||||
container_id: str, container_name: str):
|
||||
def __init__(self, timestamp, duration, context, container_type, container_src, container_id, container_name):
|
||||
self.timestamp = timestamp
|
||||
self.duration = duration
|
||||
self.context = context
|
||||
|
|
@ -594,20 +590,20 @@ class LongTask(Message):
|
|||
self.container_name = container_name
|
||||
|
||||
|
||||
class SetNodeURLBasedAttribute(Message):
|
||||
class SetNodeAttributeURLBased(Message):
|
||||
__id__ = 60
|
||||
|
||||
def __init__(self, id, name: str, value: str, base_url: str):
|
||||
def __init__(self, id, name, value, base_url):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.base_url = base_url
|
||||
|
||||
|
||||
class SetStyleData(Message):
|
||||
class SetCSSDataURLBased(Message):
|
||||
__id__ = 61
|
||||
|
||||
def __init__(self, id, data: str, base_url: str):
|
||||
def __init__(self, id, data, base_url):
|
||||
self.id = id
|
||||
self.data = data
|
||||
self.base_url = base_url
|
||||
|
|
@ -616,8 +612,7 @@ class SetStyleData(Message):
|
|||
class IssueEvent(Message):
|
||||
__id__ = 62
|
||||
|
||||
def __init__(self, message_id, timestamp, type: str, context_string: str,
|
||||
context: str, payload: str):
|
||||
def __init__(self, message_id, timestamp, type, context_string, context, payload):
|
||||
self.message_id = message_id
|
||||
self.timestamp = timestamp
|
||||
self.type = type
|
||||
|
|
@ -629,7 +624,7 @@ class IssueEvent(Message):
|
|||
class TechnicalInfo(Message):
|
||||
__id__ = 63
|
||||
|
||||
def __init__(self, type: str, value: str):
|
||||
def __init__(self, type, value):
|
||||
self.type = type
|
||||
self.value = value
|
||||
|
||||
|
|
@ -637,7 +632,7 @@ class TechnicalInfo(Message):
|
|||
class CustomIssue(Message):
|
||||
__id__ = 64
|
||||
|
||||
def __init__(self, name: str, payload: str):
|
||||
def __init__(self, name, payload):
|
||||
self.name = name
|
||||
self.payload = payload
|
||||
|
||||
|
|
@ -645,13 +640,58 @@ class CustomIssue(Message):
|
|||
class PageClose(Message):
|
||||
__id__ = 65
|
||||
|
||||
def __init__(self, ):
|
||||
|
||||
|
||||
|
||||
class AssetCache(Message):
|
||||
__id__ = 66
|
||||
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
|
||||
|
||||
class CSSInsertRuleURLBased(Message):
|
||||
__id__ = 67
|
||||
|
||||
def __init__(self, id, rule, index, base_url):
|
||||
self.id = id
|
||||
self.rule = rule
|
||||
self.index = index
|
||||
self.base_url = base_url
|
||||
|
||||
|
||||
class MouseClick(Message):
|
||||
__id__ = 69
|
||||
|
||||
def __init__(self, id, hesitation_time, label, selector):
|
||||
self.id = id
|
||||
self.hesitation_time = hesitation_time
|
||||
self.label = label
|
||||
self.selector = selector
|
||||
|
||||
|
||||
class CreateIFrameDocument(Message):
|
||||
__id__ = 70
|
||||
|
||||
def __init__(self, frame_id, id):
|
||||
self.frame_id = frame_id
|
||||
self.id = id
|
||||
|
||||
|
||||
class IOSBatchMeta(Message):
|
||||
__id__ = 107
|
||||
|
||||
def __init__(self, timestamp, length, first_index):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.first_index = first_index
|
||||
|
||||
|
||||
class IOSSessionStart(Message):
|
||||
__id__ = 90
|
||||
|
||||
def __init__(self, timestamp, project_id, tracker_version: str,
|
||||
rev_id: str, user_uuid: str, user_os: str, user_os_version: str,
|
||||
user_device: str, user_device_type: str, user_country: str):
|
||||
def __init__(self, timestamp, project_id, tracker_version, rev_id, user_uuid, user_os, user_os_version, user_device, user_device_type, user_country):
|
||||
self.timestamp = timestamp
|
||||
self.project_id = project_id
|
||||
self.tracker_version = tracker_version
|
||||
|
|
@ -674,17 +714,27 @@ class IOSSessionEnd(Message):
|
|||
class IOSMetadata(Message):
|
||||
__id__ = 92
|
||||
|
||||
def __init__(self, timestamp, length, key: str, value: str):
|
||||
def __init__(self, timestamp, length, key, value):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
||||
class IOSCustomEvent(Message):
|
||||
__id__ = 93
|
||||
|
||||
def __init__(self, timestamp, length, name, payload):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.name = name
|
||||
self.payload = payload
|
||||
|
||||
|
||||
class IOSUserID(Message):
|
||||
__id__ = 94
|
||||
|
||||
def __init__(self, timestamp, length, value: str):
|
||||
def __init__(self, timestamp, length, value):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.value = value
|
||||
|
|
@ -693,26 +743,91 @@ class IOSUserID(Message):
|
|||
class IOSUserAnonymousID(Message):
|
||||
__id__ = 95
|
||||
|
||||
def __init__(self, timestamp, length, value: str):
|
||||
def __init__(self, timestamp, length, value):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.value = value
|
||||
|
||||
|
||||
class IOSScreenLeave(Message):
|
||||
__id__ = 99
|
||||
class IOSScreenChanges(Message):
|
||||
__id__ = 96
|
||||
|
||||
def __init__(self, timestamp, length, title: str, view_name: str):
|
||||
def __init__(self, timestamp, length, x, y, width, height):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
|
||||
class IOSCrash(Message):
|
||||
__id__ = 97
|
||||
|
||||
def __init__(self, timestamp, length, name, reason, stacktrace):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.name = name
|
||||
self.reason = reason
|
||||
self.stacktrace = stacktrace
|
||||
|
||||
|
||||
class IOSScreenEnter(Message):
|
||||
__id__ = 98
|
||||
|
||||
def __init__(self, timestamp, length, title, view_name):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.title = title
|
||||
self.view_name = view_name
|
||||
|
||||
|
||||
class IOSScreenLeave(Message):
|
||||
__id__ = 99
|
||||
|
||||
def __init__(self, timestamp, length, title, view_name):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.title = title
|
||||
self.view_name = view_name
|
||||
|
||||
|
||||
class IOSClickEvent(Message):
|
||||
__id__ = 100
|
||||
|
||||
def __init__(self, timestamp, length, label, x, y):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.label = label
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
|
||||
class IOSInputEvent(Message):
|
||||
__id__ = 101
|
||||
|
||||
def __init__(self, timestamp, length, value, value_masked, label):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.value = value
|
||||
self.value_masked = value_masked
|
||||
self.label = label
|
||||
|
||||
|
||||
class IOSPerformanceEvent(Message):
|
||||
__id__ = 102
|
||||
|
||||
def __init__(self, timestamp, length, name, value):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
|
||||
class IOSLog(Message):
|
||||
__id__ = 103
|
||||
|
||||
def __init__(self, timestamp, length, severity: str, content: str):
|
||||
def __init__(self, timestamp, length, severity, content):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.severity = severity
|
||||
|
|
@ -722,20 +837,31 @@ class IOSLog(Message):
|
|||
class IOSInternalError(Message):
|
||||
__id__ = 104
|
||||
|
||||
def __init__(self, timestamp, length, content: str):
|
||||
def __init__(self, timestamp, length, content):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.content = content
|
||||
|
||||
|
||||
class IOSNetworkCall(Message):
|
||||
__id__ = 105
|
||||
|
||||
def __init__(self, timestamp, length, duration, headers, body, url, success, method, status):
|
||||
self.timestamp = timestamp
|
||||
self.length = length
|
||||
self.duration = duration
|
||||
self.headers = headers
|
||||
self.body = body
|
||||
self.url = url
|
||||
self.success = success
|
||||
self.method = method
|
||||
self.status = status
|
||||
|
||||
|
||||
class IOSPerformanceAggregated(Message):
|
||||
__id__ = 110
|
||||
|
||||
def __init__(self, timestamp_start, timestamp_end, min_fps, avg_fps,
|
||||
max_fps, min_cpu, avg_cpu, max_cpu,
|
||||
min_memory, avg_memory, max_memory,
|
||||
min_battery, avg_battery, max_battery
|
||||
):
|
||||
def __init__(self, timestamp_start, timestamp_end, min_fps, avg_fps, max_fps, min_cpu, avg_cpu, max_cpu, min_memory, avg_memory, max_memory, min_battery, avg_battery, max_battery):
|
||||
self.timestamp_start = timestamp_start
|
||||
self.timestamp_end = timestamp_end
|
||||
self.min_fps = min_fps
|
||||
|
|
@ -750,3 +876,16 @@ class IOSPerformanceAggregated(Message):
|
|||
self.min_battery = min_battery
|
||||
self.avg_battery = avg_battery
|
||||
self.max_battery = max_battery
|
||||
|
||||
|
||||
class IOSIssueEvent(Message):
|
||||
__id__ = 111
|
||||
|
||||
def __init__(self, timestamp, type, context_string, context, payload):
|
||||
self.timestamp = timestamp
|
||||
self.type = type
|
||||
self.context_string = context_string
|
||||
self.context = context
|
||||
self.payload = payload
|
||||
|
||||
|
||||
|
|
|
|||
728
ee/connectors/msgcodec/msgcodec.py
Normal file
728
ee/connectors/msgcodec/msgcodec.py
Normal file
|
|
@ -0,0 +1,728 @@
|
|||
# Auto-generated, do not edit
|
||||
|
||||
from msgcodec.codec import Codec
|
||||
from msgcodec.messages import *
|
||||
|
||||
class MessageCodec(Codec):
|
||||
|
||||
def read_message_id(self, reader: io.BytesIO) -> int:
|
||||
"""
|
||||
Read and return the first byte where the message id is encoded
|
||||
"""
|
||||
id_ = self.read_uint(reader)
|
||||
return id_
|
||||
|
||||
def encode(self, m: Message) -> bytes:
|
||||
...
|
||||
|
||||
def decode(self, b: bytes) -> Message:
|
||||
reader = io.BytesIO(b)
|
||||
message_id = self.read_message_id(reader)
|
||||
|
||||
if message_id == 80:
|
||||
return BatchMeta(
|
||||
page_no=self.read_uint(reader),
|
||||
first_index=self.read_uint(reader),
|
||||
timestamp=self.read_int(reader)
|
||||
)
|
||||
|
||||
if message_id == 0:
|
||||
return Timestamp(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 1:
|
||||
return SessionStart(
|
||||
timestamp=self.read_uint(reader),
|
||||
project_id=self.read_uint(reader),
|
||||
tracker_version=self.read_string(reader),
|
||||
rev_id=self.read_string(reader),
|
||||
user_uuid=self.read_string(reader),
|
||||
user_agent=self.read_string(reader),
|
||||
user_os=self.read_string(reader),
|
||||
user_os_version=self.read_string(reader),
|
||||
user_browser=self.read_string(reader),
|
||||
user_browser_version=self.read_string(reader),
|
||||
user_device=self.read_string(reader),
|
||||
user_device_type=self.read_string(reader),
|
||||
user_device_memory_size=self.read_uint(reader),
|
||||
user_device_heap_size=self.read_uint(reader),
|
||||
user_country=self.read_string(reader),
|
||||
user_id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 2:
|
||||
return SessionDisconnect(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 3:
|
||||
return SessionEnd(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 4:
|
||||
return SetPageLocation(
|
||||
url=self.read_string(reader),
|
||||
referrer=self.read_string(reader),
|
||||
navigation_start=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 5:
|
||||
return SetViewportSize(
|
||||
width=self.read_uint(reader),
|
||||
height=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 6:
|
||||
return SetViewportScroll(
|
||||
x=self.read_int(reader),
|
||||
y=self.read_int(reader)
|
||||
)
|
||||
|
||||
if message_id == 7:
|
||||
return CreateDocument(
|
||||
|
||||
)
|
||||
|
||||
if message_id == 8:
|
||||
return CreateElementNode(
|
||||
id=self.read_uint(reader),
|
||||
parent_id=self.read_uint(reader),
|
||||
index=self.read_uint(reader),
|
||||
tag=self.read_string(reader),
|
||||
svg=self.read_boolean(reader)
|
||||
)
|
||||
|
||||
if message_id == 9:
|
||||
return CreateTextNode(
|
||||
id=self.read_uint(reader),
|
||||
parent_id=self.read_uint(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 10:
|
||||
return MoveNode(
|
||||
id=self.read_uint(reader),
|
||||
parent_id=self.read_uint(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 11:
|
||||
return RemoveNode(
|
||||
id=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 12:
|
||||
return SetNodeAttribute(
|
||||
id=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 13:
|
||||
return RemoveNodeAttribute(
|
||||
id=self.read_uint(reader),
|
||||
name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 14:
|
||||
return SetNodeData(
|
||||
id=self.read_uint(reader),
|
||||
data=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 15:
|
||||
return SetCSSData(
|
||||
id=self.read_uint(reader),
|
||||
data=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 16:
|
||||
return SetNodeScroll(
|
||||
id=self.read_uint(reader),
|
||||
x=self.read_int(reader),
|
||||
y=self.read_int(reader)
|
||||
)
|
||||
|
||||
if message_id == 17:
|
||||
return SetInputTarget(
|
||||
id=self.read_uint(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 18:
|
||||
return SetInputValue(
|
||||
id=self.read_uint(reader),
|
||||
value=self.read_string(reader),
|
||||
mask=self.read_int(reader)
|
||||
)
|
||||
|
||||
if message_id == 19:
|
||||
return SetInputChecked(
|
||||
id=self.read_uint(reader),
|
||||
checked=self.read_boolean(reader)
|
||||
)
|
||||
|
||||
if message_id == 20:
|
||||
return MouseMove(
|
||||
x=self.read_uint(reader),
|
||||
y=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 21:
|
||||
return MouseClickDepricated(
|
||||
id=self.read_uint(reader),
|
||||
hesitation_time=self.read_uint(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 22:
|
||||
return ConsoleLog(
|
||||
level=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 23:
|
||||
return PageLoadTiming(
|
||||
request_start=self.read_uint(reader),
|
||||
response_start=self.read_uint(reader),
|
||||
response_end=self.read_uint(reader),
|
||||
dom_content_loaded_event_start=self.read_uint(reader),
|
||||
dom_content_loaded_event_end=self.read_uint(reader),
|
||||
load_event_start=self.read_uint(reader),
|
||||
load_event_end=self.read_uint(reader),
|
||||
first_paint=self.read_uint(reader),
|
||||
first_contentful_paint=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 24:
|
||||
return PageRenderTiming(
|
||||
speed_index=self.read_uint(reader),
|
||||
visually_complete=self.read_uint(reader),
|
||||
time_to_interactive=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 25:
|
||||
return JSException(
|
||||
name=self.read_string(reader),
|
||||
message=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 26:
|
||||
return IntegrationEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
source=self.read_string(reader),
|
||||
name=self.read_string(reader),
|
||||
message=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 27:
|
||||
return RawCustomEvent(
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 28:
|
||||
return UserID(
|
||||
id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 29:
|
||||
return UserAnonymousID(
|
||||
id=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 30:
|
||||
return Metadata(
|
||||
key=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 31:
|
||||
return PageEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
url=self.read_string(reader),
|
||||
referrer=self.read_string(reader),
|
||||
loaded=self.read_boolean(reader),
|
||||
request_start=self.read_uint(reader),
|
||||
response_start=self.read_uint(reader),
|
||||
response_end=self.read_uint(reader),
|
||||
dom_content_loaded_event_start=self.read_uint(reader),
|
||||
dom_content_loaded_event_end=self.read_uint(reader),
|
||||
load_event_start=self.read_uint(reader),
|
||||
load_event_end=self.read_uint(reader),
|
||||
first_paint=self.read_uint(reader),
|
||||
first_contentful_paint=self.read_uint(reader),
|
||||
speed_index=self.read_uint(reader),
|
||||
visually_complete=self.read_uint(reader),
|
||||
time_to_interactive=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 32:
|
||||
return InputEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
value=self.read_string(reader),
|
||||
value_masked=self.read_boolean(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 33:
|
||||
return ClickEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
hesitation_time=self.read_uint(reader),
|
||||
label=self.read_string(reader),
|
||||
selector=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 34:
|
||||
return ErrorEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
source=self.read_string(reader),
|
||||
name=self.read_string(reader),
|
||||
message=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 35:
|
||||
return ResourceEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader),
|
||||
ttfb=self.read_uint(reader),
|
||||
header_size=self.read_uint(reader),
|
||||
encoded_body_size=self.read_uint(reader),
|
||||
decoded_body_size=self.read_uint(reader),
|
||||
url=self.read_string(reader),
|
||||
type=self.read_string(reader),
|
||||
success=self.read_boolean(reader),
|
||||
method=self.read_string(reader),
|
||||
status=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 36:
|
||||
return CustomEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 37:
|
||||
return CSSInsertRule(
|
||||
id=self.read_uint(reader),
|
||||
rule=self.read_string(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 38:
|
||||
return CSSDeleteRule(
|
||||
id=self.read_uint(reader),
|
||||
index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 39:
|
||||
return Fetch(
|
||||
method=self.read_string(reader),
|
||||
url=self.read_string(reader),
|
||||
request=self.read_string(reader),
|
||||
response=self.read_string(reader),
|
||||
status=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 40:
|
||||
return Profiler(
|
||||
name=self.read_string(reader),
|
||||
duration=self.read_uint(reader),
|
||||
args=self.read_string(reader),
|
||||
result=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 41:
|
||||
return OTable(
|
||||
key=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 42:
|
||||
return StateAction(
|
||||
type=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 43:
|
||||
return StateActionEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
type=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 44:
|
||||
return Redux(
|
||||
action=self.read_string(reader),
|
||||
state=self.read_string(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 45:
|
||||
return Vuex(
|
||||
mutation=self.read_string(reader),
|
||||
state=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 46:
|
||||
return MobX(
|
||||
type=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 47:
|
||||
return NgRx(
|
||||
action=self.read_string(reader),
|
||||
state=self.read_string(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 48:
|
||||
return GraphQL(
|
||||
operation_kind=self.read_string(reader),
|
||||
operation_name=self.read_string(reader),
|
||||
variables=self.read_string(reader),
|
||||
response=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 49:
|
||||
return PerformanceTrack(
|
||||
frames=self.read_int(reader),
|
||||
ticks=self.read_int(reader),
|
||||
total_js_heap_size=self.read_uint(reader),
|
||||
used_js_heap_size=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 50:
|
||||
return GraphQLEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
operation_kind=self.read_string(reader),
|
||||
operation_name=self.read_string(reader),
|
||||
variables=self.read_string(reader),
|
||||
response=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 51:
|
||||
return FetchEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
method=self.read_string(reader),
|
||||
url=self.read_string(reader),
|
||||
request=self.read_string(reader),
|
||||
response=self.read_string(reader),
|
||||
status=self.read_uint(reader),
|
||||
duration=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 52:
|
||||
return DOMDrop(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 53:
|
||||
return ResourceTiming(
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader),
|
||||
ttfb=self.read_uint(reader),
|
||||
header_size=self.read_uint(reader),
|
||||
encoded_body_size=self.read_uint(reader),
|
||||
decoded_body_size=self.read_uint(reader),
|
||||
url=self.read_string(reader),
|
||||
initiator=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 54:
|
||||
return ConnectionInformation(
|
||||
downlink=self.read_uint(reader),
|
||||
type=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 55:
|
||||
return SetPageVisibility(
|
||||
hidden=self.read_boolean(reader)
|
||||
)
|
||||
|
||||
if message_id == 56:
|
||||
return PerformanceTrackAggr(
|
||||
timestamp_start=self.read_uint(reader),
|
||||
timestamp_end=self.read_uint(reader),
|
||||
min_fps=self.read_uint(reader),
|
||||
avg_fps=self.read_uint(reader),
|
||||
max_fps=self.read_uint(reader),
|
||||
min_cpu=self.read_uint(reader),
|
||||
avg_cpu=self.read_uint(reader),
|
||||
max_cpu=self.read_uint(reader),
|
||||
min_total_js_heap_size=self.read_uint(reader),
|
||||
avg_total_js_heap_size=self.read_uint(reader),
|
||||
max_total_js_heap_size=self.read_uint(reader),
|
||||
min_used_js_heap_size=self.read_uint(reader),
|
||||
avg_used_js_heap_size=self.read_uint(reader),
|
||||
max_used_js_heap_size=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 59:
|
||||
return LongTask(
|
||||
timestamp=self.read_uint(reader),
|
||||
duration=self.read_uint(reader),
|
||||
context=self.read_uint(reader),
|
||||
container_type=self.read_uint(reader),
|
||||
container_src=self.read_string(reader),
|
||||
container_id=self.read_string(reader),
|
||||
container_name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 60:
|
||||
return SetNodeAttributeURLBased(
|
||||
id=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
value=self.read_string(reader),
|
||||
base_url=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 61:
|
||||
return SetCSSDataURLBased(
|
||||
id=self.read_uint(reader),
|
||||
data=self.read_string(reader),
|
||||
base_url=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 62:
|
||||
return IssueEvent(
|
||||
message_id=self.read_uint(reader),
|
||||
timestamp=self.read_uint(reader),
|
||||
type=self.read_string(reader),
|
||||
context_string=self.read_string(reader),
|
||||
context=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 63:
|
||||
return TechnicalInfo(
|
||||
type=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 64:
|
||||
return CustomIssue(
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 65:
|
||||
return PageClose(
|
||||
|
||||
)
|
||||
|
||||
if message_id == 66:
|
||||
return AssetCache(
|
||||
url=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 67:
|
||||
return CSSInsertRuleURLBased(
|
||||
id=self.read_uint(reader),
|
||||
rule=self.read_string(reader),
|
||||
index=self.read_uint(reader),
|
||||
base_url=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 69:
|
||||
return MouseClick(
|
||||
id=self.read_uint(reader),
|
||||
hesitation_time=self.read_uint(reader),
|
||||
label=self.read_string(reader),
|
||||
selector=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 70:
|
||||
return CreateIFrameDocument(
|
||||
frame_id=self.read_uint(reader),
|
||||
id=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 107:
|
||||
return IOSBatchMeta(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
first_index=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 90:
|
||||
return IOSSessionStart(
|
||||
timestamp=self.read_uint(reader),
|
||||
project_id=self.read_uint(reader),
|
||||
tracker_version=self.read_string(reader),
|
||||
rev_id=self.read_string(reader),
|
||||
user_uuid=self.read_string(reader),
|
||||
user_os=self.read_string(reader),
|
||||
user_os_version=self.read_string(reader),
|
||||
user_device=self.read_string(reader),
|
||||
user_device_type=self.read_string(reader),
|
||||
user_country=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 91:
|
||||
return IOSSessionEnd(
|
||||
timestamp=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 92:
|
||||
return IOSMetadata(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
key=self.read_string(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 93:
|
||||
return IOSCustomEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 94:
|
||||
return IOSUserID(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 95:
|
||||
return IOSUserAnonymousID(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
value=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 96:
|
||||
return IOSScreenChanges(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
x=self.read_uint(reader),
|
||||
y=self.read_uint(reader),
|
||||
width=self.read_uint(reader),
|
||||
height=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 97:
|
||||
return IOSCrash(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
reason=self.read_string(reader),
|
||||
stacktrace=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 98:
|
||||
return IOSScreenEnter(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
title=self.read_string(reader),
|
||||
view_name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 99:
|
||||
return IOSScreenLeave(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
title=self.read_string(reader),
|
||||
view_name=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 100:
|
||||
return IOSClickEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
label=self.read_string(reader),
|
||||
x=self.read_uint(reader),
|
||||
y=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 101:
|
||||
return IOSInputEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
value=self.read_string(reader),
|
||||
value_masked=self.read_boolean(reader),
|
||||
label=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 102:
|
||||
return IOSPerformanceEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
name=self.read_string(reader),
|
||||
value=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 103:
|
||||
return IOSLog(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
severity=self.read_string(reader),
|
||||
content=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 104:
|
||||
return IOSInternalError(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
content=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 105:
|
||||
return IOSNetworkCall(
|
||||
timestamp=self.read_uint(reader),
|
||||
length=self.read_uint(reader),
|
||||
duration=self.read_uint(reader),
|
||||
headers=self.read_string(reader),
|
||||
body=self.read_string(reader),
|
||||
url=self.read_string(reader),
|
||||
success=self.read_boolean(reader),
|
||||
method=self.read_string(reader),
|
||||
status=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 110:
|
||||
return IOSPerformanceAggregated(
|
||||
timestamp_start=self.read_uint(reader),
|
||||
timestamp_end=self.read_uint(reader),
|
||||
min_fps=self.read_uint(reader),
|
||||
avg_fps=self.read_uint(reader),
|
||||
max_fps=self.read_uint(reader),
|
||||
min_cpu=self.read_uint(reader),
|
||||
avg_cpu=self.read_uint(reader),
|
||||
max_cpu=self.read_uint(reader),
|
||||
min_memory=self.read_uint(reader),
|
||||
avg_memory=self.read_uint(reader),
|
||||
max_memory=self.read_uint(reader),
|
||||
min_battery=self.read_uint(reader),
|
||||
avg_battery=self.read_uint(reader),
|
||||
max_battery=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 111:
|
||||
return IOSIssueEvent(
|
||||
timestamp=self.read_uint(reader),
|
||||
type=self.read_string(reader),
|
||||
context_string=self.read_string(reader),
|
||||
context=self.read_string(reader),
|
||||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
|
|
@ -661,24 +661,24 @@ $$
|
|||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS autocomplete_unique_project_id_md5value_type_idx ON autocomplete (project_id, md5(value), type);
|
||||
CREATE index IF NOT EXISTS autocomplete_project_id_idx ON autocomplete (project_id);
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_project_id_idx ON autocomplete (project_id);
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_type_idx ON public.autocomplete (type);
|
||||
|
||||
CREATE INDEX autocomplete_value_clickonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'CLICK';
|
||||
CREATE INDEX autocomplete_value_customonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'CUSTOM';
|
||||
CREATE INDEX autocomplete_value_graphqlonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'GRAPHQL';
|
||||
CREATE INDEX autocomplete_value_inputonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'INPUT';
|
||||
CREATE INDEX autocomplete_value_locationonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'LOCATION';
|
||||
CREATE INDEX autocomplete_value_referreronly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'REFERRER';
|
||||
CREATE INDEX autocomplete_value_requestonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'REQUEST';
|
||||
CREATE INDEX autocomplete_value_revidonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'REVID';
|
||||
CREATE INDEX autocomplete_value_stateactiononly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'STATEACTION';
|
||||
CREATE INDEX autocomplete_value_useranonymousidonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERANONYMOUSID';
|
||||
CREATE INDEX autocomplete_value_userbrowseronly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERBROWSER';
|
||||
CREATE INDEX autocomplete_value_usercountryonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERCOUNTRY';
|
||||
CREATE INDEX autocomplete_value_userdeviceonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERDEVICE';
|
||||
CREATE INDEX autocomplete_value_useridonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERID';
|
||||
CREATE INDEX autocomplete_value_userosonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USEROS';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_clickonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'CLICK';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_customonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'CUSTOM';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_graphqlonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'GRAPHQL';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_inputonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'INPUT';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_locationonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'LOCATION';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_referreronly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'REFERRER';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_requestonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'REQUEST';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_revidonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'REVID';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_stateactiononly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'STATEACTION';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_useranonymousidonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERANONYMOUSID';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_userbrowseronly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERBROWSER';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_usercountryonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERCOUNTRY';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_userdeviceonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERDEVICE';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_useridonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USERID';
|
||||
CREATE INDEX IF NOT EXISTS autocomplete_value_userosonly_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops) WHERE type = 'USEROS';
|
||||
|
||||
BEGIN
|
||||
IF NOT EXISTS(SELECT *
|
||||
|
|
|
|||
12
ee/utilities/package-lock.json
generated
12
ee/utilities/package-lock.json
generated
|
|
@ -112,9 +112,9 @@
|
|||
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
|
||||
"integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ=="
|
||||
"version": "18.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz",
|
||||
"integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg=="
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
|
|
@ -1179,9 +1179,9 @@
|
|||
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
|
||||
"integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ=="
|
||||
"version": "18.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz",
|
||||
"integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.8",
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ const extractPayloadFromRequest = async function (req, res) {
|
|||
return helper.extractPayloadFromRequest(req);
|
||||
}
|
||||
filters.filter = helper.objectToObjectOfArrays(filters.filter);
|
||||
filters.filter = helper.transformFilters(filters.filter);
|
||||
debug && console.log("payload/filters:" + JSON.stringify(filters))
|
||||
return Object.keys(filters).length > 0 ? filters : undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ const LiveSessionPure = lazy(() => import('Components/Session/LiveSession'));
|
|||
const OnboardingPure = lazy(() => import('Components/Onboarding/Onboarding'));
|
||||
const ClientPure = lazy(() => import('Components/Client/Client'));
|
||||
const AssistPure = lazy(() => import('Components/Assist'));
|
||||
const BugFinderPure = lazy(() => import('Components/BugFinder/BugFinder'));
|
||||
const BugFinderPure = lazy(() => import('Components/Overview'));
|
||||
const DashboardPure = lazy(() => import('Components/Dashboard/NewDashboard'));
|
||||
const ErrorsPure = lazy(() => import('Components/Errors/Errors'));
|
||||
const FunnelDetailsPure = lazy(() => import('Components/Funnels/FunnelDetails'));
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function SessionList(props: Props) {
|
|||
|
||||
return (
|
||||
<div style={{ width: '50vw' }}>
|
||||
<div className="border-r shadow h-screen" style={{ backgroundColor: '#FAFAFA', zIndex: 999, width: '100%', minWidth: '700px' }}>
|
||||
<div className="border-r shadow h-screen overflow-y-auto" style={{ backgroundColor: '#FAFAFA', zIndex: 999, width: '100%', minWidth: '700px' }}>
|
||||
<div className="p-4">
|
||||
<div className="text-2xl">
|
||||
{props.userId}'s <span className="color-gray-medium">Live Sessions</span>{' '}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ function SessionListHeader({ activeTab, count, applyFilter, filter }) {
|
|||
}, [label]);
|
||||
|
||||
const { startDate, endDate, rangeValue } = filter;
|
||||
const period = new Record({ start: startDate, end: endDate, rangeName: rangeValue });
|
||||
const period = new Record({ start: startDate, end: endDate, rangeName: rangeValue, timezoneOffset: getTimeZoneOffset() });
|
||||
|
||||
const onDateChange = (e) => {
|
||||
const dateValues = e.toJSON();
|
||||
|
|
@ -36,10 +36,12 @@ function SessionListHeader({ activeTab, count, applyFilter, filter }) {
|
|||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
const dateValues = period.toJSON();
|
||||
dateValues.startDate = moment(dateValues.startDate).startOf('day').utcOffset(getTimeZoneOffset(), true).valueOf();
|
||||
dateValues.endDate = moment(dateValues.endDate).endOf('day').utcOffset(getTimeZoneOffset(), true).valueOf();
|
||||
applyFilter(dateValues);
|
||||
if (label) {
|
||||
const dateValues = period.toJSON();
|
||||
dateValues.startDate = moment(dateValues.startDate).startOf('day').utcOffset(getTimeZoneOffset(), true).valueOf();
|
||||
dateValues.endDate = moment(dateValues.endDate).endOf('day').utcOffset(getTimeZoneOffset(), true).valueOf();
|
||||
applyFilter(dateValues);
|
||||
}
|
||||
}, [label]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ export default class IntegrationForm extends React.PureComponent {
|
|||
|
||||
onChangeSelect = ({ value }) => {
|
||||
const { sites, list, name } = this.props;
|
||||
const site = sites.find(s => s.id === value);
|
||||
const site = sites.find(s => s.id === value.value);
|
||||
this.setState({ currentSiteId: site.id })
|
||||
this.init(value);
|
||||
this.init(value.value);
|
||||
}
|
||||
|
||||
init = (siteId) => {
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ function UserForm(props: Props) {
|
|||
));
|
||||
}
|
||||
|
||||
export default connect(state => ({
|
||||
export default connect((state: any) => ({
|
||||
isEnterprise: state.getIn([ 'user', 'account', 'edition' ]) === 'ee',
|
||||
isSmtp: state.getIn([ 'user', 'account', 'smtp' ]),
|
||||
}))(UserForm);
|
||||
28
frontend/app/components/Overview/Overview.tsx
Normal file
28
frontend/app/components/Overview/Overview.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
import NoSessionsMessage from 'Shared/NoSessionsMessage';
|
||||
import MainSearchBar from 'Shared/MainSearchBar';
|
||||
import SessionSearch from 'Shared/SessionSearch';
|
||||
import SessionListContainer from 'Shared/SessionListContainer/SessionListContainer';
|
||||
|
||||
function Overview() {
|
||||
return (
|
||||
<div className="page-margin container-90 flex relative">
|
||||
<div className="flex-1 flex">
|
||||
<div className={'w-full mx-auto'} style={{ maxWidth: '1300px' }}>
|
||||
<NoSessionsMessage />
|
||||
|
||||
<div className="mb-5">
|
||||
<MainSearchBar />
|
||||
<SessionSearch />
|
||||
|
||||
<div className="my-4" />
|
||||
<SessionListContainer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageTitle('Sessions - OpenReplay')(Overview);
|
||||
1
frontend/app/components/Overview/index.ts
Normal file
1
frontend/app/components/Overview/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './Overview';
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React, { Fragment, useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { NoContent, Loader, Pagination } from 'UI';
|
||||
import { List } from 'immutable';
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export default function<Value extends ValueObject>({ placeholder='Select', name
|
|||
const opacity = state.isDisabled ? 0.5 : 1;
|
||||
const transition = 'opacity 300ms';
|
||||
|
||||
return { ...provided, opacity, transition };
|
||||
return { ...provided, opacity, transition, fontWeight: 'bold' };
|
||||
},
|
||||
input: (provided: any) => ({
|
||||
...provided,
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ function SelectDateRange(props: Props) {
|
|||
};
|
||||
|
||||
const isCustomRange = period.rangeName === CUSTOM_RANGE;
|
||||
const customRange = isCustomRange ? period.rangeFormatted(undefined, timezone) : '';
|
||||
const customRange = isCustomRange ? period.rangeFormatted() : '';
|
||||
return (
|
||||
<div className="relative">
|
||||
<Select
|
||||
|
|
@ -75,7 +75,7 @@ function SelectDateRange(props: Props) {
|
|||
width: '770px',
|
||||
}}
|
||||
>
|
||||
<DateRangePopup onApply={onApplyDateRange} onCancel={() => setIsCustom(false)} selectedDateRange={period.range} />
|
||||
<DateRangePopup timezone={timezone} onApply={onApplyDateRange} onCancel={() => setIsCustom(false)} selectedDateRange={period.range} />
|
||||
</div>
|
||||
</OutsideClickDetectingDiv>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,42 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import {
|
||||
Link,
|
||||
Icon,
|
||||
} from 'UI';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Link, Icon } from 'UI';
|
||||
import { session as sessionRoute, liveSession as liveSessionRoute } from 'App/routes';
|
||||
|
||||
const PLAY_ICON_NAMES = {
|
||||
notPlayed: 'play-fill',
|
||||
played: 'play-circle-light',
|
||||
hovered: 'play-hover'
|
||||
}
|
||||
hovered: 'play-hover',
|
||||
};
|
||||
|
||||
const getDefaultIconName = (isViewed) => !isViewed ? PLAY_ICON_NAMES.notPlayed : PLAY_ICON_NAMES.played
|
||||
const getDefaultIconName = (isViewed: any) => (!isViewed ? PLAY_ICON_NAMES.notPlayed : PLAY_ICON_NAMES.played);
|
||||
|
||||
interface Props {
|
||||
isAssist: boolean;
|
||||
viewed: boolean;
|
||||
sessionId: string;
|
||||
onClick?: () => void;
|
||||
queryParams: any;
|
||||
}
|
||||
export default function PlayLink(props: Props) {
|
||||
const { isAssist, viewed, sessionId, onClick = null } = props
|
||||
const defaultIconName = getDefaultIconName(viewed)
|
||||
const { isAssist, viewed, sessionId, onClick = null, queryParams } = props;
|
||||
const defaultIconName = getDefaultIconName(viewed);
|
||||
|
||||
const [isHovered, toggleHover] = useState(false)
|
||||
const [iconName, setIconName] = useState(defaultIconName)
|
||||
const [isHovered, toggleHover] = useState(false);
|
||||
const [iconName, setIconName] = useState(defaultIconName);
|
||||
|
||||
useEffect(() => {
|
||||
if (isHovered) setIconName(PLAY_ICON_NAMES.hovered)
|
||||
else setIconName(getDefaultIconName(viewed))
|
||||
}, [isHovered, viewed])
|
||||
if (isHovered) setIconName(PLAY_ICON_NAMES.hovered);
|
||||
else setIconName(getDefaultIconName(viewed));
|
||||
}, [isHovered, viewed]);
|
||||
|
||||
return (
|
||||
<Link
|
||||
onClick={onClick ? onClick : () => {}}
|
||||
to={ isAssist ? liveSessionRoute(sessionId) : sessionRoute(sessionId) }
|
||||
to={isAssist ? liveSessionRoute(sessionId, queryParams) : sessionRoute(sessionId)}
|
||||
onMouseEnter={() => toggleHover(true)}
|
||||
onMouseLeave={() => toggleHover(false)}
|
||||
>
|
||||
<Icon name={iconName} size={38} color={isAssist ? "tealx" : "teal"} />
|
||||
<Icon name={iconName} size={38} color={isAssist ? 'tealx' : 'teal'} />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,192 +1,191 @@
|
|||
import React from 'react'
|
||||
import React, { useEffect } from 'react';
|
||||
import cn from 'classnames';
|
||||
import {
|
||||
CountryFlag,
|
||||
Avatar,
|
||||
TextEllipsis,
|
||||
Label,
|
||||
Icon,
|
||||
} from 'UI';
|
||||
import { CountryFlag, Avatar, TextEllipsis, Label, Icon } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { durationFormatted, formatTimeOrDate } from 'App/date';
|
||||
import stl from './sessionItem.module.css';
|
||||
import Counter from './Counter'
|
||||
import Counter from './Counter';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import SessionMetaList from './SessionMetaList';
|
||||
import PlayLink from './PlayLink';
|
||||
import ErrorBars from './ErrorBars';
|
||||
import { assist as assistRoute, liveSession, sessions as sessionsRoute, isRoute } from "App/routes";
|
||||
import { assist as assistRoute, liveSession, sessions as sessionsRoute, isRoute } from 'App/routes';
|
||||
import { capitalize } from 'App/utils';
|
||||
|
||||
const ASSIST_ROUTE = assistRoute();
|
||||
const ASSIST_LIVE_SESSION = liveSession()
|
||||
const ASSIST_LIVE_SESSION = liveSession();
|
||||
const SESSIONS_ROUTE = sessionsRoute();
|
||||
|
||||
interface Props {
|
||||
session: {
|
||||
sessionId: string;
|
||||
userBrowser: string;
|
||||
userOs: string;
|
||||
userId: string;
|
||||
userAnonymousId: string;
|
||||
userDisplayName: string;
|
||||
userCountry: string;
|
||||
startedAt: number;
|
||||
duration: string;
|
||||
eventsCount: number;
|
||||
errorsCount: number;
|
||||
pagesCount: number;
|
||||
viewed: boolean;
|
||||
favorite: boolean;
|
||||
userDeviceType: string;
|
||||
userUuid: string;
|
||||
userNumericHash: number;
|
||||
live: boolean;
|
||||
metadata: Record<string, any>;
|
||||
userSessionsCount: number;
|
||||
issueTypes: [];
|
||||
active: boolean;
|
||||
},
|
||||
onUserClick?: (userId: string, userAnonymousId: string) => void;
|
||||
hasUserFilter?: boolean;
|
||||
disableUser?: boolean;
|
||||
metaList?: Array<any>;
|
||||
// showActive?: boolean;
|
||||
lastPlayedSessionId?: string;
|
||||
live?: boolean;
|
||||
onClick?: any
|
||||
session: {
|
||||
sessionId: string;
|
||||
userBrowser: string;
|
||||
userOs: string;
|
||||
userId: string;
|
||||
userAnonymousId: string;
|
||||
userDisplayName: string;
|
||||
userCountry: string;
|
||||
startedAt: number;
|
||||
duration: string;
|
||||
eventsCount: number;
|
||||
errorsCount: number;
|
||||
pagesCount: number;
|
||||
viewed: boolean;
|
||||
favorite: boolean;
|
||||
userDeviceType: string;
|
||||
userUuid: string;
|
||||
userNumericHash: number;
|
||||
live: boolean;
|
||||
metadata: Record<string, any>;
|
||||
userSessionsCount: number;
|
||||
issueTypes: [];
|
||||
active: boolean;
|
||||
};
|
||||
onUserClick?: (userId: string, userAnonymousId: string) => void;
|
||||
hasUserFilter?: boolean;
|
||||
disableUser?: boolean;
|
||||
metaList?: Array<any>;
|
||||
// showActive?: boolean;
|
||||
lastPlayedSessionId?: string;
|
||||
live?: boolean;
|
||||
onClick?: any;
|
||||
}
|
||||
|
||||
function SessionItem(props: RouteComponentProps & Props) {
|
||||
const { settingsStore } = useStore();
|
||||
const { timezone } = settingsStore.sessionSettings;
|
||||
const { settingsStore } = useStore();
|
||||
const { timezone } = settingsStore.sessionSettings;
|
||||
const [isIframe, setIsIframe] = React.useState(false);
|
||||
|
||||
const {
|
||||
session,
|
||||
onUserClick = () => null,
|
||||
hasUserFilter = false,
|
||||
disableUser = false,
|
||||
metaList = [],
|
||||
lastPlayedSessionId,
|
||||
onClick = null,
|
||||
} = props;
|
||||
const {
|
||||
session,
|
||||
onUserClick = () => null,
|
||||
hasUserFilter = false,
|
||||
disableUser = false,
|
||||
metaList = [],
|
||||
lastPlayedSessionId,
|
||||
onClick = null,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
sessionId,
|
||||
userBrowser,
|
||||
userOs,
|
||||
userId,
|
||||
userAnonymousId,
|
||||
userDisplayName,
|
||||
userCountry,
|
||||
startedAt,
|
||||
duration,
|
||||
eventsCount,
|
||||
viewed,
|
||||
userDeviceType,
|
||||
userNumericHash,
|
||||
live,
|
||||
metadata,
|
||||
issueTypes,
|
||||
active,
|
||||
} = session;
|
||||
const {
|
||||
sessionId,
|
||||
userBrowser,
|
||||
userOs,
|
||||
userId,
|
||||
userAnonymousId,
|
||||
userDisplayName,
|
||||
userCountry,
|
||||
startedAt,
|
||||
duration,
|
||||
eventsCount,
|
||||
viewed,
|
||||
userDeviceType,
|
||||
userNumericHash,
|
||||
live,
|
||||
metadata,
|
||||
issueTypes,
|
||||
active,
|
||||
} = session;
|
||||
|
||||
const location = props.location;
|
||||
const location = props.location;
|
||||
const queryParams = Object.fromEntries(new URLSearchParams(location.search));
|
||||
|
||||
const formattedDuration = durationFormatted(duration);
|
||||
const hasUserId = userId || userAnonymousId;
|
||||
const isSessions = isRoute(SESSIONS_ROUTE, location.pathname);
|
||||
const isAssist = isRoute(ASSIST_ROUTE, location.pathname) || isRoute(ASSIST_LIVE_SESSION, location.pathname);
|
||||
const isLastPlayed = lastPlayedSessionId === sessionId;
|
||||
const formattedDuration = durationFormatted(duration);
|
||||
const hasUserId = userId || userAnonymousId;
|
||||
const isSessions = isRoute(SESSIONS_ROUTE, location.pathname);
|
||||
const isAssist = isRoute(ASSIST_ROUTE, location.pathname) || isRoute(ASSIST_LIVE_SESSION, location.pathname);
|
||||
const isLastPlayed = lastPlayedSessionId === sessionId;
|
||||
|
||||
const _metaList = Object.keys(metadata).filter(i => metaList.includes(i)).map(key => {
|
||||
const value = metadata[key];
|
||||
return { label: key, value };
|
||||
});
|
||||
const _metaList = Object.keys(metadata)
|
||||
.filter((i) => metaList.includes(i))
|
||||
.map((key) => {
|
||||
const value = metadata[key];
|
||||
return { label: key, value };
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={ cn(stl.sessionItem, "flex flex-col p-2") } id="session-item" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="flex items-start">
|
||||
<div className={ cn('flex items-center w-full')}>
|
||||
<div className="flex items-center pr-2 shrink-0" style={{ width: "40%"}}>
|
||||
<div><Avatar isActive={active} seed={ userNumericHash } isAssist={isAssist} /></div>
|
||||
<div className="flex flex-col overflow-hidden color-gray-medium ml-3 justify-between items-center shrink-0">
|
||||
<div
|
||||
className={cn('text-lg', {'color-teal cursor-pointer': !disableUser && hasUserId, [stl.userName]: !disableUser && hasUserId, 'color-gray-medium' : disableUser || !hasUserId})}
|
||||
onClick={() => (!disableUser && !hasUserFilter) && onUserClick(userId, userAnonymousId)}
|
||||
>
|
||||
<TextEllipsis text={userDisplayName} maxWidth="200px" popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
return (
|
||||
<div className={cn(stl.sessionItem, 'flex flex-col p-2')} id="session-item" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="flex items-start">
|
||||
<div className={cn('flex items-center w-full')}>
|
||||
<div className="flex items-center pr-2 shrink-0" style={{ width: '40%' }}>
|
||||
<div>
|
||||
<Avatar isActive={active} seed={userNumericHash} isAssist={isAssist} />
|
||||
</div>
|
||||
<div className="flex flex-col overflow-hidden color-gray-medium ml-3 justify-between items-center shrink-0">
|
||||
<div
|
||||
className={cn('text-lg', {
|
||||
'color-teal cursor-pointer': !disableUser && hasUserId,
|
||||
[stl.userName]: !disableUser && hasUserId,
|
||||
'color-gray-medium': disableUser || !hasUserId,
|
||||
})}
|
||||
onClick={() => !disableUser && !hasUserFilter && onUserClick(userId, userAnonymousId)}
|
||||
>
|
||||
<TextEllipsis text={userDisplayName} maxWidth="200px" popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ width: '20%' }} className="px-2 flex flex-col justify-between">
|
||||
<div>
|
||||
<TextEllipsis text={formatTimeOrDate(startedAt, timezone)} popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
</div>
|
||||
<div className="flex items-center color-gray-medium py-1">
|
||||
{!isAssist && (
|
||||
<>
|
||||
<div className="color-gray-medium">
|
||||
<span className="mr-1">{eventsCount}</span>
|
||||
<span>{eventsCount === 0 || eventsCount > 1 ? 'Events' : 'Event'}</span>
|
||||
</div>
|
||||
<Icon name="circle-fill" size={3} className="mx-4" />
|
||||
</>
|
||||
)}
|
||||
<div>{live ? <Counter startTime={startedAt} /> : formattedDuration}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ width: '30%' }} className="px-2 flex flex-col justify-between">
|
||||
<div style={{ height: '21px' }}>
|
||||
<CountryFlag country={userCountry} style={{ paddingTop: '4px' }} label />
|
||||
</div>
|
||||
<div className="color-gray-medium flex items-center py-1">
|
||||
<span className="capitalize" style={{ maxWidth: '70px' }}>
|
||||
<TextEllipsis text={capitalize(userBrowser)} popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
</span>
|
||||
<Icon name="circle-fill" size={3} className="mx-4" />
|
||||
<span className="capitalize" style={{ maxWidth: '70px' }}>
|
||||
<TextEllipsis text={capitalize(userOs)} popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
</span>
|
||||
<Icon name="circle-fill" size={3} className="mx-4" />
|
||||
<span className="capitalize" style={{ maxWidth: '70px' }}>
|
||||
<TextEllipsis text={capitalize(userDeviceType)} popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{isSessions && (
|
||||
<div style={{ width: '10%' }} className="self-center px-2 flex items-center">
|
||||
<ErrorBars count={issueTypes.length} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ width: "20%" }} className="px-2 flex flex-col justify-between">
|
||||
<div>
|
||||
<TextEllipsis text={formatTimeOrDate(startedAt, timezone)} popupProps={{ inverted: true, size: 'tiny' }} />
|
||||
</div>
|
||||
<div className="flex items-center color-gray-medium py-1">
|
||||
{!isAssist && (
|
||||
<>
|
||||
<div className="color-gray-medium">
|
||||
<span className="mr-1">{ eventsCount }</span>
|
||||
<span>{ eventsCount === 0 || eventsCount > 1 ? 'Events' : 'Event' }</span>
|
||||
</div>
|
||||
<Icon name="circle-fill" size={3} className="mx-4" />
|
||||
</>
|
||||
)}
|
||||
<div>{ live ? <Counter startTime={startedAt} /> : formattedDuration }</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ width: "30%" }} className="px-2 flex flex-col justify-between">
|
||||
<div style={{ height: '21px'}}>
|
||||
<CountryFlag country={ userCountry } style={{ paddingTop: '4px' }} label />
|
||||
</div>
|
||||
<div className="color-gray-medium flex items-center py-1">
|
||||
<span className="capitalize" style={{ maxWidth: '70px'}}>
|
||||
<TextEllipsis text={ capitalize(userBrowser) } popupProps={{ inverted: true, size: "tiny" }} />
|
||||
</span>
|
||||
<Icon name="circle-fill" size={3} className="mx-4" />
|
||||
<span className="capitalize" style={{ maxWidth: '70px'}}>
|
||||
<TextEllipsis text={ capitalize(userOs) } popupProps={{ inverted: true, size: "tiny" }} />
|
||||
</span>
|
||||
<Icon name="circle-fill" size={3} className="mx-4" />
|
||||
<span className="capitalize" style={{ maxWidth: '70px'}}>
|
||||
<TextEllipsis text={ capitalize(userDeviceType) } popupProps={{ inverted: true, size: "tiny" }} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{ isSessions && (
|
||||
<div style={{ width: "10%"}} className="self-center px-2 flex items-center">
|
||||
<ErrorBars count={issueTypes.length} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<div className={ stl.playLink } id="play-button" data-viewed={ viewed }>
|
||||
{ isSessions && (
|
||||
<div className="mr-4 flex-shrink-0 w-24">
|
||||
{ isLastPlayed && (
|
||||
<Label className="bg-gray-lightest p-1 px-2 rounded-lg">
|
||||
<span className="color-gray-medium text-xs" style={{ whiteSpace: 'nowrap'}}>LAST PLAYED</span>
|
||||
</Label>
|
||||
)}
|
||||
<div className="flex items-center">
|
||||
<div className={stl.playLink} id="play-button" data-viewed={viewed}>
|
||||
{isSessions && (
|
||||
<div className="mr-4 flex-shrink-0 w-24">
|
||||
{isLastPlayed && (
|
||||
<Label className="bg-gray-lightest p-1 px-2 rounded-lg">
|
||||
<span className="color-gray-medium text-xs" style={{ whiteSpace: 'nowrap' }}>
|
||||
LAST PLAYED
|
||||
</span>
|
||||
</Label>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<PlayLink isAssist={isAssist} sessionId={sessionId} viewed={viewed} onClick={onClick} queryParams={queryParams} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<PlayLink
|
||||
isAssist={isAssist}
|
||||
sessionId={sessionId}
|
||||
viewed={viewed}
|
||||
onClick={onClick}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{_metaList.length > 0 && <SessionMetaList className="mt-4" metaList={_metaList} />}
|
||||
</div>
|
||||
{ _metaList.length > 0 && (
|
||||
<SessionMetaList className="mt-4" metaList={_metaList} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter<Props>(observer<Props>(SessionItem))
|
||||
export default withRouter<Props>(observer<Props>(SessionItem));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import SessionList from './components/SessionList';
|
||||
import SessionHeader from './components/SessionHeader';
|
||||
|
||||
interface Props {}
|
||||
function SessionListContainer(props: Props) {
|
||||
return (
|
||||
<div className="widget-wrapper">
|
||||
<SessionHeader />
|
||||
<div className="p-4">
|
||||
<SessionList />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionListContainer;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
function NoContentMessage({ activeTab }: any) {
|
||||
return <div>{getNoContentMessage(activeTab)}</div>;
|
||||
}
|
||||
|
||||
export default connect((state: any) => ({
|
||||
activeTab: state.getIn(['search', 'activeTab']),
|
||||
}))(NoContentMessage);
|
||||
|
||||
function getNoContentMessage(activeTab: any) {
|
||||
let str = 'No recordings found';
|
||||
if (activeTab.type !== 'all') {
|
||||
str += ' with ' + activeTab.name;
|
||||
return str;
|
||||
}
|
||||
|
||||
return str + '!';
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import React from 'react';
|
||||
import { numberWithCommas } from 'App/utils';
|
||||
import { applyFilter } from 'Duck/search';
|
||||
import Period from 'Types/app/period';
|
||||
import SelectDateRange from 'Shared/SelectDateRange';
|
||||
import SessionTags from '../SessionTags';
|
||||
import { connect } from 'react-redux';
|
||||
import SessionSort from '../SessionSort';
|
||||
|
||||
interface Props {
|
||||
listCount: number;
|
||||
filter: any;
|
||||
applyFilter: (filter: any) => void;
|
||||
}
|
||||
function SessionHeader(props: Props) {
|
||||
const { listCount, filter: { startDate, endDate, rangeValue } } = props;
|
||||
const period = Period({ start: startDate, end: endDate, rangeName: rangeValue });
|
||||
|
||||
const onDateChange = (e: any) => {
|
||||
const dateValues = e.toJSON();
|
||||
props.applyFilter(dateValues);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center p-4 justify-between">
|
||||
<div className="flex items-center">
|
||||
<div className="mr-3 text-lg">
|
||||
<span className="font-bold">Sessions</span> <span className="color-gray-medium ml-2">{listCount}</span>
|
||||
</div>
|
||||
<SessionTags />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<SelectDateRange period={period} onChange={onDateChange} right={true} />
|
||||
<div className="mx-2" />
|
||||
<SessionSort />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: any) => ({
|
||||
filter: state.getIn(['search', 'instance']),
|
||||
listCount: numberWithCommas(state.getIn(['sessions', 'total'])),
|
||||
}),
|
||||
{ applyFilter }
|
||||
)(SessionHeader);
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionHeader';
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import SessionItem from 'Shared/SessionItem';
|
||||
import { NoContent, Loader, Pagination } from 'UI';
|
||||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
import NoContentMessage from '../NoContentMessage';
|
||||
import { fetchSessions, addFilterByKeyAndValue, updateCurrentPage, setScrollPosition } from 'Duck/search';
|
||||
|
||||
interface Props {
|
||||
loading: boolean;
|
||||
list: any;
|
||||
currentPage: number;
|
||||
total: number;
|
||||
filters: any;
|
||||
lastPlayedSessionId: string;
|
||||
metaList: any;
|
||||
scrollY: number;
|
||||
addFilterByKeyAndValue: (key: string, value: any, operator?: string) => void;
|
||||
updateCurrentPage: (page: number) => void;
|
||||
setScrollPosition: (scrollPosition: number) => void;
|
||||
fetchSessions: () => void;
|
||||
}
|
||||
function SessionList(props: Props) {
|
||||
const { loading, list, currentPage, total, filters, lastPlayedSessionId, metaList } = props;
|
||||
const _filterKeys = filters.map((i: any) => i.key);
|
||||
const hasUserFilter = _filterKeys.includes(FilterKey.USERID) || _filterKeys.includes(FilterKey.USERANONYMOUSID);
|
||||
|
||||
useEffect(() => {
|
||||
const { scrollY } = props;
|
||||
window.scrollTo(0, scrollY);
|
||||
if (total === 0) {
|
||||
props.fetchSessions()
|
||||
}
|
||||
|
||||
return () => {
|
||||
props.setScrollPosition(window.scrollY);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onUserClick = (userId: any) => {
|
||||
if (userId) {
|
||||
props.addFilterByKeyAndValue(FilterKey.USERID, userId);
|
||||
} else {
|
||||
props.addFilterByKeyAndValue(FilterKey.USERID, '', 'isUndefined');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Loader loading={loading}>
|
||||
<NoContent
|
||||
title={
|
||||
<div className="flex items-center justify-center flex-col">
|
||||
<AnimatedSVG name={ICONS.NO_RESULTS} size={170} />
|
||||
<div className="mt-2" />
|
||||
<NoContentMessage />
|
||||
</div>
|
||||
}
|
||||
subtext={<div>Please try changing your search parameters.</div>}
|
||||
show={!loading && list.size === 0}
|
||||
>
|
||||
{list.map((session: any) => (
|
||||
<React.Fragment key={session.sessionId}>
|
||||
<SessionItem
|
||||
session={session}
|
||||
hasUserFilter={hasUserFilter}
|
||||
onUserClick={onUserClick}
|
||||
metaList={metaList}
|
||||
lastPlayedSessionId={lastPlayedSessionId}
|
||||
/>
|
||||
<div className="border-b" />
|
||||
</React.Fragment>
|
||||
))}
|
||||
</NoContent>
|
||||
|
||||
{total > 0 && (
|
||||
<div className="w-full flex items-center justify-center py-6">
|
||||
<Pagination
|
||||
page={currentPage}
|
||||
totalPages={Math.ceil(total / 10)}
|
||||
onPageChange={(page) => props.updateCurrentPage(page)}
|
||||
limit={10}
|
||||
debounceRequest={1000}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Loader>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: any) => ({
|
||||
list: state.getIn(['sessions', 'list']),
|
||||
filters: state.getIn(['search', 'instance', 'filters']),
|
||||
lastPlayedSessionId: state.getIn(['sessions', 'lastPlayedSessionId']),
|
||||
metaList: state.getIn(['customFields', 'list']).map((i: any) => i.key),
|
||||
loading: state.getIn(['sessions', 'loading']),
|
||||
currentPage: state.getIn(['search', 'currentPage']) || 1,
|
||||
total: state.getIn(['sessions', 'total']) || 0,
|
||||
scrollY: state.getIn(['search', 'scrollY']),
|
||||
}),
|
||||
{ updateCurrentPage, addFilterByKeyAndValue, setScrollPosition, fetchSessions }
|
||||
)(SessionList);
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionList';
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import Select from 'Shared/Select';
|
||||
import { sort } from 'Duck/sessions';
|
||||
import { applyFilter } from 'Duck/search';
|
||||
|
||||
const sortOptionsMap = {
|
||||
'startTs-desc': 'Newest',
|
||||
'startTs-asc': 'Oldest',
|
||||
'eventsCount-asc': 'Events Ascending',
|
||||
'eventsCount-desc': 'Events Descending',
|
||||
};
|
||||
|
||||
const sortOptions = Object.entries(sortOptionsMap).map(([value, label]) => ({ value, label }));
|
||||
|
||||
interface Props {
|
||||
filter: any;
|
||||
options: any;
|
||||
applyFilter: (filter: any) => void;
|
||||
sort: (sort: string, sign: number) => void;
|
||||
}
|
||||
|
||||
function SessionSort(props: Props) {
|
||||
const { sort, order } = props.filter;
|
||||
const onSort = ({ value }: any) => {
|
||||
value = value.value;
|
||||
const [sort, order] = value.split('-');
|
||||
const sign = order === 'desc' ? -1 : 1;
|
||||
props.applyFilter({ order, sort });
|
||||
props.sort(sort, sign);
|
||||
};
|
||||
|
||||
const defaultOption = `${sort}-${order}`;
|
||||
return <Select name="sortSessions" plain right options={sortOptions} onChange={onSort} defaultValue={defaultOption} />;
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: any) => ({
|
||||
filter: state.getIn(['search', 'instance']),
|
||||
}),
|
||||
{ sort, applyFilter }
|
||||
)(SessionSort);
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionSort';
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
.dropdown {
|
||||
display: flex !important;
|
||||
padding: 4px 6px;
|
||||
border-radius: 3px;
|
||||
color: $gray-darkest;
|
||||
font-weight: 500;
|
||||
&:hover {
|
||||
background-color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdownTrigger {
|
||||
padding: 4px 8px;
|
||||
border-radius: 3px;
|
||||
&:hover {
|
||||
background-color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdownIcon {
|
||||
margin-top: 2px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import React from 'react';
|
||||
import { setActiveTab } from 'Duck/search';
|
||||
import { connect } from 'react-redux';
|
||||
import { issues_types } from 'Types/session/issue';
|
||||
import { Icon } from 'UI';
|
||||
import cn from 'classnames';
|
||||
|
||||
interface Props {
|
||||
setActiveTab: typeof setActiveTab;
|
||||
activeTab: any;
|
||||
tags: any;
|
||||
total: number;
|
||||
}
|
||||
function SessionTags(props: Props) {
|
||||
const { activeTab, tags, total } = props;
|
||||
const disable = activeTab.type === 'all' && total === 0;
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
{tags &&
|
||||
tags.map((tag: any, index: any) => (
|
||||
<div key={index}>
|
||||
<TagItem
|
||||
onClick={() => props.setActiveTab(tag)}
|
||||
label={tag.name}
|
||||
isActive={activeTab.type === tag.type}
|
||||
icon={tag.icon}
|
||||
disabled={disable && tag.type !== 'all'}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: any) => {
|
||||
const isEnterprise = state.getIn(['user', 'account', 'edition']) === 'ee';
|
||||
return {
|
||||
activeTab: state.getIn(['search', 'activeTab']),
|
||||
tags: issues_types.filter((tag: any) => (isEnterprise ? tag.type !== 'bookmark' : tag.type !== 'vault')),
|
||||
total: state.getIn(['sessions', 'total']) || 0,
|
||||
};
|
||||
},
|
||||
{
|
||||
setActiveTab,
|
||||
}
|
||||
)(SessionTags);
|
||||
|
||||
function TagItem({ isActive, onClick, label, icon = '', disabled = false }: any) {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={onClick}
|
||||
className={cn('transition group rounded ml-2 px-2 py-1 flex items-center uppercase text-sm hover:bg-teal hover:text-white', {
|
||||
'bg-teal text-white': isActive,
|
||||
'bg-active-blue color-teal': !isActive,
|
||||
'disabled': disabled,
|
||||
})}
|
||||
>
|
||||
{icon && <Icon name={icon} color="teal" size="14" className={cn('group-hover:fill-white mr-2', { 'fill-white': isActive })} />}
|
||||
<span className="leading-none font-bold">{label}</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionTags';
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import React from 'react';
|
||||
import { Icon } from 'UI';
|
||||
import styles from './noContent.module.css';
|
||||
|
||||
export default ({
|
||||
title = <div>No data available.</div>,
|
||||
subtext,
|
||||
icon,
|
||||
iconSize = 100,
|
||||
size,
|
||||
show = true,
|
||||
children = null,
|
||||
empty = false,
|
||||
image = null,
|
||||
style = {},
|
||||
}) => (!show ? children :
|
||||
<div className={ `${ styles.wrapper } ${ size && styles[ size ] }` } style={style}>
|
||||
{
|
||||
icon && <Icon name={icon} size={iconSize} />
|
||||
}
|
||||
{ title && <div className={ styles.title }>{ title }</div> }
|
||||
{
|
||||
subtext &&
|
||||
<div className={ styles.subtext }>{ subtext }</div>
|
||||
}
|
||||
{
|
||||
image && <div className="mt-4 flex justify-center">{ image } </div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
29
frontend/app/components/ui/NoContent/NoContent.tsx
Normal file
29
frontend/app/components/ui/NoContent/NoContent.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import React from 'react';
|
||||
import { Icon } from 'UI';
|
||||
import styles from './noContent.module.css';
|
||||
|
||||
interface Props {
|
||||
title?: any;
|
||||
subtext?: any;
|
||||
icon?: string;
|
||||
iconSize?: number;
|
||||
size?: number;
|
||||
show?: boolean;
|
||||
children?: any;
|
||||
image?: any;
|
||||
style?: any;
|
||||
}
|
||||
export default function NoContent(props: Props) {
|
||||
const { title = '', subtext = '', icon, iconSize, size, show, children, image, style } = props;
|
||||
|
||||
return !show ? (
|
||||
children
|
||||
) : (
|
||||
<div className={`${styles.wrapper} ${size && styles[size]}`} style={style}>
|
||||
{icon && <Icon name={icon} size={iconSize} />}
|
||||
{title && <div className={styles.title}>{title}</div>}
|
||||
{subtext && <div className={styles.subtext}>{subtext}</div>}
|
||||
{image && <div className="mt-4 flex justify-center">{image} </div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -45,15 +45,3 @@
|
|||
height: 166px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: block;
|
||||
margin: auto;
|
||||
background-image: svg-load(empty-state.svg, fill=#CCC);
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
width: 166px;
|
||||
height: 166px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const durationFormatted = (duration: Duration):string => {
|
|||
duration = duration.toFormat('h\'h\'m\'m');
|
||||
} else if (duration.as('months') < 1) { // show in days and hours
|
||||
duration = duration.toFormat('d\'d\'h\'h');
|
||||
} else { //
|
||||
} else {
|
||||
duration = duration.toFormat('m\'m\'s\'s\'');
|
||||
}
|
||||
|
||||
|
|
@ -133,4 +133,4 @@ export const countDaysFrom = (timestamp: number): number => {
|
|||
const date = DateTime.fromMillis(timestamp);
|
||||
const d = new Date();
|
||||
return Math.round(Math.abs(d.getTime() - date.toJSDate().getTime()) / (1000 * 3600 * 24));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import origMoment from "moment";
|
|||
import { extendMoment } from "moment-range";
|
||||
export const moment = extendMoment(origMoment);
|
||||
import { DateTime } from "luxon";
|
||||
import { TIMEZONE } from 'App/constants/storageKeys';
|
||||
|
||||
export const CUSTOM_RANGE = "CUSTOM_RANGE";
|
||||
|
||||
|
|
@ -42,39 +43,42 @@ export function getDateRangeLabel(value) {
|
|||
}
|
||||
|
||||
export function getDateRangeFromValue(value) {
|
||||
const tz = JSON.parse(localStorage.getItem(TIMEZONE));
|
||||
const offset = tz ? tz.label.slice(-6) : 0;
|
||||
|
||||
switch (value) {
|
||||
case DATE_RANGE_VALUES.LAST_30_MINUTES:
|
||||
return moment.range(
|
||||
moment().startOf("hour").subtract(30, "minutes"),
|
||||
moment().startOf("hour")
|
||||
moment().utcOffset(offset, true).startOf("hour").subtract(30, "minutes"),
|
||||
moment().utcOffset(offset, true).startOf("hour")
|
||||
);
|
||||
case DATE_RANGE_VALUES.YESTERDAY:
|
||||
return moment.range(
|
||||
moment().utcOffset(offset, true).subtract(1, "days").startOf("day"),
|
||||
moment().utcOffset(offset, true).subtract(1, "days").endOf("day")
|
||||
);
|
||||
case DATE_RANGE_VALUES.TODAY:
|
||||
return moment.range(moment().startOf("day"), moment().endOf("day"));
|
||||
case DATE_RANGE_VALUES.YESTERDAY:
|
||||
return moment.range(
|
||||
moment().subtract(1, "days").startOf("day"),
|
||||
moment().subtract(1, "days").endOf("day")
|
||||
);
|
||||
return moment.range(moment().utcOffset(offset, true).startOf("day"), moment().utcOffset(offset, true).endOf("day"));
|
||||
case DATE_RANGE_VALUES.LAST_24_HOURS:
|
||||
return moment.range(moment().subtract(24, "hours"), moment());
|
||||
return moment.range(moment().utcOffset(offset, true).subtract(24, "hours"), moment().utcOffset(offset, true));
|
||||
case DATE_RANGE_VALUES.LAST_7_DAYS:
|
||||
return moment.range(
|
||||
moment().subtract(7, "days").startOf("day"),
|
||||
moment().endOf("day")
|
||||
moment().utcOffset(offset, true).subtract(7, "days").startOf("day"),
|
||||
moment().utcOffset(offset, true).endOf("day")
|
||||
);
|
||||
case DATE_RANGE_VALUES.LAST_30_DAYS:
|
||||
return moment.range(
|
||||
moment().subtract(30, "days").startOf("day"),
|
||||
moment().endOf("day")
|
||||
moment().utcOffset(offset, true).subtract(30, "days").startOf("day"),
|
||||
moment().utcOffset(offset, true).endOf("day")
|
||||
);
|
||||
case DATE_RANGE_VALUES.THIS_MONTH:
|
||||
return moment().range("month");
|
||||
return moment().utcOffset(offset, true).range("month");
|
||||
case DATE_RANGE_VALUES.LAST_MONTH:
|
||||
return moment().subtract(1, "months").range("month");
|
||||
return moment().utcOffset(offset, true).subtract(1, "months").range("month");
|
||||
case DATE_RANGE_VALUES.THIS_YEAR:
|
||||
return moment().range("year");
|
||||
return moment().utcOffset(offset, true).range("year");
|
||||
case DATE_RANGE_VALUES.CUSTOM_RANGE:
|
||||
return moment.range(moment(), moment());
|
||||
return moment.range(moment().utcOffset(offset, true), moment().utcOffset(offset, true));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,13 +137,13 @@ export const reduceThenFetchResource =
|
|||
const filter = getState().getIn(['search', 'instance']).toData();
|
||||
|
||||
const activeTab = getState().getIn(['search', 'activeTab']);
|
||||
if (activeTab.type !== 'all' && activeTab.type !== 'bookmark') {
|
||||
if (activeTab.type !== 'all' && activeTab.type !== 'bookmark' && activeTab.type !== 'vault') {
|
||||
const tmpFilter = filtersMap[FilterKey.ISSUE];
|
||||
tmpFilter.value = [activeTab.type];
|
||||
filter.filters = filter.filters.concat(tmpFilter);
|
||||
}
|
||||
|
||||
if (activeTab.type === 'bookmark') {
|
||||
if (activeTab.type === 'bookmark' || activeTab.type === 'vault') {
|
||||
filter.bookmarked = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@ import type {
|
|||
RawCssInsertRule,
|
||||
} from './raw'
|
||||
import RawMessageReader from './RawMessageReader'
|
||||
import type { RawMessageReaderI } from './RawMessageReader'
|
||||
import { resolveURL, resolveCSS } from './urlResolve'
|
||||
|
||||
interface RawMessageReaderI {
|
||||
readMessage(): RawMessage | null
|
||||
}
|
||||
|
||||
const resolveMsg = {
|
||||
"set_node_attribute_url_based": (msg: RawSetNodeAttributeURLBased): RawSetNodeAttribute =>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@
|
|||
import PrimitiveReader from './PrimitiveReader'
|
||||
import type { RawMessage } from './raw'
|
||||
|
||||
export interface RawMessageReaderI {
|
||||
readMessage(): RawMessage | null
|
||||
}
|
||||
|
||||
export default class RawMessageReader extends PrimitiveReader {
|
||||
readMessage(): RawMessage | null {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
import type { Timed } from './timed'
|
||||
import type { RawMessage } from './raw'
|
||||
import type { RawBatchMeta,
|
||||
import type {
|
||||
RawBatchMeta,
|
||||
RawTimestamp,
|
||||
RawSessionDisconnect,
|
||||
RawSetPageLocation,
|
||||
|
|
@ -60,7 +61,8 @@ import type { RawBatchMeta,
|
|||
RawIosClickEvent,
|
||||
RawIosPerformanceEvent,
|
||||
RawIosLog,
|
||||
RawIosNetworkCall, } from './raw'
|
||||
RawIosNetworkCall,
|
||||
} from './raw'
|
||||
|
||||
export type Message = RawMessage & Timed
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Auto-generated, do not edit
|
||||
|
||||
export const TP_MAP = {
|
||||
80: "batch_meta",
|
||||
80: "batch_meta",
|
||||
0: "timestamp",
|
||||
2: "session_disconnect",
|
||||
4: "set_page_location",
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export const sessions = params => queried('/sessions', params);
|
|||
export const assist = params => queried('/assist', params);
|
||||
|
||||
export const session = (sessionId = ':sessionId', hash) => hashed(`/session/${ sessionId }`, hash);
|
||||
export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/assist/${ sessionId }`, hash);
|
||||
export const liveSession = (sessionId = ':sessionId', params, hash) => hashed(queried(`/assist/${ sessionId }`, params), hash);
|
||||
// export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/live/session/${ sessionId }`, hash);
|
||||
|
||||
export const errors = params => queried('/errors', params);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { createStore, applyMiddleware } from 'redux';
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
import { Map } from 'immutable';
|
||||
import indexReducer from './duck';
|
||||
|
|
@ -9,13 +9,16 @@ const storage = new LocalStorage({
|
|||
jwt: String,
|
||||
});
|
||||
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && window.env.NODE_ENV === "development"
|
||||
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose;
|
||||
|
||||
const storageState = storage.state();
|
||||
const initialState = Map({
|
||||
jwt: storageState.jwt,
|
||||
// TODO: store user
|
||||
});
|
||||
|
||||
const store = createStore(indexReducer, initialState, applyMiddleware(thunk, apiMiddleware));
|
||||
const store = createStore(indexReducer, initialState, composeEnhancers(applyMiddleware(thunk, apiMiddleware)));
|
||||
store.subscribe(() => {
|
||||
const state = store.getState();
|
||||
storage.sync({
|
||||
|
|
|
|||
|
|
@ -11,4 +11,8 @@
|
|||
input.no-focus:focus {
|
||||
outline: none !important;
|
||||
border: solid thin transparent !important;
|
||||
}
|
||||
|
||||
.widget-wrapper {
|
||||
@apply rounded border bg-white;
|
||||
}
|
||||
|
|
@ -26,43 +26,43 @@ const RANGE_LABELS = {
|
|||
[THIS_YEAR]: "This Year",
|
||||
};
|
||||
|
||||
function getRange(rangeName) {
|
||||
function getRange(rangeName, offset) {
|
||||
switch (rangeName) {
|
||||
case TODAY:
|
||||
return moment.range(moment().startOf("day"), moment().endOf("day"));
|
||||
case YESTERDAY:
|
||||
return moment.range(
|
||||
moment().subtract(1, "days").startOf("day"),
|
||||
moment().subtract(1, "days").endOf("day")
|
||||
moment().utcOffset(offset).subtract(1, "days").startOf("day"),
|
||||
moment().utcOffset(offset).subtract(1, "days").endOf("day")
|
||||
);
|
||||
case LAST_24_HOURS:
|
||||
return moment.range(
|
||||
// moment().startOf("hour").subtract(24, "hours"),
|
||||
// moment().startOf("hour")
|
||||
moment().subtract(24, 'hours'),
|
||||
moment(),
|
||||
moment().utcOffset(offset).subtract(24, 'hours'),
|
||||
moment().utcOffset(offset),
|
||||
);
|
||||
case LAST_30_MINUTES:
|
||||
return moment.range(
|
||||
moment().startOf("hour").subtract(30, "minutes"),
|
||||
moment().startOf("hour")
|
||||
moment().utcOffset(offset).startOf("hour").subtract(30, "minutes"),
|
||||
moment().utcOffset(offset).startOf("hour")
|
||||
);
|
||||
case LAST_7_DAYS:
|
||||
return moment.range(
|
||||
moment().subtract(7, "days").startOf("day"),
|
||||
moment().endOf("day")
|
||||
moment().utcOffset(offset).subtract(7, "days").startOf("day"),
|
||||
moment().utcOffset(offset).endOf("day")
|
||||
);
|
||||
case LAST_30_DAYS:
|
||||
return moment.range(
|
||||
moment().subtract(30, "days").startOf("day"),
|
||||
moment().endOf("day")
|
||||
moment().utcOffset(offset).subtract(30, "days").startOf("day"),
|
||||
moment().utcOffset(offset).endOf("day")
|
||||
);
|
||||
case THIS_MONTH:
|
||||
return moment().range("month");
|
||||
return moment().utcOffset(offset).range("month");
|
||||
case LAST_MONTH:
|
||||
return moment().subtract(1, "months").range("month");
|
||||
return moment().utcOffset(offset).subtract(1, "months").range("month");
|
||||
case THIS_YEAR:
|
||||
return moment().range("year");
|
||||
return moment().utcOffset(offset).range("year");
|
||||
default:
|
||||
return moment.range();
|
||||
}
|
||||
|
|
@ -77,10 +77,11 @@ export default Record(
|
|||
},
|
||||
{
|
||||
fromJS: (period) => {
|
||||
const offset = period.timezoneOffset || 0
|
||||
if (!period.rangeName || period.rangeName === CUSTOM_RANGE) {
|
||||
const range = moment.range(
|
||||
moment(period.start || 0),
|
||||
moment(period.end || 0)
|
||||
moment(period.start || 0).utcOffset(offset),
|
||||
moment(period.end || 0).utcOffset(offset)
|
||||
);
|
||||
return {
|
||||
...period,
|
||||
|
|
@ -89,7 +90,7 @@ export default Record(
|
|||
end: range.end.unix() * 1000,
|
||||
};
|
||||
}
|
||||
const range = getRange(period.rangeName);
|
||||
const range = getRange(period.rangeName, offset);
|
||||
return {
|
||||
...period,
|
||||
range,
|
||||
|
|
@ -97,14 +98,6 @@ export default Record(
|
|||
end: range.end.unix() * 1000,
|
||||
};
|
||||
},
|
||||
// fromFilter: filter => {
|
||||
// const range = getRange(filter.rangeName);
|
||||
// return {
|
||||
// start: range.start.unix() * 1000,
|
||||
// end: range.end.unix() * 1000,
|
||||
// rangeName: filter.rangeName,
|
||||
// }
|
||||
// },
|
||||
methods: {
|
||||
toJSON() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,18 @@ import { List } from 'immutable';
|
|||
import Watchdog from 'Types/watchdog'
|
||||
|
||||
export const issues_types = List([
|
||||
{ 'type': 'js_exception', 'visible': true, 'order': 0, 'name': 'Errors', 'icon': 'funnel/exclamation-circle' },
|
||||
{ 'type': 'bad_request', 'visible': true, 'order': 1, 'name': 'Bad Requests', 'icon': 'funnel/file-medical-alt' },
|
||||
{ 'type': 'missing_resource', 'visible': true, 'order': 2, 'name': 'Missing Images', 'icon': 'funnel/image' },
|
||||
{ 'type': 'click_rage', 'visible': true, 'order': 3, 'name': 'Click Rage', 'icon': 'funnel/emoji-angry' },
|
||||
{ 'type': 'dead_click', 'visible': true, 'order': 4, 'name': 'Dead Clicks', 'icon': 'funnel/dizzy' },
|
||||
{ 'type': 'memory', 'visible': true, 'order': 5, 'name': 'High Memory', 'icon': 'funnel/sd-card' },
|
||||
{ 'type': 'cpu', 'visible': true, 'order': 6, 'name': 'High CPU', 'icon': 'funnel/cpu' },
|
||||
{ 'type': 'crash', 'visible': true, 'order': 7, 'name': 'Crashes', 'icon': 'funnel/file-earmark-break' },
|
||||
{ 'type': 'custom', 'visible': false, 'order': 8, 'name': 'Custom', 'icon': 'funnel/exclamation-circle' }
|
||||
{ 'type': 'all', 'visible': true, 'order': 0, 'name': 'All', 'icon': '' },
|
||||
{ 'type': 'js_exception', 'visible': true, 'order': 1, 'name': 'Errors', 'icon': 'funnel/exclamation-circle' },
|
||||
{ 'type': 'click_rage', 'visible': true, 'order': 2, 'name': 'Click Rage', 'icon': 'funnel/emoji-angry' },
|
||||
{ 'type': 'crash', 'visible': true, 'order': 3, 'name': 'Crashes', 'icon': 'funnel/file-earmark-break' },
|
||||
{ 'type': 'memory', 'visible': true, 'order': 4, 'name': 'High Memory', 'icon': 'funnel/sd-card' },
|
||||
{ 'type': 'vault', 'visible': true, 'order': 5, 'name': 'Vault', 'icon': 'safe' },
|
||||
{ 'type': 'bookmark', 'visible': true, 'order': 5, 'name': 'Bookmarks', 'icon': 'safe' },
|
||||
// { 'type': 'bad_request', 'visible': true, 'order': 1, 'name': 'Bad Requests', 'icon': 'funnel/file-medical-alt' },
|
||||
// { 'type': 'missing_resource', 'visible': true, 'order': 2, 'name': 'Missing Images', 'icon': 'funnel/image' },
|
||||
// { 'type': 'dead_click', 'visible': true, 'order': 4, 'name': 'Dead Clicks', 'icon': 'funnel/dizzy' },
|
||||
// { 'type': 'cpu', 'visible': true, 'order': 6, 'name': 'High CPU', 'icon': 'funnel/cpu' },
|
||||
// { 'type': 'custom', 'visible': false, 'order': 8, 'name': 'Custom', 'icon': 'funnel/exclamation-circle' }
|
||||
]).map(Watchdog)
|
||||
|
||||
export const issues_types_map = {}
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
require('dotenv').config()
|
||||
|
||||
// TODO: (the problem is during the build time the frontend is isolated)
|
||||
//const trackerInfo = require('../tracker/tracker/package.json');
|
||||
|
||||
const oss = {
|
||||
name: 'oss',
|
||||
PRODUCTION: true,
|
||||
SENTRY_ENABLED: false,
|
||||
SENTRY_URL: "",
|
||||
CAPTCHA_ENABLED: process.env.CAPTCHA_ENABLED === 'true',
|
||||
CAPTCHA_SITE_KEY: process.env.CAPTCHA_SITE_KEY,
|
||||
ORIGIN: () => 'window.location.origin',
|
||||
API_EDP: () => 'window.location.origin + "/api"',
|
||||
ASSETS_HOST: () => 'window.location.origin + "/assets"',
|
||||
VERSION: '1.7.0',
|
||||
SOURCEMAP: true,
|
||||
MINIO_ENDPOINT: process.env.MINIO_ENDPOINT,
|
||||
MINIO_PORT: process.env.MINIO_PORT,
|
||||
MINIO_USE_SSL: process.env.MINIO_USE_SSL,
|
||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||
ICE_SERVERS: process.env.ICE_SERVERS,
|
||||
TRACKER_VERSION: '3.5.15' // trackerInfo.version,
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
oss,
|
||||
};
|
||||
16
mobs/README.md
Normal file
16
mobs/README.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Message Object Binary Schema and Code Generator from Templates
|
||||
|
||||
|
||||
To generate all necessary files for the project:
|
||||
|
||||
```sh
|
||||
ruby run.rb
|
||||
|
||||
```
|
||||
|
||||
In order generated .go file to fit the go formatting style:
|
||||
```sh
|
||||
gofmt -w ../backend/pkg/messages/messages.go
|
||||
|
||||
```
|
||||
(Otherwise there will be changes in stage)
|
||||
172
mobs/ios_messages.rb
Normal file
172
mobs/ios_messages.rb
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
message 107, 'IOSBatchMeta', :replayer => false do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
uint 'FirstIndex'
|
||||
end
|
||||
|
||||
message 90, 'IOSSessionStart', :replayer => true do
|
||||
uint 'Timestamp'
|
||||
# uint 'Length'
|
||||
|
||||
uint 'ProjectID'
|
||||
string 'TrackerVersion'
|
||||
string 'RevID'
|
||||
string 'UserUUID'
|
||||
# string 'UserAgent'
|
||||
string 'UserOS'
|
||||
string 'UserOSVersion'
|
||||
# string 'UserBrowser'
|
||||
# string 'UserBrowserVersion'
|
||||
string 'UserDevice'
|
||||
string 'UserDeviceType'
|
||||
# uint 'UserDeviceMemorySize'
|
||||
# uint 'UserDeviceHeapSize'
|
||||
string 'UserCountry'
|
||||
end
|
||||
|
||||
message 91, 'IOSSessionEnd' do
|
||||
uint 'Timestamp'
|
||||
end
|
||||
|
||||
message 92, 'IOSMetadata' do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Key'
|
||||
string 'Value'
|
||||
end
|
||||
|
||||
message 93, 'IOSCustomEvent', :seq_index => true, :replayer => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Name'
|
||||
string 'Payload'
|
||||
end
|
||||
|
||||
message 94, 'IOSUserID' do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Value'
|
||||
end
|
||||
|
||||
message 95, 'IOSUserAnonymousID' do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Value'
|
||||
end
|
||||
|
||||
message 96, 'IOSScreenChanges', :replayer => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
uint 'X'
|
||||
uint 'Y'
|
||||
uint 'Width'
|
||||
uint 'Height'
|
||||
end
|
||||
|
||||
message 97, 'IOSCrash', :seq_index => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Name'
|
||||
string 'Reason'
|
||||
string 'Stacktrace'
|
||||
end
|
||||
|
||||
message 98, 'IOSScreenEnter', :seq_index => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Title'
|
||||
string 'ViewName'
|
||||
end
|
||||
|
||||
message 99, 'IOSScreenLeave' do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Title'
|
||||
string 'ViewName'
|
||||
end
|
||||
|
||||
message 100, 'IOSClickEvent', :seq_index => true, :replayer => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Label'
|
||||
uint 'X'
|
||||
uint 'Y'
|
||||
end
|
||||
|
||||
message 101, 'IOSInputEvent', :seq_index => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Value'
|
||||
boolean 'ValueMasked'
|
||||
string 'Label'
|
||||
end
|
||||
|
||||
=begin
|
||||
Name/Value may be :
|
||||
"physicalMemory": Total memory in bytes
|
||||
"processorCount": Total processors in device
|
||||
?"activeProcessorCount": Number of currently used processors
|
||||
"systemUptime": Elapsed time (in seconds) since last boot
|
||||
?"isLowPowerModeEnabled": Possible values (1 or 0)
|
||||
2/3!"thermalState": Possible values (0:nominal 1:fair 2:serious 3:critical)
|
||||
!"batteryLevel": Possible values (0 .. 100)
|
||||
"batteryState": Possible values (0:unknown 1:unplugged 2:charging 3:full)
|
||||
"orientation": Possible values (0unknown 1:portrait 2:portraitUpsideDown 3:landscapeLeft 4:landscapeRight 5:faceUp 6:faceDown)
|
||||
"mainThreadCPU": Possible values (0 .. 100)
|
||||
"memoryUsage": Used memory in bytes
|
||||
=end
|
||||
message 102, 'IOSPerformanceEvent', :replayer => true, :seq_index => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Name'
|
||||
uint 'Value'
|
||||
end
|
||||
|
||||
message 103, 'IOSLog', :replayer => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Severity' # Possible values ("info", "error")
|
||||
string 'Content'
|
||||
end
|
||||
|
||||
message 104, 'IOSInternalError' do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
string 'Content'
|
||||
end
|
||||
|
||||
message 105, 'IOSNetworkCall', :replayer => true, :seq_index => true do
|
||||
uint 'Timestamp'
|
||||
uint 'Length'
|
||||
uint 'Duration'
|
||||
string 'Headers'
|
||||
string 'Body'
|
||||
string 'URL'
|
||||
boolean 'Success'
|
||||
string 'Method'
|
||||
uint 'Status'
|
||||
end
|
||||
message 110, 'IOSPerformanceAggregated', :swift => false do
|
||||
uint 'TimestampStart'
|
||||
uint 'TimestampEnd'
|
||||
uint 'MinFPS'
|
||||
uint 'AvgFPS'
|
||||
uint 'MaxFPS'
|
||||
uint 'MinCPU'
|
||||
uint 'AvgCPU'
|
||||
uint 'MaxCPU'
|
||||
uint 'MinMemory'
|
||||
uint 'AvgMemory'
|
||||
uint 'MaxMemory'
|
||||
uint 'MinBattery'
|
||||
uint 'AvgBattery'
|
||||
uint 'MaxBattery'
|
||||
end
|
||||
|
||||
message 111, 'IOSIssueEvent', :seq_index => true do
|
||||
uint 'Timestamp'
|
||||
string 'Type'
|
||||
string 'ContextString'
|
||||
string 'Context'
|
||||
string 'Payload'
|
||||
end
|
||||
409
mobs/messages.rb
Normal file
409
mobs/messages.rb
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
# Special one for Batch Meta. Message id could define the version
|
||||
message 80, 'BatchMeta', :replayer => false do
|
||||
uint 'PageNo'
|
||||
uint 'FirstIndex'
|
||||
int 'Timestamp'
|
||||
end
|
||||
message 0, 'Timestamp' do
|
||||
uint 'Timestamp'
|
||||
end
|
||||
message 1, 'SessionStart', :js => false, :replayer => false do
|
||||
uint 'Timestamp'
|
||||
uint 'ProjectID'
|
||||
string 'TrackerVersion'
|
||||
string 'RevID'
|
||||
string 'UserUUID'
|
||||
string 'UserAgent'
|
||||
string 'UserOS'
|
||||
string 'UserOSVersion'
|
||||
string 'UserBrowser'
|
||||
string 'UserBrowserVersion'
|
||||
string 'UserDevice'
|
||||
string 'UserDeviceType'
|
||||
uint 'UserDeviceMemorySize'
|
||||
uint 'UserDeviceHeapSize'
|
||||
string 'UserCountry'
|
||||
string 'UserID'
|
||||
end
|
||||
# Depricated (not used) since OpenReplay tracker 3.0.0
|
||||
message 2, 'SessionDisconnect', :js => false do
|
||||
uint 'Timestamp'
|
||||
end
|
||||
message 3, 'SessionEnd', :js => false, :replayer => false do
|
||||
uint 'Timestamp'
|
||||
end
|
||||
message 4, 'SetPageLocation' do
|
||||
string 'URL'
|
||||
string 'Referrer'
|
||||
uint 'NavigationStart'
|
||||
end
|
||||
message 5, 'SetViewportSize' do
|
||||
uint 'Width'
|
||||
uint 'Height'
|
||||
end
|
||||
message 6, 'SetViewportScroll' do
|
||||
int 'X'
|
||||
int 'Y'
|
||||
end
|
||||
message 7, 'CreateDocument' do
|
||||
end
|
||||
message 8, 'CreateElementNode' do
|
||||
uint 'ID'
|
||||
uint 'ParentID'
|
||||
uint 'index'
|
||||
string 'Tag'
|
||||
boolean 'SVG'
|
||||
end
|
||||
message 9, 'CreateTextNode' do
|
||||
uint 'ID'
|
||||
uint 'ParentID'
|
||||
uint 'Index'
|
||||
end
|
||||
message 10, 'MoveNode' do
|
||||
uint 'ID'
|
||||
uint 'ParentID'
|
||||
uint 'Index'
|
||||
end
|
||||
message 11, 'RemoveNode' do
|
||||
uint 'ID'
|
||||
end
|
||||
message 12, 'SetNodeAttribute' do
|
||||
uint 'ID'
|
||||
string 'Name'
|
||||
string 'Value'
|
||||
end
|
||||
message 13, 'RemoveNodeAttribute' do
|
||||
uint 'ID'
|
||||
string 'Name'
|
||||
end
|
||||
message 14, 'SetNodeData' do
|
||||
uint 'ID'
|
||||
string 'Data'
|
||||
end
|
||||
# Depricated starting from 5.5.11 in favor of SetStyleData
|
||||
message 15, 'SetCSSData', :js => false do
|
||||
uint 'ID'
|
||||
string 'Data'
|
||||
end
|
||||
message 16, 'SetNodeScroll' do
|
||||
uint 'ID'
|
||||
int 'X'
|
||||
int 'Y'
|
||||
end
|
||||
message 17, 'SetInputTarget', :replayer => false do
|
||||
uint 'ID'
|
||||
string 'Label'
|
||||
end
|
||||
message 18, 'SetInputValue' do
|
||||
uint 'ID'
|
||||
string 'Value'
|
||||
int 'Mask'
|
||||
end
|
||||
message 19, 'SetInputChecked' do
|
||||
uint 'ID'
|
||||
boolean 'Checked'
|
||||
end
|
||||
message 20, 'MouseMove' do
|
||||
uint 'X'
|
||||
uint 'Y'
|
||||
end
|
||||
# Depricated since OpenReplay 1.2.0
|
||||
message 21, 'MouseClickDepricated', :js => false, :replayer => false do
|
||||
uint 'ID'
|
||||
uint 'HesitationTime'
|
||||
string 'Label'
|
||||
end
|
||||
message 22, 'ConsoleLog' do
|
||||
string 'Level'
|
||||
string 'Value'
|
||||
end
|
||||
message 23, 'PageLoadTiming', :replayer => false do
|
||||
uint 'RequestStart'
|
||||
uint 'ResponseStart'
|
||||
uint 'ResponseEnd'
|
||||
uint 'DomContentLoadedEventStart'
|
||||
uint 'DomContentLoadedEventEnd'
|
||||
uint 'LoadEventStart'
|
||||
uint 'LoadEventEnd'
|
||||
uint 'FirstPaint'
|
||||
uint 'FirstContentfulPaint'
|
||||
end
|
||||
message 24, 'PageRenderTiming', :replayer => false do
|
||||
uint 'SpeedIndex'
|
||||
uint 'VisuallyComplete'
|
||||
uint 'TimeToInteractive'
|
||||
end
|
||||
message 25, 'JSException', :replayer => false do
|
||||
string 'Name'
|
||||
string 'Message'
|
||||
string 'Payload'
|
||||
end
|
||||
message 26, 'IntegrationEvent', :js => false, :replayer => false do
|
||||
uint 'Timestamp'
|
||||
string 'Source'
|
||||
string 'Name'
|
||||
string 'Message'
|
||||
string 'Payload'
|
||||
end
|
||||
message 27, 'RawCustomEvent', :replayer => false do
|
||||
string 'Name'
|
||||
string 'Payload'
|
||||
end
|
||||
message 28, 'UserID', :replayer => false do
|
||||
string 'ID'
|
||||
end
|
||||
message 29, 'UserAnonymousID', :replayer => false do
|
||||
string 'ID'
|
||||
end
|
||||
message 30, 'Metadata', :replayer => false do
|
||||
string 'Key'
|
||||
string 'Value'
|
||||
end
|
||||
message 31, 'PageEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'URL'
|
||||
string 'Referrer'
|
||||
boolean 'Loaded'
|
||||
uint 'RequestStart'
|
||||
uint 'ResponseStart'
|
||||
uint 'ResponseEnd'
|
||||
uint 'DomContentLoadedEventStart'
|
||||
uint 'DomContentLoadedEventEnd'
|
||||
uint 'LoadEventStart'
|
||||
uint 'LoadEventEnd'
|
||||
uint 'FirstPaint'
|
||||
uint 'FirstContentfulPaint'
|
||||
uint 'SpeedIndex'
|
||||
uint 'VisuallyComplete'
|
||||
uint 'TimeToInteractive'
|
||||
end
|
||||
message 32, 'InputEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'Value'
|
||||
boolean 'ValueMasked'
|
||||
string 'Label'
|
||||
end
|
||||
message 33, 'ClickEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
uint 'HesitationTime'
|
||||
string 'Label'
|
||||
string 'Selector'
|
||||
end
|
||||
message 34, 'ErrorEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'Source'
|
||||
string 'Name'
|
||||
string 'Message'
|
||||
string 'Payload'
|
||||
end
|
||||
message 35, 'ResourceEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
uint 'Duration'
|
||||
uint 'TTFB'
|
||||
uint 'HeaderSize'
|
||||
uint 'EncodedBodySize'
|
||||
uint 'DecodedBodySize'
|
||||
string 'URL'
|
||||
string 'Type'
|
||||
boolean 'Success'
|
||||
string 'Method'
|
||||
uint 'Status'
|
||||
end
|
||||
message 36, 'CustomEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'Name'
|
||||
string 'Payload'
|
||||
end
|
||||
|
||||
|
||||
message 37, 'CSSInsertRule' do
|
||||
uint 'ID'
|
||||
string 'Rule'
|
||||
uint 'Index'
|
||||
end
|
||||
message 38, 'CSSDeleteRule' do
|
||||
uint 'ID'
|
||||
uint 'Index'
|
||||
end
|
||||
|
||||
message 39, 'Fetch' do
|
||||
string 'Method'
|
||||
string 'URL'
|
||||
string 'Request'
|
||||
string 'Response'
|
||||
uint 'Status'
|
||||
uint 'Timestamp'
|
||||
uint 'Duration'
|
||||
end
|
||||
message 40, 'Profiler' do
|
||||
string 'Name'
|
||||
uint 'Duration'
|
||||
string 'Args'
|
||||
string 'Result'
|
||||
end
|
||||
|
||||
message 41, 'OTable' do
|
||||
string 'Key'
|
||||
string 'Value'
|
||||
end
|
||||
message 42, 'StateAction', :replayer => false do
|
||||
string 'Type'
|
||||
end
|
||||
message 43, 'StateActionEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'Type'
|
||||
end
|
||||
|
||||
message 44, 'Redux' do
|
||||
string 'Action'
|
||||
string 'State'
|
||||
uint 'Duration'
|
||||
end
|
||||
message 45, 'Vuex' do
|
||||
string 'Mutation'
|
||||
string 'State'
|
||||
end
|
||||
message 46, 'MobX' do
|
||||
string 'Type'
|
||||
string 'Payload'
|
||||
end
|
||||
message 47, 'NgRx' do
|
||||
string 'Action'
|
||||
string 'State'
|
||||
uint 'Duration'
|
||||
end
|
||||
message 48, 'GraphQL' do
|
||||
string 'OperationKind'
|
||||
string 'OperationName'
|
||||
string 'Variables'
|
||||
string 'Response'
|
||||
end
|
||||
message 49, 'PerformanceTrack' do
|
||||
int 'Frames'
|
||||
int 'Ticks'
|
||||
uint 'TotalJSHeapSize'
|
||||
uint 'UsedJSHeapSize'
|
||||
end
|
||||
message 50, 'GraphQLEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'OperationKind'
|
||||
string 'OperationName'
|
||||
string 'Variables'
|
||||
string 'Response'
|
||||
end
|
||||
message 51, 'FetchEvent', :js => false, :replayer => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'Method'
|
||||
string 'URL'
|
||||
string 'Request'
|
||||
string 'Response'
|
||||
uint 'Status'
|
||||
uint 'Duration'
|
||||
end
|
||||
message 52, 'DOMDrop', :js => false, :replayer => false do
|
||||
uint 'Timestamp'
|
||||
end
|
||||
message 53, 'ResourceTiming', :replayer => false do
|
||||
uint 'Timestamp'
|
||||
uint 'Duration'
|
||||
uint 'TTFB'
|
||||
uint 'HeaderSize'
|
||||
uint 'EncodedBodySize'
|
||||
uint 'DecodedBodySize'
|
||||
string 'URL'
|
||||
string 'Initiator'
|
||||
end
|
||||
message 54, 'ConnectionInformation' do
|
||||
uint 'Downlink'
|
||||
string 'Type'
|
||||
end
|
||||
message 55, 'SetPageVisibility' do
|
||||
boolean 'hidden'
|
||||
end
|
||||
message 56, 'PerformanceTrackAggr', :js => false, :replayer => false do
|
||||
uint 'TimestampStart'
|
||||
uint 'TimestampEnd'
|
||||
uint 'MinFPS'
|
||||
uint 'AvgFPS'
|
||||
uint 'MaxFPS'
|
||||
uint 'MinCPU'
|
||||
uint 'AvgCPU'
|
||||
uint 'MaxCPU'
|
||||
uint 'MinTotalJSHeapSize'
|
||||
uint 'AvgTotalJSHeapSize'
|
||||
uint 'MaxTotalJSHeapSize'
|
||||
uint 'MinUsedJSHeapSize'
|
||||
uint 'AvgUsedJSHeapSize'
|
||||
uint 'MaxUsedJSHeapSize'
|
||||
end
|
||||
message 59, 'LongTask' do
|
||||
uint 'Timestamp'
|
||||
uint 'Duration'
|
||||
uint 'Context'
|
||||
uint 'ContainerType'
|
||||
string 'ContainerSrc'
|
||||
string 'ContainerId'
|
||||
string 'ContainerName'
|
||||
end
|
||||
message 60, 'SetNodeAttributeURLBased', :replayer => false do
|
||||
uint 'ID'
|
||||
string 'Name'
|
||||
string 'Value'
|
||||
string 'BaseURL'
|
||||
end
|
||||
# Might replace SetCSSData (although BaseURL is useless after rewriting)
|
||||
message 61, 'SetCSSDataURLBased', :replayer => false do
|
||||
uint 'ID'
|
||||
string 'Data'
|
||||
string 'BaseURL'
|
||||
end
|
||||
message 62, 'IssueEvent', :replayer => false, :js => false do
|
||||
uint 'MessageID'
|
||||
uint 'Timestamp'
|
||||
string 'Type'
|
||||
string 'ContextString'
|
||||
string 'Context'
|
||||
string 'Payload'
|
||||
end
|
||||
message 63, 'TechnicalInfo', :replayer => false do
|
||||
string 'Type'
|
||||
string 'Value'
|
||||
end
|
||||
message 64, 'CustomIssue', :replayer => false do
|
||||
string 'Name'
|
||||
string 'Payload'
|
||||
end
|
||||
# Since 5.6.6; only for websocket (might be probably replaced with ws.close())
|
||||
# Depricated
|
||||
message 65, 'PageClose', :replayer => false do
|
||||
end
|
||||
message 66, 'AssetCache', :replayer => false, :js => false do
|
||||
string 'URL'
|
||||
end
|
||||
message 67, 'CSSInsertRuleURLBased', :replayer => false do
|
||||
uint 'ID'
|
||||
string 'Rule'
|
||||
uint 'Index'
|
||||
string 'BaseURL'
|
||||
end
|
||||
message 69, 'MouseClick' do
|
||||
uint 'ID'
|
||||
uint 'HesitationTime'
|
||||
string 'Label'
|
||||
string 'Selector'
|
||||
end
|
||||
|
||||
# Since 3.4.0
|
||||
message 70, 'CreateIFrameDocument' do
|
||||
uint 'FrameID'
|
||||
uint 'ID'
|
||||
end
|
||||
124
mobs/primitives/primitives.go
Normal file
124
mobs/primitives/primitives.go
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
package messages
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
func ReadByte(reader io.Reader) (byte, error) {
|
||||
p := make([]byte, 1)
|
||||
_, err := io.ReadFull(reader, p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return p[0], nil
|
||||
}
|
||||
|
||||
func SkipBytes(reader io.ReadSeeker) error {
|
||||
n, err := ReadUint(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := reader.Seek(n, io.SeekCurrent);
|
||||
return err
|
||||
}
|
||||
|
||||
func ReadData(reader io.Reader) ([]byte, error) {
|
||||
n, err := ReadUint(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := make([]byte, n)
|
||||
_, err := io.ReadFull(reader, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func ReadUint(reader io.Reader) (uint64, error) {
|
||||
var x uint64
|
||||
var s uint
|
||||
i := 0
|
||||
for {
|
||||
b, err := ReadByte(reader)
|
||||
if err != nil {
|
||||
return x, err
|
||||
}
|
||||
if b < 0x80 {
|
||||
if i > 9 || i == 9 && b > 1 {
|
||||
return x, errors.New("overflow")
|
||||
}
|
||||
return x | uint64(b)<<s, nil
|
||||
}
|
||||
x |= uint64(b&0x7f) << s
|
||||
s += 7
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func ReadInt(reader io.Reader) (int64, error) {
|
||||
ux, err := ReadUint(reader)
|
||||
x := int64(ux >> 1)
|
||||
if err != nil {
|
||||
return x, err
|
||||
}
|
||||
if ux&1 != 0 {
|
||||
x = ^x
|
||||
}
|
||||
return x, err
|
||||
}
|
||||
|
||||
func ReadBoolean(reader io.Reader) (bool, error) {
|
||||
p := make([]byte, 1)
|
||||
_, err := io.ReadFull(reader, p)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return p[0] == 1, nil
|
||||
}
|
||||
|
||||
func ReadString(reader io.Reader) (string, error) {
|
||||
l, err := ReadUint(reader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
buf := make([]byte, l)
|
||||
_, err = io.ReadFull(reader, buf)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
func WriteUint(v uint64, buf []byte, p int) int {
|
||||
for v >= 0x80 {
|
||||
buf[p] = byte(v) | 0x80
|
||||
v >>= 7
|
||||
p++
|
||||
}
|
||||
buf[p] = byte(v)
|
||||
return p + 1
|
||||
}
|
||||
|
||||
func WriteInt(v int64, buf []byte, p int) int {
|
||||
uv := uint64(v) << 1
|
||||
if v < 0 {
|
||||
uv = ^uv
|
||||
}
|
||||
return WriteUint(uv, buf, p)
|
||||
}
|
||||
|
||||
func WriteBoolean(v bool, buf []byte, p int) int {
|
||||
if v {
|
||||
buf[p] = 1
|
||||
} else {
|
||||
buf[p] = 0
|
||||
}
|
||||
return p + 1
|
||||
}
|
||||
|
||||
func WriteString(str string, buf []byte, p int) int {
|
||||
p = WriteUint(uint64(len(str)), buf, p)
|
||||
return p + copy(buf[p:], str)
|
||||
}
|
||||
62
mobs/primitives/primitives.py
Normal file
62
mobs/primitives/primitives.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import io
|
||||
|
||||
class Codec:
|
||||
"""
|
||||
Implements encode/decode primitives
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def read_boolean(reader: io.BytesIO):
|
||||
b = reader.read(1)
|
||||
return b == 1
|
||||
|
||||
@staticmethod
|
||||
def read_uint(reader: io.BytesIO):
|
||||
"""
|
||||
The ending "big" doesn't play any role here,
|
||||
since we're dealing with data per one byte
|
||||
"""
|
||||
x = 0 # the result
|
||||
s = 0 # the shift (our result is big-ending)
|
||||
i = 0 # n of byte (max 9 for uint64)
|
||||
while True:
|
||||
b = reader.read(1)
|
||||
num = int.from_bytes(b, "big", signed=False)
|
||||
# print(i, x)
|
||||
|
||||
if num < 0x80:
|
||||
if i > 9 | i == 9 & num > 1:
|
||||
raise OverflowError()
|
||||
return int(x | num << s)
|
||||
x |= (num & 0x7f) << s
|
||||
s += 7
|
||||
i += 1
|
||||
|
||||
@staticmethod
|
||||
def read_int(reader: io.BytesIO) -> int:
|
||||
"""
|
||||
ux, err := ReadUint(reader)
|
||||
x := int64(ux >> 1)
|
||||
if err != nil {
|
||||
return x, err
|
||||
}
|
||||
if ux&1 != 0 {
|
||||
x = ^x
|
||||
}
|
||||
return x, err
|
||||
"""
|
||||
ux = Codec.read_uint(reader)
|
||||
x = int(ux >> 1)
|
||||
|
||||
if ux & 1 != 0:
|
||||
x = - x - 1
|
||||
return x
|
||||
|
||||
@staticmethod
|
||||
def read_string(reader: io.BytesIO) -> str:
|
||||
length = Codec.read_uint(reader)
|
||||
s = reader.read(length)
|
||||
try:
|
||||
return s.decode("utf-8", errors="replace").replace("\x00", "\uFFFD")
|
||||
except UnicodeDecodeError:
|
||||
return None
|
||||
60
mobs/primitives/primitives.swift
Normal file
60
mobs/primitives/primitives.swift
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
extension Data {
|
||||
func readByte(offset: inout Int) -> UInt8 {
|
||||
if offset >= self.count {
|
||||
fatalError(">>> Error reading Byte")
|
||||
}
|
||||
let b = self[offset]
|
||||
offset += 1
|
||||
return b
|
||||
}
|
||||
func readUint(offset: inout Int) -> UInt64 {
|
||||
var x: UInt64 = 0
|
||||
var s: Int = 0
|
||||
var i: Int = 0
|
||||
while true {
|
||||
let b = readByte(offset: &offset)
|
||||
if b < 0x80 {
|
||||
if i > 9 || i == 9 && b > 1 {
|
||||
fatalError(">>> Error reading UInt")
|
||||
}
|
||||
return x | UInt64(b)<<s
|
||||
}
|
||||
x |= UInt64(b&0x7f) << s
|
||||
s += 7
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
func readInt(offset: inout Int) -> Int64 {
|
||||
let ux = readUint(offset: &offset)
|
||||
var x = Int64(ux >> 1)
|
||||
if ux&1 != 0 {
|
||||
x = ~x
|
||||
}
|
||||
return x
|
||||
}
|
||||
func readBoolean(offset: inout Int) -> Bool {
|
||||
return readByte(offset: &offset) == 1
|
||||
}
|
||||
mutating func writeUint(_ input: UInt64) {
|
||||
var v = input
|
||||
while v >= 0x80 {
|
||||
append(UInt8(v.littleEndian & 0x7F) | 0x80) // v.littleEndian ?
|
||||
v >>= 7
|
||||
}
|
||||
append(UInt8(v))
|
||||
}
|
||||
mutating func writeInt(_ v: Int64) {
|
||||
var uv = UInt64(v) << 1
|
||||
if v < 0 {
|
||||
uv = ~uv
|
||||
}
|
||||
writeUint(uv)
|
||||
}
|
||||
mutating func writeBoolean(_ v: Bool) {
|
||||
if v {
|
||||
append(1)
|
||||
} else {
|
||||
append(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
136
mobs/run.rb
Normal file
136
mobs/run.rb
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
require 'erb'
|
||||
|
||||
|
||||
# TODO: change method names to correct (CapitalCase and camelCase, not CamalCase and firstLower)
|
||||
class String
|
||||
def camel_case
|
||||
return self if self !~ /_/ && self =~ /[A-Z]+.*/
|
||||
split('_').map{|e| e.capitalize}.join.upperize
|
||||
end
|
||||
|
||||
def camel_case_lower
|
||||
self.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join.upperize
|
||||
end
|
||||
|
||||
def upperize
|
||||
self.sub('Id', 'ID').sub('Url', 'URL')
|
||||
end
|
||||
|
||||
def first_lower
|
||||
self.sub(/^[A-Z]+/) {|f| f.downcase }
|
||||
end
|
||||
|
||||
def underscore
|
||||
self.gsub(/::/, '/').
|
||||
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
||||
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
||||
tr("-", "_").
|
||||
downcase
|
||||
end
|
||||
end
|
||||
|
||||
class Attribute
|
||||
attr_reader :name, :type
|
||||
def initialize(name:, type:)
|
||||
@name = name
|
||||
@type = type
|
||||
end
|
||||
|
||||
def type_js
|
||||
case @type
|
||||
when :int
|
||||
"number"
|
||||
when :uint
|
||||
"number"
|
||||
when :json
|
||||
# TODO
|
||||
# raise "Unexpected attribute type: data type attribute #{@name} found in JS template"
|
||||
"string"
|
||||
when :data
|
||||
raise "Unexpected attribute type: data type attribute #{@name} found in JS template"
|
||||
else
|
||||
@type
|
||||
end
|
||||
end
|
||||
|
||||
def type_go
|
||||
case @type
|
||||
when :int
|
||||
'int64'
|
||||
when :uint
|
||||
'uint64'
|
||||
when :string
|
||||
'string'
|
||||
when :data
|
||||
'[]byte'
|
||||
when :boolean
|
||||
'bool'
|
||||
when :json
|
||||
'interface{}'
|
||||
end
|
||||
end
|
||||
|
||||
def lengh_encoded
|
||||
case @type
|
||||
when :string, :data
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
$context = :web
|
||||
|
||||
class Message
|
||||
attr_reader :id, :name, :js, :replayer, :swift, :seq_index, :attributes, :context
|
||||
def initialize(name:, id:, js: $context == :web, replayer: $context == :web, swift: $context == :ios, seq_index: false, &block)
|
||||
@id = id
|
||||
@name = name
|
||||
@js = js
|
||||
@replayer = replayer
|
||||
@swift = swift
|
||||
@seq_index = seq_index
|
||||
@context = $context
|
||||
@attributes = []
|
||||
instance_eval &block
|
||||
end
|
||||
|
||||
%i(int uint boolean string data).each do |type|
|
||||
define_method type do |name, opts = {}|
|
||||
opts.merge!(
|
||||
name: name,
|
||||
type: type,
|
||||
)
|
||||
@attributes << Attribute.new(opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$ids = []
|
||||
$messages = []
|
||||
def message(id, name, opts = {}, &block)
|
||||
raise "id duplicated #{name}" if $ids.include? id
|
||||
raise "id is too big #{name}" if id > 120
|
||||
$ids << id
|
||||
opts[:id] = id
|
||||
opts[:name] = name
|
||||
msg = Message.new(opts, &block)
|
||||
$messages << msg
|
||||
end
|
||||
|
||||
require './messages.rb'
|
||||
|
||||
$context = :ios
|
||||
require './ios_messages.rb'
|
||||
|
||||
Dir["templates/*.erb"].each do |tpl|
|
||||
e = ERB.new(File.read(tpl))
|
||||
path = tpl.split '/'
|
||||
t = '../' + path[1].gsub('~', '/')
|
||||
t = t[0..-5]
|
||||
File.write(t, e.result)
|
||||
puts tpl + ' --> ' + t
|
||||
end
|
||||
10
mobs/templates/backend~pkg~messages~filters.go.erb
Normal file
10
mobs/templates/backend~pkg~messages~filters.go.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Auto-generated, do not edit
|
||||
package messages
|
||||
|
||||
func IsReplayerType(id int) bool {
|
||||
return <%= $messages.select { |msg| msg.replayer }.map{ |msg| "#{msg.id} == id" }.join(' || ') %>
|
||||
}
|
||||
|
||||
func IsIOSType(id int) bool {
|
||||
return <%= $messages.select { |msg| msg.context == :ios }.map{ |msg| "#{msg.id} == id"}.join(' || ') %>
|
||||
}
|
||||
12
mobs/templates/backend~pkg~messages~get-timestamp.go.erb
Normal file
12
mobs/templates/backend~pkg~messages~get-timestamp.go.erb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Auto-generated, do not edit
|
||||
package messages
|
||||
|
||||
func GetTimestamp(message Message) uint64 {
|
||||
switch msg := message.(type) {
|
||||
<% $messages.select { |msg| msg.swift }.each do |msg| %>
|
||||
case *<%= msg.name %>:
|
||||
return msg.Timestamp
|
||||
<% end %>
|
||||
}
|
||||
return uint64(message.Meta().Timestamp)
|
||||
}
|
||||
22
mobs/templates/backend~pkg~messages~messages.go.erb
Normal file
22
mobs/templates/backend~pkg~messages~messages.go.erb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Auto-generated, do not edit
|
||||
package messages
|
||||
<% $messages.each do |msg| %>
|
||||
type <%= msg.name %> struct {
|
||||
message
|
||||
<%= msg.attributes.map { |attr|
|
||||
" #{attr.name} #{attr.type_go}" }.join "\n" %>
|
||||
}
|
||||
|
||||
func (msg *<%= msg.name %>) Encode() []byte {
|
||||
buf := make([]byte, <%= msg.attributes.count * 10 + 1 %><%= msg.attributes.map { |attr| "+len(msg.#{attr.name})" if attr.lengh_encoded }.compact.join %>)
|
||||
buf[0] = <%= msg.id %>
|
||||
p := 1
|
||||
<%= msg.attributes.map { |attr|
|
||||
" p = Write#{attr.type.to_s.camel_case}(msg.#{attr.name}, buf, p)" }.join "\n" %>
|
||||
return buf[:p]
|
||||
}
|
||||
|
||||
func (msg *<%= msg.name %>) TypeID() int {
|
||||
return <%= msg.id %>
|
||||
}
|
||||
<% end %>
|
||||
26
mobs/templates/backend~pkg~messages~read-message.go.erb
Normal file
26
mobs/templates/backend~pkg~messages~read-message.go.erb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Auto-generated, do not edit
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func ReadMessage(reader io.Reader) (Message, error) {
|
||||
t, err := ReadUint(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch t {
|
||||
<% $messages.each do |msg| %>
|
||||
case <%= msg.id %>:
|
||||
msg := &<%= msg.name %>{}
|
||||
<%= msg.attributes.map { |attr|
|
||||
" if msg.#{attr.name}, err = Read#{attr.type.to_s.camel_case}(reader); err != nil {
|
||||
return nil, err
|
||||
}" }.join "\n" %>
|
||||
return msg, nil
|
||||
<% end %>
|
||||
}
|
||||
return nil, fmt.Errorf("Unknown message code: %v", t)
|
||||
}
|
||||
16
mobs/templates/ee~connectors~msgcodec~messages.py.erb
Normal file
16
mobs/templates/ee~connectors~msgcodec~messages.py.erb
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Auto-generated, do not edit
|
||||
|
||||
from abc import ABC
|
||||
|
||||
class Message(ABC):
|
||||
pass
|
||||
|
||||
<% $messages.each do |msg| %>
|
||||
class <%= msg.name %>(Message):
|
||||
__id__ = <%= msg.id %>
|
||||
|
||||
def __init__(self, <%= msg.attributes.map { |attr| "#{attr.name.underscore}" }.join ", " %>):
|
||||
<%= msg.attributes.map { |attr| "self.#{attr.name.underscore} = #{attr.name.underscore}" }.join "\n "
|
||||
%>
|
||||
|
||||
<% end %>
|
||||
29
mobs/templates/ee~connectors~msgcodec~msgcodec.py.erb
Normal file
29
mobs/templates/ee~connectors~msgcodec~msgcodec.py.erb
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Auto-generated, do not edit
|
||||
|
||||
from msgcodec.codec import Codec
|
||||
from msgcodec.messages import *
|
||||
|
||||
class MessageCodec(Codec):
|
||||
|
||||
def read_message_id(self, reader: io.BytesIO) -> int:
|
||||
"""
|
||||
Read and return the first byte where the message id is encoded
|
||||
"""
|
||||
id_ = self.read_uint(reader)
|
||||
return id_
|
||||
|
||||
def encode(self, m: Message) -> bytes:
|
||||
...
|
||||
|
||||
def decode(self, b: bytes) -> Message:
|
||||
reader = io.BytesIO(b)
|
||||
message_id = self.read_message_id(reader)
|
||||
<% $messages.each do |msg| %>
|
||||
if message_id == <%= msg.id %>:
|
||||
return <%= msg.name %>(
|
||||
<%= msg.attributes.map { |attr|
|
||||
"#{attr.name.underscore}=self.read_#{attr.type.to_s}(reader)" }
|
||||
.join ",\n "
|
||||
%>
|
||||
)
|
||||
<% end %>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Auto-generated, do not edit
|
||||
|
||||
import PrimitiveReader from './PrimitiveReader'
|
||||
import type { RawMessage } from './raw'
|
||||
|
||||
|
||||
export default class RawMessageReader extends PrimitiveReader {
|
||||
readMessage(): RawMessage | null {
|
||||
const p = this.p
|
||||
const resetPointer = () => {
|
||||
this.p = p
|
||||
return null
|
||||
}
|
||||
|
||||
const tp = this.readUint()
|
||||
if (tp === null) { return resetPointer() }
|
||||
|
||||
switch (tp) {
|
||||
<% $messages.select { |msg| msg.js || msg.replayer }.each do |msg| %>
|
||||
case <%= msg.id %>: {
|
||||
<%= msg.attributes.map { |attr|
|
||||
" const #{attr.name.first_lower} = this.read#{attr.type.to_s.camel_case}(); if (#{attr.name.first_lower} === null) { return resetPointer() }" }.join "\n" %>
|
||||
return {
|
||||
tp: "<%= msg.name.underscore %>",
|
||||
<%= msg.attributes.map { |attr|
|
||||
" #{attr.name.first_lower}," }.join "\n" %>
|
||||
};
|
||||
}
|
||||
<% end %>
|
||||
default:
|
||||
throw new Error(`Unrecognizable message type: ${ tp }; Pointer at the position ${this.p} of ${this.buf.length}`)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Auto-generated, do not edit
|
||||
|
||||
import type { Timed } from './timed'
|
||||
import type { RawMessage } from './raw'
|
||||
import type {
|
||||
<%= $messages.select { |msg| msg.js || msg.replayer }.map { |msg| " Raw#{msg.name.underscore.camel_case}," }.join "\n" %>
|
||||
} from './raw'
|
||||
|
||||
export type Message = RawMessage & Timed
|
||||
|
||||
<% $messages.select { |msg| msg.js || msg.replayer }.each do |msg| %>
|
||||
export type <%= msg.name.underscore.camel_case %> = Raw<%= msg.name.underscore.camel_case %> & Timed
|
||||
<% end %>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Auto-generated, do not edit
|
||||
|
||||
export const TP_MAP = {
|
||||
<%= $messages.select { |msg| msg.js || msg.replayer }.map { |msg| " #{msg.id}: \"#{msg.name.underscore}\"," }.join "\n" %>
|
||||
}
|
||||
|
||||
<% $messages.select { |msg| msg.js || msg.replayer }.each do |msg| %>
|
||||
export interface Raw<%= msg.name.underscore.camel_case %> {
|
||||
tp: "<%= msg.name.underscore %>",
|
||||
<%= msg.attributes.map { |attr| " #{attr.name.first_lower}: #{attr.type_js}," }.join "\n" %>
|
||||
}
|
||||
<% end %>
|
||||
|
||||
export type RawMessage = <%= $messages.select { |msg| msg.js || msg.replayer }.map { |msg| "Raw#{msg.name.underscore.camel_case}" }.join " | " %>;
|
||||
36
mobs/templates/ios/ASMessage.swift
Normal file
36
mobs/templates/ios/ASMessage.swift
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Auto-generated, do not edit
|
||||
import UIKit
|
||||
|
||||
enum ASMessageType: UInt64 {
|
||||
<%= $messages.map { |msg| " case #{msg.name.first_lower} = #{msg.id}" }.join "\n" %>
|
||||
}
|
||||
<% $messages.each do |msg| %>
|
||||
class AS<%= msg.name.to_s.camel_case %>: ASMessage {
|
||||
<%= msg.attributes[2..-1].map { |attr| " let #{attr.property}: #{attr.type_swift}" }.join "\n" %>
|
||||
|
||||
init(<%= msg.attributes[2..-1].map { |attr| "#{attr.property}: #{attr.type_swift}" }.join ", " %>) {
|
||||
<%= msg.attributes[2..-1].map { |attr| " self.#{attr.property} = #{attr.property}" }.join "\n" %>
|
||||
super.init(messageType: .<%= "#{msg.name.first_lower}" %>)
|
||||
}
|
||||
|
||||
override init?(genericMessage: GenericMessage) {
|
||||
<% if msg.attributes.length > 2 %> do {
|
||||
var offset = 0
|
||||
<%= msg.attributes[2..-1].map { |attr| " self.#{attr.property} = try genericMessage.body.read#{attr.type_swift_read}(offset: &offset)" }.join "\n" %>
|
||||
super.init(genericMessage: genericMessage)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
<% else %>
|
||||
super.init(genericMessage: genericMessage)
|
||||
<% end %>}
|
||||
|
||||
override func contentData() -> Data {
|
||||
return Data(values: UInt64(<%= "#{msg.id}"%>), timestamp<% if msg.attributes.length > 2 %>, Data(values: <%= msg.attributes[2..-1].map { |attr| attr.property }.join ", "%>)<% end %>)
|
||||
}
|
||||
|
||||
override var description: String {
|
||||
return "-->> <%= msg.name.to_s.camel_case %>(<%= "#{msg.id}"%>): timestamp:\(timestamp) <%= msg.attributes[2..-1].map { |attr| "#{attr.property}:\\(#{attr.property})" }.join " "%>";
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
31
mobs/templates/tracker~tracker~src~common~messages.ts.erb
Normal file
31
mobs/templates/tracker~tracker~src~common~messages.ts.erb
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Auto-generated, do not edit
|
||||
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 }
|
||||
): C & ((...args: A) => T) {
|
||||
function _Class(...args: A) {
|
||||
return new Class(...args);
|
||||
}
|
||||
_Class.prototype = Class.prototype;
|
||||
return <C & ((...args: A) => T)>_Class;
|
||||
}
|
||||
|
||||
export const classes: Map<number, Function> = new Map();
|
||||
|
||||
<% $messages.select { |msg| msg.js }.each do |msg| %>
|
||||
class _<%= msg.name %> implements Message {
|
||||
readonly _id: number = <%= msg.id %>;
|
||||
constructor(
|
||||
<%= msg.attributes.map { |attr| "public #{attr.name.first_lower}: #{attr.type_js}" }.join ",\n " %>
|
||||
) {}
|
||||
encode(writer: Writer): boolean {
|
||||
return writer.uint(<%= msg.id %>)<%= " &&" if msg.attributes.length() > 0 %>
|
||||
<%= msg.attributes.map { |attr| "writer.#{attr.type}(this.#{attr.name.first_lower})" }.join " &&\n " %>;
|
||||
}
|
||||
}
|
||||
export const <%= msg.name %> = bindNew(_<%= msg.name %>);
|
||||
classes.set(<%= msg.id %>, <%= msg.name %>);
|
||||
|
||||
<% end %>
|
||||
3
scripts/dockerfiles/alpine/Dockerfile
Normal file
3
scripts/dockerfiles/alpine/Dockerfile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
FROM alpine
|
||||
# Fix busybox vulnerability
|
||||
RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
||||
|
|
@ -2,39 +2,104 @@
|
|||
|
||||
This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org).
|
||||
|
||||
### 4.2.0
|
||||
|
||||
- Support for Kubernetes v1.19.0 was removed
|
||||
- "[8810](https://github.com/kubernetes/ingress-nginx/pull/8810) Prepare for v1.3.0"
|
||||
- "[8808](https://github.com/kubernetes/ingress-nginx/pull/8808) revert arch var name"
|
||||
- "[8805](https://github.com/kubernetes/ingress-nginx/pull/8805) Bump k8s.io/klog/v2 from 2.60.1 to 2.70.1"
|
||||
- "[8803](https://github.com/kubernetes/ingress-nginx/pull/8803) Update to nginx base with alpine v3.16"
|
||||
- "[8802](https://github.com/kubernetes/ingress-nginx/pull/8802) chore: start v1.3.0 release process"
|
||||
- "[8798](https://github.com/kubernetes/ingress-nginx/pull/8798) Add v1.24.0 to test matrix"
|
||||
- "[8796](https://github.com/kubernetes/ingress-nginx/pull/8796) fix: add MAC_OS variable for static-check"
|
||||
- "[8793](https://github.com/kubernetes/ingress-nginx/pull/8793) changed to alpine-v3.16"
|
||||
- "[8781](https://github.com/kubernetes/ingress-nginx/pull/8781) Bump github.com/stretchr/testify from 1.7.5 to 1.8.0"
|
||||
- "[8778](https://github.com/kubernetes/ingress-nginx/pull/8778) chore: remove stable.txt from release process"
|
||||
- "[8775](https://github.com/kubernetes/ingress-nginx/pull/8775) Remove stable"
|
||||
- "[8773](https://github.com/kubernetes/ingress-nginx/pull/8773) Bump github/codeql-action from 2.1.14 to 2.1.15"
|
||||
- "[8772](https://github.com/kubernetes/ingress-nginx/pull/8772) Bump ossf/scorecard-action from 1.1.1 to 1.1.2"
|
||||
- "[8771](https://github.com/kubernetes/ingress-nginx/pull/8771) fix bullet md format"
|
||||
- "[8770](https://github.com/kubernetes/ingress-nginx/pull/8770) Add condition for monitoring.coreos.com/v1 API"
|
||||
- "[8769](https://github.com/kubernetes/ingress-nginx/pull/8769) Fix typos and add links to developer guide"
|
||||
- "[8767](https://github.com/kubernetes/ingress-nginx/pull/8767) change v1.2.0 to v1.2.1 in deploy doc URLs"
|
||||
- "[8765](https://github.com/kubernetes/ingress-nginx/pull/8765) Bump github/codeql-action from 1.0.26 to 2.1.14"
|
||||
- "[8752](https://github.com/kubernetes/ingress-nginx/pull/8752) Bump github.com/spf13/cobra from 1.4.0 to 1.5.0"
|
||||
- "[8751](https://github.com/kubernetes/ingress-nginx/pull/8751) Bump github.com/stretchr/testify from 1.7.2 to 1.7.5"
|
||||
- "[8750](https://github.com/kubernetes/ingress-nginx/pull/8750) added announcement"
|
||||
- "[8740](https://github.com/kubernetes/ingress-nginx/pull/8740) change sha e2etestrunner and echoserver"
|
||||
- "[8738](https://github.com/kubernetes/ingress-nginx/pull/8738) Update docs to make it easier for noobs to follow step by step"
|
||||
- "[8737](https://github.com/kubernetes/ingress-nginx/pull/8737) updated baseimage sha"
|
||||
- "[8736](https://github.com/kubernetes/ingress-nginx/pull/8736) set ld-musl-path"
|
||||
- "[8733](https://github.com/kubernetes/ingress-nginx/pull/8733) feat: migrate leaderelection lock to leases"
|
||||
- "[8726](https://github.com/kubernetes/ingress-nginx/pull/8726) prometheus metric: upstream_latency_seconds"
|
||||
- "[8720](https://github.com/kubernetes/ingress-nginx/pull/8720) Ci pin deps"
|
||||
- "[8719](https://github.com/kubernetes/ingress-nginx/pull/8719) Working OpenTelemetry sidecar (base nginx image)"
|
||||
- "[8714](https://github.com/kubernetes/ingress-nginx/pull/8714) Create Openssf scorecard"
|
||||
- "[8708](https://github.com/kubernetes/ingress-nginx/pull/8708) Bump github.com/prometheus/common from 0.34.0 to 0.35.0"
|
||||
- "[8703](https://github.com/kubernetes/ingress-nginx/pull/8703) Bump actions/dependency-review-action from 1 to 2"
|
||||
- "[8701](https://github.com/kubernetes/ingress-nginx/pull/8701) Fix several typos"
|
||||
- "[8699](https://github.com/kubernetes/ingress-nginx/pull/8699) fix the gosec test and a make target for it"
|
||||
- "[8698](https://github.com/kubernetes/ingress-nginx/pull/8698) Bump actions/upload-artifact from 2.3.1 to 3.1.0"
|
||||
- "[8697](https://github.com/kubernetes/ingress-nginx/pull/8697) Bump actions/setup-go from 2.2.0 to 3.2.0"
|
||||
- "[8695](https://github.com/kubernetes/ingress-nginx/pull/8695) Bump actions/download-artifact from 2 to 3"
|
||||
- "[8694](https://github.com/kubernetes/ingress-nginx/pull/8694) Bump crazy-max/ghaction-docker-buildx from 1.6.2 to 3.3.1"
|
||||
|
||||
### 4.1.2
|
||||
|
||||
- "[8587](https://github.com/kubernetes/ingress-nginx/pull/8587) Add CAP_SYS_CHROOT to DS/PSP when needed"
|
||||
- "[8458](https://github.com/kubernetes/ingress-nginx/pull/8458) Add portNamePreffix Helm chart parameter"
|
||||
- "[8522](https://github.com/kubernetes/ingress-nginx/pull/8522) Add documentation for controller.service.loadBalancerIP in Helm chart"
|
||||
|
||||
### 4.1.0
|
||||
|
||||
- "[8481](https://github.com/kubernetes/ingress-nginx/pull/8481) Fix log creation in chroot script"
|
||||
- "[8479](https://github.com/kubernetes/ingress-nginx/pull/8479) changed nginx base img tag to img built with alpine3.14.6"
|
||||
- "[8478](https://github.com/kubernetes/ingress-nginx/pull/8478) update base images and protobuf gomod"
|
||||
- "[8468](https://github.com/kubernetes/ingress-nginx/pull/8468) Fallback to ngx.var.scheme for redirectScheme with use-forward-headers when X-Forwarded-Proto is empty"
|
||||
- "[8456](https://github.com/kubernetes/ingress-nginx/pull/8456) Implement object deep inspector"
|
||||
- "[8455](https://github.com/kubernetes/ingress-nginx/pull/8455) Update dependencies"
|
||||
- "[8454](https://github.com/kubernetes/ingress-nginx/pull/8454) Update index.md"
|
||||
- "[8447](https://github.com/kubernetes/ingress-nginx/pull/8447) typo fixing"
|
||||
- "[8446](https://github.com/kubernetes/ingress-nginx/pull/8446) Fix suggested annotation-value-word-blocklist"
|
||||
- "[8444](https://github.com/kubernetes/ingress-nginx/pull/8444) replace deprecated topology key in example with current one"
|
||||
- "[8443](https://github.com/kubernetes/ingress-nginx/pull/8443) Add dependency review enforcement"
|
||||
- "[8434](https://github.com/kubernetes/ingress-nginx/pull/8434) added new auth-tls-match-cn annotation"
|
||||
- "[8426](https://github.com/kubernetes/ingress-nginx/pull/8426) Bump github.com/prometheus/common from 0.32.1 to 0.33.0"
|
||||
|
||||
### 4.0.18
|
||||
"[8291](https://github.com/kubernetes/ingress-nginx/pull/8291) remove git tag env from cloud build"
|
||||
"[8286](https://github.com/kubernetes/ingress-nginx/pull/8286) Fix OpenTelemetry sidecar image build"
|
||||
"[8277](https://github.com/kubernetes/ingress-nginx/pull/8277) Add OpenSSF Best practices badge"
|
||||
"[8273](https://github.com/kubernetes/ingress-nginx/pull/8273) Issue#8241"
|
||||
"[8267](https://github.com/kubernetes/ingress-nginx/pull/8267) Add fsGroup value to admission-webhooks/job-patch charts"
|
||||
"[8262](https://github.com/kubernetes/ingress-nginx/pull/8262) Updated confusing error"
|
||||
"[8256](https://github.com/kubernetes/ingress-nginx/pull/8256) fix: deny locations with invalid auth-url annotation"
|
||||
"[8253](https://github.com/kubernetes/ingress-nginx/pull/8253) Add a certificate info metric"
|
||||
"[8236](https://github.com/kubernetes/ingress-nginx/pull/8236) webhook: remove useless code."
|
||||
"[8227](https://github.com/kubernetes/ingress-nginx/pull/8227) Update libraries in webhook image"
|
||||
"[8225](https://github.com/kubernetes/ingress-nginx/pull/8225) fix inconsistent-label-cardinality for prometheus metrics: nginx_ingress_controller_requests"
|
||||
"[8221](https://github.com/kubernetes/ingress-nginx/pull/8221) Do not validate ingresses with unknown ingress class in admission webhook endpoint"
|
||||
"[8210](https://github.com/kubernetes/ingress-nginx/pull/8210) Bump github.com/prometheus/client_golang from 1.11.0 to 1.12.1"
|
||||
"[8209](https://github.com/kubernetes/ingress-nginx/pull/8209) Bump google.golang.org/grpc from 1.43.0 to 1.44.0"
|
||||
"[8204](https://github.com/kubernetes/ingress-nginx/pull/8204) Add Artifact Hub lint"
|
||||
"[8203](https://github.com/kubernetes/ingress-nginx/pull/8203) Fix Indentation of example and link to cert-manager tutorial"
|
||||
"[8201](https://github.com/kubernetes/ingress-nginx/pull/8201) feat(metrics): add path and method labels to requests countera"
|
||||
"[8199](https://github.com/kubernetes/ingress-nginx/pull/8199) use functional options to reduce number of methods creating an EchoDeployment"
|
||||
"[8196](https://github.com/kubernetes/ingress-nginx/pull/8196) docs: fix inconsistent controller annotation"
|
||||
"[8191](https://github.com/kubernetes/ingress-nginx/pull/8191) Using Go install for misspell"
|
||||
"[8186](https://github.com/kubernetes/ingress-nginx/pull/8186) prometheus+grafana using servicemonitor"
|
||||
"[8185](https://github.com/kubernetes/ingress-nginx/pull/8185) Append elements on match, instead of removing for cors-annotations"
|
||||
"[8179](https://github.com/kubernetes/ingress-nginx/pull/8179) Bump github.com/opencontainers/runc from 1.0.3 to 1.1.0"
|
||||
"[8173](https://github.com/kubernetes/ingress-nginx/pull/8173) Adding annotations to the controller service account"
|
||||
"[8163](https://github.com/kubernetes/ingress-nginx/pull/8163) Update the $req_id placeholder description"
|
||||
"[8162](https://github.com/kubernetes/ingress-nginx/pull/8162) Versioned static manifests"
|
||||
"[8159](https://github.com/kubernetes/ingress-nginx/pull/8159) Adding some geoip variables and default values"
|
||||
"[8155](https://github.com/kubernetes/ingress-nginx/pull/8155) #7271 feat: avoid-pdb-creation-when-default-backend-disabled-and-replicas-gt-1"
|
||||
"[8151](https://github.com/kubernetes/ingress-nginx/pull/8151) Automatically generate helm docs"
|
||||
"[8143](https://github.com/kubernetes/ingress-nginx/pull/8143) Allow to configure delay before controller exits"
|
||||
"[8136](https://github.com/kubernetes/ingress-nginx/pull/8136) add ingressClass option to helm chart - back compatibility with ingress.class annotations"
|
||||
"[8126](https://github.com/kubernetes/ingress-nginx/pull/8126) Example for JWT"
|
||||
|
||||
- "[8291](https://github.com/kubernetes/ingress-nginx/pull/8291) remove git tag env from cloud build"
|
||||
- "[8286](https://github.com/kubernetes/ingress-nginx/pull/8286) Fix OpenTelemetry sidecar image build"
|
||||
- "[8277](https://github.com/kubernetes/ingress-nginx/pull/8277) Add OpenSSF Best practices badge"
|
||||
- "[8273](https://github.com/kubernetes/ingress-nginx/pull/8273) Issue#8241"
|
||||
- "[8267](https://github.com/kubernetes/ingress-nginx/pull/8267) Add fsGroup value to admission-webhooks/job-patch charts"
|
||||
- "[8262](https://github.com/kubernetes/ingress-nginx/pull/8262) Updated confusing error"
|
||||
- "[8256](https://github.com/kubernetes/ingress-nginx/pull/8256) fix: deny locations with invalid auth-url annotation"
|
||||
- "[8253](https://github.com/kubernetes/ingress-nginx/pull/8253) Add a certificate info metric"
|
||||
- "[8236](https://github.com/kubernetes/ingress-nginx/pull/8236) webhook: remove useless code."
|
||||
- "[8227](https://github.com/kubernetes/ingress-nginx/pull/8227) Update libraries in webhook image"
|
||||
- "[8225](https://github.com/kubernetes/ingress-nginx/pull/8225) fix inconsistent-label-cardinality for prometheus metrics: nginx_ingress_controller_requests"
|
||||
- "[8221](https://github.com/kubernetes/ingress-nginx/pull/8221) Do not validate ingresses with unknown ingress class in admission webhook endpoint"
|
||||
- "[8210](https://github.com/kubernetes/ingress-nginx/pull/8210) Bump github.com/prometheus/client_golang from 1.11.0 to 1.12.1"
|
||||
- "[8209](https://github.com/kubernetes/ingress-nginx/pull/8209) Bump google.golang.org/grpc from 1.43.0 to 1.44.0"
|
||||
- "[8204](https://github.com/kubernetes/ingress-nginx/pull/8204) Add Artifact Hub lint"
|
||||
- "[8203](https://github.com/kubernetes/ingress-nginx/pull/8203) Fix Indentation of example and link to cert-manager tutorial"
|
||||
- "[8201](https://github.com/kubernetes/ingress-nginx/pull/8201) feat(metrics): add path and method labels to requests countera"
|
||||
- "[8199](https://github.com/kubernetes/ingress-nginx/pull/8199) use functional options to reduce number of methods creating an EchoDeployment"
|
||||
- "[8196](https://github.com/kubernetes/ingress-nginx/pull/8196) docs: fix inconsistent controller annotation"
|
||||
- "[8191](https://github.com/kubernetes/ingress-nginx/pull/8191) Using Go install for misspell"
|
||||
- "[8186](https://github.com/kubernetes/ingress-nginx/pull/8186) prometheus+grafana using servicemonitor"
|
||||
- "[8185](https://github.com/kubernetes/ingress-nginx/pull/8185) Append elements on match, instead of removing for cors-annotations"
|
||||
- "[8179](https://github.com/kubernetes/ingress-nginx/pull/8179) Bump github.com/opencontainers/runc from 1.0.3 to 1.1.0"
|
||||
- "[8173](https://github.com/kubernetes/ingress-nginx/pull/8173) Adding annotations to the controller service account"
|
||||
- "[8163](https://github.com/kubernetes/ingress-nginx/pull/8163) Update the $req_id placeholder description"
|
||||
- "[8162](https://github.com/kubernetes/ingress-nginx/pull/8162) Versioned static manifests"
|
||||
- "[8159](https://github.com/kubernetes/ingress-nginx/pull/8159) Adding some geoip variables and default values"
|
||||
- "[8155](https://github.com/kubernetes/ingress-nginx/pull/8155) #7271 feat: avoid-pdb-creation-when-default-backend-disabled-and-replicas-gt-1"
|
||||
- "[8151](https://github.com/kubernetes/ingress-nginx/pull/8151) Automatically generate helm docs"
|
||||
- "[8143](https://github.com/kubernetes/ingress-nginx/pull/8143) Allow to configure delay before controller exits"
|
||||
- "[8136](https://github.com/kubernetes/ingress-nginx/pull/8136) add ingressClass option to helm chart - back compatibility with ingress.class annotations"
|
||||
- "[8126](https://github.com/kubernetes/ingress-nginx/pull/8126) Example for JWT"
|
||||
|
||||
|
||||
### 4.0.15
|
||||
|
|
@ -119,11 +184,11 @@ This file documents all notable changes to [ingress-nginx](https://github.com/ku
|
|||
|
||||
- [7707] https://github.com/kubernetes/ingress-nginx/pull/7707 Release v1.0.2 of ingress-nginx
|
||||
|
||||
### 4.0.2
|
||||
### 4.0.2
|
||||
|
||||
- [7681] https://github.com/kubernetes/ingress-nginx/pull/7681 Release v1.0.1 of ingress-nginx
|
||||
|
||||
### 4.0.1
|
||||
### 4.0.1
|
||||
|
||||
- [7535] https://github.com/kubernetes/ingress-nginx/pull/7535 Release v1.0.0 ingress-nginx
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,46 @@
|
|||
annotations:
|
||||
artifacthub.io/changes: |
|
||||
- "#8253 Add a certificate info metric"
|
||||
- "#8225 fix inconsistent-label-cardinality for prometheus metrics: nginx_ingress_controller_requests"
|
||||
- "#8162 Versioned static manifests"
|
||||
- "#8159 Adding some geoip variables and default values"
|
||||
- "#8221 Do not validate ingresses with unknown ingress class in admission webhook endpoint"
|
||||
- "[8810](https://github.com/kubernetes/ingress-nginx/pull/8810) Prepare for v1.3.0"
|
||||
- "[8808](https://github.com/kubernetes/ingress-nginx/pull/8808) revert arch var name"
|
||||
- "[8805](https://github.com/kubernetes/ingress-nginx/pull/8805) Bump k8s.io/klog/v2 from 2.60.1 to 2.70.1"
|
||||
- "[8803](https://github.com/kubernetes/ingress-nginx/pull/8803) Update to nginx base with alpine v3.16"
|
||||
- "[8802](https://github.com/kubernetes/ingress-nginx/pull/8802) chore: start v1.3.0 release process"
|
||||
- "[8798](https://github.com/kubernetes/ingress-nginx/pull/8798) Add v1.24.0 to test matrix"
|
||||
- "[8796](https://github.com/kubernetes/ingress-nginx/pull/8796) fix: add MAC_OS variable for static-check"
|
||||
- "[8793](https://github.com/kubernetes/ingress-nginx/pull/8793) changed to alpine-v3.16"
|
||||
- "[8781](https://github.com/kubernetes/ingress-nginx/pull/8781) Bump github.com/stretchr/testify from 1.7.5 to 1.8.0"
|
||||
- "[8778](https://github.com/kubernetes/ingress-nginx/pull/8778) chore: remove stable.txt from release process"
|
||||
- "[8775](https://github.com/kubernetes/ingress-nginx/pull/8775) Remove stable"
|
||||
- "[8773](https://github.com/kubernetes/ingress-nginx/pull/8773) Bump github/codeql-action from 2.1.14 to 2.1.15"
|
||||
- "[8772](https://github.com/kubernetes/ingress-nginx/pull/8772) Bump ossf/scorecard-action from 1.1.1 to 1.1.2"
|
||||
- "[8771](https://github.com/kubernetes/ingress-nginx/pull/8771) fix bullet md format"
|
||||
- "[8770](https://github.com/kubernetes/ingress-nginx/pull/8770) Add condition for monitoring.coreos.com/v1 API"
|
||||
- "[8769](https://github.com/kubernetes/ingress-nginx/pull/8769) Fix typos and add links to developer guide"
|
||||
- "[8767](https://github.com/kubernetes/ingress-nginx/pull/8767) change v1.2.0 to v1.2.1 in deploy doc URLs"
|
||||
- "[8765](https://github.com/kubernetes/ingress-nginx/pull/8765) Bump github/codeql-action from 1.0.26 to 2.1.14"
|
||||
- "[8752](https://github.com/kubernetes/ingress-nginx/pull/8752) Bump github.com/spf13/cobra from 1.4.0 to 1.5.0"
|
||||
- "[8751](https://github.com/kubernetes/ingress-nginx/pull/8751) Bump github.com/stretchr/testify from 1.7.2 to 1.7.5"
|
||||
- "[8750](https://github.com/kubernetes/ingress-nginx/pull/8750) added announcement"
|
||||
- "[8740](https://github.com/kubernetes/ingress-nginx/pull/8740) change sha e2etestrunner and echoserver"
|
||||
- "[8738](https://github.com/kubernetes/ingress-nginx/pull/8738) Update docs to make it easier for noobs to follow step by step"
|
||||
- "[8737](https://github.com/kubernetes/ingress-nginx/pull/8737) updated baseimage sha"
|
||||
- "[8736](https://github.com/kubernetes/ingress-nginx/pull/8736) set ld-musl-path"
|
||||
- "[8733](https://github.com/kubernetes/ingress-nginx/pull/8733) feat: migrate leaderelection lock to leases"
|
||||
- "[8726](https://github.com/kubernetes/ingress-nginx/pull/8726) prometheus metric: upstream_latency_seconds"
|
||||
- "[8720](https://github.com/kubernetes/ingress-nginx/pull/8720) Ci pin deps"
|
||||
- "[8719](https://github.com/kubernetes/ingress-nginx/pull/8719) Working OpenTelemetry sidecar (base nginx image)"
|
||||
- "[8714](https://github.com/kubernetes/ingress-nginx/pull/8714) Create Openssf scorecard"
|
||||
- "[8708](https://github.com/kubernetes/ingress-nginx/pull/8708) Bump github.com/prometheus/common from 0.34.0 to 0.35.0"
|
||||
- "[8703](https://github.com/kubernetes/ingress-nginx/pull/8703) Bump actions/dependency-review-action from 1 to 2"
|
||||
- "[8701](https://github.com/kubernetes/ingress-nginx/pull/8701) Fix several typos"
|
||||
- "[8699](https://github.com/kubernetes/ingress-nginx/pull/8699) fix the gosec test and a make target for it"
|
||||
- "[8698](https://github.com/kubernetes/ingress-nginx/pull/8698) Bump actions/upload-artifact from 2.3.1 to 3.1.0"
|
||||
- "[8697](https://github.com/kubernetes/ingress-nginx/pull/8697) Bump actions/setup-go from 2.2.0 to 3.2.0"
|
||||
- "[8695](https://github.com/kubernetes/ingress-nginx/pull/8695) Bump actions/download-artifact from 2 to 3"
|
||||
- "[8694](https://github.com/kubernetes/ingress-nginx/pull/8694) Bump crazy-max/ghaction-docker-buildx from 1.6.2 to 3.3.1"
|
||||
artifacthub.io/prerelease: "false"
|
||||
apiVersion: v2
|
||||
appVersion: 1.1.2
|
||||
appVersion: 1.3.0
|
||||
description: Ingress controller for Kubernetes using NGINX as a reverse proxy and
|
||||
load balancer
|
||||
home: https://github.com/kubernetes/ingress-nginx
|
||||
|
|
@ -15,11 +48,13 @@ icon: https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Nginx_logo.svg/5
|
|||
keywords:
|
||||
- ingress
|
||||
- nginx
|
||||
kubeVersion: '>=1.19.0-0'
|
||||
kubeVersion: '>=1.20.0-0'
|
||||
maintainers:
|
||||
- name: ChiefAlexander
|
||||
- name: rikatz
|
||||
- name: strongjz
|
||||
- name: tao12345666333
|
||||
name: ingress-nginx
|
||||
sources:
|
||||
- https://github.com/kubernetes/ingress-nginx
|
||||
type: application
|
||||
version: 4.0.18
|
||||
version: 4.2.0
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer
|
||||
|
||||
  
|
||||
  
|
||||
|
||||
To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources.
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ controller:
|
|||
|
||||
### AWS L7 ELB with SSL Termination
|
||||
|
||||
Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/main/deploy/aws/l7/service-l7.yaml):
|
||||
Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/ab3a789caae65eec4ad6e3b46b19750b481b6bce/deploy/aws/l7/service-l7.yaml):
|
||||
|
||||
```yaml
|
||||
controller:
|
||||
|
|
@ -128,7 +128,7 @@ controller:
|
|||
|
||||
### AWS route53-mapper
|
||||
|
||||
To configure the LoadBalancer service with the [route53-mapper addon](https://github.com/kubernetes/kops/tree/master/addons/route53-mapper), add the `domainName` annotation and `dns` label:
|
||||
To configure the LoadBalancer service with the [route53-mapper addon](https://github.com/kubernetes/kops/blob/be63d4f1a7a46daaf1c4c482527328236850f111/addons/route53-mapper/README.md), add the `domainName` annotation and `dns` label:
|
||||
|
||||
```yaml
|
||||
controller:
|
||||
|
|
@ -231,7 +231,7 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu
|
|||
|
||||
## Requirements
|
||||
|
||||
Kubernetes: `>=1.19.0-0`
|
||||
Kubernetes: `>=1.20.0-0`
|
||||
|
||||
## Values
|
||||
|
||||
|
|
@ -244,7 +244,8 @@ Kubernetes: `>=1.19.0-0`
|
|||
| controller.admissionWebhooks.createSecretJob.resources | object | `{}` | |
|
||||
| controller.admissionWebhooks.enabled | bool | `true` | |
|
||||
| controller.admissionWebhooks.existingPsp | string | `""` | Use an existing PSP instead of creating one |
|
||||
| controller.admissionWebhooks.failurePolicy | string | `"Fail"` | |
|
||||
| controller.admissionWebhooks.extraEnvs | list | `[]` | Additional environment variables to set |
|
||||
| controller.admissionWebhooks.failurePolicy | string | `"Fail"` | Admission Webhook failure policy to use |
|
||||
| controller.admissionWebhooks.key | string | `"/usr/local/certificates/key"` | |
|
||||
| controller.admissionWebhooks.labels | object | `{}` | Labels to be added to admission webhooks |
|
||||
| controller.admissionWebhooks.namespaceSelector | object | `{}` | |
|
||||
|
|
@ -254,7 +255,7 @@ Kubernetes: `>=1.19.0-0`
|
|||
| controller.admissionWebhooks.patch.image.digest | string | `"sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660"` | |
|
||||
| controller.admissionWebhooks.patch.image.image | string | `"ingress-nginx/kube-webhook-certgen"` | |
|
||||
| controller.admissionWebhooks.patch.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| controller.admissionWebhooks.patch.image.registry | string | `"k8s.gcr.io"` | |
|
||||
| controller.admissionWebhooks.patch.image.registry | string | `"registry.k8s.io"` | |
|
||||
| controller.admissionWebhooks.patch.image.tag | string | `"v1.1.1"` | |
|
||||
| controller.admissionWebhooks.patch.labels | object | `{}` | Labels to be added to patch job resources |
|
||||
| controller.admissionWebhooks.patch.nodeSelector."kubernetes.io/os" | string | `"linux"` | |
|
||||
|
|
@ -306,12 +307,14 @@ Kubernetes: `>=1.19.0-0`
|
|||
| controller.hostPort.ports.https | int | `443` | 'hostPort' https port |
|
||||
| controller.hostname | object | `{}` | Optionally customize the pod hostname. |
|
||||
| controller.image.allowPrivilegeEscalation | bool | `true` | |
|
||||
| controller.image.digest | string | `"sha256:28b11ce69e57843de44e3db6413e98d09de0f6688e33d4bd384002a44f78405c"` | |
|
||||
| controller.image.chroot | bool | `false` | |
|
||||
| controller.image.digest | string | `"sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5"` | |
|
||||
| controller.image.digestChroot | string | `"sha256:0fcb91216a22aae43b374fc2e6a03b8afe9e8c78cbf07a09d75636dc4ea3c191"` | |
|
||||
| controller.image.image | string | `"ingress-nginx/controller"` | |
|
||||
| controller.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| controller.image.registry | string | `"k8s.gcr.io"` | |
|
||||
| controller.image.registry | string | `"registry.k8s.io"` | |
|
||||
| controller.image.runAsUser | int | `101` | |
|
||||
| controller.image.tag | string | `"v1.1.2"` | |
|
||||
| controller.image.tag | string | `"v1.3.0"` | |
|
||||
| controller.ingressClass | string | `"nginx"` | For backwards compatibility with ingress.class annotation, use ingressClass. Algorithm is as follows, first ingressClassName is considered, if not present, controller looks for ingress.class annotation |
|
||||
| controller.ingressClassByName | bool | `false` | Process IngressClass per name (additionally as per spec.controller). |
|
||||
| controller.ingressClassResource.controllerValue | string | `"k8s.io/ingress-nginx"` | Controller-value of the controller that is processing this ingressClass |
|
||||
|
|
@ -399,6 +402,7 @@ Kubernetes: `>=1.19.0-0`
|
|||
| controller.service.ipFamilies | list | `["IPv4"]` | List of IP families (e.g. IPv4, IPv6) assigned to the service. This field is usually assigned automatically based on cluster configuration and the ipFamilyPolicy field. |
|
||||
| controller.service.ipFamilyPolicy | string | `"SingleStack"` | Represents the dual-stack-ness requested or required by this Service. Possible values are SingleStack, PreferDualStack or RequireDualStack. The ipFamilies and clusterIPs fields depend on the value of this field. |
|
||||
| controller.service.labels | object | `{}` | |
|
||||
| controller.service.loadBalancerIP | string | `""` | Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer |
|
||||
| controller.service.loadBalancerSourceRanges | list | `[]` | |
|
||||
| controller.service.nodePorts.http | string | `""` | |
|
||||
| controller.service.nodePorts.https | string | `""` | |
|
||||
|
|
@ -409,6 +413,7 @@ Kubernetes: `>=1.19.0-0`
|
|||
| controller.service.targetPorts.http | string | `"http"` | |
|
||||
| controller.service.targetPorts.https | string | `"https"` | |
|
||||
| controller.service.type | string | `"LoadBalancer"` | |
|
||||
| controller.shareProcessNamespace | bool | `false` | |
|
||||
| controller.sysctls | object | `{}` | See https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ for notes on enabling and using sysctls |
|
||||
| controller.tcp.annotations | object | `{}` | Annotations to be added to the tcp config configmap |
|
||||
| controller.tcp.configMapNamespace | string | `""` | Allows customization of the tcp-services-configmap; defaults to $(POD_NAMESPACE) |
|
||||
|
|
@ -437,7 +442,7 @@ Kubernetes: `>=1.19.0-0`
|
|||
| defaultBackend.image.image | string | `"defaultbackend-amd64"` | |
|
||||
| defaultBackend.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| defaultBackend.image.readOnlyRootFilesystem | bool | `true` | |
|
||||
| defaultBackend.image.registry | string | `"k8s.gcr.io"` | |
|
||||
| defaultBackend.image.registry | string | `"registry.k8s.io"` | |
|
||||
| defaultBackend.image.runAsNonRoot | bool | `true` | |
|
||||
| defaultBackend.image.runAsUser | int | `65534` | |
|
||||
| defaultBackend.image.tag | string | `"1.5"` | |
|
||||
|
|
@ -474,6 +479,7 @@ Kubernetes: `>=1.19.0-0`
|
|||
| dhParam | string | `nil` | A base64-encoded Diffie-Hellman parameter. This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` |
|
||||
| imagePullSecrets | list | `[]` | Optional array of imagePullSecrets containing private registry credentials |
|
||||
| podSecurityPolicy.enabled | bool | `false` | |
|
||||
| portNamePrefix | string | `""` | Prefix for TCP and UDP ports names in ingress controller service |
|
||||
| rbac.create | bool | `true` | |
|
||||
| rbac.scope | bool | `false` | |
|
||||
| revisionHistoryLimit | int | `10` | Rollback limit |
|
||||
|
|
@ -481,6 +487,6 @@ Kubernetes: `>=1.19.0-0`
|
|||
| serviceAccount.automountServiceAccountToken | bool | `true` | |
|
||||
| serviceAccount.create | bool | `true` | |
|
||||
| serviceAccount.name | string | `""` | |
|
||||
| tcp | object | `{}` | TCP service key:value pairs |
|
||||
| udp | object | `{}` | UDP service key:value pairs |
|
||||
| tcp | object | `{}` | TCP service key-value pairs |
|
||||
| udp | object | `{}` | UDP service key-value pairs |
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ controller:
|
|||
|
||||
### AWS L7 ELB with SSL Termination
|
||||
|
||||
Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/main/deploy/aws/l7/service-l7.yaml):
|
||||
Annotate the controller as shown in the [nginx-ingress l7 patch](https://github.com/kubernetes/ingress-nginx/blob/ab3a789caae65eec4ad6e3b46b19750b481b6bce/deploy/aws/l7/service-l7.yaml):
|
||||
|
||||
```yaml
|
||||
controller:
|
||||
|
|
@ -127,7 +127,7 @@ controller:
|
|||
|
||||
### AWS route53-mapper
|
||||
|
||||
To configure the LoadBalancer service with the [route53-mapper addon](https://github.com/kubernetes/kops/tree/master/addons/route53-mapper), add the `domainName` annotation and `dns` label:
|
||||
To configure the LoadBalancer service with the [route53-mapper addon](https://github.com/kubernetes/kops/blob/be63d4f1a7a46daaf1c4c482527328236850f111/addons/route53-mapper/README.md), add the `domainName` annotation and `dns` label:
|
||||
|
||||
```yaml
|
||||
controller:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
controller:
|
||||
kind: DaemonSet
|
||||
image:
|
||||
repository: ingress-controller/controller
|
||||
tag: 1.0.0-dev
|
||||
digest: null
|
||||
admissionWebhooks:
|
||||
enabled: false
|
||||
service:
|
||||
type: ClusterIP
|
||||
|
||||
tcp:
|
||||
9000: "default/test:8080"
|
||||
|
||||
udp:
|
||||
9001: "default/test:8080"
|
||||
|
||||
portNamePrefix: "port"
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
controller:
|
||||
image:
|
||||
repository: ingress-controller/controller
|
||||
tag: 1.0.0-dev
|
||||
digest: null
|
||||
admissionWebhooks:
|
||||
enabled: false
|
||||
service:
|
||||
type: ClusterIP
|
||||
|
||||
tcp:
|
||||
9000: "default/test:8080"
|
||||
|
||||
udp:
|
||||
9001: "default/test:8080"
|
||||
|
||||
portNamePrefix: "port"
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
controller:
|
||||
service:
|
||||
type: ClusterIP
|
||||
admissionWebhooks:
|
||||
enabled: true
|
||||
extraEnvs:
|
||||
- name: FOO
|
||||
value: foo
|
||||
- name: TEST
|
||||
value: test
|
||||
patch:
|
||||
enabled: true
|
||||
|
|
@ -43,11 +43,40 @@ capabilities:
|
|||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
{{- if .Values.controller.image.chroot }}
|
||||
- SYS_CHROOT
|
||||
{{- end }}
|
||||
runAsUser: {{ .Values.controller.image.runAsUser }}
|
||||
allowPrivilegeEscalation: {{ .Values.controller.image.allowPrivilegeEscalation }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get specific image
|
||||
*/}}
|
||||
{{- define "ingress-nginx.image" -}}
|
||||
{{- if .chroot -}}
|
||||
{{- printf "%s-chroot" .image -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s" .image -}}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Get specific image digest
|
||||
*/}}
|
||||
{{- define "ingress-nginx.imageDigest" -}}
|
||||
{{- if .chroot -}}
|
||||
{{- if .digestChroot -}}
|
||||
{{- printf "@%s" .digestChroot -}}
|
||||
{{- end }}
|
||||
{{- else -}}
|
||||
{{ if .digest -}}
|
||||
{{- printf "@%s" .digest -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified controller name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ spec:
|
|||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
{{- if .Values.controller.admissionWebhooks.extraEnvs }}
|
||||
{{- toYaml .Values.controller.admissionWebhooks.extraEnvs | nindent 12 }}
|
||||
{{- end }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
{{- if .Values.controller.admissionWebhooks.createSecretJob.resources }}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ spec:
|
|||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
{{- if .Values.controller.admissionWebhooks.extraEnvs }}
|
||||
{{- toYaml .Values.controller.admissionWebhooks.extraEnvs | nindent 12 }}
|
||||
{{- end }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
{{- if .Values.controller.admissionWebhooks.patchWebhookJob.resources }}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,13 @@ rules:
|
|||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
{{- if and .Values.controller.scope.enabled .Values.controller.scope.namespace }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
|
|
|
|||
|
|
@ -67,11 +67,14 @@ spec:
|
|||
- name: {{ $sysctl | quote }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.controller.shareProcessNamespace }}
|
||||
shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Values.controller.containerName }}
|
||||
{{- with .Values.controller.image }}
|
||||
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}"
|
||||
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}"
|
||||
{{- end }}
|
||||
imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
|
||||
{{- if .Values.controller.lifecycle }}
|
||||
|
|
@ -79,14 +82,7 @@ spec:
|
|||
{{- end }}
|
||||
args:
|
||||
{{- include "ingress-nginx.params" . | nindent 12 }}
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
runAsUser: {{ .Values.controller.image.runAsUser }}
|
||||
allowPrivilegeEscalation: {{ .Values.controller.image.allowPrivilegeEscalation }}
|
||||
securityContext: {{ include "controller.containerSecurityContext" . | nindent 12 }}
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
|
|
@ -128,7 +124,7 @@ spec:
|
|||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.tcp }}
|
||||
- name: {{ $key }}-tcp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
|
||||
containerPort: {{ $key }}
|
||||
protocol: TCP
|
||||
{{- if $.Values.controller.hostPort.enabled }}
|
||||
|
|
@ -136,7 +132,7 @@ spec:
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.udp }}
|
||||
- name: {{ $key }}-udp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp
|
||||
containerPort: {{ $key }}
|
||||
protocol: UDP
|
||||
{{- if $.Values.controller.hostPort.enabled }}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,14 @@ spec:
|
|||
- name: {{ $sysctl | quote }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.controller.shareProcessNamespace }}
|
||||
shareProcessNamespace: {{ .Values.controller.shareProcessNamespace }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Values.controller.containerName }}
|
||||
{{- with .Values.controller.image }}
|
||||
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}"
|
||||
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}"
|
||||
{{- end }}
|
||||
imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
|
||||
{{- if .Values.controller.lifecycle }}
|
||||
|
|
@ -125,7 +128,7 @@ spec:
|
|||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.tcp }}
|
||||
- name: {{ $key }}-tcp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
|
||||
containerPort: {{ $key }}
|
||||
protocol: TCP
|
||||
{{- if $.Values.controller.hostPort.enabled }}
|
||||
|
|
@ -133,7 +136,7 @@ spec:
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.udp }}
|
||||
- name: {{ $key }}-udp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp
|
||||
containerPort: {{ $key }}
|
||||
protocol: UDP
|
||||
{{- if $.Values.controller.hostPort.enabled }}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{{- if and .Values.controller.metrics.enabled .Values.controller.metrics.prometheusRule.enabled -}}
|
||||
{{- if and ( .Values.controller.metrics.enabled ) ( .Values.controller.metrics.prometheusRule.enabled ) ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) -}}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PrometheusRule
|
||||
metadata:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ metadata:
|
|||
spec:
|
||||
allowedCapabilities:
|
||||
- NET_BIND_SERVICE
|
||||
{{- if .Values.controller.image.chroot }}
|
||||
- SYS_CHROOT
|
||||
{{- end }}
|
||||
{{- if .Values.controller.sysctls }}
|
||||
allowedUnsafeSysctls:
|
||||
{{- range $sysctl, $value := .Values.controller.sysctls }}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,21 @@ rules:
|
|||
- configmaps
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- leases
|
||||
resourceNames:
|
||||
- {{ .Values.controller.electionID }}
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ spec:
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.tcp }}
|
||||
- name: {{ $key }}-tcp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
|
||||
port: {{ $key }}
|
||||
protocol: TCP
|
||||
targetPort: {{ $key }}-tcp
|
||||
targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
|
||||
{{- if $.Values.controller.service.nodePorts.tcp }}
|
||||
{{- if index $.Values.controller.service.nodePorts.tcp $key }}
|
||||
nodePort: {{ index $.Values.controller.service.nodePorts.tcp $key }}
|
||||
|
|
@ -63,10 +63,10 @@ spec:
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.udp }}
|
||||
- name: {{ $key }}-udp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp
|
||||
port: {{ $key }}
|
||||
protocol: UDP
|
||||
targetPort: {{ $key }}-udp
|
||||
targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp
|
||||
{{- if $.Values.controller.service.nodePorts.udp }}
|
||||
{{- if index $.Values.controller.service.nodePorts.udp $key }}
|
||||
nodePort: {{ index $.Values.controller.service.nodePorts.udp $key }}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ spec:
|
|||
{{- if .Values.controller.service.healthCheckNodePort }}
|
||||
healthCheckNodePort: {{ .Values.controller.service.healthCheckNodePort }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version -}}
|
||||
{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}}
|
||||
{{- if .Values.controller.service.ipFamilyPolicy }}
|
||||
ipFamilyPolicy: {{ .Values.controller.service.ipFamilyPolicy }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version -}}
|
||||
{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}}
|
||||
{{- if .Values.controller.service.ipFamilies }}
|
||||
ipFamilies: {{ toYaml .Values.controller.service.ipFamilies | nindent 4 }}
|
||||
{{- end }}
|
||||
|
|
@ -74,10 +74,10 @@ spec:
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.tcp }}
|
||||
- name: {{ $key }}-tcp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
|
||||
port: {{ $key }}
|
||||
protocol: TCP
|
||||
targetPort: {{ $key }}-tcp
|
||||
targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
|
||||
{{- if $.Values.controller.service.nodePorts.tcp }}
|
||||
{{- if index $.Values.controller.service.nodePorts.tcp $key }}
|
||||
nodePort: {{ index $.Values.controller.service.nodePorts.tcp $key }}
|
||||
|
|
@ -85,10 +85,10 @@ spec:
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.udp }}
|
||||
- name: {{ $key }}-udp
|
||||
- name: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp
|
||||
port: {{ $key }}
|
||||
protocol: UDP
|
||||
targetPort: {{ $key }}-udp
|
||||
targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-udp
|
||||
{{- if $.Values.controller.service.nodePorts.udp }}
|
||||
{{- if index $.Values.controller.service.nodePorts.udp $key }}
|
||||
nodePort: {{ index $.Values.controller.service.nodePorts.udp $key }}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,16 @@ commonLabels: {}
|
|||
controller:
|
||||
name: controller
|
||||
image:
|
||||
registry: k8s.gcr.io
|
||||
## Keep false as default for now!
|
||||
chroot: false
|
||||
registry: registry.k8s.io
|
||||
image: ingress-nginx/controller
|
||||
## for backwards compatibility consider setting the full image url via the repository value below
|
||||
## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail
|
||||
## repository:
|
||||
tag: "v1.1.2"
|
||||
digest: sha256:28b11ce69e57843de44e3db6413e98d09de0f6688e33d4bd384002a44f78405c
|
||||
tag: "v1.3.0"
|
||||
digest: sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5
|
||||
digestChroot: sha256:0fcb91216a22aae43b374fc2e6a03b8afe9e8c78cbf07a09d75636dc4ea3c191
|
||||
pullPolicy: IfNotPresent
|
||||
# www-data -> uid 101
|
||||
runAsUser: 101
|
||||
|
|
@ -272,7 +275,7 @@ controller:
|
|||
##
|
||||
topologySpreadConstraints: []
|
||||
# - maxSkew: 1
|
||||
# topologyKey: failure-domain.beta.kubernetes.io/zone
|
||||
# topologyKey: topology.kubernetes.io/zone
|
||||
# whenUnsatisfiable: DoNotSchedule
|
||||
# labelSelector:
|
||||
# matchLabels:
|
||||
|
|
@ -457,7 +460,8 @@ controller:
|
|||
##
|
||||
externalIPs: []
|
||||
|
||||
# loadBalancerIP: ""
|
||||
# -- Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
|
||||
loadBalancerIP: ""
|
||||
loadBalancerSourceRanges: []
|
||||
|
||||
enableHttp: true
|
||||
|
|
@ -529,6 +533,10 @@ controller:
|
|||
## Ref: https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer
|
||||
# externalTrafficPolicy: ""
|
||||
|
||||
# shareProcessNamespace enables process namespace sharing within the pod.
|
||||
# This can be used for example to signal log rotation using `kill -USR1` from a sidecar.
|
||||
shareProcessNamespace: false
|
||||
|
||||
# -- Additional containers to be added to the controller pod.
|
||||
# See https://github.com/lemonldap-ng-controller/lemonldap-ng-controller as example.
|
||||
extraContainers: []
|
||||
|
|
@ -572,7 +580,7 @@ controller:
|
|||
extraModules: []
|
||||
## Modules, which are mounted into the core nginx image
|
||||
# - name: opentelemetry
|
||||
# image: busybox
|
||||
# image: registry.k8s.io/ingress-nginx/opentelemetry:v20220415-controller-v1.2.0-beta.0-2-g81c2afd97@sha256:ce61e2cf0b347dffebb2dcbf57c33891d2217c1bad9c0959c878e5be671ef941
|
||||
#
|
||||
# The image must contain a `/usr/local/bin/init_module.sh` executable, which
|
||||
# will be executed as initContainers, to move its config files within the
|
||||
|
|
@ -586,6 +594,15 @@ controller:
|
|||
## These annotations will be added to the ValidatingWebhookConfiguration and
|
||||
## the Jobs Spec of the admission webhooks.
|
||||
enabled: true
|
||||
# -- Additional environment variables to set
|
||||
extraEnvs: []
|
||||
# extraEnvs:
|
||||
# - name: FOO
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# key: FOO
|
||||
# name: secret-resource
|
||||
# -- Admission Webhook failure policy to use
|
||||
failurePolicy: Fail
|
||||
# timeoutSeconds: 10
|
||||
port: 8443
|
||||
|
|
@ -623,7 +640,7 @@ controller:
|
|||
patch:
|
||||
enabled: true
|
||||
image:
|
||||
registry: k8s.gcr.io
|
||||
registry: registry.k8s.io
|
||||
image: ingress-nginx/kube-webhook-certgen
|
||||
## for backwards compatibility consider setting the full image url via the repository value below
|
||||
## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail
|
||||
|
|
@ -750,7 +767,7 @@ defaultBackend:
|
|||
|
||||
name: defaultbackend
|
||||
image:
|
||||
registry: k8s.gcr.io
|
||||
registry: registry.k8s.io
|
||||
image: defaultbackend-amd64
|
||||
## for backwards compatibility consider setting the full image url via the repository value below
|
||||
## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail
|
||||
|
|
@ -901,18 +918,22 @@ serviceAccount:
|
|||
imagePullSecrets: []
|
||||
# - name: secretName
|
||||
|
||||
# -- TCP service key:value pairs
|
||||
# -- TCP service key-value pairs
|
||||
## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md
|
||||
##
|
||||
tcp: {}
|
||||
# 8080: "default/example-tcp-svc:9000"
|
||||
|
||||
# -- UDP service key:value pairs
|
||||
# -- UDP service key-value pairs
|
||||
## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md
|
||||
##
|
||||
udp: {}
|
||||
# 53: "kube-system/kube-dns:53"
|
||||
|
||||
# -- Prefix for TCP and UDP ports names in ingress controller service
|
||||
## Some cloud providers, like Yandex Cloud may have a requirements for a port name regex to support cloud load balancer integration
|
||||
portNamePrefix: ""
|
||||
|
||||
# -- (string) A base64-encoded Diffie-Hellman parameter.
|
||||
# This can be generated with: `openssl dhparam 4096 2> /dev/null | base64`
|
||||
## Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param
|
||||
|
|
|
|||
25
tracker/.husky/pre-commit
Executable file
25
tracker/.husky/pre-commit
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
if git diff --cached --name-only | grep --quiet '^tracker/tracker/'
|
||||
then
|
||||
echo "tracker"
|
||||
pwd
|
||||
cd tracker/tracker
|
||||
|
||||
npm run lint-front
|
||||
|
||||
cd ../../
|
||||
fi
|
||||
|
||||
if git diff --cached --name-only | grep --quiet '^tracker/tracker-assist/'
|
||||
then
|
||||
echo "tracker-assist"
|
||||
cd tracker/tracker-assist
|
||||
|
||||
npm run lint-front
|
||||
|
||||
cd ../../
|
||||
fi
|
||||
|
||||
exit 0
|
||||
8
tracker/tracker-assist/.eslintignore
Normal file
8
tracker/tracker-assist/.eslintignore
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
node_modules
|
||||
npm-debug.log
|
||||
lib
|
||||
cjs
|
||||
build
|
||||
.cache
|
||||
.eslintrc.cjs
|
||||
src/common/messages.ts
|
||||
49
tracker/tracker-assist/.eslintrc.cjs
Normal file
49
tracker/tracker-assist/.eslintrc.cjs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* eslint-disable */
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'prettier'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
'no-empty': [
|
||||
'error',
|
||||
{
|
||||
allowEmptyCatch: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/unbound-method': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'warn',
|
||||
'@typescript-eslint/prefer-readonly': 'warn',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/restrict-plus-operands': 'warn',
|
||||
'@typescript-eslint/no-unsafe-return': 'warn',
|
||||
'no-useless-escape': 'warn',
|
||||
'no-control-regex': 'warn',
|
||||
'@typescript-eslint/restrict-template-expressions': 'warn',
|
||||
'@typescript-eslint/no-useless-constructor': 'warn',
|
||||
'@typescript-eslint/no-this-alias': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'warn',
|
||||
'@typescript-eslint/no-unsafe-argument': 'warn',
|
||||
'no-unused-expressions': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'warn',
|
||||
'@typescript-eslint/no-useless-constructor': 'warn',
|
||||
'semi': ["error", "never"],
|
||||
'quotes': ["error", "single"],
|
||||
'comma-dangle': ["error", "always"]
|
||||
},
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue