From 68cdb08395781d50d42a99838bd32dfbd20694b5 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 2 Mar 2022 20:42:44 +0100 Subject: [PATCH 1/2] feat(DB): graphql_details support feat(api): graphql_details support --- api/chalicelib/core/sessions.py | 37 +++++++++++++++++-- api/schemas.py | 21 +++++++++-- .../db/init_dbs/postgresql/1.5.X/1.5.X.sql | 25 ++++++++----- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/api/chalicelib/core/sessions.py b/api/chalicelib/core/sessions.py index 0bf3c9366..dc6bf85c7 100644 --- a/api/chalicelib/core/sessions.py +++ b/api/chalicelib/core/sessions.py @@ -592,14 +592,15 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr is_any = _isAny_opreator(event.operator) if not isinstance(event.value, list): event.value = [event.value] - if not is_any and len(event.value) == 0 and event_type not in [schemas.EventType.request_details] \ + if not is_any and len(event.value) == 0 and event_type not in [schemas.EventType.request_details, + schemas.EventType.graphql_details] \ or event_type in [schemas.PerformanceEventType.location_dom_complete, schemas.PerformanceEventType.location_largest_contentful_paint_time, schemas.PerformanceEventType.location_ttfb, schemas.PerformanceEventType.location_avg_cpu_load, schemas.PerformanceEventType.location_avg_memory_usage ] and (event.source is None or len(event.source) == 0) \ - or event_type in [schemas.EventType.request_details] and ( + or event_type in [schemas.EventType.request_details, schemas.EventType.graphql_details] and ( event.filters is None or len(event.filters) == 0): continue op = __get_sql_operator(event.operator) @@ -848,7 +849,37 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr event_where.append( _multiple_conditions(f"main.response_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) else: - print(f"undefined fetch filter: {f.type}") + print(f"undefined FETCH filter: {f.type}") + elif event_type == schemas.EventType.graphql_details: + event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " + for j, f in enumerate(event.filters): + is_any = _isAny_opreator(f.operator) + if is_any or len(f.value) == 0: + continue + op = __get_sql_operator(f.operator) + e_k_f = e_k + f"_graphql{j}" + full_args = {**full_args, **_multiple_values(f.value, value_key=e_k_f)} + if f.type == schemas.GraphqlFilterType._name: + event_where.append( + _multiple_conditions(f"main.{events.event_type.GRAPHQL.column} {op} %({e_k_f})s", f.value, + value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._status_code: + event_where.append( + _multiple_conditions(f"main.status_code {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._method: + event_where.append( + _multiple_conditions(f"main.method {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._duration: + event_where.append( + _multiple_conditions(f"main.duration {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._request_body: + event_where.append( + _multiple_conditions(f"main.request_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._response_body: + event_where.append( + _multiple_conditions(f"main.response_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + else: + print(f"undefined GRAPHQL filter: {f.type}") else: continue if event_index == 0 or or_events: diff --git a/api/schemas.py b/api/schemas.py index 6c94e2efa..2acdab45f 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -386,6 +386,7 @@ class EventType(str, Enum): request = "REQUEST" request_details = "FETCH" graphql = "GRAPHQL" + graphql_details = "GRAPHQL_DETAILS" state_action = "STATEACTION" error = "ERROR" click_ios = "CLICK_IOS" @@ -512,8 +513,17 @@ class FetchFilterType(str, Enum): _response_body = "FETCH_RESPONSE_BODY" -class RequestFilterSchema(BaseModel): - type: FetchFilterType = Field(...) +class GraphqlFilterType(str, Enum): + _name = "GRAPHQL_NAME" + _status_code = "GRAPHQL_STATUS_CODE" + _method = "GRAPHQL_METHOD" + _duration = "GRAPHQL_DURATION" + _request_body = "GRAPHQL_REQUEST_BODY" + _response_body = "GRAPHQL_RESPONSE_BODY" + + +class RequestGraphqlFilterSchema(BaseModel): + type: Union[FetchFilterType, GraphqlFilterType] = Field(...) value: List[Union[int, str]] = Field(...) operator: Union[SearchEventOperator, MathOperator] = Field(...) @@ -525,7 +535,7 @@ class _SessionSearchEventRaw(__MixedSearchFilter): operator: SearchEventOperator = Field(...) source: Optional[List[Union[ErrorSource, int, str]]] = Field(None) sourceOperator: Optional[MathOperator] = Field(None) - filters: Optional[List[RequestFilterSchema]] = Field(None) + filters: Optional[List[RequestGraphqlFilterSchema]] = Field(None) @root_validator def event_validator(cls, values): @@ -552,7 +562,10 @@ class _SessionSearchEventRaw(__MixedSearchFilter): values["source"] = [ErrorSource.js_exception] elif values.get("type") == EventType.request_details: assert isinstance(values.get("filters"), List) and len(values.get("filters", [])) > 0, \ - f"filters should be defined for {EventType.request_details}" + f"filters should be defined for {EventType.request_details.value}" + elif values.get("type") == EventType.graphql_details: + assert isinstance(values.get("filters"), List) and len(values.get("filters", [])) > 0, \ + f"filters should be defined for {EventType.graphql_details.value}" return values diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.X/1.5.X.sql b/scripts/helm/db/init_dbs/postgresql/1.5.X/1.5.X.sql index b774c4bea..ce3eafd2a 100644 --- a/scripts/helm/db/init_dbs/postgresql/1.5.X/1.5.X.sql +++ b/scripts/helm/db/init_dbs/postgresql/1.5.X/1.5.X.sql @@ -7,17 +7,17 @@ $$ SELECT 'v1.5.X' $$ LANGUAGE sql IMMUTABLE; -CREATE TYPE events_common.http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); +CREATE TYPE http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); ALTER TABLE events_common.requests - ADD COLUMN IF NOT EXISTS schema text NULL, - ADD COLUMN IF NOT EXISTS host text NULL, - ADD COLUMN IF NOT EXISTS base_path text NULL, - ADD COLUMN IF NOT EXISTS query_string text NULL, - ADD COLUMN IF NOT EXISTS request_body text NULL, - ADD COLUMN IF NOT EXISTS response_body text NULL, - ADD COLUMN IF NOT EXISTS status_code text NULL, - ADD COLUMN IF NOT EXISTS method events_common.http_method NULL; + ADD COLUMN IF NOT EXISTS schema text NULL, + ADD COLUMN IF NOT EXISTS host text NULL, + ADD COLUMN IF NOT EXISTS base_path text NULL, + ADD COLUMN IF NOT EXISTS query_string text NULL, + ADD COLUMN IF NOT EXISTS request_body text NULL, + ADD COLUMN IF NOT EXISTS response_body text NULL, + ADD COLUMN IF NOT EXISTS status_code text NULL, + ADD COLUMN IF NOT EXISTS method http_method NULL; -- Split requests-URL: Takes too long to use -- UPDATE events_common.requests @@ -50,4 +50,11 @@ ALTER TABLE events_common.requests -- END; +ALTER TABLE events.graphql + ADD COLUMN IF NOT EXISTS request_body text NULL, + ADD COLUMN IF NOT EXISTS response_body text NULL, + ADD COLUMN IF NOT EXISTS status_code text NULL, + ADD COLUMN IF NOT EXISTS method http_method NULL, + ADD COLUMN IF NOT EXISTS duration integer NULL; + COMMIT; \ No newline at end of file From b3da76a1bb10cc3b4db6b6fe20d400799f59197a Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Thu, 3 Mar 2022 12:56:46 +0100 Subject: [PATCH 2/2] feat(api): custom_metrics fixed ignore metricValue for timeseries --- api/schemas.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/schemas.py b/api/schemas.py index 2acdab45f..1b0ab9ac5 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -794,10 +794,10 @@ class CreateCustomMetricsSchema(CustomMetricChartPayloadSchema): # This is used to handle wrong values sent by the UI @root_validator(pre=True) def remove_metric_value(cls, values): - if values.get("metric_type") == MetricType.timeseries \ - or values.get("metric_type") == MetricType.table \ - and values.get("metric_of") != TableMetricOfType.issues: - values["metric_of"] = [] + if values.get("metricType") == MetricType.timeseries \ + or values.get("metricType") == MetricType.table \ + and values.get("metricOf") != TableMetricOfType.issues: + values["metricValue"] = [] return values @root_validator