fix(proxy): attribute /v1/messages spend rows to /messages in daily activity

Anthropic-native /v1/messages requests are logged with call type
anthropic_messages, which had no entry in ROUTE_ENDPOINT_MAPPING. Their
daily spend rows were written with no endpoint, so Usage > Endpoint
Activity never showed /messages traffic even though model, key and
provider views counted it

Map anthropic_messages to /messages. The missing-param error for the
route now names /messages instead of the raw route type, matching the
other mapped routes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sebastian Curland 2026-11-01 17:38:08 +02:00
parent 60fc121ce8
commit acbe973106
3 changed files with 41 additions and 1 deletions

View file

@ -155,6 +155,7 @@ ROUTE_ENDPOINT_MAPPING: Final = {
"arerank": "/rerank",
"aresponses": "/responses",
"_aresponses_websocket": "/responses",
"anthropic_messages": "/messages",
"alist_input_items": "/responses/{response_id}/input_items",
"aimage_edit": "/images/edits",
"acancel_responses": "/responses/{response_id}/cancel",

View file

@ -1852,6 +1852,45 @@ async def test_endpoint_field_maps_retrieve_batch_spend_row_to_batches_endpoint(
assert transaction["endpoint"] == "/batches"
@pytest.mark.asyncio
async def test_endpoint_field_maps_anthropic_messages_spend_row_to_messages_endpoint():
writer = DBSpendUpdateWriter()
mock_prisma = MagicMock()
mock_prisma.get_request_status = MagicMock(return_value="success")
payload = {
"request_id": "req-anthropic-messages",
"user": "test-user",
"call_type": "anthropic_messages",
"startTime": "2024-01-01T12:00:00",
"api_key": "test-key",
"model": "claude-sonnet-4-5",
"custom_llm_provider": "anthropic",
"model_group": "claude-sonnet-4-5",
"prompt_tokens": 15,
"completion_tokens": 10,
"spend": 0.0175,
"metadata": '{"usage_object": {}}',
}
writer.daily_spend_update_queue.add_update = AsyncMock()
await writer.add_spend_log_transaction_to_daily_user_transaction(
payload=payload,
prisma_client=mock_prisma,
)
writer.daily_spend_update_queue.add_update.assert_called_once()
call_args = writer.daily_spend_update_queue.add_update.call_args[1]
update_dict = call_args["update"]
assert len(update_dict) == 1
for key, transaction in update_dict.items():
assert key == "test-user_2024-01-01_test-key_claude-sonnet-4-5_anthropic_/messages"
assert transaction["endpoint"] == "/messages"
@pytest.mark.asyncio
async def test_update_daily_spend_logs_detailed_error_on_batch_upsert_failure():
"""

View file

@ -1485,7 +1485,7 @@ async def test_route_request_keeps_key_fallbacks_out_of_pass_through_provider_bo
("atranscription", "file", "/audio/transcriptions"),
("arerank", "query", "/rerank"),
("acompact_responses", "input", "/responses/compact"),
("anthropic_messages", "messages", "anthropic_messages"),
("anthropic_messages", "messages", "/messages"),
("agenerate_content", "contents", "agenerate_content"),
("aocr", "document", "/ocr"),
("avector_store_search", "query", "avector_store_search"),