vectorwave 0.1.4__tar.gz → 0.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {vectorwave-0.1.4/src/vectorwave.egg-info → vectorwave-0.1.6}/PKG-INFO +30 -2
  2. {vectorwave-0.1.4 → vectorwave-0.1.6}/Readme.md +28 -1
  3. {vectorwave-0.1.4 → vectorwave-0.1.6}/pyproject.toml +3 -2
  4. vectorwave-0.1.6/src/tests/conftest.py +27 -0
  5. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/database/test_db.py +3 -0
  6. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/models/test_db_config.py +36 -1
  7. vectorwave-0.1.6/src/tests/monitoring/alert/test_alerter.py +70 -0
  8. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/monitoring/test_async_trace.py +24 -1
  9. vectorwave-0.1.6/src/tests/monitoring/test_tracer.py +353 -0
  10. vectorwave-0.1.6/src/tests/search/test_execution_search.py +125 -0
  11. vectorwave-0.1.6/src/tests/utils/test_function_cahe.py +126 -0
  12. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/__init__.py +2 -1
  13. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/core/decorator.py +41 -22
  14. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/database/db.py +15 -6
  15. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/database/db_search.py +100 -6
  16. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/models/db_config.py +20 -1
  17. vectorwave-0.1.6/src/vectorwave/monitoring/alert/base.py +8 -0
  18. vectorwave-0.1.6/src/vectorwave/monitoring/alert/factory.py +19 -0
  19. vectorwave-0.1.6/src/vectorwave/monitoring/alert/null_alerter.py +7 -0
  20. vectorwave-0.1.6/src/vectorwave/monitoring/alert/webhook_alerter.py +69 -0
  21. vectorwave-0.1.6/src/vectorwave/monitoring/monitoring.py +0 -0
  22. vectorwave-0.1.6/src/vectorwave/monitoring/tracer.py +395 -0
  23. vectorwave-0.1.6/src/vectorwave/prediction/__init__.py +0 -0
  24. vectorwave-0.1.6/src/vectorwave/prediction/predictor.py +0 -0
  25. vectorwave-0.1.6/src/vectorwave/search/__init__.py +0 -0
  26. vectorwave-0.1.6/src/vectorwave/search/execution_search.py +129 -0
  27. vectorwave-0.1.6/src/vectorwave/search/extended_search.py +0 -0
  28. vectorwave-0.1.6/src/vectorwave/search/rag_search.py +0 -0
  29. vectorwave-0.1.6/src/vectorwave/utils/__init__.py +0 -0
  30. vectorwave-0.1.6/src/vectorwave/utils/function_cache.py +73 -0
  31. vectorwave-0.1.6/src/vectorwave/vectorizer/__init__.py +0 -0
  32. {vectorwave-0.1.4 → vectorwave-0.1.6/src/vectorwave.egg-info}/PKG-INFO +30 -2
  33. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave.egg-info/SOURCES.txt +18 -0
  34. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave.egg-info/requires.txt +1 -0
  35. vectorwave-0.1.4/src/tests/monitoring/test_tracer.py +0 -256
  36. vectorwave-0.1.4/src/vectorwave/monitoring/tracer.py +0 -246
  37. {vectorwave-0.1.4 → vectorwave-0.1.6}/LICENSE +0 -0
  38. {vectorwave-0.1.4 → vectorwave-0.1.6}/MANIFEST.in +0 -0
  39. {vectorwave-0.1.4 → vectorwave-0.1.6}/NOTICE +0 -0
  40. {vectorwave-0.1.4 → vectorwave-0.1.6}/setup.cfg +0 -0
  41. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/__init__.py +0 -0
  42. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/batch/__init__.py +0 -0
  43. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/batch/test_batch.py +0 -0
  44. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/core/__init__.py +0 -0
  45. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/core/test_decorator.py +0 -0
  46. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/database/__init__.py +0 -0
  47. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/database/test_db_search.py +0 -0
  48. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/exception/__init__.py +0 -0
  49. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/models/__init__.py +0 -0
  50. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/tests/monitoring/__init__.py +0 -0
  51. {vectorwave-0.1.4/src/tests/prediction → vectorwave-0.1.6/src/tests/monitoring/alert}/__init__.py +0 -0
  52. {vectorwave-0.1.4/src/tests/vectorizer → vectorwave-0.1.6/src/tests/prediction}/__init__.py +0 -0
  53. {vectorwave-0.1.4/src/vectorwave/batch → vectorwave-0.1.6/src/tests/search}/__init__.py +0 -0
  54. {vectorwave-0.1.4/src/vectorwave/core → vectorwave-0.1.6/src/tests/utils}/__init__.py +0 -0
  55. {vectorwave-0.1.4/src/vectorwave/database → vectorwave-0.1.6/src/tests/vectorizer}/__init__.py +0 -0
  56. {vectorwave-0.1.4/src/vectorwave/exception → vectorwave-0.1.6/src/vectorwave/batch}/__init__.py +0 -0
  57. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/batch/batch.py +0 -0
  58. {vectorwave-0.1.4/src/vectorwave/models → vectorwave-0.1.6/src/vectorwave/core}/__init__.py +0 -0
  59. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/core/core.py +0 -0
  60. {vectorwave-0.1.4/src/vectorwave/monitoring → vectorwave-0.1.6/src/vectorwave/database}/__init__.py +0 -0
  61. {vectorwave-0.1.4/src/vectorwave/prediction → vectorwave-0.1.6/src/vectorwave/exception}/__init__.py +0 -0
  62. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/exception/exceptions.py +0 -0
  63. {vectorwave-0.1.4/src/vectorwave/vectorizer → vectorwave-0.1.6/src/vectorwave/models}/__init__.py +0 -0
  64. /vectorwave-0.1.4/src/vectorwave/monitoring/monitoring.py → /vectorwave-0.1.6/src/vectorwave/monitoring/__init__.py +0 -0
  65. /vectorwave-0.1.4/src/vectorwave/prediction/predictor.py → /vectorwave-0.1.6/src/vectorwave/monitoring/alert/__init__.py +0 -0
  66. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/vectorizer/base.py +0 -0
  67. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/vectorizer/factory.py +0 -0
  68. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/vectorizer/huggingface_vectorizer.py +0 -0
  69. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave/vectorizer/openai_vectorizer.py +0 -0
  70. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave.egg-info/dependency_links.txt +0 -0
  71. {vectorwave-0.1.4 → vectorwave-0.1.6}/src/vectorwave.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectorwave
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: VectorWave: Seamless Auto-Vectorization Framework
5
5
  Author-email: junyeonggim <junyeonggim5@gmail.com>
6
6
  License-Expression: MIT
@@ -20,6 +20,7 @@ License-File: NOTICE
20
20
  Requires-Dist: weaviate-client>=4.0.0
21
21
  Requires-Dist: pydantic-settings>=2.0.0
22
22
  Requires-Dist: sentence-transformers
23
+ Requires-Dist: requests
23
24
  Dynamic: license-file
24
25
 
25
26
 
@@ -395,7 +396,6 @@ def other_function():
395
396
  pass
396
397
  ```
397
398
 
398
- **Tag Merging and Validation Rules**
399
399
 
400
400
  1. **Validation (Important):** Tags (global or function-specific) will **only** be saved to Weaviate if their key (e.g., `run_id`, `team`, `priority`) was first defined in the `.weaviate_properties` file (Step 1). Tags not defined in the schema are **ignored**, and a warning is logged at startup.
401
401
 
@@ -408,6 +408,34 @@ def other_function():
408
408
 
409
409
  -----
410
410
 
411
+ ### 🚀 Real-time Error Alerting (Webhook)
412
+
413
+ Beyond just logging, `VectorWave` can send **real-time notifications via webhook** the instant an error occurs. This functionality is built directly into the tracer and can be activated simply by updating your `.env` file.
414
+
415
+ **How it Works:**
416
+ 1. An exception is raised within a function decorated by `@trace_span` or `@vectorize`.
417
+ 2. The tracer catches the exception in its `except` block and immediately calls the `alerter` object.
418
+ 3. The alerter reads the `.env` configuration and uses the `WebhookAlerter` to dispatch the error details to your specified URL.
419
+ 4. The notification is optimized for **Discord Embeds**, sending a rich report including the error code, trace ID, captured attributes (`user_id`, etc.), and the full stack trace.
420
+
421
+ **How to Enable:**
422
+ Add the following two variables to your `test_ex/.env` file (or environment variables):
423
+
424
+ ```ini
425
+ # .env file
426
+
427
+ # 1. Set the alerter strategy to 'webhook'. (Default: "none")
428
+ ALERTER_STRATEGY="webhook"
429
+
430
+ # 2. Provide your webhook URL from Discord, Slack, etc.
431
+ ALERTER_WEBHOOK_URL="[https://discord.com/api/webhooks/YOUR_HOOK_ID/](https://discord.com/api/webhooks/YOUR_HOOK_ID/)..."
432
+ With just these two lines, running test_ex/example.py will now instantly send a Discord alert when the CustomValueError is raised.
433
+
434
+ Extensibility (Strategy Pattern): The alerting system is built on a Strategy Pattern. You can easily extend it by implementing the BaseAlerter interface to support other channels like email, PagerDuty, or more.
435
+
436
+ **Tag Merging and Validation Rules**
437
+ ```
438
+
411
439
  ## 🤝 Contributing
412
440
 
413
441
  Bug reports, feature requests, and code contributions are all welcome. For details, please see [CONTRIBUTING.md](https://www.google.com/search?q=httpsS://www.google.com/search%3Fq%3DCONTRIBUTING.md).
@@ -371,7 +371,6 @@ def other_function():
371
371
  pass
372
372
  ```
