diff --git a/api/chalicelib/core/custom_metrics.py b/api/chalicelib/core/custom_metrics.py index f26fdb6a9..0e9061a11 100644 --- a/api/chalicelib/core/custom_metrics.py +++ b/api/chalicelib/core/custom_metrics.py @@ -110,6 +110,25 @@ def get_sessions(project_id, user_id, metric_id, data: schemas.CustomMetricSessi return results +def get_funnel_issues(project_id, user_id, metric_id, data: schemas.CustomMetricSessionsPayloadSchema): + metric = get(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False) + if metric is None: + return None + metric: schemas.CreateCustomMetricsSchema = __merge_metric_with_data(metric=metric, data=data) + if metric is None: + return None + results = [] + for s in metric.series: + s.filter.startDate = data.startTimestamp + s.filter.endDate = data.endTimestamp + s.filter.limit = data.limit + s.filter.page = data.page + results.append({"seriesId": s.series_id, "seriesName": s.name, + **funnels.get_issues_on_the_fly_widget(project_id=project_id, data=s.filter)}) + + return results + + def try_sessions(project_id, user_id, data: schemas.CustomMetricSessionsPayloadSchema): results = [] if data.series is None: diff --git a/api/chalicelib/core/funnels.py b/api/chalicelib/core/funnels.py index e0eb99dc3..22774fb16 100644 --- a/api/chalicelib/core/funnels.py +++ b/api/chalicelib/core/funnels.py @@ -296,6 +296,19 @@ def get_issues_on_the_fly(funnel_id, user_id, project_id, data: schemas.FunnelSe last_stage=len(data.events)))} +# def get_issues_on_the_fly_widget(project_id, data: schemas.FunnelSearchPayloadSchema): +def get_issues_on_the_fly_widget(project_id, data: schemas.CustomMetricSeriesFilterSchema): + data.events = filter_stages(data.events) + data.events = __fix_stages(data.events) + if len(data.events) < 0: + return {"issues": []} + + return { + "issues": helper.dict_to_camel_case( + significance.get_issues_list(filter_d=data.dict(), project_id=project_id, first_stage=1, + last_stage=len(data.events)))} + + def get(funnel_id, project_id, user_id, flatten=True, fix_stages=True): with pg_client.PostgresClient() as cur: cur.execute( diff --git a/api/routers/subs/metrics.py b/api/routers/subs/metrics.py index a33b75d0b..57e3b28f7 100644 --- a/api/routers/subs/metrics.py +++ b/api/routers/subs/metrics.py @@ -1,7 +1,7 @@ from fastapi import Body, Depends import schemas -from chalicelib.core import dashboards, custom_metrics +from chalicelib.core import dashboards, custom_metrics, funnels from or_dependencies import OR_context from routers.base import get_routers @@ -107,13 +107,24 @@ def try_custom_metric(projectId: int, data: schemas.TryCustomMetricsPayloadSchem @app.post('/{projectId}/metrics/try/sessions', tags=["dashboard"]) @app.post('/{projectId}/custom_metrics/try/sessions', tags=["customMetrics"]) -def try_custom_metric_sessions(projectId: int, - data: schemas.CustomMetricSessionsPayloadSchema = Body(...), +def try_custom_metric_sessions(projectId: int, data: schemas.CustomMetricSessionsPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): data = custom_metrics.try_sessions(project_id=projectId, user_id=context.user_id, data=data) return {"data": data} +@app.post('/{projectId}/metrics/try/issues', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/try/issues', tags=["customMetrics"]) +def try_custom_metric_funnel_issues(projectId: int, data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + if len(data.series) == 0: + return {"data": []} + data.series[0].filter.startDate = data.startTimestamp + data.series[0].filter.endDate = data.endTimestamp + data = funnels.get_issues_on_the_fly_widget(project_id=projectId, data=data.series[0].filter) + return {"data": data} + + @app.post('/{projectId}/metrics', tags=["dashboard"]) @app.put('/{projectId}/metrics', tags=["dashboard"]) @app.post('/{projectId}/custom_metrics', tags=["customMetrics"]) @@ -149,6 +160,17 @@ def get_custom_metric_sessions(projectId: int, metric_id: int, return {"data": data} +@app.post('/{projectId}/metrics/{metric_id}/issues', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/issues', tags=["customMetrics"]) +def get_custom_metric__funnel_issues(projectId: int, metric_id: int, + data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.get_funnel_issues(project_id=projectId, user_id=context.user_id, metric_id=metric_id, data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + @app.post('/{projectId}/metrics/{metric_id}/chart', tags=["dashboard"]) @app.post('/{projectId}/custom_metrics/{metric_id}/chart', tags=["customMetrics"]) def get_custom_metric_chart(projectId: int, metric_id: int, data: schemas.CustomMetricChartPayloadSchema = Body(...), diff --git a/api/schemas.py b/api/schemas.py index 0902fb269..c1979811e 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -872,6 +872,14 @@ class TryCustomMetricsPayloadSchema(CustomMetricChartPayloadSchema): class CreateCustomMetricsSchema(TryCustomMetricsPayloadSchema): series: List[CustomMetricCreateSeriesSchema] = Field(..., min_items=1) + @root_validator(pre=True) + def transform_series(cls, values): + if values.get("series") is not None and len(values["series"]) > 1 and values.get( + "metric_type") == MetricType.funnel.value: + values["series"] = [values["series"][0]] + + return values + class CustomMetricUpdateSeriesSchema(CustomMetricCreateSeriesSchema): series_id: Optional[int] = Field(None) diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 01153848f..1fb572626 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -37,6 +37,7 @@ ALTER TABLE dashboards ALTER COLUMN user_id DROP NOT NULL; COMMIT; +ALTER TYPE metric_type ADD VALUE IF NOT EXISTS 'funnel'; INSERT INTO metrics (name, category, default_config, is_predefined, is_template, is_public, predefined_key, metric_type, view_type) diff --git a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql index 5bf02f4e1..d044f1636 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -201,11 +201,11 @@ $$ CREATE TABLE IF NOT EXISTS basic_authentication ( user_id integer NOT NULL REFERENCES users (user_id) ON DELETE CASCADE, - password text DEFAULT NULL, - invitation_token text NULL DEFAULT NULL, - invited_at timestamp without time zone NULL DEFAULT NULL, - change_pwd_token text NULL DEFAULT NULL, - change_pwd_expire_at timestamp without time zone NULL DEFAULT NULL, + password text DEFAULT NULL, + invitation_token text NULL DEFAULT NULL, + invited_at timestamp without time zone NULL DEFAULT NULL, + change_pwd_token text NULL DEFAULT NULL, + change_pwd_expire_at timestamp without time zone NULL DEFAULT NULL, changed_at timestamp, UNIQUE (user_id) ); @@ -726,7 +726,7 @@ $$ CREATE INDEX IF NOT EXISTS traces_created_at_idx ON traces (created_at); CREATE INDEX IF NOT EXISTS traces_action_idx ON traces (action); - CREATE TYPE metric_type AS ENUM ('timeseries','table', 'predefined'); + CREATE TYPE metric_type AS ENUM ('timeseries','table', 'predefined','funnel'); CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart','areaChart','barChart','stackedBarChart','stackedBarLineChart','overview','map'); CREATE TABLE IF NOT EXISTS metrics ( diff --git a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 3f5552640..b0275a3a8 100644 --- a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql +++ b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -25,6 +25,8 @@ ALTER TABLE dashboards COMMIT; +ALTER TYPE metric_type ADD VALUE IF NOT EXISTS 'predefined'; + INSERT INTO metrics (name, category, default_config, is_predefined, is_template, is_public, predefined_key, metric_type, view_type) VALUES ('Captured sessions', 'web vitals', '{ diff --git a/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/scripts/helm/db/init_dbs/postgresql/init_schema.sql index 6cbd17dc8..f870b7824 100644 --- a/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -150,11 +150,11 @@ $$ CREATE TABLE basic_authentication ( user_id integer NOT NULL REFERENCES users (user_id) ON DELETE CASCADE, - password text DEFAULT NULL, - invitation_token text NULL DEFAULT NULL, - invited_at timestamp without time zone NULL DEFAULT NULL, - change_pwd_token text NULL DEFAULT NULL, - change_pwd_expire_at timestamp without time zone NULL DEFAULT NULL, + password text DEFAULT NULL, + invitation_token text NULL DEFAULT NULL, + invited_at timestamp without time zone NULL DEFAULT NULL, + change_pwd_token text NULL DEFAULT NULL, + change_pwd_expire_at timestamp without time zone NULL DEFAULT NULL, changed_at timestamp, UNIQUE (user_id) ); @@ -877,7 +877,7 @@ $$ CREATE INDEX jobs_start_at_idx ON jobs (start_at); CREATE INDEX jobs_project_id_idx ON jobs (project_id); - CREATE TYPE metric_type AS ENUM ('timeseries','table', 'predefined'); + CREATE TYPE metric_type AS ENUM ('timeseries','table', 'predefined', 'funnel'); CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart','areaChart','barChart','stackedBarChart','stackedBarLineChart','overview','map'); CREATE TABLE metrics (