Skip to content

Commit baf464d

Browse files
[getsentry/action-github-commit] Auto commit
1 parent ffa47f8 commit baf464d

1 file changed

Lines changed: 208 additions & 13 deletions

File tree

tests/web/rpc/v1/test_endpoint_trace_item_table/test_endpoint_trace_item_table.py

Lines changed: 208 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3480,9 +3480,7 @@ def test_uniq_aggregation_with_default_value_double(self) -> None:
34803480
Column(
34813481
conditional_aggregation=AttributeConditionalAggregation(
34823482
aggregate=Function.FUNCTION_UNIQ,
3483-
key=AttributeKey(
3484-
type=AttributeKey.TYPE_STRING, name="user"
3485-
),
3483+
key=AttributeKey(type=AttributeKey.TYPE_STRING, name="user"),
34863484
label="count_unique(user)",
34873485
extrapolation_mode=ExtrapolationMode.EXTRAPOLATION_MODE_NONE,
34883486
default_value_double=0.0,
@@ -3527,9 +3525,7 @@ def test_uniq_formula_with_default_value_double(self) -> None:
35273525
left=Column(
35283526
conditional_aggregation=AttributeConditionalAggregation(
35293527
aggregate=Function.FUNCTION_UNIQ,
3530-
key=AttributeKey(
3531-
type=AttributeKey.TYPE_STRING, name="user"
3532-
),
3528+
key=AttributeKey(type=AttributeKey.TYPE_STRING, name="user"),
35333529
label="count_unique_a",
35343530
extrapolation_mode=ExtrapolationMode.EXTRAPOLATION_MODE_NONE,
35353531
default_value_double=0.0,
@@ -3539,9 +3535,7 @@ def test_uniq_formula_with_default_value_double(self) -> None:
35393535
right=Column(
35403536
conditional_aggregation=AttributeConditionalAggregation(
35413537
aggregate=Function.FUNCTION_UNIQ,
3542-
key=AttributeKey(
3543-
type=AttributeKey.TYPE_STRING, name="user"
3544-
),
3538+
key=AttributeKey(type=AttributeKey.TYPE_STRING, name="user"),
35453539
label="count_unique_b",
35463540
extrapolation_mode=ExtrapolationMode.EXTRAPOLATION_MODE_NONE,
35473541
default_value_double=0.0,
@@ -3744,6 +3738,18 @@ def _str_array(*values: str) -> AnyValue:
37443738
return AnyValue(array_value=ArrayValue(values=[AnyValue(string_value=v) for v in values]))
37453739

37463740

3741+
def _int_array(*values: int) -> AnyValue:
3742+
return AnyValue(array_value=ArrayValue(values=[AnyValue(int_value=v) for v in values]))
3743+
3744+
3745+
def _double_array(*values: float) -> AnyValue:
3746+
return AnyValue(array_value=ArrayValue(values=[AnyValue(double_value=v) for v in values]))
3747+
3748+
3749+
def _bool_array(*values: bool) -> AnyValue:
3750+
return AnyValue(array_value=ArrayValue(values=[AnyValue(bool_value=v) for v in values]))
3751+
3752+
37473753
class TestArrayWildcardSearch(BaseApiTest):
37483754
@pytest.mark.clickhouse_db
37493755
@pytest.mark.redis_db
@@ -3835,6 +3841,198 @@ def test_not_like_filter_on_array_attribute(self) -> None:
38353841
# Only the item with ["success", "cached"] should match (no "error" elements)
38363842
assert len(response.column_values[0].results) == 1
38373843

3844+
@pytest.mark.clickhouse_db
3845+
@pytest.mark.redis_db
3846+
def test_trace_item_table_array_op_equals_includes_string_ignore_case(self) -> None:
3847+
"""OP_EQUALS with ignore_case matches a string in a TYPE_ARRAY (element-wise)."""
3848+
span_ts = BASE_TIME - timedelta(minutes=1)
3849+
items_storage = get_storage(StorageKey("eap_items"))
3850+
write_raw_unprocessed_events(
3851+
items_storage, # type: ignore
3852+
[
3853+
gen_item_message(span_ts, attributes={"tags": _str_array("ERROR", "other")}),
3854+
gen_item_message(
3855+
span_ts, attributes={"tags": _str_array("success", "cached", "http-error")}
3856+
),
3857+
gen_item_message(span_ts, attributes={"tags": _str_array("Error", "timeout")}),
3858+
],
3859+
)
3860+
message = TraceItemTableRequest(
3861+
meta=RequestMeta(
3862+
project_ids=[1, 2, 3],
3863+
organization_id=1,
3864+
cogs_category="something",
3865+
referrer="something",
3866+
start_timestamp=START_TIMESTAMP,
3867+
end_timestamp=END_TIMESTAMP,
3868+
trace_item_type=TraceItemType.TRACE_ITEM_TYPE_SPAN,
3869+
),
3870+
filter=TraceItemFilter(
3871+
comparison_filter=ComparisonFilter(
3872+
key=AttributeKey(
3873+
type=AttributeKey.TYPE_ARRAY,
3874+
name="tags",
3875+
),
3876+
op=ComparisonFilter.OP_EQUALS,
3877+
value=AttributeValue(val_str="error"),
3878+
ignore_case=True,
3879+
)
3880+
),
3881+
columns=[
3882+
Column(key=AttributeKey(type=AttributeKey.TYPE_STRING, name="sentry.item_id")),
3883+
Column(key=AttributeKey(type=AttributeKey.TYPE_ARRAY, name="tags")),
3884+
],
3885+
)
3886+
response = EndpointTraceItemTable().execute(message)
3887+
assert len(response.column_values[0].results) == 2
3888+
by_name = {cv.attribute_name: cv for cv in response.column_values}
3889+
for row in by_name["tags"].results:
3890+
vals = [e.val_str for e in row.val_array.values if e.WhichOneof("value") == "val_str"]
3891+
assert "error" in [val.lower() for val in vals]
3892+
3893+
@pytest.mark.clickhouse_db
3894+
@pytest.mark.redis_db
3895+
def test_trace_item_table_array_op_equals_includes_int(self) -> None:
3896+
"""OP_EQUALS on TYPE_ARRAY with val_int=45 returns rows where some element is 45."""
3897+
span_ts = BASE_TIME - timedelta(minutes=1)
3898+
items_storage = get_storage(StorageKey("eap_items"))
3899+
write_raw_unprocessed_events(
3900+
items_storage, # type: ignore
3901+
[
3902+
gen_item_message(span_ts, attributes={"frame_linenos": _int_array(1, 45, 200)}),
3903+
gen_item_message(span_ts, attributes={"frame_linenos": _int_array(10, 20)}),
3904+
gen_item_message(span_ts, attributes={"frame_linenos": _int_array(45, 99)}),
3905+
],
3906+
)
3907+
message = TraceItemTableRequest(
3908+
meta=RequestMeta(
3909+
project_ids=[1, 2, 3],
3910+
organization_id=1,
3911+
cogs_category="something",
3912+
referrer="something",
3913+
start_timestamp=START_TIMESTAMP,
3914+
end_timestamp=END_TIMESTAMP,
3915+
trace_item_type=TraceItemType.TRACE_ITEM_TYPE_SPAN,
3916+
),
3917+
filter=TraceItemFilter(
3918+
comparison_filter=ComparisonFilter(
3919+
key=AttributeKey(
3920+
type=AttributeKey.TYPE_ARRAY,
3921+
name="frame_linenos",
3922+
),
3923+
op=ComparisonFilter.OP_EQUALS,
3924+
value=AttributeValue(val_int=45),
3925+
)
3926+
),
3927+
columns=[
3928+
Column(key=AttributeKey(type=AttributeKey.TYPE_STRING, name="sentry.item_id")),
3929+
Column(key=AttributeKey(type=AttributeKey.TYPE_ARRAY, name="frame_linenos")),
3930+
],
3931+
)
3932+
response = EndpointTraceItemTable().execute(message)
3933+
assert len(response.column_values[0].results) == 2
3934+
by_name = {cv.attribute_name: cv for cv in response.column_values}
3935+
assert by_name["frame_linenos"].results[0].WhichOneof("value") == "val_array"
3936+
for row in by_name["frame_linenos"].results:
3937+
int_vals = [
3938+
e.val_int for e in row.val_array.values if e.WhichOneof("value") == "val_int"
3939+
]
3940+
assert 45 in int_vals
3941+
3942+
@pytest.mark.clickhouse_db
3943+
@pytest.mark.redis_db
3944+
@pytest.mark.parametrize(
3945+
"attr_name,match_attrs,no_match_attrs,filter_value,check_row",
3946+
[
3947+
pytest.param(
3948+
"arr_eq_flt",
3949+
{"arr_eq_flt": _double_array(0.0, 1.5, 2.0)},
3950+
{"arr_eq_flt": _double_array(0.1, 0.2)},
3951+
AttributeValue(val_float=1.5),
3952+
lambda row: any(
3953+
isclose(e.val_double, 1.5)
3954+
for e in row.val_array.values
3955+
if e.WhichOneof("value") == "val_double"
3956+
)
3957+
or any(
3958+
isclose(e.val_float, 1.5)
3959+
for e in row.val_array.values
3960+
if e.WhichOneof("value") == "val_float"
3961+
),
3962+
id="val_float",
3963+
),
3964+
pytest.param(
3965+
"arr_eq_dbl",
3966+
{"arr_eq_dbl": _double_array(9.9, 1.0)},
3967+
{"arr_eq_dbl": _double_array(0.0, 0.0)},
3968+
AttributeValue(val_double=9.9),
3969+
lambda row: any(
3970+
e.WhichOneof("value") == "val_double" and e.val_double == 9.9
3971+
for e in row.val_array.values
3972+
),
3973+
id="val_double",
3974+
),
3975+
pytest.param(
3976+
"arr_eq_bool",
3977+
{"arr_eq_bool": _bool_array(False, True)},
3978+
{"arr_eq_bool": _bool_array(False, False)},
3979+
AttributeValue(val_bool=True),
3980+
lambda row: any(
3981+
e.WhichOneof("value") == "val_bool" and e.val_bool is True
3982+
for e in row.val_array.values
3983+
),
3984+
id="val_bool",
3985+
),
3986+
],
3987+
)
3988+
def test_trace_item_table_array_op_equals_all_scalar_rhs_types(
3989+
self,
3990+
attr_name: str,
3991+
match_attrs: dict[str, AnyValue],
3992+
no_match_attrs: dict[str, AnyValue],
3993+
filter_value: AttributeValue,
3994+
check_row: Any,
3995+
) -> None:
3996+
"""OP_EQUALS on TYPE_ARRAY: each scalar AttributeValue type matches a stored element"""
3997+
span_ts = BASE_TIME - timedelta(minutes=1)
3998+
items_storage = get_storage(StorageKey("eap_items"))
3999+
write_raw_unprocessed_events(
4000+
items_storage, # type: ignore
4001+
[
4002+
gen_item_message(span_ts, attributes=match_attrs),
4003+
gen_item_message(span_ts, attributes=no_match_attrs),
4004+
],
4005+
)
4006+
message = TraceItemTableRequest(
4007+
meta=RequestMeta(
4008+
project_ids=[1, 2, 3],
4009+
organization_id=1,
4010+
cogs_category="something",
4011+
referrer="something",
4012+
start_timestamp=START_TIMESTAMP,
4013+
end_timestamp=END_TIMESTAMP,
4014+
trace_item_type=TraceItemType.TRACE_ITEM_TYPE_SPAN,
4015+
),
4016+
filter=TraceItemFilter(
4017+
comparison_filter=ComparisonFilter(
4018+
key=AttributeKey(
4019+
type=AttributeKey.TYPE_ARRAY,
4020+
name=attr_name,
4021+
),
4022+
op=ComparisonFilter.OP_EQUALS,
4023+
value=filter_value,
4024+
)
4025+
),
4026+
columns=[
4027+
Column(key=AttributeKey(type=AttributeKey.TYPE_STRING, name="sentry.item_id")),
4028+
Column(key=AttributeKey(type=AttributeKey.TYPE_ARRAY, name=attr_name)),
4029+
],
4030+
)
4031+
response = EndpointTraceItemTable().execute(message)
4032+
by_name = {cv.attribute_name: cv for cv in response.column_values}
4033+
assert len(by_name[attr_name].results) == 1
4034+
assert check_row(by_name[attr_name].results[0])
4035+
38384036

38394037
class TestTraceItemTableArrayColumn(BaseApiTest):
38404038
@pytest.mark.clickhouse_db
@@ -3881,10 +4079,7 @@ def test_select_array_column_returns_val_array(self) -> None:
38814079
"beta",
38824080
]
38834081
assert by_name["cols"].results[0].WhichOneof("value") == "val_array"
3884-
assert [e.val_str for e in by_name["cols"].results[0].val_array.values] == [
3885-
"1",
3886-
"3",
3887-
]
4082+
assert [e.val_int for e in by_name["cols"].results[0].val_array.values] == [1, 3]
38884083

38894084

38904085
class TestUtils:

0 commit comments

Comments
 (0)