change(api): assist stats api moved to ee (#1598)
This commit is contained in:
parent
bd2bcd378b
commit
325d893db5
11 changed files with 149 additions and 140 deletions
|
|
@ -3,7 +3,6 @@ from apscheduler.triggers.interval import IntervalTrigger
|
|||
|
||||
from chalicelib.core import telemetry
|
||||
from chalicelib.core import weekly_report, jobs, health
|
||||
from chalicelib.core import assist_stats
|
||||
|
||||
|
||||
async def run_scheduled_jobs() -> None:
|
||||
|
|
@ -26,10 +25,6 @@ async def weekly_health_cron() -> None:
|
|||
health.weekly_cron()
|
||||
|
||||
|
||||
async def assist_events_aggregates_cron() -> None:
|
||||
assist_stats.insert_aggregated_data()
|
||||
|
||||
|
||||
cron_jobs = [
|
||||
{"func": telemetry_cron, "trigger": CronTrigger(day_of_week="*"),
|
||||
"misfire_grace_time": 60 * 60, "max_instances": 1},
|
||||
|
|
@ -40,7 +35,5 @@ cron_jobs = [
|
|||
{"func": health_cron, "trigger": IntervalTrigger(hours=0, minutes=30, start_date="2023-04-01 0:0:0", jitter=300),
|
||||
"misfire_grace_time": 60 * 60, "max_instances": 1},
|
||||
{"func": weekly_health_cron, "trigger": CronTrigger(day_of_week="sun", hour=5),
|
||||
"misfire_grace_time": 60 * 60, "max_instances": 1},
|
||||
{"func": assist_events_aggregates_cron,
|
||||
"trigger": IntervalTrigger(hours=1, start_date="2023-04-01 0:0:0", jitter=10), }
|
||||
"misfire_grace_time": 60 * 60, "max_instances": 1}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from chalicelib.core import log_tool_rollbar, sourcemaps, events, sessions_assig
|
|||
log_tool_stackdriver, reset_password, log_tool_cloudwatch, log_tool_sentry, log_tool_sumologic, log_tools, sessions, \
|
||||
log_tool_newrelic, announcements, log_tool_bugsnag, weekly_report, integration_jira_cloud, integration_github, \
|
||||
assist, mobile, tenants, boarding, notifications, webhook, users, \
|
||||
custom_metrics, saved_search, integrations_global, assist_stats
|
||||
custom_metrics, saved_search, integrations_global
|
||||
from chalicelib.core.collaboration_msteams import MSTeams
|
||||
from chalicelib.core.collaboration_slack import Slack
|
||||
from or_dependencies import OR_context, OR_role
|
||||
|
|
@ -860,59 +860,3 @@ async def check_recording_status(project_id: int):
|
|||
def health_check():
|
||||
return {}
|
||||
|
||||
|
||||
@public_app.get('/{project_id}/assist-stats/avg', tags=["assist-stats"])
|
||||
def get_assist_stats_avg(
|
||||
project_id: int,
|
||||
startTimestamp: int = None,
|
||||
endTimestamp: int = None,
|
||||
userId: str = None
|
||||
):
|
||||
return assist_stats.get_averages(
|
||||
project_id=project_id,
|
||||
start_timestamp=startTimestamp,
|
||||
end_timestamp=endTimestamp,
|
||||
user_id=userId)
|
||||
|
||||
|
||||
@public_app.get(
|
||||
'/{project_id}/assist-stats/top-members',
|
||||
tags=["assist-stats"],
|
||||
response_model=schemas.AssistStatsTopMembersResponse
|
||||
)
|
||||
def get_assist_stats_top_members(
|
||||
project_id: int,
|
||||
startTimestamp: int = None,
|
||||
endTimestamp: int = None,
|
||||
sort: Optional[str] = Query(default="sessionsAssisted",
|
||||
description="Sort options: " + ", ".join(assist_stats.event_type_mapping)),
|
||||
order: str = "desc",
|
||||
userId: int = None,
|
||||
page: int = 0,
|
||||
limit: int = 5
|
||||
):
|
||||
return assist_stats.get_top_members(
|
||||
project_id=project_id,
|
||||
start_timestamp=startTimestamp,
|
||||
end_timestamp=endTimestamp,
|
||||
sort_by=sort,
|
||||
sort_order=order,
|
||||
user_id=userId,
|
||||
page=page,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
|
||||
@public_app.post(
|
||||
'/{project_id}/assist-stats/sessions',
|
||||
tags=["assist-stats"],
|
||||
response_model=schemas.AssistStatsSessionsResponse
|
||||
)
|
||||
def get_assist_stats_sessions(
|
||||
project_id: int,
|
||||
data: schemas.AssistStatsSessionsRequest = Body(...),
|
||||
):
|
||||
return assist_stats.get_sessions(
|
||||
project_id=project_id,
|
||||
data=data
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1581,75 +1581,3 @@ class ModuleStatus(BaseModel):
|
|||
"offline-recordings", "alerts"] = Field(..., description="Possible values: notes, bugs, live")
|
||||
status: bool = Field(...)
|
||||
|
||||
|
||||
class AssistStatsAverage(BaseModel):
|
||||
key: str = Field(...)
|
||||
avg: float = Field(...)
|
||||
chartData: List[dict] = Field(...)
|
||||
|
||||
|
||||
class AssistStatsMember(BaseModel):
|
||||
name: str
|
||||
count: int
|
||||
assist_duration: Optional[int] = Field(default=0)
|
||||
call_duration: Optional[int] = Field(default=0)
|
||||
control_duration: Optional[int] = Field(default=0)
|
||||
assist_count: Optional[int] = Field(default=0)
|
||||
|
||||
|
||||
class AssistStatsSessionAgent(BaseModel):
|
||||
name: str
|
||||
id: int
|
||||
|
||||
|
||||
class AssistStatsTopMembersResponse(BaseModel):
|
||||
total: int
|
||||
list: List[AssistStatsMember]
|
||||
|
||||
|
||||
class AssistStatsSessionRecording(BaseModel):
|
||||
recordId: int = Field(...)
|
||||
name: str = Field(...)
|
||||
duration: int = Field(...)
|
||||
|
||||
|
||||
class AssistStatsSession(BaseModel):
|
||||
sessionId: str = Field(...)
|
||||
timestamp: int = Field(...)
|
||||
teamMembers: List[AssistStatsSessionAgent] = Field(...)
|
||||
assistDuration: Optional[int] = Field(default=0)
|
||||
callDuration: Optional[int] = Field(default=0)
|
||||
controlDuration: Optional[int] = Field(default=0)
|
||||
# recordings: list[AssistStatsSessionRecording] = Field(default=[])
|
||||
|
||||
|
||||
assist_sort_options = ["timestamp", "assist_duration", "call_duration", "control_duration"]
|
||||
|
||||
|
||||
class AssistStatsSessionsRequest(BaseModel):
|
||||
startTimestamp: int = Field(...)
|
||||
endTimestamp: int = Field(...)
|
||||
limit: Optional[int] = Field(default=10)
|
||||
page: Optional[int] = Field(default=1)
|
||||
sort: Optional[str] = Field(default="timestamp",
|
||||
enum=assist_sort_options)
|
||||
order: Optional[str] = Field(default="desc", choices=["desc", "asc"])
|
||||
userId: Optional[int] = Field(default=None)
|
||||
|
||||
@field_validator("sort")
|
||||
def validate_sort(cls, v):
|
||||
if v not in assist_sort_options:
|
||||
raise ValueError(f"Invalid sort option. Allowed options: {', '.join(assist_sort_options)}")
|
||||
return v
|
||||
|
||||
@field_validator("order")
|
||||
def validate_order(cls, v):
|
||||
if v not in ["desc", "asc"]:
|
||||
raise ValueError("Invalid order option. Must be 'desc' or 'asc'.")
|
||||
return v
|
||||
|
||||
|
||||
class AssistStatsSessionsResponse(BaseModel):
|
||||
total: int = Field(...)
|
||||
page: int = Field(...)
|
||||
list: List[AssistStatsSession] = Field(default=[])
|
||||
|
|
|
|||
1
ee/api/.gitignore
vendored
1
ee/api/.gitignore
vendored
|
|
@ -251,7 +251,6 @@ Pipfile.lock
|
|||
/routers/subs/__init__.py
|
||||
/routers/__init__.py
|
||||
/chalicelib/core/assist.py
|
||||
/chalicelib/core/assist_stats.py
|
||||
/auth/__init__.py
|
||||
/auth/auth_apikey.py
|
||||
/build.sh
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ rm -rf ./crons/__init__.py
|
|||
rm -rf ./routers/subs/__init__.py
|
||||
rm -rf ./routers/__init__.py
|
||||
rm -rf ./chalicelib/core/assist.py
|
||||
rm -rf ./chalicelib/core/assist_stats.py
|
||||
rm -rf ./auth/__init__.py
|
||||
rm -rf ./auth/auth_apikey.py
|
||||
rm -rf ./build.sh
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
from apscheduler.triggers.interval import IntervalTrigger
|
||||
|
||||
from chalicelib.utils import events_queue
|
||||
from chalicelib.core import assist_stats
|
||||
|
||||
|
||||
async def pg_events_queue() -> None:
|
||||
events_queue.global_queue.force_flush()
|
||||
|
||||
|
||||
async def assist_events_aggregates_cron() -> None:
|
||||
assist_stats.insert_aggregated_data()
|
||||
|
||||
|
||||
ee_cron_jobs = [
|
||||
{"func": pg_events_queue, "trigger": IntervalTrigger(minutes=5), "misfire_grace_time": 20, "max_instances": 1},
|
||||
{"func": assist_events_aggregates_cron,
|
||||
"trigger": IntervalTrigger(hours=1, start_date="2023-04-01 0:0:0", jitter=10), }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from chalicelib.core import roles, traces, assist_records, sessions
|
||||
from chalicelib.core import unlock, signals
|
||||
from chalicelib.core import sessions_insights
|
||||
from chalicelib.core import sessions_insights, assist_stats
|
||||
from chalicelib.utils import assist_helper
|
||||
|
||||
unlock.check()
|
||||
|
|
@ -135,3 +135,60 @@ def send_interactions(projectId: int, data: schemas.SignalsSchema = Body(...),
|
|||
def sessions_search(projectId: int, data: schemas.GetInsightsSchema = Body(...),
|
||||
context: schemas.CurrentContext = Depends(OR_context)):
|
||||
return {'data': sessions_insights.fetch_selected(data=data, project_id=projectId)}
|
||||
|
||||
|
||||
@public_app.get('/{project_id}/assist-stats/avg', tags=["assist-stats"])
|
||||
def get_assist_stats_avg(
|
||||
project_id: int,
|
||||
startTimestamp: int = None,
|
||||
endTimestamp: int = None,
|
||||
userId: str = None
|
||||
):
|
||||
return assist_stats.get_averages(
|
||||
project_id=project_id,
|
||||
start_timestamp=startTimestamp,
|
||||
end_timestamp=endTimestamp,
|
||||
user_id=userId)
|
||||
|
||||
|
||||
@public_app.get(
|
||||
'/{project_id}/assist-stats/top-members',
|
||||
tags=["assist-stats"],
|
||||
response_model=schemas.AssistStatsTopMembersResponse
|
||||
)
|
||||
def get_assist_stats_top_members(
|
||||
project_id: int,
|
||||
startTimestamp: int = None,
|
||||
endTimestamp: int = None,
|
||||
sort: Optional[str] = Query(default="sessionsAssisted",
|
||||
description="Sort options: " + ", ".join(assist_stats.event_type_mapping)),
|
||||
order: str = "desc",
|
||||
userId: int = None,
|
||||
page: int = 0,
|
||||
limit: int = 5
|
||||
):
|
||||
return assist_stats.get_top_members(
|
||||
project_id=project_id,
|
||||
start_timestamp=startTimestamp,
|
||||
end_timestamp=endTimestamp,
|
||||
sort_by=sort,
|
||||
sort_order=order,
|
||||
user_id=userId,
|
||||
page=page,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
|
||||
@public_app.post(
|
||||
'/{project_id}/assist-stats/sessions',
|
||||
tags=["assist-stats"],
|
||||
response_model=schemas.AssistStatsSessionsResponse
|
||||
)
|
||||
def get_assist_stats_sessions(
|
||||
project_id: int,
|
||||
data: schemas.AssistStatsSessionsRequest = Body(...),
|
||||
):
|
||||
return assist_stats.get_sessions(
|
||||
project_id=project_id,
|
||||
data=data
|
||||
)
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
from .schemas import *
|
||||
from .schemas_ee import *
|
||||
from .assist_stats_schema import *
|
||||
from . import overrides as _overrides
|
||||
|
|
|
|||
78
ee/api/schemas/assist_stats_schema.py
Normal file
78
ee/api/schemas/assist_stats_schema.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
from typing import Optional, List
|
||||
|
||||
from pydantic import Field, field_validator
|
||||
|
||||
from .overrides import BaseModel, Enum, ORUnion
|
||||
|
||||
|
||||
class AssistStatsAverage(BaseModel):
|
||||
key: str = Field(...)
|
||||
avg: float = Field(...)
|
||||
chartData: List[dict] = Field(...)
|
||||
|
||||
|
||||
class AssistStatsMember(BaseModel):
|
||||
name: str
|
||||
count: int
|
||||
assist_duration: Optional[int] = Field(default=0)
|
||||
call_duration: Optional[int] = Field(default=0)
|
||||
control_duration: Optional[int] = Field(default=0)
|
||||
assist_count: Optional[int] = Field(default=0)
|
||||
|
||||
|
||||
class AssistStatsSessionAgent(BaseModel):
|
||||
name: str
|
||||
id: int
|
||||
|
||||
|
||||
class AssistStatsTopMembersResponse(BaseModel):
|
||||
total: int
|
||||
list: List[AssistStatsMember]
|
||||
|
||||
|
||||
class AssistStatsSessionRecording(BaseModel):
|
||||
recordId: int = Field(...)
|
||||
name: str = Field(...)
|
||||
duration: int = Field(...)
|
||||
|
||||
|
||||
class AssistStatsSession(BaseModel):
|
||||
sessionId: str = Field(...)
|
||||
timestamp: int = Field(...)
|
||||
teamMembers: List[AssistStatsSessionAgent] = Field(...)
|
||||
assistDuration: Optional[int] = Field(default=0)
|
||||
callDuration: Optional[int] = Field(default=0)
|
||||
controlDuration: Optional[int] = Field(default=0)
|
||||
# recordings: list[AssistStatsSessionRecording] = Field(default=[])
|
||||
|
||||
|
||||
assist_sort_options = ["timestamp", "assist_duration", "call_duration", "control_duration"]
|
||||
|
||||
|
||||
class AssistStatsSessionsRequest(BaseModel):
|
||||
startTimestamp: int = Field(...)
|
||||
endTimestamp: int = Field(...)
|
||||
limit: Optional[int] = Field(default=10)
|
||||
page: Optional[int] = Field(default=1)
|
||||
sort: Optional[str] = Field(default="timestamp",
|
||||
enum=assist_sort_options)
|
||||
order: Optional[str] = Field(default="desc", choices=["desc", "asc"])
|
||||
userId: Optional[int] = Field(default=None)
|
||||
|
||||
@field_validator("sort")
|
||||
def validate_sort(cls, v):
|
||||
if v not in assist_sort_options:
|
||||
raise ValueError(f"Invalid sort option. Allowed options: {', '.join(assist_sort_options)}")
|
||||
return v
|
||||
|
||||
@field_validator("order")
|
||||
def validate_order(cls, v):
|
||||
if v not in ["desc", "asc"]:
|
||||
raise ValueError("Invalid order option. Must be 'desc' or 'asc'.")
|
||||
return v
|
||||
|
||||
|
||||
class AssistStatsSessionsResponse(BaseModel):
|
||||
total: int = Field(...)
|
||||
page: int = Field(...)
|
||||
list: List[AssistStatsSession] = Field(default=[])
|
||||
|
|
@ -156,3 +156,6 @@ class CardInsights(schemas.CardInsights):
|
|||
|
||||
|
||||
CardSchema = ORUnion(Union[schemas.__cards_union_base, CardInsights], discriminator='metric_type')
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue