Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(metrics): remove usages of span metric models #76785

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from sentry.models.environment import Environment
from sentry.models.project import Project
from sentry.sentry_metrics.models import SpanAttributeExtractionRuleCondition
from sentry.sentry_metrics.querying.constants import COEFFICIENT_OPERATORS
from sentry.sentry_metrics.querying.data.mapping.base import (
Mapper,
Expand Down Expand Up @@ -426,12 +425,6 @@ def _extract_unit(self, timeseries: Timeseries) -> str | None:
if parsed_mri.entity == "c":
return None

if rule_id := parsed_mri.span_attribute_rule_id:
try:
return SpanAttributeExtractionRuleCondition.objects.get(id=rule_id).config.unit
except SpanAttributeExtractionRuleCondition.DoesNotExist:
return None

return parsed_mri.unit

return None
Expand Down
47 changes: 2 additions & 45 deletions src/sentry/snuba/metrics/naming_layer/mri.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,9 @@
from enum import Enum
from typing import cast

import sentry_sdk
from sentry_kafka_schemas.codecs import ValidationError

from sentry.exceptions import InvalidParams
from sentry.sentry_metrics.extraction_rules import SPAN_ATTRIBUTE_PREFIX
from sentry.sentry_metrics.models import SpanAttributeExtractionRuleCondition
from sentry.sentry_metrics.use_case_id_registry import UseCaseID
from sentry.snuba.dataset import EntityKey
from sentry.snuba.metrics.units import format_value_using_unit_and_op
Expand Down Expand Up @@ -210,15 +207,6 @@ class ParsedMRI:
def mri_string(self) -> str:
return f"{self.entity}:{self.namespace}/{self.name}@{self.unit}"

@property
def span_attribute_rule_id(self):
if self.name.startswith(SPAN_ATTRIBUTE_PREFIX):
try:
return int(self.name[len(SPAN_ATTRIBUTE_PREFIX) :])
except ValueError:
return None
return None


@dataclass
class ParsedMRIField:
Expand Down Expand Up @@ -264,24 +252,6 @@ def format_mri_field(field: str) -> str:
parsed = parse_mri_field(field)

if parsed:
if condition_id := parsed.mri.span_attribute_rule_id:
try:
condition = SpanAttributeExtractionRuleCondition.objects.get(id=condition_id)
config = condition.config
if condition.value:
filter_str = f' filtered by "{condition.value}"'
else:
filter_str = ""

return f"{parsed.op}({config.span_attribute}){filter_str}"
except SpanAttributeExtractionRuleCondition.DoesNotExist:
with sentry_sdk.new_scope() as scope:
scope.set_tag("field", field)
sentry_sdk.capture_message(
"Trying to format MRI field for non-existent span metric."
)
return field

return str(parsed)

else:
Expand All @@ -304,22 +274,9 @@ def format_mri_field_value(field: str, value: str) -> str:
if parsed_mri_field is None:
return value

if condition_id := parsed_mri_field.mri.span_attribute_rule_id:
try:
condition = SpanAttributeExtractionRuleCondition.objects.get(id=condition_id)
unit = cast(MetricUnit, condition.config.unit)
except SpanAttributeExtractionRuleCondition.DoesNotExist:
with sentry_sdk.new_scope() as scope:
scope.set_tag("field", field)
sentry_sdk.capture_message(
"Trying to format MRI field for non-existent span metric."
)
return value

else:
unit = cast(MetricUnit, parsed_mri_field.mri.unit)

unit = cast(MetricUnit, parsed_mri_field.mri.unit)
return format_value_using_unit_and_op(float(value), unit, parsed_mri_field.op)

except InvalidParams:
return value

Expand Down
8 changes: 0 additions & 8 deletions src/sentry/testutils/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@
)
from sentry.sentry_apps.services.app.serial import serialize_sentry_app_installation
from sentry.sentry_apps.services.hook import hook_service
from sentry.sentry_metrics.models import SpanAttributeExtractionRuleConfig
from sentry.signals import project_created
from sentry.silo.base import SiloMode
from sentry.snuba.dataset import Dataset
Expand Down Expand Up @@ -1219,13 +1218,6 @@ def create_sentry_app_installation_for_provider(
sentry_app_installation=installation,
)

@staticmethod
@assume_test_silo_mode(SiloMode.REGION)
def create_span_attribute_extraction_config(
dictionary: dict[str, Any], user_id: int, project: Project
) -> SpanAttributeExtractionRuleConfig:
return SpanAttributeExtractionRuleConfig.from_dict(dictionary, user_id, project)

@staticmethod
@assume_test_silo_mode(SiloMode.CONTROL)
def create_stacktrace_link_schema():
Expand Down
3 changes: 0 additions & 3 deletions src/sentry/testutils/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,6 @@ def create_sentry_app_installation(self, *args, **kwargs):
def create_sentry_app_installation_for_provider(self, *args, **kwargs):
return Factories.create_sentry_app_installation_for_provider(*args, **kwargs)

def create_span_attribute_extraction_config(self, *args, **kwargs):
return Factories.create_span_attribute_extraction_config(*args, **kwargs)

def create_stacktrace_link_schema(self, *args, **kwargs):
return Factories.create_stacktrace_link_schema(*args, **kwargs)

Expand Down
135 changes: 0 additions & 135 deletions tests/sentry/sentry_metrics/querying/data/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from sentry.snuba.metrics.naming_layer import TransactionMRI
from sentry.testutils.cases import BaseMetricsTestCase, TestCase
from sentry.testutils.helpers.datetime import freeze_time
from sentry.testutils.pytest.fixtures import django_db_all

pytestmark = pytest.mark.sentry_metrics

Expand Down Expand Up @@ -1411,140 +1410,6 @@ def test_query_with_basic_formula_and_coercible_units(self):
assert meta[0][1]["unit"] == "nanosecond"
assert meta[0][1]["scaling_factor"] is None

@django_db_all(reset_sequences=True)
def test_span_metrics_with_coercible_units(self):

configs = [
{
"spanAttribute": "my_duration_nano",
"aggregates": ["count", "p50", "p75", "p95", "p99"],
"unit": "nanosecond",
"tags": [],
"conditions": [
{"value": ""},
],
},
{
"spanAttribute": "my_duration_micro",
"aggregates": ["count", "p50", "p75", "p95", "p99"],
"unit": "microsecond",
"tags": [],
"conditions": [
{"value": ""},
],
},
]
objects = []
for config in configs:
o = self.create_span_attribute_extraction_config(
dictionary=config, user_id=self.user.id, project=self.project
)
objects.append(o)

mri_1 = f"d:custom/span_attribute_{objects[0].conditions.all().get().id}@none"
mri_2 = f"d:custom/span_attribute_{objects[1].conditions.all().get().id}@none"
for mri, value in ((mri_1, 20), (mri_1, 10), (mri_2, 15), (mri_2, 5)):
self.store_metric(
self.project.organization.id,
self.project.id,
mri,
{},
self.ts(self.now()),
value,
)

for formula, expected_result, expected_unit_family in (
# (($query_2 * 1000) + 10000.0)
("($query_2 + 10)", 30000.0, UnitFamily.DURATION.value),
# (($query_2 * 1000) + (10 * 2) * 1000)
("($query_2 + (10 * 2))", 40000.0, UnitFamily.DURATION.value),
# (10000.0 + ($query_2 * 1000))
("(10 + $query_2)", 30000.0, UnitFamily.DURATION.value),
# (($query_2 + 1000) + (10000.0 + 20000.0))
("($query_2 + (10 + 20))", 50000.0, UnitFamily.DURATION.value),
# ((10000.0 + 20000.0) + ($query_2 + 1000))
("((10 + 20) + $query_2)", 50000.0, UnitFamily.DURATION.value),
# ($query_2 * 1000 + 10000.0) + ($query_2 * 1000)
("($query_2 + 10) + $query_2", 50000.0, UnitFamily.DURATION.value),
# ($query_2 * 1000 + 10000.0) + $query_1
("($query_2 + 10) + $query_1", 30015.0, UnitFamily.DURATION.value),
# ($query_1 + 10) + ($query_2 * 1000)
("($query_1 + 10) + $query_2", 20025.0, UnitFamily.DURATION.value),
):
query_1 = self.mql("avg", mri_1)
query_2 = self.mql("sum", mri_2)

results = self.run_query(
mql_queries=[
MQLQuery(formula, query_1=MQLQuery(query_1), query_2=MQLQuery(query_2))
],
start=self.now() - timedelta(minutes=30),
end=self.now() + timedelta(hours=1, minutes=30),
interval=3600,
organization=self.project.organization,
projects=[self.project],
environments=[],
referrer="metrics.data.api",
)
data = results["data"]
assert len(data) == 1
assert data[0][0]["by"] == {}
assert data[0][0]["series"] == [None, expected_result, None]
assert data[0][0]["totals"] == expected_result
meta = results["meta"]
assert len(meta) == 1
assert meta[0][1]["unit_family"] == expected_unit_family
assert meta[0][1]["unit"] == "nanosecond"
assert meta[0][1]["scaling_factor"] is None

