From 81a0d163c9dfe953da0482fad7234f331d3e677e Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Thu, 13 Mar 2025 16:12:04 -0700 Subject: [PATCH 1/5] feat(signal): return signal data given entity name --- src/dispatch/signal/models.py | 7 ++++ src/dispatch/signal/service.py | 77 +++++++++++++++++++++++++++++++++- src/dispatch/signal/views.py | 20 +++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/dispatch/signal/models.py b/src/dispatch/signal/models.py index f491d882d723..4ad305a72ef1 100644 --- a/src/dispatch/signal/models.py +++ b/src/dispatch/signal/models.py @@ -379,6 +379,13 @@ class AdditionalMetadata(DispatchBase): important: Optional[bool] +class SignalData(DispatchBase): + num_signals_alerted: Optional[int] + num_signals_snoozed: Optional[int] + num_snoozes_active: Optional[int] + num_snoozes_expired: Optional[int] + + class SignalInstanceBase(DispatchBase): project: Optional[ProjectRead] case: Optional[CaseReadMinimal] diff --git a/src/dispatch/signal/service.py b/src/dispatch/signal/service.py index 00e59ba1d5f9..a2623b5fde3c 100644 --- a/src/dispatch/signal/service.py +++ b/src/dispatch/signal/service.py @@ -7,10 +7,11 @@ from fastapi import HTTPException, status from pydantic.error_wrappers import ErrorWrapper, ValidationError -from sqlalchemy import asc, desc, or_ +from sqlalchemy import asc, desc, or_, func, and_, select, cast from sqlalchemy.orm import Session from sqlalchemy.orm.query import Query from sqlalchemy.sql.expression import true +from sqlalchemy.dialects.postgresql import JSONB from dispatch.auth.models import DispatchUser from dispatch.case.models import Case @@ -34,8 +35,10 @@ SignalNotIdentifiedException, ) from .models import ( + assoc_signal_instance_entities, Signal, SignalCreate, + SignalData, SignalEngagement, SignalEngagementCreate, SignalEngagementRead, @@ -965,3 +968,75 @@ def get_cases_for_signal_by_resolution_reason( .order_by(desc(Case.created_at)) .limit(limit) ) + + +def get_signal_data( + *, db_session: Session, entity_name: str, entity_type_id: int +) -> Optional[SignalData]: + """Gets a signal data for a given named entity and type.""" + entity_subquery = ( + db_session.query( + func.jsonb_build_array( + func.jsonb_build_object( + "or", + func.jsonb_build_array( + func.jsonb_build_object( + "model", "Entity", "field", "id", "op", "==", "value", Entity.id + ) + ), + ) + ) + ) + .filter(and_(Entity.value == entity_name, Entity.entity_type_id == entity_type_id)) + .as_scalar() + ) + + active_count = func.count().filter(SignalFilter.expiration > func.current_date()) + expired_count = func.count().filter(SignalFilter.expiration <= func.current_date()) + + query = db_session.query( + active_count.label("active_count"), expired_count.label("expired_count") + ).filter(cast(SignalFilter.expression, JSONB).op("@>")(entity_subquery)) + + snooze_result = db_session.execute(query).fetchone() + if snooze_result: + print( + f"Active Count: {snooze_result.active_count}, Expired Count: {snooze_result.expired_count}" + ) + + count_with_snooze = func.count().filter(SignalInstance.filter_action == "snooze") + count_without_snooze = func.count().filter( + (SignalInstance.filter_action != "snooze") | (SignalInstance.filter_action.is_(None)) + ) + + query = ( + select( + [ + count_with_snooze.label("count_with_snooze"), + count_without_snooze.label("count_without_snooze"), + ] + ) + .select_from( + assoc_signal_instance_entities.join( + Entity, assoc_signal_instance_entities.c.entity_id == Entity.id + ).join( + SignalInstance, + assoc_signal_instance_entities.c.signal_instance_id == SignalInstance.id, + ) + ) + .where(and_(Entity.value == entity_name, Entity.entity_type_id == entity_type_id)) + ) + + signal_result = db_session.execute(query).fetchone() + if signal_result: + print( + f"Count with Snooze: {signal_result.count_with_snooze}, " + f"Count without Snooze: {signal_result.count_without_snooze}" + ) + + return SignalData( + num_signals_alerted=signal_result.count_without_snooze, + num_signals_snoozed=signal_result.count_with_snooze, + num_snoozes_active=snooze_result.active_count, + num_snoozes_expired=snooze_result.expired_count, + ) diff --git a/src/dispatch/signal/views.py b/src/dispatch/signal/views.py index 398e9f5fa71e..d8a8d306999e 100644 --- a/src/dispatch/signal/views.py +++ b/src/dispatch/signal/views.py @@ -17,6 +17,7 @@ from .models import ( SignalCreate, + SignalData, SignalEngagementCreate, SignalEngagementPagination, SignalEngagementRead, @@ -40,6 +41,7 @@ delete_signal_filter, get, get_by_primary_or_external_id, + get_signal_data, get_signal_engagement, get_signal_filter, update, @@ -336,3 +338,21 @@ def delete_signal(db_session: DbSession, signal_id: Union[str, PrimaryKey]): detail=[{"msg": "A signal with this id does not exist."}], ) delete(db_session=db_session, signal_id=signal.id) + + +@router.get("/data/{entity_name}", response_model=SignalData) +def return_signal_data( + db_session: DbSession, + entity_name: str, + entity_type_id: int, +): + """Gets a signal data given a named entity and entity type id.""" + signal_data = get_signal_data( + db_session=db_session, entity_name=entity_name, entity_type_id=entity_type_id + ) + if not signal_data: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=[{"msg": "No signals with that entity name were found."}], + ) + return signal_data From 505132fdbed13cef7d968f2880eb21447e20f11a Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Mon, 17 Mar 2025 14:39:17 -0700 Subject: [PATCH 2/5] adding num_days and changing to parameters --- src/dispatch/signal/service.py | 15 ++++++++-- src/dispatch/signal/views.py | 51 +++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/dispatch/signal/service.py b/src/dispatch/signal/service.py index a2623b5fde3c..0d2e377ac540 100644 --- a/src/dispatch/signal/service.py +++ b/src/dispatch/signal/service.py @@ -971,7 +971,7 @@ def get_cases_for_signal_by_resolution_reason( def get_signal_data( - *, db_session: Session, entity_name: str, entity_type_id: int + *, db_session: Session, entity_value: str, entity_type_id: int, num_days: int | None ) -> Optional[SignalData]: """Gets a signal data for a given named entity and type.""" entity_subquery = ( @@ -987,7 +987,7 @@ def get_signal_data( ) ) ) - .filter(and_(Entity.value == entity_name, Entity.entity_type_id == entity_type_id)) + .filter(and_(Entity.value == entity_value, Entity.entity_type_id == entity_type_id)) .as_scalar() ) @@ -1004,6 +1004,9 @@ def get_signal_data( f"Active Count: {snooze_result.active_count}, Expired Count: {snooze_result.expired_count}" ) + # Calculate the date threshold based on num_days + date_threshold = datetime.utcnow() - timedelta(days=num_days) if num_days is not None else None + count_with_snooze = func.count().filter(SignalInstance.filter_action == "snooze") count_without_snooze = func.count().filter( (SignalInstance.filter_action != "snooze") | (SignalInstance.filter_action.is_(None)) @@ -1024,7 +1027,13 @@ def get_signal_data( assoc_signal_instance_entities.c.signal_instance_id == SignalInstance.id, ) ) - .where(and_(Entity.value == entity_name, Entity.entity_type_id == entity_type_id)) + .where( + and_( + Entity.value == entity_value, + Entity.entity_type_id == entity_type_id, + SignalInstance.created_at >= date_threshold if date_threshold else True, + ) + ) ) signal_result = db_session.execute(query).fetchone() diff --git a/src/dispatch/signal/views.py b/src/dispatch/signal/views.py index d8a8d306999e..5740b03184f6 100644 --- a/src/dispatch/signal/views.py +++ b/src/dispatch/signal/views.py @@ -1,7 +1,16 @@ import logging from typing import Union -from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request, Response, status +from fastapi import ( + APIRouter, + BackgroundTasks, + Depends, + HTTPException, + Query, + Request, + Response, + status, +) from pydantic.error_wrappers import ErrorWrapper, ValidationError from sqlalchemy.exc import IntegrityError @@ -274,6 +283,28 @@ def get_signals(common: CommonParameters): return search_filter_sort_paginate(model="Signal", **common) +@router.get("/data", response_model=SignalData) +def return_signal_data( + db_session: DbSession, + entity_value: str = Query(..., description="The name of the entity"), + entity_type_id: int = Query(..., description="The ID of the entity type"), + num_days: int = Query(None, description="The number of days to look back"), +): + """Gets a signal data given a named entity and entity type id.""" + signal_data = get_signal_data( + db_session=db_session, + entity_value=entity_value, + entity_type_id=entity_type_id, + num_days=num_days, + ) + if not signal_data: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=[{"msg": "No signals with that entity name were found."}], + ) + return signal_data + + @router.get("/{signal_id}", response_model=SignalRead) def get_signal(db_session: DbSession, signal_id: Union[str, PrimaryKey]): """Gets a signal by its id.""" @@ -338,21 +369,3 @@ def delete_signal(db_session: DbSession, signal_id: Union[str, PrimaryKey]): detail=[{"msg": "A signal with this id does not exist."}], ) delete(db_session=db_session, signal_id=signal.id) - - -@router.get("/data/{entity_name}", response_model=SignalData) -def return_signal_data( - db_session: DbSession, - entity_name: str, - entity_type_id: int, -): - """Gets a signal data given a named entity and entity type id.""" - signal_data = get_signal_data( - db_session=db_session, entity_name=entity_name, entity_type_id=entity_type_id - ) - if not signal_data: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=[{"msg": "No signals with that entity name were found."}], - ) - return signal_data From a667a81689df0206b9d4d05f6c32e940b74974aa Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Mon, 17 Mar 2025 14:52:39 -0700 Subject: [PATCH 3/5] adding tests --- tests/signal/test_signal_data_service.py | 155 +++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tests/signal/test_signal_data_service.py diff --git a/tests/signal/test_signal_data_service.py b/tests/signal/test_signal_data_service.py new file mode 100644 index 000000000000..b94d967d4b66 --- /dev/null +++ b/tests/signal/test_signal_data_service.py @@ -0,0 +1,155 @@ +from datetime import datetime, timedelta, timezone + + +def test_get_signal_data_basic(session, entity, entity_type, signal, signal_instance): + """Test the basic functionality of get_signal_data.""" + from dispatch.signal.service import get_signal_data + + # Setup: Associate the entity with the signal instance + entity.entity_type = entity_type + signal_instance.entities.append(entity) + signal_instance.signal = signal + session.commit() + + # Execute: Call the service function + signal_data = get_signal_data( + db_session=session, + entity_value=entity.value, + entity_type_id=entity_type.id, + num_days=None, + ) + + # Assert: Check the result + assert signal_data is not None + assert signal_data.num_signals_alerted >= 0 + assert signal_data.num_signals_snoozed >= 0 + assert signal_data.num_snoozes_active >= 0 + assert signal_data.num_snoozes_expired >= 0 + + +def test_get_signal_data_with_num_days(session, entity, entity_type, signal, signal_instance): + """Test get_signal_data with the num_days parameter.""" + from dispatch.signal.service import get_signal_data + + # Setup: Associate the entity with the signal instance + entity.entity_type = entity_type + signal_instance.entities.append(entity) + signal_instance.signal = signal + # Set created_at to a specific time for testing + signal_instance.created_at = datetime.utcnow() - timedelta(days=3) + session.commit() + + # Execute: Call the service function with num_days=7 (should include our instance) + signal_data_7_days = get_signal_data( + db_session=session, + entity_value=entity.value, + entity_type_id=entity_type.id, + num_days=7, + ) + + # Execute: Call the service function with num_days=1 (should exclude our instance) + signal_data_1_day = get_signal_data( + db_session=session, + entity_value=entity.value, + entity_type_id=entity_type.id, + num_days=1, + ) + + # Assert: Check the results + assert signal_data_7_days is not None + assert signal_data_7_days.num_signals_alerted + signal_data_7_days.num_signals_snoozed > 0 + + assert signal_data_1_day is not None + assert signal_data_1_day.num_signals_alerted + signal_data_1_day.num_signals_snoozed == 0 + + +def test_get_signal_data_with_snooze_filter( + session, entity, entity_type, signal, signal_instance, signal_filter +): + """Test get_signal_data with a snooze filter applied.""" + from dispatch.signal.service import get_signal_data + from dispatch.signal.models import SignalFilterAction + + # Setup: Associate the entity with the signal instance and add a snooze filter + entity.entity_type = entity_type + signal_instance.entities.append(entity) + signal_instance.signal = signal + signal_instance.filter_action = SignalFilterAction.snooze + + # Create a snooze filter that's active + signal_filter.action = SignalFilterAction.snooze + signal_filter.expiration = datetime.now(timezone.utc) + timedelta(days=1) + signal_filter.expression = [ + {"or": [{"model": "Entity", "field": "id", "op": "==", "value": entity.id}]} + ] + signal.filters.append(signal_filter) + + session.commit() + + # Execute: Call the service function + signal_data = get_signal_data( + db_session=session, + entity_value=entity.value, + entity_type_id=entity_type.id, + num_days=None, + ) + + # Assert: Check the result + assert signal_data is not None + assert signal_data.num_signals_snoozed > 0 + assert signal_data.num_snoozes_active > 0 + + +def test_get_signal_data_with_expired_snooze_filter( + session, entity, entity_type, signal, signal_instance, signal_filter +): + """Test get_signal_data with an expired snooze filter.""" + from dispatch.signal.service import get_signal_data + from dispatch.signal.models import SignalFilterAction + + # Setup: Associate the entity with the signal instance and add an expired snooze filter + entity.entity_type = entity_type + signal_instance.entities.append(entity) + signal_instance.signal = signal + + # Create a snooze filter that's expired + signal_filter.action = SignalFilterAction.snooze + signal_filter.expiration = datetime.now(timezone.utc) - timedelta(days=1) + signal_filter.expression = [ + {"or": [{"model": "Entity", "field": "id", "op": "==", "value": entity.id}]} + ] + signal.filters.append(signal_filter) + + session.commit() + + # Execute: Call the service function + signal_data = get_signal_data( + db_session=session, + entity_value=entity.value, + entity_type_id=entity_type.id, + num_days=None, + ) + + # Assert: Check the result + assert signal_data is not None + assert signal_data.num_snoozes_expired > 0 + + +def test_get_signal_data_not_found(session, entity_type): + """Test get_signal_data when no signals are found.""" + from dispatch.signal.service import get_signal_data + + # Execute: Call the service function with a non-existent entity value + signal_data = get_signal_data( + db_session=session, + entity_value="non-existent-entity", + entity_type_id=entity_type.id, + num_days=None, + ) + + # Assert: Check the result + assert signal_data is not None + assert signal_data.num_signals_alerted == 0 + assert signal_data.num_signals_snoozed == 0 + assert signal_data.num_snoozes_active == 0 + assert signal_data.num_snoozes_expired == 0 From 5ba62461e60828c07310b07e289f9e7a8ac6aedf Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Mon, 17 Mar 2025 15:02:06 -0700 Subject: [PATCH 4/5] removing debug statements and unnecessary error code --- src/dispatch/signal/service.py | 9 --------- src/dispatch/signal/views.py | 5 ----- 2 files changed, 14 deletions(-) diff --git a/src/dispatch/signal/service.py b/src/dispatch/signal/service.py index 0d2e377ac540..bb5a9260ce6e 100644 --- a/src/dispatch/signal/service.py +++ b/src/dispatch/signal/service.py @@ -999,10 +999,6 @@ def get_signal_data( ).filter(cast(SignalFilter.expression, JSONB).op("@>")(entity_subquery)) snooze_result = db_session.execute(query).fetchone() - if snooze_result: - print( - f"Active Count: {snooze_result.active_count}, Expired Count: {snooze_result.expired_count}" - ) # Calculate the date threshold based on num_days date_threshold = datetime.utcnow() - timedelta(days=num_days) if num_days is not None else None @@ -1037,11 +1033,6 @@ def get_signal_data( ) signal_result = db_session.execute(query).fetchone() - if signal_result: - print( - f"Count with Snooze: {signal_result.count_with_snooze}, " - f"Count without Snooze: {signal_result.count_without_snooze}" - ) return SignalData( num_signals_alerted=signal_result.count_without_snooze, diff --git a/src/dispatch/signal/views.py b/src/dispatch/signal/views.py index 5740b03184f6..1dae1b9c95e0 100644 --- a/src/dispatch/signal/views.py +++ b/src/dispatch/signal/views.py @@ -297,11 +297,6 @@ def return_signal_data( entity_type_id=entity_type_id, num_days=num_days, ) - if not signal_data: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=[{"msg": "No signals with that entity name were found."}], - ) return signal_data From 2e9519e6b1c3a92266bc9ae2ec5c40c23db2afb7 Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Tue, 18 Mar 2025 10:28:09 -0700 Subject: [PATCH 5/5] changing data to stats --- src/dispatch/signal/models.py | 6 +-- src/dispatch/signal/service.py | 14 +++--- src/dispatch/signal/views.py | 12 ++--- tests/signal/test_signal_data_service.py | 64 +++++++++++++----------- 4 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/dispatch/signal/models.py b/src/dispatch/signal/models.py index 4ad305a72ef1..ad8b8dcb0e8a 100644 --- a/src/dispatch/signal/models.py +++ b/src/dispatch/signal/models.py @@ -379,9 +379,9 @@ class AdditionalMetadata(DispatchBase): important: Optional[bool] -class SignalData(DispatchBase): - num_signals_alerted: Optional[int] - num_signals_snoozed: Optional[int] +class SignalStats(DispatchBase): + num_signal_instances_alerted: Optional[int] + num_signal_instances_snoozed: Optional[int] num_snoozes_active: Optional[int] num_snoozes_expired: Optional[int] diff --git a/src/dispatch/signal/service.py b/src/dispatch/signal/service.py index bb5a9260ce6e..fe2419b0f0c7 100644 --- a/src/dispatch/signal/service.py +++ b/src/dispatch/signal/service.py @@ -38,7 +38,6 @@ assoc_signal_instance_entities, Signal, SignalCreate, - SignalData, SignalEngagement, SignalEngagementCreate, SignalEngagementRead, @@ -51,6 +50,7 @@ SignalFilterUpdate, SignalInstance, SignalInstanceCreate, + SignalStats, SignalUpdate, assoc_signal_entity_types, ) @@ -970,10 +970,10 @@ def get_cases_for_signal_by_resolution_reason( ) -def get_signal_data( +def get_signal_stats( *, db_session: Session, entity_value: str, entity_type_id: int, num_days: int | None -) -> Optional[SignalData]: - """Gets a signal data for a given named entity and type.""" +) -> Optional[SignalStats]: + """Gets a signal statistics for a given named entity and type.""" entity_subquery = ( db_session.query( func.jsonb_build_array( @@ -1034,9 +1034,9 @@ def get_signal_data( signal_result = db_session.execute(query).fetchone() - return SignalData( - num_signals_alerted=signal_result.count_without_snooze, - num_signals_snoozed=signal_result.count_with_snooze, + return SignalStats( + num_signal_instances_alerted=signal_result.count_without_snooze, + num_signal_instances_snoozed=signal_result.count_with_snooze, num_snoozes_active=snooze_result.active_count, num_snoozes_expired=snooze_result.expired_count, ) diff --git a/src/dispatch/signal/views.py b/src/dispatch/signal/views.py index 1dae1b9c95e0..276a497630ff 100644 --- a/src/dispatch/signal/views.py +++ b/src/dispatch/signal/views.py @@ -26,7 +26,6 @@ from .models import ( SignalCreate, - SignalData, SignalEngagementCreate, SignalEngagementPagination, SignalEngagementRead, @@ -40,6 +39,7 @@ SignalInstanceRead, SignalPagination, SignalRead, + SignalStats, SignalUpdate, ) from .service import ( @@ -50,7 +50,7 @@ delete_signal_filter, get, get_by_primary_or_external_id, - get_signal_data, + get_signal_stats, get_signal_engagement, get_signal_filter, update, @@ -283,15 +283,15 @@ def get_signals(common: CommonParameters): return search_filter_sort_paginate(model="Signal", **common) -@router.get("/data", response_model=SignalData) -def return_signal_data( +@router.get("/stats", response_model=SignalStats) +def return_signal_stats( db_session: DbSession, entity_value: str = Query(..., description="The name of the entity"), entity_type_id: int = Query(..., description="The ID of the entity type"), num_days: int = Query(None, description="The number of days to look back"), ): - """Gets a signal data given a named entity and entity type id.""" - signal_data = get_signal_data( + """Gets a signal statistics given a named entity and entity type id.""" + signal_data = get_signal_stats( db_session=db_session, entity_value=entity_value, entity_type_id=entity_type_id, diff --git a/tests/signal/test_signal_data_service.py b/tests/signal/test_signal_data_service.py index b94d967d4b66..914594dbd782 100644 --- a/tests/signal/test_signal_data_service.py +++ b/tests/signal/test_signal_data_service.py @@ -1,9 +1,9 @@ from datetime import datetime, timedelta, timezone -def test_get_signal_data_basic(session, entity, entity_type, signal, signal_instance): - """Test the basic functionality of get_signal_data.""" - from dispatch.signal.service import get_signal_data +def test_get_signal_stats_basic(session, entity, entity_type, signal, signal_instance): + """Test the basic functionality of get_signal_stats.""" + from dispatch.signal.service import get_signal_stats # Setup: Associate the entity with the signal instance entity.entity_type = entity_type @@ -12,7 +12,7 @@ def test_get_signal_data_basic(session, entity, entity_type, signal, signal_inst session.commit() # Execute: Call the service function - signal_data = get_signal_data( + signal_data = get_signal_stats( db_session=session, entity_value=entity.value, entity_type_id=entity_type.id, @@ -21,15 +21,15 @@ def test_get_signal_data_basic(session, entity, entity_type, signal, signal_inst # Assert: Check the result assert signal_data is not None - assert signal_data.num_signals_alerted >= 0 - assert signal_data.num_signals_snoozed >= 0 + assert signal_data.num_signal_instances_alerted >= 0 + assert signal_data.num_signal_instances_snoozed >= 0 assert signal_data.num_snoozes_active >= 0 assert signal_data.num_snoozes_expired >= 0 -def test_get_signal_data_with_num_days(session, entity, entity_type, signal, signal_instance): - """Test get_signal_data with the num_days parameter.""" - from dispatch.signal.service import get_signal_data +def test_get_signal_stats_with_num_days(session, entity, entity_type, signal, signal_instance): + """Test get_signal_stats with the num_days parameter.""" + from dispatch.signal.service import get_signal_stats # Setup: Associate the entity with the signal instance entity.entity_type = entity_type @@ -40,7 +40,7 @@ def test_get_signal_data_with_num_days(session, entity, entity_type, signal, sig session.commit() # Execute: Call the service function with num_days=7 (should include our instance) - signal_data_7_days = get_signal_data( + signal_data_7_days = get_signal_stats( db_session=session, entity_value=entity.value, entity_type_id=entity_type.id, @@ -48,7 +48,7 @@ def test_get_signal_data_with_num_days(session, entity, entity_type, signal, sig ) # Execute: Call the service function with num_days=1 (should exclude our instance) - signal_data_1_day = get_signal_data( + signal_data_1_day = get_signal_stats( db_session=session, entity_value=entity.value, entity_type_id=entity_type.id, @@ -57,17 +57,25 @@ def test_get_signal_data_with_num_days(session, entity, entity_type, signal, sig # Assert: Check the results assert signal_data_7_days is not None - assert signal_data_7_days.num_signals_alerted + signal_data_7_days.num_signals_snoozed > 0 + assert ( + signal_data_7_days.num_signal_instances_alerted + + signal_data_7_days.num_signal_instances_snoozed + > 0 + ) assert signal_data_1_day is not None - assert signal_data_1_day.num_signals_alerted + signal_data_1_day.num_signals_snoozed == 0 + assert ( + signal_data_1_day.num_signal_instances_alerted + + signal_data_1_day.num_signal_instances_snoozed + == 0 + ) -def test_get_signal_data_with_snooze_filter( +def test_get_signal_stats_with_snooze_filter( session, entity, entity_type, signal, signal_instance, signal_filter ): - """Test get_signal_data with a snooze filter applied.""" - from dispatch.signal.service import get_signal_data + """Test get_signal_stats with a snooze filter applied.""" + from dispatch.signal.service import get_signal_stats from dispatch.signal.models import SignalFilterAction # Setup: Associate the entity with the signal instance and add a snooze filter @@ -87,7 +95,7 @@ def test_get_signal_data_with_snooze_filter( session.commit() # Execute: Call the service function - signal_data = get_signal_data( + signal_data = get_signal_stats( db_session=session, entity_value=entity.value, entity_type_id=entity_type.id, @@ -96,15 +104,15 @@ def test_get_signal_data_with_snooze_filter( # Assert: Check the result assert signal_data is not None - assert signal_data.num_signals_snoozed > 0 + assert signal_data.num_signal_instances_snoozed > 0 assert signal_data.num_snoozes_active > 0 -def test_get_signal_data_with_expired_snooze_filter( +def test_get_signal_stats_with_expired_snooze_filter( session, entity, entity_type, signal, signal_instance, signal_filter ): - """Test get_signal_data with an expired snooze filter.""" - from dispatch.signal.service import get_signal_data + """Test get_signal_stats with an expired snooze filter.""" + from dispatch.signal.service import get_signal_stats from dispatch.signal.models import SignalFilterAction # Setup: Associate the entity with the signal instance and add an expired snooze filter @@ -123,7 +131,7 @@ def test_get_signal_data_with_expired_snooze_filter( session.commit() # Execute: Call the service function - signal_data = get_signal_data( + signal_data = get_signal_stats( db_session=session, entity_value=entity.value, entity_type_id=entity_type.id, @@ -135,12 +143,12 @@ def test_get_signal_data_with_expired_snooze_filter( assert signal_data.num_snoozes_expired > 0 -def test_get_signal_data_not_found(session, entity_type): - """Test get_signal_data when no signals are found.""" - from dispatch.signal.service import get_signal_data +def test_get_signal_stats_not_found(session, entity_type): + """Test get_signal_stats when no signals are found.""" + from dispatch.signal.service import get_signal_stats # Execute: Call the service function with a non-existent entity value - signal_data = get_signal_data( + signal_data = get_signal_stats( db_session=session, entity_value="non-existent-entity", entity_type_id=entity_type.id, @@ -149,7 +157,7 @@ def test_get_signal_data_not_found(session, entity_type): # Assert: Check the result assert signal_data is not None - assert signal_data.num_signals_alerted == 0 - assert signal_data.num_signals_snoozed == 0 + assert signal_data.num_signal_instances_alerted == 0 + assert signal_data.num_signal_instances_snoozed == 0 assert signal_data.num_snoozes_active == 0 assert signal_data.num_snoozes_expired == 0