litellm/tests/unit/proxy/telemetry/test_blocks.py
devin-ai-integration[bot] bfcb0ff474
feat(telemetry): record proxy requests and provider attempts into the telemetry sink (#45489)
* feat(telemetry): record proxy requests and provider attempts into the telemetry sink

* fix(telemetry): validate env settings, fix the window and only record the request's own provider calls

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(telemetry): bind the call id from a typed local

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(telemetry): record a finished request into the sink current when it finishes

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(telemetry): record every failed provider attempt, including retries and fallbacks on a shared logging object

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(telemetry): report timeouts and connection failures as their own provider status classes

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(telemetry): record failed attempts from the per-deployment failure hook instead of a new core logging hook

Reverts the async_log_attempt_failure_event hook added to CustomLogger and
litellm_logging in 3421b38685. The router already calls
async_post_call_failure_deployment_hook once per failed attempt, retries and
fallbacks included, so every failed fallback still gets its own row without
touching the shared logging object.

* fix(telemetry): register the attempt logger only once a telemetry group is turned on

A proxy that never opts in now carries no telemetry callback. Once registered
the logger stays, returning early while every group is off.

---------

Co-authored-by: nate <nate@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-13 18:46:06 -07:00

37 lines
1.2 KiB
Python

from typing import Final
import pytest
from litellm.proxy.telemetry.blocks import count_blocks
from litellm.telemetry.records import BlockCounts, BlockType
def test_counts_string_content_part_lists_tool_calls_and_tool_messages() -> None:
messages: Final = [
{"role": "system", "content": "be brief"},
{
"role": "user",
"content": [
{"type": "text", "text": "what is in this picture"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,AAAA"}},
{"type": "something_new"},
],
},
{"role": "assistant", "content": None, "tool_calls": [{"id": "a"}, {"id": "b"}]},
{"role": "tool", "content": "42", "tool_call_id": "a"},
]
assert count_blocks(messages) == BlockCounts(
total=7,
by_type=(
(BlockType.IMAGE, 1),
(BlockType.OTHER, 1),
(BlockType.TEXT, 2),
(BlockType.TOOL_RESULT, 1),
(BlockType.TOOL_USE, 2),
),
)
@pytest.mark.parametrize("messages", [None, "a prompt string", [{"content": "no role"}]])
def test_anything_that_is_not_a_message_list_has_no_block_counts(messages: object) -> None:
assert count_blocks(messages) is None