18
18
_DEPENDENCY ,
19
19
_REQ_RETRY_NAME ,
20
20
_CUSTOMER_STATSBEAT_LANGUAGE ,
21
+ _APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL ,
21
22
_DEFAULT_STATS_SHORT_EXPORT_INTERVAL ,
22
23
_UNKNOWN ,
23
24
_TYPE_MAP ,
40
41
from azure .monitor .opentelemetry .exporter .statsbeat ._state import _REQUESTS_MAP
41
42
from azure .monitor .opentelemetry .exporter .statsbeat ._utils import (
42
43
categorize_status_code ,
44
+ _get_customer_sdkstats_export_interval
43
45
)
44
46
45
47
def convert_envelope_names_to_base_type (envelope_name ):
@@ -64,12 +66,13 @@ def setUp(self):
64
66
CustomerStatsbeatMetrics ._instance = None
65
67
66
68
self .env_patcher = mock .patch .dict (os .environ , {
67
- "APPLICATIONINSIGHTS_STATSBEAT_ENABLED_PREVIEW" : "true"
69
+ "APPLICATIONINSIGHTS_STATSBEAT_ENABLED_PREVIEW" : "true" ,
70
+ "APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL" : ""
68
71
})
69
72
self .env_patcher .start ()
70
73
self .mock_options = mock .Mock ()
71
74
self .mock_options .instrumentation_key = "363331ca-f431-4119-bdcd-31a75920f958"
72
- self .mock_options .network_collection_interval = _DEFAULT_STATS_SHORT_EXPORT_INTERVAL
75
+ self .mock_options .network_collection_interval = _get_customer_sdkstats_export_interval ()
73
76
self .mock_options .connection_string = "InstrumentationKey=363331ca-f431-4119-bdcd-31a75920f958;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/"
74
77
self .mock_options .language = _CUSTOMER_STATSBEAT_LANGUAGE
75
78
self .original_trace_provider = trace ._TRACER_PROVIDER
@@ -80,16 +83,25 @@ def setUp(self):
80
83
def tearDown (self ):
81
84
self .env_patcher .stop ()
82
85
# Restore trace provider
86
+
83
87
trace ._TRACER_PROVIDER = self .original_trace_provider
84
- # Clean up singleton instances to prevent cross-test contamination
88
+
85
89
if hasattr (self .mock_options , 'metrics' ) and self .mock_options .metrics :
86
90
metrics = self .mock_options .metrics
91
+
87
92
if hasattr (metrics , '_customer_statsbeat_metric_reader' ):
88
- try :
89
- # Shutdown to prevent additional periodic exports
90
- metrics ._customer_statsbeat_metric_reader .shutdown ()
91
- except Exception :
92
- pass # Ignore shutdown errors
93
+ reader = metrics ._customer_statsbeat_metric_reader
94
+ if not getattr (reader , '_shutdown' , False ):
95
+ setattr (reader , '_shutdown' , True )
96
+
97
+ metrics ._customer_statsbeat_metric_reader = None
98
+
99
+ if hasattr (metrics , '_customer_statsbeat_exporter' ):
100
+ metrics ._customer_statsbeat_exporter = None
101
+
102
+ if hasattr (metrics , '_customer_statsbeat_meter_provider' ):
103
+ metrics ._customer_statsbeat_meter_provider = None
104
+
93
105
CustomerStatsbeatMetrics ._instance = None
94
106
95
107
def test_customer_statsbeat_not_initialized_when_disabled (self ):
@@ -108,6 +120,61 @@ def test_customer_statsbeat_not_initialized_when_disabled(self):
108
120
# Verify callbacks return empty lists when disabled
109
121
self .assertEqual (metrics ._item_success_callback (mock .Mock ()), [])
110
122
self .assertEqual (metrics ._item_drop_callback (mock .Mock ()), [])
123
+
124
+ def test_custom_export_interval_from_env_var (self ):
125
+ """Test that a custom export interval is picked up from the environment variable."""
126
+ # Use a non-default value to test
127
+ custom_interval = 300
128
+
129
+ # Mock the environment variable with our custom interval
130
+ with mock .patch .dict (os .environ , {
131
+ _APPLICATIONINSIGHTS_STATSBEAT_ENABLED_PREVIEW : "true" ,
132
+ _APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL : str (custom_interval )
133
+ }):
134
+ # Get the export interval
135
+ actual_interval = _get_customer_sdkstats_export_interval ()
136
+
137
+ # Verify it matches our custom value
138
+ self .assertEqual (
139
+ actual_interval ,
140
+ custom_interval ,
141
+ f"Expected export interval to be { custom_interval } , got { actual_interval } "
142
+ )
143
+
144
+ # Verify the CustomerStatsbeatMetrics instance picks up the custom interval
145
+ CustomerStatsbeatMetrics ._instance = None
146
+ metrics = CustomerStatsbeatMetrics (self .mock_options .connection_string )
147
+ self .assertEqual (
148
+ metrics ._customer_statsbeat_metric_reader ._export_interval_millis ,
149
+ custom_interval ,
150
+ f"CustomerStatsbeatMetrics should use export interval { custom_interval } , got { metrics ._customer_statsbeat_metric_reader ._export_interval_millis } "
151
+ )
152
+
153
+ def test_default_export_interval_when_env_var_empty (self ):
154
+ """Test that the default export interval is used when the environment variable is empty."""
155
+ # Mock the environment variable as empty
156
+ with mock .patch .dict (os .environ , {
157
+ _APPLICATIONINSIGHTS_STATSBEAT_ENABLED_PREVIEW : "true" ,
158
+ _APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL : ""
159
+ }):
160
+ # Get the export interval
161
+ actual_interval = _get_customer_sdkstats_export_interval ()
162
+
163
+ # Verify it matches the default value
164
+ self .assertEqual (
165
+ actual_interval ,
166
+ _DEFAULT_STATS_SHORT_EXPORT_INTERVAL ,
167
+ f"Expected export interval to be default { _DEFAULT_STATS_SHORT_EXPORT_INTERVAL } , got { actual_interval } "
168
+ )
169
+
170
+ # Verify the CustomerStatsbeatMetrics instance picks up the default interval
171
+ CustomerStatsbeatMetrics ._instance = None
172
+ metrics = CustomerStatsbeatMetrics (self .mock_options .connection_string )
173
+ self .assertEqual (
174
+ metrics ._customer_statsbeat_metric_reader ._export_interval_millis ,
175
+ _DEFAULT_STATS_SHORT_EXPORT_INTERVAL ,
176
+ f"CustomerStatsbeatMetrics should use default export interval { _DEFAULT_STATS_SHORT_EXPORT_INTERVAL } , got { metrics ._customer_statsbeat_metric_reader ._export_interval_millis } "
177
+ )
111
178
112
179
def test_successful_items_count (self ):
113
180
successful_dependencies = 0
0 commit comments