def apdex(column: Column, satisfied: Literal) -> Expression: tolerated = multiply(satisfied, Literal(None, 4)) return div( plus( countIf( binary_condition(None, ConditionFunctions.LTE, column, satisfied)), div( countIf( binary_condition( None, BooleanFunctions.AND, binary_condition( None, ConditionFunctions.GT, column, satisfied, ), binary_condition( None, ConditionFunctions.LTE, column, tolerated, ), ), ), Literal(None, 2), ), ), count(), )
def process_functions(exp: Expression) -> Expression: if isinstance(exp, FunctionCall) and exp.function_name == "impact": assert len(exp.parameters) == 3 column = exp.parameters[0] satisfied = exp.parameters[1] user_column = exp.parameters[2] return plus( minus(Literal(None, 1), apdex(column, satisfied)), multiply( minus( Literal(None, 1), div( Literal(None, 1), FunctionCall( None, "sqrt", (FunctionCall(None, "uniq", user_column)), ), ), ), Literal(None, 3), ), ) return exp
def __group_time_function(self, column_name: str, granularity: int, alias: Optional[str]) -> FunctionCall: function_call = { 3600: FunctionCall( alias, "toStartOfHour", (Column(None, None, column_name), Literal(None, "Universal")), ), 60: FunctionCall( alias, "toStartOfMinute", (Column(None, None, column_name), Literal(None, "Universal")), ), 86400: FunctionCall( alias, "toDate", (Column(None, None, column_name), Literal(None, "Universal")), ), }.get(granularity) if not function_call: function_call = FunctionCall( alias, "toDateTime", ( multiply( FunctionCall( None, "intDiv", ( FunctionCall( None, "toUInt32", (Column(None, None, column_name), ), ), Literal(None, granularity), ), ), Literal(None, granularity), ), Literal(None, "Universal"), ), ) return function_call
def time_expr( self, column_name: str, granularity: int, alias: Optional[str] ) -> str: function_call = { 3600: FunctionCall( alias, "toStartOfHour", (Column(None, column_name, None),) ), 60: FunctionCall( alias, "toStartOfMinute", (Column(None, column_name, None),) ), 86400: FunctionCall(alias, "toDate", (Column(None, column_name, None),)), }.get(granularity) if not function_call: # "toDateTime(intDiv(toUInt32({column}), {granularity}) * {granularity})", function_call = FunctionCall( alias, "toDateTime", ( multiply( FunctionCall( None, "intDiv", ( FunctionCall( None, "toUInt32", (Column(None, column_name, None),), ), Literal(None, granularity), ), ), Literal(None, granularity), ), ), ) return function_call
id="granularity-86400", ), pytest.param( 1440, None, FunctionCall( "my_time", "toDateTime", ( multiply( FunctionCall( None, "intDiv", ( FunctionCall( None, "toUInt32", (Column(None, None, "finish_ts"),), ), Literal(None, 1440), ), ), Literal(None, 1440), ), Literal(None, "Universal"), ), ), None, "(toDateTime(multiply(intDiv(toUInt32(finish_ts), 1440), 1440), 'Universal') AS my_time)", "", id="granularity-1440", ), ]
def test_apdex_format_expressions() -> None: unprocessed = Query( QueryEntity(EntityKey.EVENTS, ColumnSet([])), selected_columns=[ SelectedExpression(name=None, expression=Column(None, None, "column2")), SelectedExpression( "perf", FunctionCall( "perf", "apdex", (Column(None, None, "column1"), Literal(None, 300)) ), ), ], ) expected = Query( QueryEntity(EntityKey.EVENTS, ColumnSet([])), selected_columns=[ SelectedExpression(name=None, expression=Column(None, None, "column2")), SelectedExpression( "perf", divide( plus( FunctionCall( None, "countIf", ( binary_condition( ConditionFunctions.LTE, Column(None, None, "column1"), Literal(None, 300), ), ), ), divide( FunctionCall( None, "countIf", ( binary_condition( BooleanFunctions.AND, binary_condition( ConditionFunctions.GT, Column(None, None, "column1"), Literal(None, 300), ), binary_condition( ConditionFunctions.LTE, Column(None, None, "column1"), multiply( Literal(None, 300), Literal(None, 4) ), ), ), ), ), Literal(None, 2), ), ), FunctionCall( None, "count", (), ), "perf", ), ), ], ) apdex_processor().process_query(unprocessed, HTTPQuerySettings()) assert expected.get_selected_columns() == unprocessed.get_selected_columns() ret = unprocessed.get_selected_columns()[1].expression.accept( ClickhouseExpressionFormatter() ) assert ret == ( "(divide(plus(countIf(lessOrEquals(column1, 300)), " "divide(countIf(greater(column1, 300) AND " "lessOrEquals(column1, multiply(300, 4))), 2)), count()) AS perf)" )
def test_impact_format_expressions() -> None: unprocessed = Query( {}, TableSource("events", ColumnSet([])), selected_columns=[ Column(None, "column2", None), FunctionCall( "perf", "impact", ( Column(None, "column1", None), Literal(None, 300), Column(None, "user", None), ), ), ], ) expected = Query( {}, TableSource("events", ColumnSet([])), selected_columns=[ Column(None, "column2", None), plus( minus( Literal(None, 1), div( plus( countIf( binary_condition( None, ConditionFunctions.LTE, Column(None, "column1", None), Literal(None, 300), ), ), div( countIf( binary_condition( None, BooleanFunctions.AND, binary_condition( None, ConditionFunctions.GT, Column(None, "column1", None), Literal(None, 300), ), binary_condition( None, ConditionFunctions.LTE, Column(None, "column1", None), multiply( Literal(None, 300), Literal(None, 4) ), ), ), ), Literal(None, 2), ), ), count(), ), ), multiply( minus( Literal(None, 1), div( Literal(None, 1), FunctionCall( None, "sqrt", ( FunctionCall( None, "uniq", Column( alias=None, column_name="user", table_name=None, ), ) ), ), ), ), Literal(None, 3), ), ), ], ) ImpactProcessor().process_query(unprocessed, HTTPRequestSettings()) assert ( expected.get_selected_columns_from_ast() == unprocessed.get_selected_columns_from_ast() ) ret = unprocessed.get_selected_columns_from_ast()[1].accept( ClickhouseExpressionFormatter() ) assert ret == ( "plus(minus(1, div(plus(countIf(lessOrEquals(column1, 300)), " "div(countIf(and(greater(column1, 300), lessOrEquals(column1, " "multiply(300, 4)))), 2)), count())), " "multiply(minus(1, div(1, sqrt(user, uniq(user)))), 3))" )
def test_apdex_format_expressions() -> None: unprocessed = Query( {}, TableSource("events", ColumnSet([])), selected_columns=[ Column(None, "column2", None), FunctionCall( "perf", "apdex", (Column(None, "column1", None), Literal(None, 300)) ), ], ) expected = Query( {}, TableSource("events", ColumnSet([])), selected_columns=[ Column(None, "column2", None), div( plus( FunctionCall( None, "countIf", ( binary_condition( None, ConditionFunctions.LTE, Column(None, "column1", None), Literal(None, 300), ), ), ), div( FunctionCall( None, "countIf", ( binary_condition( None, BooleanFunctions.AND, binary_condition( None, ConditionFunctions.GT, Column(None, "column1", None), Literal(None, 300), ), binary_condition( None, ConditionFunctions.LTE, Column(None, "column1", None), multiply(Literal(None, 300), Literal(None, 4)), ), ), ), ), Literal(None, 2), ), ), FunctionCall(None, "count", (),), ), ], ) ApdexProcessor().process_query(unprocessed, HTTPRequestSettings()) assert ( expected.get_selected_columns_from_ast() == unprocessed.get_selected_columns_from_ast() ) ret = unprocessed.get_selected_columns_from_ast()[1].accept( ClickhouseExpressionFormatter() ) assert ret == ( "div(plus(countIf(lessOrEquals(column1, 300)), " "div(countIf(and(greater(column1, 300), " "lessOrEquals(column1, multiply(300, 4)))), 2)), count())" )
FunctionCall("my_start", "toDate", (Column(None, "start_ts", None),)), "(toDate(start_ts) AS my_start)", ), ( 1440, FunctionCall( "my_start", "toDateTime", ( multiply( FunctionCall( None, "intDiv", ( FunctionCall( None, "toUInt32", (Column(None, "start_ts", None),), ), Literal(None, 1440), ), ), Literal(None, 1440), ), ), ), "(toDateTime(multiply(intDiv(toUInt32(start_ts), 1440), 1440)) AS my_start)", ), ] @pytest.mark.parametrize("granularity, ast_value, formatted_value", tests) def test_timeseries_column_format_expressions(