diff --git a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/__init__.py b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/__init__.py index 2812218456..e45eea54dd 100644 --- a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/__init__.py +++ b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/__init__.py @@ -51,7 +51,9 @@ def _instrument(self, **kwargs): for wrapped_method in WRAPPED_METHODS: wrap_object = wrapped_method.get("object") wrap_method = wrapped_method.get("method") - if getattr(qdrant_client, wrap_object, None): + wrapped_object = getattr(qdrant_client, wrap_object, None) + + if wrapped_object and hasattr(wrapped_object, wrap_method): wrap_function_wrapper( MODULE, f"{wrap_object}.{wrap_method}", diff --git a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/async_qdrant_client_methods.json b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/async_qdrant_client_methods.json index ec161a5ee6..8a7fb53032 100644 --- a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/async_qdrant_client_methods.json +++ b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/async_qdrant_client_methods.json @@ -49,6 +49,21 @@ "method": "query_batch", "span_name": "qdrant.query_batch" }, + { + "object": "AsyncQdrantClient", + "method": "query_batch_points", + "span_name": "qdrant.query_batch_points" + }, + { + "object": "AsyncQdrantClient", + "method": "query_points", + "span_name": "qdrant.query_points" + }, + { + "object": "AsyncQdrantClient", + "method": "query_points_groups", + "span_name": "qdrant.query_points_groups" + }, { "object": "AsyncQdrantClient", "method": "discover", @@ -114,4 +129,4 @@ "method": "batch_update_points", "span_name": "qdrant.batch_update_points" } -] \ No newline at end of file +] diff --git a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/qdrant_client_methods.json b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/qdrant_client_methods.json index a5295f2aca..d7240da8cf 100644 --- a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/qdrant_client_methods.json +++ b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/qdrant_client_methods.json @@ -49,6 +49,21 @@ "method": "query_batch", "span_name": "qdrant.query_batch" }, + { + "object": "QdrantClient", + "method": "query_batch_points", + "span_name": "qdrant.query_batch_points" + }, + { + "object": "QdrantClient", + "method": "query_points", + "span_name": "qdrant.query_points" + }, + { + "object": "QdrantClient", + "method": "query_points_groups", + "span_name": "qdrant.query_points_groups" + }, { "object": "QdrantClient", "method": "discover", @@ -114,4 +129,4 @@ "method": "batch_update_points", "span_name": "qdrant.batch_update_points" } -] \ No newline at end of file +] diff --git a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/version.py b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/version.py index 7f532dc4ae..4d8afa5ba7 100644 --- a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/version.py +++ b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/version.py @@ -1 +1 @@ -__version__ = "0.44.1" +__version__ = "0.45.0" diff --git a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/wrapper.py b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/wrapper.py index b1a694b042..cc88bec5d5 100644 --- a/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/wrapper.py +++ b/packages/opentelemetry-instrumentation-qdrant/opentelemetry/instrumentation/qdrant/wrapper.py @@ -62,11 +62,13 @@ def _wrap(tracer, to_wrap, wrapped, instance, args, kwargs): "search_groups", "query", "discover", + "query_points", + "query_points_groups", "recommend", "recommend_groups", ]: _set_search_attributes(span, args, kwargs) - elif method in ["search_batch", "recommend_batch", "discover_batch"]: + elif method in ["search_batch", "recommend_batch", "discover_batch", "query_batch_points"]: _set_batch_search_attributes(span, args, kwargs, method) response = wrapped(*args, **kwargs) diff --git a/packages/opentelemetry-instrumentation-qdrant/pyproject.toml b/packages/opentelemetry-instrumentation-qdrant/pyproject.toml index 38ff3122c6..8c556dd336 100644 --- a/packages/opentelemetry-instrumentation-qdrant/pyproject.toml +++ b/packages/opentelemetry-instrumentation-qdrant/pyproject.toml @@ -8,7 +8,7 @@ show_missing = true [tool.poetry] name = "opentelemetry-instrumentation-qdrant" -version = "0.44.1" +version = "0.45.0" description = "OpenTelemetry Qdrant instrumentation" authors = [ "Gal Kleinman ", @@ -27,7 +27,7 @@ python = ">=3.9,<4" opentelemetry-api = "^1.28.0" opentelemetry-instrumentation = ">=0.50b0" opentelemetry-semantic-conventions = ">=0.50b0" -opentelemetry-semantic-conventions-ai = "0.4.11" +opentelemetry-semantic-conventions-ai = "0.4.13" [tool.poetry.group.dev.dependencies] autopep8 = "^2.2.0" diff --git a/packages/opentelemetry-instrumentation-qdrant/tests/test_qdrant_instrumentation.py b/packages/opentelemetry-instrumentation-qdrant/tests/test_qdrant_instrumentation.py index b07be02b3b..ea944b04d7 100644 --- a/packages/opentelemetry-instrumentation-qdrant/tests/test_qdrant_instrumentation.py +++ b/packages/opentelemetry-instrumentation-qdrant/tests/test_qdrant_instrumentation.py @@ -2,7 +2,6 @@ from qdrant_client import QdrantClient, models from opentelemetry.semconv_ai import SpanAttributes - # This fixture returns an empty in-memroy QdrantClient instance for each test @pytest.fixture def qdrant(): @@ -106,7 +105,7 @@ def search_batch(qdrant: QdrantClient): ) -def test_qdrant_search(exporter, qdrant): +def test_qdrant_search_batch(exporter, qdrant): upload_collection(qdrant) search_batch(qdrant) @@ -118,3 +117,81 @@ def test_qdrant_search(exporter, qdrant): == COLLECTION_NAME ) assert span.attributes.get(SpanAttributes.QDRANT_SEARCH_BATCH_REQUESTS_COUNT) == 4 + + +def query_points(qdrant: QdrantClient): + from opentelemetry.instrumentation.qdrant import version + print(f"Qdrant Instrumentation Version: {version.__version__}") + + qdrant.query_points(COLLECTION_NAME, query=[0.1] * EMBEDDING_DIM, limit=1) + + +def test_qdrant_query_points(exporter, qdrant): + if not hasattr(qdrant, "query_points"): + pytest.skip("query_points method is not available in this QdrantClient version, available in qdrant-client v1.10.0 and later") + + upload_collection(qdrant) + query_points(qdrant) + + spans = exporter.get_finished_spans() + span = next(span for span in spans if span.name == "qdrant.query_points") + + assert ( + span.attributes.get(SpanAttributes.QDRANT_QUERY_POINTS_COLLECTION_NAME) + == COLLECTION_NAME + ) + assert span.attributes.get(SpanAttributes.VECTOR_DB_QUERY_TOP_K) == 1 + + +def query_batch_points(qdrant: QdrantClient): + qdrant.query_batch_points( + COLLECTION_NAME, + requests=[ + models.QueryRequest(query=[0.1] * EMBEDDING_DIM, limit=10), + models.QueryRequest(query=[0.2] * EMBEDDING_DIM, limit=5), + models.QueryRequest(query=[0.42] * EMBEDDING_DIM, limit=2), + models.QueryRequest(query=[0.21] * EMBEDDING_DIM, limit=1), + ], + ) + + +def test_qdrant_query_batch_points(exporter, qdrant): + if not hasattr(qdrant, "query_batch_points"): + pytest.skip("query_batch_points method is not available in this qdrant-client version, available in qdrant-client v1.10.0 and later") + + upload_collection(qdrant) + query_batch_points(qdrant) + + spans = exporter.get_finished_spans() + span = next(span for span in spans if span.name == "qdrant.query_batch_points") + + assert ( + span.attributes.get(SpanAttributes.QDRANT_QUERY_BATCH_POINTS_COLLECTION_NAME) + == COLLECTION_NAME + ) + assert span.attributes.get(SpanAttributes.QDRANT_QUERY_BATCH_POINTS_REQUESTS_COUNT) == 4 + + +def query_points_groups(qdrant: QdrantClient): + from opentelemetry.instrumentation.qdrant import version + print(f"Qdrant Instrumentation Version: {version.__version__}") + + qdrant.query_points_groups(COLLECTION_NAME, query=[0.1] * EMBEDDING_DIM, limit=1, group_by="id") + + +def test_qdrant_query_points_groups(exporter, qdrant): + if not hasattr(qdrant, "query_points_groups"): + pytest.skip("query_points_groups method is not available in this qdrant-client version, available in qdrant-client v1.11.0 and later") + + upload_collection(qdrant) + query_points_groups(qdrant) + + spans = exporter.get_finished_spans() + span = next(span for span in spans if span.name == "qdrant.query_points_groups") + + assert ( + span.attributes.get(SpanAttributes.QDRANT_QUERY_POINTS_GROUPS_COLLECTION_NAME) + == COLLECTION_NAME + ) + assert span.attributes.get(SpanAttributes.VECTOR_DB_QUERY_TOP_K) == 1 +