373
373
 
374
- **Tag Merging and Validation Rules**
375
374
 
376
375
  1. **Validation (Important):** Tags (global or function-specific) will **only** be saved to Weaviate if their key (e.g., `run_id`, `team`, `priority`) was first defined in the `.weaviate_properties` file (Step 1). Tags not defined in the schema are **ignored**, and a warning is logged at startup.
377
376
 
@@ -384,6 +383,34 @@ def other_function():
384
383
 
385
384
  -----
386
385
 
386
+ ### 🚀 Real-time Error Alerting (Webhook)
387
+
388
+ Beyond just logging, `VectorWave` can send **real-time notifications via webhook** the instant an error occurs. This functionality is built directly into the tracer and can be activated simply by updating your `.env` file.
389
+
390
+ **How it Works:**
391
+ 1. An exception is raised within a function decorated by `@trace_span` or `@vectorize`.
392
+ 2. The tracer catches the exception in its `except` block and immediately calls the `alerter` object.
393
+ 3. The alerter reads the `.env` configuration and uses the `WebhookAlerter` to dispatch the error details to your specified URL.
394
+ 4. The notification is optimized for **Discord Embeds**, sending a rich report including the error code, trace ID, captured attributes (`user_id`, etc.), and the full stack trace.
395
+
396
+ **How to Enable:**
397
+ Add the following two variables to your `test_ex/.env` file (or environment variables):
398
+
399
+ ```ini
400
+ # .env file
401
+
402
+ # 1. Set the alerter strategy to 'webhook'. (Default: "none")
403
+ ALERTER_STRATEGY="webhook"
404
+
405
+ # 2. Provide your webhook URL from Discord, Slack, etc.
406
+ ALERTER_WEBHOOK_URL="[https://discord.com/api/webhooks/YOUR_HOOK_ID/](https://discord.com/api/webhooks/YOUR_HOOK_ID/)..."
407
+ With just these two lines, running test_ex/example.py will now instantly send a Discord alert when the CustomValueError is raised.
408
+
409
+ Extensibility (Strategy Pattern): The alerting system is built on a Strategy Pattern. You can easily extend it by implementing the BaseAlerter interface to support other channels like email, PagerDuty, or more.
410
+
411
+ **Tag Merging and Validation Rules**
412
+ ```
413
+
387
414
  ## 🤝 Contributing
388
415
 
389
416
  Bug reports, feature requests, and code contributions are all welcome. For details, please see [CONTRIBUTING.md](https://www.google.com/search?q=httpsS://www.google.com/search%3Fq%3DCONTRIBUTING.md).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vectorwave"
7
- version = "0.1.4"
7
+ version = "0.1.6"
8
8
  authors = [
9
9
  { name = "junyeonggim", email = "junyeonggim5@gmail.com" },
10
10
  ]
@@ -26,7 +26,8 @@ classifiers = [
26
26
  dependencies = [
27
27
  "weaviate-client>=4.0.0",
28
28
  "pydantic-settings>=2.0.0",
29
- "sentence-transformers"
29
+ "sentence-transformers",
30
+ "requests"
30
31
  ]
31
32
 
32
33
  [project.urls]
@@ -0,0 +1,27 @@
1
+ import pytest
2
+ import os
3
+ import logging
4
+
5
+ CACHE_FILE_PATH = ".vectorwave_functions_cache.json"
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ def _delete_cache():
10
+ """Helper function to remove the cache file if it exists."""
11
+ if os.path.exists(CACHE_FILE_PATH):
12
+ try:
13
+ os.remove(CACHE_FILE_PATH)
14
+ except OSError as e:
15
+ print(f"\n[CacheFixture Error] Failed to remove {CACHE_FILE_PATH}: {e}")
16
+
17
+
18
+ @pytest.fixture(autouse=True, scope="function")
19
+ def atomic_function_cache():
20
+ # --- SETUP (Before Test) ---
21
+ _delete_cache()
22
+
23
+ # --- Run the test ---
24
+ yield
25
+
26
+ # --- TEARDOWN (After Test) ---
27
+ _delete_cache()
@@ -355,6 +355,9 @@ def test_create_execution_schema_new(mock_vectorizer_none, test_settings):
355
355
  assert "status" in passed_props_map
356
356
  assert "duration_ms" in passed_props_map
357
357
 
358
+ assert "return_value" in passed_props_map
359
+ assert passed_props_map["return_value"].dataType == wvc.DataType.TEXT
360
+
358
361
  assert collection == mock_new_collection
359
362
 
360
363
 
@@ -148,4 +148,39 @@ def test_get_settings_loads_global_custom_values(mock_env_get, mock_open_file, m
148
148
  assert settings.global_custom_values["run_id"] == "test-run-123"
149
149
 
150
150
  # "EXPERIMENT_ID" should not be included as os.environ.get returned None.
151
- assert "experiment_id" not in settings.global_custom_values
151
+ assert "experiment_id" not in settings.global_custom_values
152
+
153
+ @patch('os.path.exists', return_value=False)
154
+ def test_get_settings_parses_sensitive_keys(mock_exists, monkeypatch):
155
+ """
156
+ Tests whether the SENSITIVE_FIELD_NAMES environment variable is correctly parsed
157
+ and converted into a lowercase set (sensitive_keys).
158
+ """
159
+ monkeypatch.setenv("SENSITIVE_FIELD_NAMES", "password, Token, api_key,, secret ")
160
+
161
+ get_weaviate_settings.cache_clear()
162
+
163
+ # 2. Act
164
+ settings = get_weaviate_settings()
165
+
166
+ # 3. Assert
167
+ assert isinstance(settings.sensitive_keys, set)
168
+ assert len(settings.sensitive_keys) == 4 # 이제 4개가 맞습니다.
169
+ assert settings.sensitive_keys == {"password", "token", "api_key", "secret"}
170
+
171
+
172
+ # [MODIFIED] @patch('os.environ.get', return_value=None) 제거, monkeypatch 인자 추가
173
+ @patch('os.path.exists', return_value=False)
174
+ def test_get_settings_sensitive_keys_default(mock_exists, monkeypatch): # <-- FIX: monkeypatch 사용
175
+ """
176
+ Test when there is no SENSITIVE_FIELD_NAMES environment variable set default
177
+ """
178
+ get_weaviate_settings.cache_clear()
179
+ monkeypatch.delenv("SENSITIVE_FIELD_NAMES", raising=False)
180
+
181
+ # 2. Act
182
+ settings = get_weaviate_settings()
183
+
184
+ # 3. Assert: check default for 5
185
+ assert settings.sensitive_keys == {"password", "api_key", "token", "secret", "auth_token"}
186
+ assert len(settings.sensitive_keys) == 5
@@ -0,0 +1,70 @@
1
+ from unittest.mock import MagicMock, patch
2
+
3
+ from vectorwave.monitoring.alert.factory import get_alerter
4
+ from vectorwave.monitoring.alert.null_alerter import NullAlerter
5
+ from vectorwave.monitoring.alert.webhook_alerter import WebhookAlerter
6
+ from vectorwave.models.db_config import WeaviateSettings
7
+
8
+ @patch('vectorwave.monitoring.alert.factory.get_weaviate_settings')
9
+ def test_get_alerter_returns_null_alerter_by_default(mock_get_settings):
10
+ """
11
+ Case 1: When .env settings are missing or ALERTER_STRATEGY="none"
12
+ - Should return NullAlerter.
13
+ """
14
+ # 1. Arrange
15
+ # Clear lru_cache to bypass caching
16
+ get_alerter.cache_clear()
17
+
18
+ # Mock default settings (strategy="none")
19
+ mock_get_settings.return_value = WeaviateSettings()
20
+
21
+ # 2. Act
22
+ alerter = get_alerter()
23
+
24
+ # 3. Assert
25
+ assert isinstance(alerter, NullAlerter)
26
+
27
+ @patch('vectorwave.monitoring.alert.factory.get_weaviate_settings')
28
+ def test_get_alerter_returns_webhook_alerter_when_configured(mock_get_settings):
29
+ """
30
+ Case 2: When ALERTER_STRATEGY="webhook" and URL is provided
31
+ - Should return WebhookAlerter.
32
+ """
33
+ # 1. Arrange
34
+ get_alerter.cache_clear()
35
+
36
+ # Mock settings object with webhook strategy and URL
37
+ settings = WeaviateSettings(
38
+ ALERTER_STRATEGY="webhook",
39
+ ALERTER_WEBHOOK_URL="https://test.webhook.url/..."
40
+ )
41
+ mock_get_settings.return_value = settings
42
+
43
+ # 2. Act
44
+ alerter = get_alerter()
45
+
46
+ # 3. Assert
47
+ assert isinstance(alerter, WebhookAlerter)
48
+ assert alerter.url == "https://test.webhook.url/..."
49
+
50
+ @patch('vectorwave.monitoring.alert.factory.get_weaviate_settings')
51
+ def test_get_alerter_returns_null_alerter_if_webhook_url_missing(mock_get_settings):
52
+ """
53
+ Case 3: When ALERTER_STRATEGY="webhook" but URL is missing
54
+ - Should log a warning and return NullAlerter.
55
+ """
56
+ # 1. Arrange
57
+ get_alerter.cache_clear()
58
+
59
+ # Mock settings with missing URL
60
+ settings = WeaviateSettings(
61
+ ALERTER_STRATEGY="webhook",
62
+ ALERTER_WEBHOOK_URL=None # URL is missing
63
+ )
64
+ mock_get_settings.return_value = settings
65
+
66
+ # 2. Act
67
+ alerter = get_alerter()
68
+
69
+ # 3. Assert
70
+ assert isinstance(alerter, NullAlerter)
@@ -23,6 +23,7 @@ async def test_trace_root_and_span_async_success(mock_tracer_deps):
23
23
  - ContextVar (trace_id) must be correctly propagated across 'await' boundaries
24
24
  '''
25
25
  mock_batch = mock_tracer_deps["batch"]
26
+ mock_alerter = mock_tracer_deps["alerter"]
26
27
 
27
28
  @trace_span(attributes_to_capture=['x'])
28
29
  async def my_async_inner_span(x):
@@ -37,6 +38,7 @@ async def test_trace_root_and_span_async_success(mock_tracer_deps):
37
38
  return result
38
39
 
39
40
  mock_batch.reset_mock()
41
+ mock_alerter.reset_mock()
40
42
 
41
43
  # --- Execution ---
42
44
  result = await my_async_workflow_root()
@@ -47,6 +49,8 @@ async def test_trace_root_and_span_async_success(mock_tracer_deps):
47
49
  # 2 calls expected: 1 (inner_span) + 1 (workflow_root)
48
50
  assert mock_batch.add_object.call_count == 2
49
51
 
52
+ mock_alerter.notify.assert_not_called()
53
+
50
54
  call_args_list = mock_batch.add_object.call_args_list
51
55
  props_map = {
52
56
  call.kwargs["properties"]["function_name"]: call.kwargs["properties"]
@@ -80,9 +84,12 @@ async def test_trace_span_async_failure(mock_tracer_deps):
80
84
  Case 2: Async span failure test
81
85
  '''
82
86
  mock_batch = mock_tracer_deps["batch"]
87
+ mock_alerter = mock_tracer_deps["alerter"]
83
88
 
84
89
  class AsyncTestError(Exception):
85
- pass
90
+ @property
91
+ def error_code(self):
92
+ return "ASYNC_TEST_FAILURE"
86
93
 
87
94
  @trace_span
88
95
  async def my_failing_async_span():
@@ -97,6 +104,20 @@ async def test_trace_span_async_failure(mock_tracer_deps):
97
104
  with pytest.raises(AsyncTestError, match="Async failure test"):
98
105
  await my_async_workflow_fail()
99
106
 
107
+ mock_alerter.notify.assert_called_once()
108
+ alert_props = mock_alerter.notify.call_args.args[0]
109
+
110
+ assert alert_props["status"] == "ERROR"
111
+ assert "AsyncTestError: Async failure test" in alert_props["error_message"]
112
+ assert alert_props["function_name"] == "my_failing_async_span"
113
+ assert alert_props["error_code"] == "ASYNC_TEST_FAILURE"
114
+
115
+ mock_batch.add_object.assert_called_once()
116
+ db_props = mock_batch.add_object.call_args.kwargs["properties"]
117
+
118
+ assert db_props == alert_props
119
+ assert db_props["span_id"] == alert_props["span_id"]
120
+
100
121
  # --- Verification (Log) ---
101
122
  # Check if the failed span log was recorded
102
123
  failing_span_props = None
@@ -116,6 +137,7 @@ async def test_span_without_root_async_does_nothing(mock_tracer_deps):
116
137
  Case 3: Async span called without a root (@trace_root) should not be logged
117
138
  '''
118
139
  mock_batch = mock_tracer_deps["batch"]
140
+ mock_alerter = mock_tracer_deps["alerter"]
119
141
 
120
142
  @trace_span
121
143
  async def my_lonely_async_span():
@@ -126,6 +148,7 @@ async def test_span_without_root_async_does_nothing(mock_tracer_deps):
126
148
 
127
149
  assert result == "lonely_result"
128
150
  mock_batch.add_object.assert_not_called()
151
+ mock_alerter.notify.assert_not_called()
129
152
 
130
153
 
131
154
  # ==================================