|
@@ -7,8 +7,10 @@ from datetime import datetime, timedelta
|
|
|
import pytest
|
|
|
from snuba_sdk import (
|
|
|
AliasedExpression,
|
|
|
+ ArithmeticOperator,
|
|
|
Column,
|
|
|
Condition,
|
|
|
+ Formula,
|
|
|
Metric,
|
|
|
MetricsQuery,
|
|
|
MetricsScope,
|
|
@@ -50,7 +52,6 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
)
|
|
|
|
|
|
resolved_metrics_query, mappings = _resolve_metrics_query(metrics_query)
|
|
|
- assert resolved_metrics_query.query.metric.public_name == "transaction.duration"
|
|
|
expected_metric_id = indexer.resolve(
|
|
|
UseCaseID.TRANSACTIONS,
|
|
|
self.project.organization_id,
|
|
@@ -59,6 +60,37 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
assert resolved_metrics_query.query.metric.id == expected_metric_id
|
|
|
assert mappings[TransactionMRI.DURATION.value] == expected_metric_id
|
|
|
|
|
|
+ def test_resolve_formula_metrics_query(self):
|
|
|
+ self.store_performance_metric(
|
|
|
+ name=TransactionMRI.DURATION.value,
|
|
|
+ project_id=self.project.id,
|
|
|
+ tags={},
|
|
|
+ value=1,
|
|
|
+ )
|
|
|
+ metrics_query = MetricsQuery(
|
|
|
+ query=Formula(
|
|
|
+ ArithmeticOperator.PLUS,
|
|
|
+ [
|
|
|
+ Timeseries(Metric(mri=TransactionMRI.DURATION.value), aggregate="count"),
|
|
|
+ Timeseries(Metric(mri=TransactionMRI.DURATION.value), aggregate="count"),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ scope=MetricsScope(
|
|
|
+ org_ids=[self.project.organization_id],
|
|
|
+ project_ids=[self.project.id],
|
|
|
+ use_case_id=UseCaseID.TRANSACTIONS.value,
|
|
|
+ ),
|
|
|
+ )
|
|
|
+
|
|
|
+ resolved_metrics_query, mappings = _resolve_metrics_query(metrics_query)
|
|
|
+ expected_metric_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ TransactionMRI.DURATION.value,
|
|
|
+ )
|
|
|
+ assert resolved_metrics_query.query.parameters[0].metric.id == expected_metric_id
|
|
|
+ assert mappings[TransactionMRI.DURATION.value] == expected_metric_id
|
|
|
+
|
|
|
def test_resolve_metrics_query_with_groupby(self):
|
|
|
self.store_performance_metric(
|
|
|
name=TransactionMRI.DURATION.value,
|
|
@@ -68,7 +100,7 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
)
|
|
|
metrics_query = MetricsQuery(
|
|
|
query=Timeseries(
|
|
|
- Metric(mri=TransactionMRI.DURATION.value),
|
|
|
+ Metric(public_name="transaction.duration"),
|
|
|
aggregate="count",
|
|
|
groupby=[Column("transaction")],
|
|
|
),
|
|
@@ -91,6 +123,7 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
|
|
|
resolved_metrics_query, mappings = _resolve_metrics_query(metrics_query)
|
|
|
assert resolved_metrics_query.query.metric.public_name == "transaction.duration"
|
|
|
+ assert resolved_metrics_query.query.metric.mri == TransactionMRI.DURATION.value
|
|
|
assert resolved_metrics_query.query.metric.id == expected_metric_id
|
|
|
assert resolved_metrics_query.query.groupby == [
|
|
|
AliasedExpression(Column(f"tags_raw[{expected_transaction_id}]"), "transaction")
|
|
@@ -98,6 +131,73 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
assert mappings[TransactionMRI.DURATION.value] == expected_metric_id
|
|
|
assert mappings["transaction"] == expected_transaction_id
|
|
|
|
|
|
+ def test_resolve_formula_metrics_query_with_groupby(self):
|
|
|
+ self.store_performance_metric(
|
|
|
+ name=TransactionMRI.DURATION.value,
|
|
|
+ project_id=self.project.id,
|
|
|
+ tags={"transaction": "/checkout", "status_code": "200"},
|
|
|
+ value=1,
|
|
|
+ )
|
|
|
+ metrics_query = MetricsQuery(
|
|
|
+ query=Formula(
|
|
|
+ ArithmeticOperator.PLUS,
|
|
|
+ [
|
|
|
+ Timeseries(
|
|
|
+ Metric(public_name="transaction.duration"),
|
|
|
+ aggregate="count",
|
|
|
+ groupby=[Column("transaction")],
|
|
|
+ ),
|
|
|
+ Timeseries(
|
|
|
+ Metric(mri=TransactionMRI.DURATION.value),
|
|
|
+ aggregate="count",
|
|
|
+ groupby=[Column("transaction")],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ groupby=[Column("status_code")],
|
|
|
+ ),
|
|
|
+ scope=MetricsScope(
|
|
|
+ org_ids=[self.project.organization_id],
|
|
|
+ project_ids=[self.project.id],
|
|
|
+ use_case_id=UseCaseID.TRANSACTIONS.value,
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ expected_metric_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ TransactionMRI.DURATION.value,
|
|
|
+ )
|
|
|
+ expected_transaction_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ "transaction",
|
|
|
+ )
|
|
|
+ expected_status_code_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ "status_code",
|
|
|
+ )
|
|
|
+
|
|
|
+ resolved_metrics_query, mappings = _resolve_metrics_query(metrics_query)
|
|
|
+ assert (
|
|
|
+ resolved_metrics_query.query.parameters[0].metric.public_name == "transaction.duration"
|
|
|
+ )
|
|
|
+ assert (
|
|
|
+ resolved_metrics_query.query.parameters[0].metric.mri == TransactionMRI.DURATION.value
|
|
|
+ )
|
|
|
+ assert resolved_metrics_query.query.parameters[0].metric.id == expected_metric_id
|
|
|
+ assert resolved_metrics_query.query.parameters[0].groupby == [
|
|
|
+ AliasedExpression(Column(f"tags_raw[{expected_transaction_id}]"), "transaction")
|
|
|
+ ]
|
|
|
+ assert resolved_metrics_query.query.parameters[1].groupby == [
|
|
|
+ AliasedExpression(Column(f"tags_raw[{expected_transaction_id}]"), "transaction")
|
|
|
+ ]
|
|
|
+ assert resolved_metrics_query.query.groupby == [
|
|
|
+ AliasedExpression(Column(f"tags_raw[{expected_status_code_id}]"), "status_code")
|
|
|
+ ]
|
|
|
+ assert mappings[TransactionMRI.DURATION.value] == expected_metric_id
|
|
|
+ assert mappings["transaction"] == expected_transaction_id
|
|
|
+ assert mappings["status_code"] == expected_status_code_id
|
|
|
+
|
|
|
def test_resolve_metrics_query_with_filters(self):
|
|
|
self.store_performance_metric(
|
|
|
name=TransactionMRI.DURATION.value,
|
|
@@ -143,7 +243,6 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
)
|
|
|
|
|
|
resolved_metrics_query, mappings = _resolve_metrics_query(metrics_query)
|
|
|
- assert resolved_metrics_query.query.metric.public_name == "transaction.duration"
|
|
|
assert resolved_metrics_query.query.metric.id == expected_metric_id
|
|
|
assert resolved_metrics_query.query.filters == [
|
|
|
Condition(Column(f"tags_raw[{expected_transaction_id}]"), Op.EQ, "/checkout"),
|
|
@@ -158,6 +257,103 @@ class MetricsQueryLayerTest(BaseMetricsLayerTestCase, TestCase):
|
|
|
assert mappings["transaction"] == expected_transaction_id
|
|
|
assert mappings["device"] == expected_device_id
|
|
|
|
|
|
+ def test_resolve_formula_metrics_query_with_filters(self):
|
|
|
+ self.store_performance_metric(
|
|
|
+ name=TransactionMRI.DURATION.value,
|
|
|
+ project_id=self.project.id,
|
|
|
+ tags={"transaction": "/checkout", "device": "BlackBerry", "status_code": "200"},
|
|
|
+ value=1,
|
|
|
+ )
|
|
|
+ metrics_query = MetricsQuery(
|
|
|
+ query=Formula(
|
|
|
+ ArithmeticOperator.PLUS,
|
|
|
+ [
|
|
|
+ Timeseries(
|
|
|
+ Metric(mri=TransactionMRI.DURATION.value),
|
|
|
+ aggregate="count",
|
|
|
+ filters=[
|
|
|
+ Condition(Column("transaction"), Op.EQ, "/checkout"),
|
|
|
+ Or(
|
|
|
+ [
|
|
|
+ Condition(Column("device"), Op.EQ, "BlackBerry"),
|
|
|
+ Condition(Column("device"), Op.EQ, "Nokia"),
|
|
|
+ ]
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ groupby=[Column("transaction")],
|
|
|
+ ),
|
|
|
+ Timeseries(
|
|
|
+ Metric(mri=TransactionMRI.DURATION.value),
|
|
|
+ aggregate="count",
|
|
|
+ filters=[
|
|
|
+ Condition(Column("transaction"), Op.EQ, "/cart"),
|
|
|
+ Or(
|
|
|
+ [
|
|
|
+ Condition(Column("device"), Op.EQ, "Android"),
|
|
|
+ Condition(Column("device"), Op.EQ, "Palm"),
|
|
|
+ ]
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ groupby=[Column("transaction")],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ filters=[Condition(Column("status_code"), Op.EQ, "200")],
|
|
|
+ ),
|
|
|
+ scope=MetricsScope(
|
|
|
+ org_ids=[self.project.organization_id],
|
|
|
+ project_ids=[self.project.id],
|
|
|
+ use_case_id=UseCaseID.TRANSACTIONS.value,
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ expected_metric_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ TransactionMRI.DURATION.value,
|
|
|
+ )
|
|
|
+ expected_transaction_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ "transaction",
|
|
|
+ )
|
|
|
+ expected_device_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ "device",
|
|
|
+ )
|
|
|
+ expected_status_code_id = indexer.resolve(
|
|
|
+ UseCaseID.TRANSACTIONS,
|
|
|
+ self.project.organization_id,
|
|
|
+ "status_code",
|
|
|
+ )
|
|
|
+
|
|
|
+ resolved_metrics_query, mappings = _resolve_metrics_query(metrics_query)
|
|
|
+ assert resolved_metrics_query.query.parameters[0].metric.id == expected_metric_id
|
|
|
+ assert resolved_metrics_query.query.parameters[0].filters == [
|
|
|
+ Condition(Column(f"tags_raw[{expected_transaction_id}]"), Op.EQ, "/checkout"),
|
|
|
+ Or(
|
|
|
+ [
|
|
|
+ Condition(Column(f"tags_raw[{expected_device_id}]"), Op.EQ, "BlackBerry"),
|
|
|
+ Condition(Column(f"tags_raw[{expected_device_id}]"), Op.EQ, "Nokia"),
|
|
|
+ ]
|
|
|
+ ),
|
|
|
+ ]
|
|
|
+ assert resolved_metrics_query.query.parameters[1].filters == [
|
|
|
+ Condition(Column(f"tags_raw[{expected_transaction_id}]"), Op.EQ, "/cart"),
|
|
|
+ Or(
|
|
|
+ [
|
|
|
+ Condition(Column(f"tags_raw[{expected_device_id}]"), Op.EQ, "Android"),
|
|
|
+ Condition(Column(f"tags_raw[{expected_device_id}]"), Op.EQ, "Palm"),
|
|
|
+ ]
|
|
|
+ ),
|
|
|
+ ]
|
|
|
+ assert resolved_metrics_query.query.filters == [
|
|
|
+ Condition(Column(f"tags_raw[{expected_status_code_id}]"), Op.EQ, "200"),
|
|
|
+ ]
|
|
|
+ assert mappings[TransactionMRI.DURATION.value] == expected_metric_id
|
|
|
+ assert mappings["transaction"] == expected_transaction_id
|
|
|
+ assert mappings["device"] == expected_device_id
|
|
|
+ assert mappings["status_code"] == expected_status_code_id
|
|
|
+
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
"day_range, sec_offset, interval, expected",
|