Skip to content

Commit 3587c5e

Browse files
committed
test: add additional tests for async embeddings generation
1 parent 7705545 commit 3587c5e

File tree

1 file changed

+226
-0
lines changed

1 file changed

+226
-0
lines changed

tests/integrations/google_genai/test_google_genai.py

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,3 +1191,229 @@ def test_embed_content_span_origin(sentry_init, capture_events, mock_genai_clien
11911191
assert event["contexts"]["trace"]["origin"] == "manual"
11921192
for span in event["spans"]:
11931193
assert span["origin"] == "auto.ai.google_genai"
1194+
1195+
1196+
@pytest.mark.asyncio
1197+
@pytest.mark.parametrize(
1198+
"send_default_pii, include_prompts",
1199+
[
1200+
(True, True),
1201+
(True, False),
1202+
(False, True),
1203+
(False, False),
1204+
],
1205+
)
1206+
async def test_async_embed_content(
1207+
sentry_init, capture_events, send_default_pii, include_prompts, mock_genai_client
1208+
):
1209+
"""Test async embed_content method."""
1210+
sentry_init(
1211+
integrations=[GoogleGenAIIntegration(include_prompts=include_prompts)],
1212+
traces_sample_rate=1.0,
1213+
send_default_pii=send_default_pii,
1214+
)
1215+
events = capture_events()
1216+
1217+
# Mock the async HTTP response
1218+
mock_http_response = create_mock_http_response(EXAMPLE_EMBED_RESPONSE_JSON)
1219+
1220+
with mock.patch.object(
1221+
mock_genai_client._api_client,
1222+
"async_request",
1223+
return_value=mock_http_response,
1224+
):
1225+
with start_transaction(name="google_genai_embeddings_async"):
1226+
await mock_genai_client.aio.models.embed_content(
1227+
model="text-embedding-004",
1228+
contents=[
1229+
"What is your name?",
1230+
"What is your favorite color?",
1231+
],
1232+
)
1233+
1234+
assert len(events) == 1
1235+
(event,) = events
1236+
1237+
assert event["type"] == "transaction"
1238+
assert event["transaction"] == "google_genai_embeddings_async"
1239+
1240+
# Should have 1 span for embeddings
1241+
assert len(event["spans"]) == 1
1242+
(embed_span,) = event["spans"]
1243+
1244+
# Check embeddings span
1245+
assert embed_span["op"] == OP.GEN_AI_EMBEDDINGS
1246+
assert embed_span["description"] == "embeddings text-embedding-004"
1247+
assert embed_span["data"][SPANDATA.GEN_AI_OPERATION_NAME] == "embeddings"
1248+
assert embed_span["data"][SPANDATA.GEN_AI_SYSTEM] == "gcp.gemini"
1249+
assert embed_span["data"][SPANDATA.GEN_AI_REQUEST_MODEL] == "text-embedding-004"
1250+
1251+
# Check input texts if PII is allowed
1252+
if send_default_pii and include_prompts:
1253+
input_texts = json.loads(embed_span["data"][SPANDATA.GEN_AI_EMBEDDINGS_INPUT])
1254+
assert input_texts == [
1255+
"What is your name?",
1256+
"What is your favorite color?",
1257+
]
1258+
else:
1259+
assert SPANDATA.GEN_AI_EMBEDDINGS_INPUT not in embed_span["data"]
1260+
1261+
# Check usage data (sum of token counts from statistics: 10 + 15 = 25)
1262+
# Note: Only available in newer versions with ContentEmbeddingStatistics
1263+
if SPANDATA.GEN_AI_USAGE_INPUT_TOKENS in embed_span["data"]:
1264+
assert embed_span["data"][SPANDATA.GEN_AI_USAGE_INPUT_TOKENS] == 25
1265+
1266+
1267+
@pytest.mark.asyncio
1268+
async def test_async_embed_content_string_input(
1269+
sentry_init, capture_events, mock_genai_client
1270+
):
1271+
"""Test async embed_content with a single string instead of list."""
1272+
sentry_init(
1273+
integrations=[GoogleGenAIIntegration(include_prompts=True)],
1274+
traces_sample_rate=1.0,
1275+
send_default_pii=True,
1276+
)
1277+
events = capture_events()
1278+
1279+
# Mock response with single embedding
1280+
single_embed_response = {
1281+
"embeddings": [
1282+
{
1283+
"values": [0.1, 0.2, 0.3],
1284+
"statistics": {
1285+
"tokenCount": 5,
1286+
"truncated": False,
1287+
},
1288+
},
1289+
],
1290+
"metadata": {
1291+
"billableCharacterCount": 10,
1292+
},
1293+
}
1294+
mock_http_response = create_mock_http_response(single_embed_response)
1295+
1296+
with mock.patch.object(
1297+
mock_genai_client._api_client, "async_request", return_value=mock_http_response
1298+
):
1299+
with start_transaction(name="google_genai_embeddings_async"):
1300+
await mock_genai_client.aio.models.embed_content(
1301+
model="text-embedding-004",
1302+
contents="Single text input",
1303+
)
1304+
1305+
(event,) = events
1306+
(embed_span,) = event["spans"]
1307+
1308+
# Check that single string is handled correctly
1309+
input_texts = json.loads(embed_span["data"][SPANDATA.GEN_AI_EMBEDDINGS_INPUT])
1310+
assert input_texts == ["Single text input"]
1311+
# Should use token_count from statistics (5), not billable_character_count (10)
1312+
# Note: Only available in newer versions with ContentEmbeddingStatistics
1313+
if SPANDATA.GEN_AI_USAGE_INPUT_TOKENS in embed_span["data"]:
1314+
assert embed_span["data"][SPANDATA.GEN_AI_USAGE_INPUT_TOKENS] == 5
1315+
1316+
1317+
@pytest.mark.asyncio
1318+
async def test_async_embed_content_error_handling(
1319+
sentry_init, capture_events, mock_genai_client
1320+
):
1321+
"""Test error handling in async embed_content."""
1322+
sentry_init(
1323+
integrations=[GoogleGenAIIntegration()],
1324+
traces_sample_rate=1.0,
1325+
)
1326+
events = capture_events()
1327+
1328+
# Mock an error at the HTTP level
1329+
with mock.patch.object(
1330+
mock_genai_client._api_client,
1331+
"async_request",
1332+
side_effect=Exception("Async Embedding API Error"),
1333+
):
1334+
with start_transaction(name="google_genai_embeddings_async"):
1335+
with pytest.raises(Exception, match="Async Embedding API Error"):
1336+
await mock_genai_client.aio.models.embed_content(
1337+
model="text-embedding-004",
1338+
contents=["This will fail"],
1339+
)
1340+
1341+
# Should have both transaction and error events
1342+
assert len(events) == 2
1343+
error_event, _ = events
1344+
1345+
assert error_event["level"] == "error"
1346+
assert error_event["exception"]["values"][0]["type"] == "Exception"
1347+
assert error_event["exception"]["values"][0]["value"] == "Async Embedding API Error"
1348+
assert error_event["exception"]["values"][0]["mechanism"]["type"] == "google_genai"
1349+
1350+
1351+
@pytest.mark.asyncio
1352+
async def test_async_embed_content_without_statistics(
1353+
sentry_init, capture_events, mock_genai_client
1354+
):
1355+
"""Test async embed_content response without statistics (older package versions)."""
1356+
sentry_init(
1357+
integrations=[GoogleGenAIIntegration()],
1358+
traces_sample_rate=1.0,
1359+
)
1360+
events = capture_events()
1361+
1362+
# Response without statistics (typical for older google-genai versions)
1363+
# Embeddings exist but don't have the statistics field
1364+
old_version_response = {
1365+
"embeddings": [
1366+
{
1367+
"values": [0.1, 0.2, 0.3],
1368+
},
1369+
{
1370+
"values": [0.2, 0.3, 0.4],
1371+
},
1372+
],
1373+
}
1374+
mock_http_response = create_mock_http_response(old_version_response)
1375+
1376+
with mock.patch.object(
1377+
mock_genai_client._api_client, "async_request", return_value=mock_http_response
1378+
):
1379+
with start_transaction(name="google_genai_embeddings_async"):
1380+
await mock_genai_client.aio.models.embed_content(
1381+
model="text-embedding-004",
1382+
contents=["Test without statistics", "Another test"],
1383+
)
1384+
1385+
(event,) = events
1386+
(embed_span,) = event["spans"]
1387+
1388+
# No usage tokens since there are no statistics in older versions
1389+
# This is expected and the integration should handle it gracefully
1390+
assert SPANDATA.GEN_AI_USAGE_INPUT_TOKENS not in embed_span["data"]
1391+
1392+
1393+
@pytest.mark.asyncio
1394+
async def test_async_embed_content_span_origin(
1395+
sentry_init, capture_events, mock_genai_client
1396+
):
1397+
"""Test that async embed_content spans have correct origin."""
1398+
sentry_init(
1399+
integrations=[GoogleGenAIIntegration()],
1400+
traces_sample_rate=1.0,
1401+
)
1402+
events = capture_events()
1403+
1404+
mock_http_response = create_mock_http_response(EXAMPLE_EMBED_RESPONSE_JSON)
1405+
1406+
with mock.patch.object(
1407+
mock_genai_client._api_client, "async_request", return_value=mock_http_response
1408+
):
1409+
with start_transaction(name="google_genai_embeddings_async"):
1410+
await mock_genai_client.aio.models.embed_content(
1411+
model="text-embedding-004",
1412+
contents=["Test origin"],
1413+
)
1414+
1415+
(event,) = events
1416+
1417+
assert event["contexts"]["trace"]["origin"] == "manual"
1418+
for span in event["spans"]:
1419+
assert span["origin"] == "auto.ai.google_genai"

0 commit comments

Comments
 (0)