@django_db_all(reset_sequences=True)
def test_span_metrics_count_span_duration(self):
config = {
"spanAttribute": "span.duration",
"aggregates": ["count"],
"unit": "millisecond",
"tags": [],
"conditions": [
{"value": ""},
],
}

o = self.create_span_attribute_extraction_config(
dictionary=config, user_id=self.user.id, project=self.project
)

mri_1 = f"c:custom/span_attribute_{o.conditions.all().get().id}@none"
for mri, value in ((mri_1, 1), (mri_1, 1)):
self.store_metric(
self.project.organization.id,
self.project.id,
mri,
{},
self.ts(self.now()),
value,
)

query_1 = self.mql("sum", mri_1)

results = self.run_query(
mql_queries=[MQLQuery(query_1)],
start=self.now() - timedelta(minutes=30),
end=self.now() + timedelta(hours=1, minutes=30),
interval=3600,
organization=self.project.organization,
projects=[self.project],
environments=[],
referrer="metrics.data.api",
)
data = results["data"]
assert len(data) == 1
assert data[0][0]["by"] == {}
assert data[0][0]["series"] == [None, 2.0, None]
meta = results["meta"]
assert len(meta) == 1
assert meta[0][1]["unit"] is None
assert meta[0][1]["scaling_factor"] is None

def test_query_with_basic_formula_and_non_coercible_units(self):
mri_1 = "d:custom/page_load@nanosecond"
mri_2 = "d:custom/page_size@byte"
Expand Down
86 changes: 0 additions & 86 deletions tests/snuba/metrics/naming_layer/test_mri.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,89 +27,3 @@ def test_format_mri_field_value(self):
assert format_mri_field_value("sum(d:spans/exclusive_time@millisecond)", "1000") == "1 s"
assert format_mri_field_value("invalid_mri_field", "100") == "100"
assert format_mri_field_value(cast(str, None), "100") == "100"

def test_span_metric_mri_field(self):
config = {
"spanAttribute": "browser.name",
"aggregates": ["count_unique"],
"unit": "none",
"tags": [],
"conditions": [
{"value": "browser.name:Chrome or browser.name:Firefox"},
],
}
project = self.create_project(organization=self.organization, name="my new project")
config_object = self.create_span_attribute_extraction_config(
dictionary=config, user_id=self.user.id, project=project
)
condition_id = config_object.conditions.get().id
assert (
format_mri_field(f"count_unique(c:custom/span_attribute_{condition_id}@none)")
== 'count_unique(browser.name) filtered by "browser.name:Chrome or browser.name:Firefox"'
)

def test_span_metric_mri_field_empty_condition(self):
config = {
"spanAttribute": "browser.name",
"aggregates": ["count_unique"],
"unit": "none",
"tags": [],
"conditions": [
{"value": ""},
],
}
project = self.create_project(organization=self.organization, name="my new project")
config_object = self.create_span_attribute_extraction_config(
dictionary=config, user_id=self.user.id, project=project
)
condition_id = config_object.conditions.get().id
assert (
format_mri_field(f"count_unique(c:custom/span_attribute_{condition_id}@none)")
== "count_unique(browser.name)"
)

def test_span_metric_mri_field_value(self):
config = {
"spanAttribute": "my_duration",
"aggregates": ["avg", "min", "max", "sum"],
"unit": "millisecond",
"tags": [],
"conditions": [
{"value": "browser.name:Chrome or browser.name:Firefox"},
],
}
project = self.create_project(organization=self.organization, name="my new project")
config_object = self.create_span_attribute_extraction_config(
dictionary=config, user_id=self.user.id, project=project
)
condition_id = config_object.conditions.get().id
assert (
format_mri_field_value(f"avg(c:custom/span_attribute_{condition_id}@none)", "1000")
== "1 s"
)

def test_span_metric_does_not_exist(self):
config = {
"spanAttribute": "my_duration",
"aggregates": ["avg", "min", "max", "sum"],
"unit": "millisecond",
"tags": [],
"conditions": [
{"value": "browser.name:Chrome or browser.name:Firefox"},
],
}
project = self.create_project(organization=self.organization, name="my new project")
self.create_span_attribute_extraction_config(
dictionary=config, user_id=self.user.id, project=project
)
non_existent_id = 65537

assert (
format_mri_field_value(f"avg(c:custom/span_attribute_{non_existent_id}@none)", "1000")
== "1000"
)

assert (
format_mri_field(f"avg(c:custom/span_attribute_{non_existent_id}@none)")
== f"avg(c:custom/span_attribute_{non_existent_id}@none)"
)
Loading