Skip to content

Commit a4902f2

Browse files
NO SNOW: fix external telemetry doc string (#3954)
1 parent 856ad27 commit a4902f2

File tree

3 files changed

+126
-5
lines changed

3 files changed

+126
-5
lines changed

src/snowflake/snowpark/_internal/event_table_telemetry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,12 @@ def enable_event_table_telemetry_collection(
243243
ext.enable_event_table_telemetry_collection("snowflake.telemetry.events", logging.INFO, True)
244244
tracer = trace.get_tracer("my_tracer")
245245
with tracer.start_as_current_span("code_store") as span:
246-
span.set_attribute("code.lineno", "21")
246+
span.set_attribute("code.lineno", "21")
247247
span.set_attribute("code.content", "session.sql(...)")
248248
logging.info("Trace being sent to event table")
249249
ext.disable_event_table_telemetry_collection()
250250
logging.info("out of scope log") # this log is not sent to event table
251-
ext.enable_event_table_telemetry_collection("db.sc.external_et", logging.DEBUG, True)
251+
ext.enable_event_table_telemetry_collection("snowflake.telemetry.events", logging.DEBUG, True)
252252
logging.debug("debug log") # this log is sent to event table because event table telemetry collection is re-enabled
253253
ext.disable_event_table_telemetry_collection()
254254

src/snowflake/snowpark/session.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4364,7 +4364,7 @@ def client_telemetry(self) -> EventTableTelemetry:
43644364
logging.info("Trace being sent to event table")
43654365
ext.disable_event_table_telemetry_collection()
43664366
logging.info("out of scope log") # this log is not sent to event table
4367-
ext.enable_event_table_telemetry_collection("db.sc.external_et", logging.DEBUG, True)
4367+
ext.enable_event_table_telemetry_collection("snowflake.telemetry.events", logging.DEBUG, True)
43684368
logging.debug("debug log") # this log is sent to event table because external telemetry is re-enabled
43694369
ext.disable_event_table_telemetry_collection()
43704370

tests/integ/test_external_telemetry.py

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
import logging
66
import threading
7-
from unittest.mock import patch, MagicMock
7+
from unittest.mock import patch, MagicMock, Mock
88
import pytest
99

10-
from snowflake.snowpark._internal.event_table_telemetry import EventTableTelemetry
10+
from snowflake.snowpark._internal.event_table_telemetry import (
11+
EventTableTelemetry,
12+
RetryWithTokenRefreshAdapter,
13+
)
1114

1215
try:
1316
from opentelemetry import trace
@@ -212,3 +215,121 @@ def test_negative_case(session, caplog):
212215
"Opentelemetry dependencies are missing, no telemetry export into event table:"
213216
in caplog.text
214217
)
218+
219+
220+
def test_external_telemetry_adapter(session):
221+
# Create mock session
222+
mock_session = Mock()
223+
mock_session._get_external_telemetry_auth_token.return_value = {
224+
"Authorization": "Bearer new_token"
225+
}
226+
227+
# Test data
228+
initial_header = {"Authorization": "Bearer initial_token"}
229+
max_retries = 2
230+
231+
# Create adapter instance
232+
adapter = RetryWithTokenRefreshAdapter(
233+
session_instance=mock_session, header=initial_header, max_retries=max_retries
234+
)
235+
236+
# Create mock request
237+
mock_request = Mock()
238+
mock_request.headers = {}
239+
240+
# Test 1: Successful request on first attempt (200 status)
241+
with patch.object(adapter.__class__.__bases__[0], "send") as mock_super_send:
242+
mock_response = Mock()
243+
mock_response.status_code = 200
244+
mock_super_send.return_value = mock_response
245+
246+
result = adapter.send(mock_request)
247+
248+
# Verify successful response
249+
assert result == mock_response
250+
assert mock_request.headers == initial_header
251+
mock_super_send.assert_called_once_with(mock_request)
252+
mock_session._get_external_telemetry_auth_token.assert_not_called()
253+
254+
# Reset mocks
255+
mock_super_send.reset_mock()
256+
mock_session._get_external_telemetry_auth_token.reset_mock()
257+
mock_request.headers = {}
258+
259+
# Test 2: Retry on 401 status code with token refresh (successful on retry)
260+
with patch.object(adapter.__class__.__bases__[0], "send") as mock_super_send:
261+
# First call returns 401, second call returns 200
262+
mock_response_401 = Mock()
263+
mock_response_401.status_code = 401
264+
mock_response_200 = Mock()
265+
mock_response_200.status_code = 200
266+
mock_super_send.side_effect = [mock_response_401, mock_response_200]
267+
268+
result = adapter.send(mock_request)
269+
270+
# Verify retry with token refresh
271+
assert result == mock_response_200
272+
assert mock_super_send.call_count == 2
273+
assert mock_session._get_external_telemetry_auth_token.call_count == 1
274+
assert adapter.header == {"Authorization": "Bearer new_token"}
275+
276+
# Reset mocks
277+
mock_super_send.reset_mock()
278+
mock_session._get_external_telemetry_auth_token.reset_mock()
279+
mock_request.headers = {}
280+
adapter.header = initial_header.copy()
281+
282+
# Test 3: Retry on generic Exception with token refresh (successful on retry)
283+
with patch.object(adapter.__class__.__bases__[0], "send") as mock_super_send:
284+
# First call raises generic Exception, second call succeeds
285+
mock_super_send.side_effect = [
286+
Exception("Generic error"),
287+
Mock(status_code=200),
288+
]
289+
290+
result = adapter.send(mock_request)
291+
292+
assert result.status_code == 200
293+
assert mock_super_send.call_count == 2
294+
assert mock_session._get_external_telemetry_auth_token.call_count == 1
295+
assert adapter.header == {"Authorization": "Bearer new_token"}
296+
297+
# Reset mocks
298+
mock_super_send.reset_mock()
299+
mock_session._get_external_telemetry_auth_token.reset_mock()
300+
mock_request.headers = {}
301+
adapter.header = initial_header.copy()
302+
303+
# Test 4: Exhaust all retries and raise exception (401 status)
304+
with patch.object(adapter.__class__.__bases__[0], "send") as mock_super_send:
305+
# All calls return 401
306+
mock_response_401 = Mock()
307+
mock_response_401.status_code = 401
308+
mock_super_send.return_value = mock_response_401
309+
310+
result = adapter.send(mock_request)
311+
312+
# Verify all retries exhausted and final 401 returned
313+
assert result == mock_response_401
314+
assert mock_super_send.call_count == max_retries + 1 # 3 total attempts
315+
assert mock_session._get_external_telemetry_auth_token.call_count == max_retries
316+
assert adapter.header == {"Authorization": "Bearer new_token"}
317+
318+
# Reset mocks
319+
mock_super_send.reset_mock()
320+
mock_session._get_external_telemetry_auth_token.reset_mock()
321+
mock_request.headers = {}
322+
adapter.header = initial_header.copy()
323+
324+
# Test 5: Exhaust all retries and raise exception (generic Exception)
325+
with patch.object(adapter.__class__.__bases__[0], "send") as mock_super_send:
326+
# All calls raise generic Exception
327+
mock_super_send.side_effect = Exception("Persistent generic error")
328+
329+
with pytest.raises(Exception, match="Persistent generic error"):
330+
adapter.send(mock_request)
331+
332+
# Verify all retries attempted
333+
assert mock_super_send.call_count == max_retries + 1 # 3 total attempts
334+
assert mock_session._get_external_telemetry_auth_token.call_count == max_retries
335+
assert adapter.header == {"Authorization": "Bearer new_token"}

0 commit comments

Comments
 (0)