Skip to content

fix(qdrant): restore search instrumentation on qdrant-client >= 1.12 - #4470

Open
basil-k-aji-dev wants to merge 1 commit into
traceloop:mainfrom
basil-k-aji-dev:fix/qdrant-async-query-instrumentation
Open

basil-k-aji-dev wants to merge 1 commit into
traceloop:mainfrom
basil-k-aji-dev:fix/qdrant-async-query-instrumentation

Conversation

@basil-k-aji-dev

Copy link
Copy Markdown
  • I have added tests that cover my changes.
  • If adding a new instrumentation or changing an existing one, I've added screenshots from some observability platform showing the change.
  • PR name follows conventional commits format: feat(instrumentation): ... or fix(instrumentation): ....
  • (If applicable) I have updated the documentation accordingly.

No screenshots: the change is the absence vs. presence of spans, which the added tests assert directly. Happy to attach a trace view if you'd prefer.


The problem

AsyncQdrantClient emits no search spans at all on qdrant-client >= 1.12.

Every search method in async_qdrant_client_methods.jsonsearch, search_batch, search_groups, query, query_batch, discover, discover_batch, recommend, recommend_batch, recommend_groups — was removed from qdrant-client in 1.12. The modern replacements were added to the sync list but never to the async one.

Because _instrument() guards each wrap with hasattr, nothing raises. The instrumentor just silently wraps nothing:

Async search-path coverage on qdrant-client 1.19.0

  search                 exists=False  instrumented=True
  search_batch           exists=False  instrumented=True
  search_groups          exists=False  instrumented=True
  query                  exists=False  instrumented=True
  query_batch            exists=False  instrumented=True
  discover               exists=False  instrumented=True
  discover_batch         exists=False  instrumented=True
  recommend              exists=False  instrumented=True
  recommend_batch        exists=False  instrumented=True
  recommend_groups       exists=False  instrumented=True
  query_points           exists=True   instrumented=False
  query_batch_points     exists=True   instrumented=False
  query_points_groups    exists=True   instrumented=False

Across both lists, 24 of 48 entries no longer resolve. The sync client is largely fine — query_points and query_batch_points are listed — but it is missing query_points_groups, so grouped queries are untraced there too.

This went unnoticed because the test dependency group pins qdrant-client>=1.9.1,<1.12, so CI has never run against a client where these methods are absent.

The fix

  • Add query_points, query_points_groups and query_batch_points to the async list; add query_points_groups to the sync list.
  • Route query_points_groups through _set_search_attributes, and map its collection-name attribute to search_groups, matching the existing query_pointssearch and query_batch_pointssearch_batch mappings.
  • Lift the test pin to qdrant-client>=1.12.
  • Add tests/test_method_coverage.py: asserts the sync and async lists stay in parity, that the modern query surface is covered, and that every non-legacy entry resolves against the installed client — so this cannot silently rot again.

Legacy entries are deliberately kept. The package declares qdrant-client >= 1.7, where those methods still exist and are still worth tracing. The hasattr guard makes them harmless on newer clients. The new coverage test excludes them explicitly.

On #3492

This started from #3492, which reports AttributeError: type object 'QdrantClient' has no attribute 'upload_records'. That crash no longer reproduces — the hasattr guard in _instrument() fixed it after v0.48.1. What the guard did was convert a loud failure into silent span loss, which is what this PR addresses. Happy to retitle or split if you'd rather track that separately.

Note on uv.lock

The lockfile is regenerated for the dependency change. Its requires-python was stale at ">=3.9, <4" while pyproject.toml already declared ">=3.10,<4", so the Python 3.9 wheel entries drop out. That is a lockfile realignment, not a change to supported Python versions.

Verification

8/8 tests pass against qdrant-client 1.19.0, ruff clean. The new coverage tests fail against the pre-fix method lists and pass after:

 parity  : FAIL -> sync-only: ['query_batch_points', 'query_points']
 req sync : FAIL -> missing ['query_points_groups']
 req async: FAIL -> missing ['query_batch_points', 'query_points', 'query_points_groups']

Possible follow-ups

retrieve, count, facet and search_matrix_pairs/search_matrix_offsets are public data-plane operations that are currently untraced. Left out to keep this focused — glad to add them in a separate PR if wanted.

AsyncQdrantClient emitted no search spans at all on qdrant-client 1.12+.
Every search method in its wrapped-method list (search, search_batch,
search_groups, query, query_batch, discover, discover_batch, recommend,
recommend_batch, recommend_groups) was removed upstream in 1.12, and the
modern replacements were never added to the async list. The hasattr guard
in _instrument() skips the missing ones, so this degraded silently rather
than raising.

Add query_points, query_points_groups and query_batch_points to the async
list, and query_points_groups to the sync list. Legacy entries are kept:
the package declares support for qdrant-client >= 1.7, where they exist.

The test group pinned qdrant-client >= 1.9.1, < 1.12, so CI never ran
against a client where these methods were absent. Lift the pin to >= 1.12
and add tests asserting the sync and async lists stay in parity, that the
modern query surface is covered, and that non-legacy entries resolve on
the installed client.

Note: uv.lock is regenerated here. Its requires-python was stale at
">=3.9, <4" while pyproject.toml already declared ">=3.10,<4", so the
py39 wheel entries drop out. This is a lockfile realignment, not a change
to supported Python versions.

Fixes traceloop#3492

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Sep 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants