From b4a16d0d93cafd4d297f98331484b3cb3cf8da33 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Thu, 23 May 2024 11:59:28 +0530 Subject: [PATCH 01/19] feat: Qdrant instrumentation --- .python-version | 1 + package-lock.json | 45 ++- packages/instrumentation-qdrant/.eslintignore | 1 + .../instrumentation-qdrant/.eslintrc.json | 18 ++ .../instrumentation-qdrant/.prettierignore | 2 + packages/instrumentation-qdrant/README.md | 55 ++++ packages/instrumentation-qdrant/package.json | 51 +++ .../instrumentation-qdrant/rollup.config.js | 37 +++ packages/instrumentation-qdrant/src/index.ts | 18 ++ .../src/instrumentation.ts | 293 ++++++++++++++++++ packages/instrumentation-qdrant/src/types.ts | 14 + .../tests/instrumentation.test.ts | 90 ++++++ packages/instrumentation-qdrant/tsconfig.json | 10 + packages/traceloop-sdk/package.json | 2 + .../initialize-options.interface.ts | 2 + .../traceloop-sdk/src/lib/tracing/index.ts | 11 + 16 files changed, 640 insertions(+), 10 deletions(-) create mode 100644 .python-version create mode 100644 packages/instrumentation-qdrant/.eslintignore create mode 100644 packages/instrumentation-qdrant/.eslintrc.json create mode 100644 packages/instrumentation-qdrant/.prettierignore create mode 100644 packages/instrumentation-qdrant/README.md create mode 100644 packages/instrumentation-qdrant/package.json create mode 100644 packages/instrumentation-qdrant/rollup.config.js create mode 100644 packages/instrumentation-qdrant/src/index.ts create mode 100644 packages/instrumentation-qdrant/src/instrumentation.ts create mode 100644 packages/instrumentation-qdrant/src/types.ts create mode 100755 packages/instrumentation-qdrant/tests/instrumentation.test.ts create mode 100644 packages/instrumentation-qdrant/tsconfig.json diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..9919bf8c --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10.13 diff --git a/package-lock.json b/package-lock.json index f25d6721..ceda22d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6480,20 +6480,20 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@qdrant/js-client-rest": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.7.0.tgz", - "integrity": "sha512-16O0EQfrrybcPVipodxykr6dMUlBzKW7a63cSDUFVgc5a1AWESwERykwjuvW5KqvKdkPcxZ2NssrvgUO1W3MgA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@qdrant/js-client-rest/-/js-client-rest-1.9.0.tgz", + "integrity": "sha512-YiX/IskbRCoAY2ujyPDI6FBcO0ygAS4pgkGaJ7DcrJFh4SZV2XHs+u0KM7mO72RWJn1eJQFF2PQwxG+401xxJg==", "dependencies": { - "@qdrant/openapi-typescript-fetch": "^1.2.1", - "@sevinf/maybe": "^0.5.0", - "undici": "^5.26.2" + "@qdrant/openapi-typescript-fetch": "1.2.6", + "@sevinf/maybe": "0.5.0", + "undici": "~5.28.4" }, "engines": { "node": ">=18.0.0", "pnpm": ">=8" }, "peerDependencies": { - "typescript": ">=4.1" + "typescript": ">=4.7" } }, "node_modules/@qdrant/openapi-typescript-fetch": { @@ -7956,6 +7956,10 @@ "resolved": "packages/instrumentation-pinecone", "link": true }, + "node_modules/@traceloop/instrumentation-qdrant": { + "resolved": "packages/instrumentation-qdrant", + "link": true + }, "node_modules/@traceloop/instrumentation-vertexai": { "resolved": "packages/instrumentation-vertexai", "link": true @@ -21829,9 +21833,9 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" }, "node_modules/undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -23500,6 +23504,25 @@ "module-details-from-path": "^1.0.3" } }, + "packages/instrumentation-qdrant": { + "name": "@traceloop/instrumentation-qdrant", + "version": "0.8.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.44.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "devDependencies": { + "@pollyjs/adapter-node-http": "^6.0.6", + "@pollyjs/core": "^6.0.6", + "@pollyjs/persister-fs": "^6.0.6", + "@qdrant/js-client-rest": "^1.9.0" + }, + "engines": { + "node": ">=14" + } + }, "packages/instrumentation-vertexai": { "name": "@traceloop/instrumentation-vertexai", "version": "0.8.0", @@ -24155,6 +24178,7 @@ "@traceloop/instrumentation-llamaindex": "^0.8.0", "@traceloop/instrumentation-openai": "^0.8.2", "@traceloop/instrumentation-pinecone": "^0.8.3", + "@traceloop/instrumentation-qdrant": "^0.8.1", "@traceloop/instrumentation-vertexai": "^0.8.0", "@types/nunjucks": "^3.2.5", "cross-fetch": "^4.0.0", @@ -24174,6 +24198,7 @@ "@pollyjs/adapter-node-http": "^6.0.6", "@pollyjs/core": "^6.0.6", "@pollyjs/persister-fs": "^6.0.6", + "@qdrant/js-client-rest": "^1.9.0", "@types/mocha": "^10.0.6", "@types/node": "^20.9.0", "@types/uuid": "^9.0.7", diff --git a/packages/instrumentation-qdrant/.eslintignore b/packages/instrumentation-qdrant/.eslintignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/packages/instrumentation-qdrant/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/packages/instrumentation-qdrant/.eslintrc.json b/packages/instrumentation-qdrant/.eslintrc.json new file mode 100644 index 00000000..9d9c0db5 --- /dev/null +++ b/packages/instrumentation-qdrant/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/packages/instrumentation-qdrant/.prettierignore b/packages/instrumentation-qdrant/.prettierignore new file mode 100644 index 00000000..258e27f6 --- /dev/null +++ b/packages/instrumentation-qdrant/.prettierignore @@ -0,0 +1,2 @@ +/dist +/coverage \ No newline at end of file diff --git a/packages/instrumentation-qdrant/README.md b/packages/instrumentation-qdrant/README.md new file mode 100644 index 00000000..3ff69398 --- /dev/null +++ b/packages/instrumentation-qdrant/README.md @@ -0,0 +1,55 @@ +# OpenTelemetry Qdrant instrumentation for Node.js + +[![NPM Published Version][npm-img]][npm-url] +[![Apache License][license-image]][license-image] + +This module provides automatic instrumentation for [`@qdrant/js-client-rest`](https://www.npmjs.com/package/@qdrant/js-client-rest) module, which may be loaded using the [`@opentelemetry/sdk-trace-node`](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package and is included in the [`@traceloop/node-server-sdk`](https://www.npmjs.com/package/@traceloop/node-server-sdk) bundle. + +If total installation size is not constrained, it is recommended to use the [`@traceloop/node-server-sdk`](https://www.npmjs.com/package/@traceloop/node-server-sdk) bundle for the most seamless instrumentation experience. + +Compatible with OpenTelemetry JS API and SDK `1.0+`. + +## Installation + +```bash +npm install --save @traceloop/instrumentation-qdrant +``` + +## Supported Versions + +- `>=1.9.0` + +## Usage + +To load a specific plugin, specify it in the registerInstrumentations's configuration: + +```js +const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); +const { + QdrantInstrumentation, +} = require("@traceloop/instrumentation-qdrant"); +const { registerInstrumentations } = require("@opentelemetry/instrumentation"); + +const provider = new NodeTracerProvider(); +provider.register(); + +registerInstrumentations({ + instrumentations: [new QdrantInstrumentation()], +}); +``` + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about OpenTelemetry JavaScript: +- For help or feedback on this project, join us on [Slack][slack-url] + +## License + +Apache 2.0 - See [LICENSE][license-url] for more information. + +[slack-url]: https://traceloop.com/slack +[license-url]: https://github.com/traceloop/openllmetry-js/blob/main/LICENSE +[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat +[npm-url]: https://www.npmjs.com/package/@traceloop/instrumentation-qdrant +[npm-img]: https://badge.fury.io/js/%40traceloop%2Finstrumentation-qdrant.svg diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json new file mode 100644 index 00000000..0b8f7dc4 --- /dev/null +++ b/packages/instrumentation-qdrant/package.json @@ -0,0 +1,51 @@ +{ + "name": "@traceloop/instrumentation-qdrant", + "version": "0.8.1", + "description": "Qdrant Instrumentation", + "main": "dist/src/index.js", + "types": "dist/src/index.d.ts", + "repository": "traceloop/openllmetry-js", + "scripts": { + "build": "rollup -c", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "test": "ts-mocha -p tsconfig.json 'tests/**/*.test.ts' --timeout 20000" + }, + "keywords": [ + "opentelemetry", + "nodejs", + "tracing", + "attributes", + "semantic conventions" + ], + "author": "Qdrant Team ", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "files": [ + "dist/src/**/*.js", + "dist/src/**/*.js.map", + "dist/src/**/*.d.ts", + "doc", + "LICENSE", + "README.md", + "package.json" + ], + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.44.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "devDependencies": { + "@pollyjs/adapter-node-http": "^6.0.6", + "@pollyjs/core": "^6.0.6", + "@pollyjs/persister-fs": "^6.0.6", + "@qdrant/js-client-rest": "^1.9.0" + }, + "homepage": "https://github.com/traceloop/openllmetry-js/tree/main/packages/instrumentation-qdrant", + "gitHead": "ef1e70d6037f7b5c061056ef2be16e3f55f02ed5" +} diff --git a/packages/instrumentation-qdrant/rollup.config.js b/packages/instrumentation-qdrant/rollup.config.js new file mode 100644 index 00000000..691c0ca5 --- /dev/null +++ b/packages/instrumentation-qdrant/rollup.config.js @@ -0,0 +1,37 @@ +const dts = require("rollup-plugin-dts"); +const typescript = require("@rollup/plugin-typescript"); +const json = require("@rollup/plugin-json"); + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const name = require("./package.json").main.replace(/\.js$/, ""); + +const bundle = (config) => ({ + ...config, + input: "src/index.ts", + external: (id) => !/^[./]/.test(id), +}); + +exports.default = [ + bundle({ + plugins: [typescript.default(), json.default()], + output: [ + { + file: `${name}.js`, + format: "cjs", + sourcemap: true, + }, + { + file: `${name}.mjs`, + format: "es", + sourcemap: true, + }, + ], + }), + bundle({ + plugins: [dts.default()], + output: { + file: `${name}.d.ts`, + format: "es", + }, + }), +]; diff --git a/packages/instrumentation-qdrant/src/index.ts b/packages/instrumentation-qdrant/src/index.ts new file mode 100644 index 00000000..f104515f --- /dev/null +++ b/packages/instrumentation-qdrant/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Traceloop + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from "./instrumentation"; +export * from "./types"; diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts new file mode 100644 index 00000000..aa4afa0b --- /dev/null +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -0,0 +1,293 @@ +/* + * Copyright Traceloop + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + Span, + SpanKind, + SpanStatusCode, + context, + trace, +} from "@opentelemetry/api"; +import { + InstrumentationBase, + InstrumentationModuleDefinition, + InstrumentationNodeModuleDefinition, + safeExecuteInTheMiddle, +} from "@opentelemetry/instrumentation"; +import { QdrantInstrumentationConfig } from "./types"; +import * as qdrant from "@qdrant/js-client-rest"; +import { version } from "../package.json"; + +export class QdrantInstrumentation extends InstrumentationBase { + protected declare _config: QdrantInstrumentationConfig; + + constructor(config: QdrantInstrumentationConfig = {}) { + super("@traceloop/instrumentation-qdrant", version, config); + } + + public override setConfig(config: QdrantInstrumentationConfig = {}) { + super.setConfig(config); + } + + protected init(): InstrumentationModuleDefinition { + const module = new InstrumentationNodeModuleDefinition( + "@qdrant/js-client-rest", + ["^1.9"], + this.wrap.bind(this), + this.unwrap.bind(this), + ); + + return module; + } + + public manuallyInstrument(module: typeof qdrant) { + this._diag.debug(`Manually patching Qdrant`); + this.wrap(module); + } + + private wrap(module: typeof qdrant) { + this._wrap(module.QdrantClient.prototype, "upsert", this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, "retrieve", this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, "search", this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, "delete", this.wrapperMethod()); + + return module; + } + + private unwrap(module: typeof qdrant) { + this._unwrap(module.QdrantClient.prototype, "upsert"); + this._unwrap(module.QdrantClient.prototype, "retrieve"); + this._unwrap(module.QdrantClient.prototype, "search"); + this._unwrap(module.QdrantClient.prototype, "delete"); + + return module; + } + + private wrapperMethod() { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const plugin = this; + // eslint-disable-next-line @typescript-eslint/ban-types + return (original: Function) => { + return function method(this: any, ...args: any) { + const span = plugin._startSpan({ + collectionName: args[0], + params: args.length > 1 ? args[1] : {}, + methodName: original.name, + }); + const execContext = trace.setSpan(context.active(), span); + const execPromise = safeExecuteInTheMiddle( + () => { + return context.with(execContext, () => { + return original.apply(this, args); + }); + }, + () => null, + ); + const wrappedPromise = plugin._wrapPromise( + original.name, + span, + execPromise, + ); + return context.bind(execContext, wrappedPromise as any); + }; + }; + } + + private _wrapPromise( + methodName: string, + span: Span, + promise: Promise, + ): Promise { + return promise + .then(async (result) => { + + const awaitedResult = (await result); + + this._endSpan({ + methodName, + span, + result: awaitedResult, + }); + + return new Promise((resolve) => { + resolve(result); + }); + }) + .catch((error: Error) => { + return new Promise((_, reject) => { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error.message, + }); + span.recordException(error); + reject(error); + }); + }) + .finally(() => { + span.end(); + }); + } + + private _startSpan({ + collectionName, + params, + methodName, + }: { + collectionName: string; + params: + | qdrant.Schemas["PointInsertOperations"] + | qdrant.Schemas["PointsSelector"] + | qdrant.Schemas["PointRequest"] + | qdrant.Schemas['SearchRequest'] + + methodName: string; + }): Span { + const span = this.tracer.startSpan(`qdrant.${collectionName}.${methodName}`, { + kind: SpanKind.CLIENT + }); + + try { + if (this._config.traceContent) { + if (methodName === "upsert") { + this._setUpsertAttributes( + span, + params as qdrant.Schemas["PointInsertOperations"], + methodName, + ); + } + else if (methodName === "delete") { + this._setDeleteAttributes(span, params as qdrant.Schemas["PointsSelector"]); + } + else if (methodName === "retrieve") { + this._setRetrieveAttributes(span, params as qdrant.Schemas["PointRequest"]); + } + + else if (methodName === "search") { + this._setSearchAttributes(span, params as qdrant.Schemas["SearchRequest"]); + } + } + } catch (e) { + this._diag.warn(e); + this._config.exceptionLogger?.(e); + } + + return span; + } + + + private _setUpsertAttributes( + span: Span, + params: qdrant.Schemas["PointInsertOperations"], + method: "add" | "update" | "upsert", + ) { + + if ("batch" in params) { + span.setAttribute( + `db.qdrant.${method}.points_count`, + JSON.stringify(params.batch.ids?.length), + ); + } + + else { + span.setAttribute( + `db.qdrant.${method}.points_count`, + JSON.stringify(params.points?.length), + ); + } + } + + private _setDeleteAttributes(span: Span, params: qdrant.Schemas["PointsSelector"]) { + if ("filter" in params) { + span.setAttribute( + "db.qdrant.delete.filter.must", + JSON.stringify(params.filter?.must), + ); + + span.setAttribute( + "db.qdrant.delete.filter.should", + JSON.stringify(params.filter?.should), + ); + + span.setAttribute( + "db.qdrant.delete.filter.must_not", + JSON.stringify(params.filter?.must_not), + ); + + span.setAttribute( + "db.qdrant.delete.filter.min_should", + JSON.stringify(params.filter?.min_should), + ); + } + + else { + span.setAttribute( + "db.qdrant.delete.point_ids", + JSON.stringify(params.points), + ); + } + } + + private _setRetrieveAttributes(span: Span, params: qdrant.Schemas["PointRequest"]) { + span.setAttribute( + "db.qdrant.retrieve.ids_count", + JSON.stringify(params.ids?.length), + ); + span.setAttribute("db.qdrant.retrieve.with_payload", JSON.stringify(params.with_payload)); + span.setAttribute("db.qdrant.retrieve.with_vector", JSON.stringify(params.with_vector)); + } + + private _setSearchAttributes(span: Span, params: qdrant.Schemas["SearchRequest"]) { + span.setAttribute( + "db.qdrant.search.query_vector", + JSON.stringify(params.vector), + ); + span.setAttribute( + "db.qdrant.search.limit", + JSON.stringify(params.limit), + ); + span.setAttribute( + "db.qdrant.search.offset", + JSON.stringify(params.offset), + ); + span.setAttribute( + "db.qdrant.search.score_threshold", + JSON.stringify(params.score_threshold), + ); + + span.setAttribute("db.qdrant.search.filter", + JSON.stringify(params.filter), + ); + } + + private _endSpan({ + methodName, + span, + result, + }: { + methodName: string; + span: Span; + result: any; + }): void { + try { + // Pass + } catch (e) { + this._diag.warn(e); + this._config.exceptionLogger?.(e); + } + + span.setStatus({ code: SpanStatusCode.OK }); + span.end(); + } +} diff --git a/packages/instrumentation-qdrant/src/types.ts b/packages/instrumentation-qdrant/src/types.ts new file mode 100644 index 00000000..45c0b60e --- /dev/null +++ b/packages/instrumentation-qdrant/src/types.ts @@ -0,0 +1,14 @@ +import { InstrumentationConfig } from "@opentelemetry/instrumentation"; + +export interface QdrantInstrumentationConfig extends InstrumentationConfig { + /** + * Whether to log prompts, completions and embeddings on traces. + * @default true + */ + traceContent?: boolean; + + /** + * A custom logger to log any exceptions that happen during span creation. + */ + exceptionLogger?: (e: Error) => void; +} diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts new file mode 100755 index 00000000..8a8f9554 --- /dev/null +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright Traceloop + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { context } from "@opentelemetry/api"; +import { AsyncHooksContextManager } from "@opentelemetry/context-async-hooks"; +import { QdrantInstrumentation } from "../src/instrumentation"; +import { + BasicTracerProvider, + InMemorySpanExporter, + SimpleSpanProcessor, +} from "@opentelemetry/sdk-trace-base"; +import * as qdrant from "@qdrant/js-client-rest"; + +const COLLECTION_NAME = "some_collection"; + +const memoryExporter = new InMemorySpanExporter(); + +describe("Test Qdrant instrumentation", function () { + const provider = new BasicTracerProvider(); + let instrumentation: QdrantInstrumentation; + let contextManager: AsyncHooksContextManager; + const qdrantClient: qdrant.QdrantClient = new qdrant.QdrantClient({ url: 'http://127.0.0.1:6333' }); + + before(async () => { + provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); + instrumentation = new QdrantInstrumentation({ traceContent: true }); + instrumentation.setTracerProvider(provider); + instrumentation.manuallyInstrument(qdrant); + }); + + beforeEach(async function () { + contextManager = new AsyncHooksContextManager().enable(); + context.setGlobalContextManager(contextManager); + memoryExporter.reset(); + + + qdrantClient.createCollection(COLLECTION_NAME, { + vectors: { + size: 3, + distance: "Cosine", + } + }) + }); + + afterEach(async () => { + await qdrantClient.deleteCollection(COLLECTION_NAME); + memoryExporter.reset(); + context.disable(); + }); + + + it("should set span attributes for Upsert", async () => { + const points = + { + batch: { + ids: [32, 23], + vectors: [ + [1.5, 2.9, 3.4], + [9.8, 2.3, 2.9], + ], + payloads: [{ style: "style3" }, { style: "style4" }], + } + }; + + qdrantClient.upsert(COLLECTION_NAME, points); + + const spans = memoryExporter.getFinishedSpans(); + + // const attributes = spans[0].attributes; + + // assert.strictEqual( + // attributes["db.qdrant.upsert.points_count"], + // JSON.stringify(points.batch.ids.length), + // ); + }); + +}); diff --git a/packages/instrumentation-qdrant/tsconfig.json b/packages/instrumentation-qdrant/tsconfig.json new file mode 100644 index 00000000..3c3ab535 --- /dev/null +++ b/packages/instrumentation-qdrant/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "." + }, + "files": [], + "include": ["src/**/*.ts", "test/**/*.ts"], + "references": [] +} diff --git a/packages/traceloop-sdk/package.json b/packages/traceloop-sdk/package.json index 121c9c85..80fde3f5 100644 --- a/packages/traceloop-sdk/package.json +++ b/packages/traceloop-sdk/package.json @@ -48,6 +48,7 @@ "@traceloop/instrumentation-llamaindex": "^0.8.0", "@traceloop/instrumentation-openai": "^0.8.2", "@traceloop/instrumentation-pinecone": "^0.8.3", + "@traceloop/instrumentation-qdrant": "^0.8.1", "@traceloop/instrumentation-vertexai": "^0.8.0", "@types/nunjucks": "^3.2.5", "cross-fetch": "^4.0.0", @@ -69,6 +70,7 @@ "@pollyjs/adapter-node-http": "^6.0.6", "@pollyjs/core": "^6.0.6", "@pollyjs/persister-fs": "^6.0.6", + "@qdrant/js-client-rest": "^1.9.0", "@types/mocha": "^10.0.6", "@types/node": "^20.9.0", "@types/uuid": "^9.0.7", diff --git a/packages/traceloop-sdk/src/lib/interfaces/initialize-options.interface.ts b/packages/traceloop-sdk/src/lib/interfaces/initialize-options.interface.ts index 61c2f57b..fa7c19ef 100644 --- a/packages/traceloop-sdk/src/lib/interfaces/initialize-options.interface.ts +++ b/packages/traceloop-sdk/src/lib/interfaces/initialize-options.interface.ts @@ -13,6 +13,7 @@ import type * as AgentsModule from "langchain/agents"; import type * as ToolsModule from "langchain/tools"; import type * as llamaindex from "llamaindex"; import type * as chromadb from "chromadb"; +import type * as qdrant from "@qdrant/js-client-rest"; /** * Options for initializing the Traceloop SDK. @@ -86,6 +87,7 @@ export interface InitializeOptions { }; llamaIndex?: typeof llamaindex; chromadb?: typeof chromadb; + qdrant?: typeof qdrant; }; /** diff --git a/packages/traceloop-sdk/src/lib/tracing/index.ts b/packages/traceloop-sdk/src/lib/tracing/index.ts index 3b11e5ea..99f1671e 100644 --- a/packages/traceloop-sdk/src/lib/tracing/index.ts +++ b/packages/traceloop-sdk/src/lib/tracing/index.ts @@ -30,6 +30,7 @@ import { CohereInstrumentation } from "@traceloop/instrumentation-cohere"; import { PineconeInstrumentation } from "@traceloop/instrumentation-pinecone"; import { LangChainInstrumentation } from "@traceloop/instrumentation-langchain"; import { ChromaDBInstrumentation } from "@traceloop/instrumentation-chromadb"; +import { QdrantInstrumentation } from "@traceloop/instrumentation-qdrant"; let _sdk: NodeSDK; let _spanProcessor: SimpleSpanProcessor | BatchSpanProcessor; @@ -44,6 +45,7 @@ let langchainInstrumentation: LangChainInstrumentation | undefined; let llamaIndexInstrumentation: LlamaIndexInstrumentation | undefined; let pineconeInstrumentation: PineconeInstrumentation | undefined; let chromadbInstrumentation: ChromaDBInstrumentation | undefined; +let qdrantInstrumentation: QdrantInstrumentation | undefined; const instrumentations: Instrumentation[] = []; @@ -93,6 +95,9 @@ export const initInstrumentations = () => { chromadbInstrumentation = new ChromaDBInstrumentation({ exceptionLogger }); instrumentations.push(chromadbInstrumentation); + + qdrantInstrumentation = new QdrantInstrumentation({ exceptionLogger }); + instrumentations.push(qdrantInstrumentation); }; export const manuallyInitInstrumentations = ( @@ -186,6 +191,12 @@ export const manuallyInitInstrumentations = ( instrumentations.push(chromadbInstrumentation); chromadbInstrumentation.manuallyInstrument(instrumentModules.chromadb); } + + if (instrumentModules?.qdrant) { + qdrantInstrumentation = new QdrantInstrumentation({ exceptionLogger }); + instrumentations.push(qdrantInstrumentation); + qdrantInstrumentation.manuallyInstrument(instrumentModules.qdrant); + } }; /** From 570e73aff47b166857d42a49f62d8b5c3984a53e Mon Sep 17 00:00:00 2001 From: Anush008 Date: Thu, 23 May 2024 12:01:43 +0530 Subject: [PATCH 02/19] docs: Updated README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 01378e2b..67461906 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ OpenLLMetry-JS can instrument everything that [OpenTelemetry already instruments - ✅ Pinecone - ✅ Chroma +- ✅ Qdrant - ⏳ Weaviate - ⏳ Milvus From 221ce02b8726082189f073aed84ccb83970f0e14 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Fri, 24 May 2024 00:16:20 +0530 Subject: [PATCH 03/19] chore: Prettier --- packages/instrumentation-qdrant/README.md | 4 +- .../src/instrumentation.ts | 94 ++++++++++--------- .../tests/instrumentation.test.ts | 16 ++-- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/packages/instrumentation-qdrant/README.md b/packages/instrumentation-qdrant/README.md index 3ff69398..963bcfa6 100644 --- a/packages/instrumentation-qdrant/README.md +++ b/packages/instrumentation-qdrant/README.md @@ -25,9 +25,7 @@ To load a specific plugin, specify it in the registerInstrumentations's configur ```js const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node"); -const { - QdrantInstrumentation, -} = require("@traceloop/instrumentation-qdrant"); +const { QdrantInstrumentation } = require("@traceloop/instrumentation-qdrant"); const { registerInstrumentations } = require("@opentelemetry/instrumentation"); const provider = new NodeTracerProvider(); diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index aa4afa0b..9bbd3d76 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -112,8 +112,7 @@ export class QdrantInstrumentation extends InstrumentationBase { ): Promise { return promise .then(async (result) => { - - const awaitedResult = (await result); + const awaitedResult = await result; this._endSpan({ methodName, @@ -147,16 +146,19 @@ export class QdrantInstrumentation extends InstrumentationBase { }: { collectionName: string; params: - | qdrant.Schemas["PointInsertOperations"] - | qdrant.Schemas["PointsSelector"] - | qdrant.Schemas["PointRequest"] - | qdrant.Schemas['SearchRequest'] + | qdrant.Schemas["PointInsertOperations"] + | qdrant.Schemas["PointsSelector"] + | qdrant.Schemas["PointRequest"] + | qdrant.Schemas["SearchRequest"]; methodName: string; }): Span { - const span = this.tracer.startSpan(`qdrant.${collectionName}.${methodName}`, { - kind: SpanKind.CLIENT - }); + const span = this.tracer.startSpan( + `qdrant.${collectionName}.${methodName}`, + { + kind: SpanKind.CLIENT, + }, + ); try { if (this._config.traceContent) { @@ -166,16 +168,21 @@ export class QdrantInstrumentation extends InstrumentationBase { params as qdrant.Schemas["PointInsertOperations"], methodName, ); - } - else if (methodName === "delete") { - this._setDeleteAttributes(span, params as qdrant.Schemas["PointsSelector"]); - } - else if (methodName === "retrieve") { - this._setRetrieveAttributes(span, params as qdrant.Schemas["PointRequest"]); - } - - else if (methodName === "search") { - this._setSearchAttributes(span, params as qdrant.Schemas["SearchRequest"]); + } else if (methodName === "delete") { + this._setDeleteAttributes( + span, + params as qdrant.Schemas["PointsSelector"], + ); + } else if (methodName === "retrieve") { + this._setRetrieveAttributes( + span, + params as qdrant.Schemas["PointRequest"], + ); + } else if (methodName === "search") { + this._setSearchAttributes( + span, + params as qdrant.Schemas["SearchRequest"], + ); } } } catch (e) { @@ -186,21 +193,17 @@ export class QdrantInstrumentation extends InstrumentationBase { return span; } - private _setUpsertAttributes( span: Span, params: qdrant.Schemas["PointInsertOperations"], method: "add" | "update" | "upsert", ) { - if ("batch" in params) { span.setAttribute( `db.qdrant.${method}.points_count`, JSON.stringify(params.batch.ids?.length), ); - } - - else { + } else { span.setAttribute( `db.qdrant.${method}.points_count`, JSON.stringify(params.points?.length), @@ -208,7 +211,10 @@ export class QdrantInstrumentation extends InstrumentationBase { } } - private _setDeleteAttributes(span: Span, params: qdrant.Schemas["PointsSelector"]) { + private _setDeleteAttributes( + span: Span, + params: qdrant.Schemas["PointsSelector"], + ) { if ("filter" in params) { span.setAttribute( "db.qdrant.delete.filter.must", @@ -229,9 +235,7 @@ export class QdrantInstrumentation extends InstrumentationBase { "db.qdrant.delete.filter.min_should", JSON.stringify(params.filter?.min_should), ); - } - - else { + } else { span.setAttribute( "db.qdrant.delete.point_ids", JSON.stringify(params.points), @@ -239,36 +243,40 @@ export class QdrantInstrumentation extends InstrumentationBase { } } - private _setRetrieveAttributes(span: Span, params: qdrant.Schemas["PointRequest"]) { + private _setRetrieveAttributes( + span: Span, + params: qdrant.Schemas["PointRequest"], + ) { span.setAttribute( "db.qdrant.retrieve.ids_count", JSON.stringify(params.ids?.length), ); - span.setAttribute("db.qdrant.retrieve.with_payload", JSON.stringify(params.with_payload)); - span.setAttribute("db.qdrant.retrieve.with_vector", JSON.stringify(params.with_vector)); - } - - private _setSearchAttributes(span: Span, params: qdrant.Schemas["SearchRequest"]) { span.setAttribute( - "db.qdrant.search.query_vector", - JSON.stringify(params.vector), + "db.qdrant.retrieve.with_payload", + JSON.stringify(params.with_payload), ); span.setAttribute( - "db.qdrant.search.limit", - JSON.stringify(params.limit), + "db.qdrant.retrieve.with_vector", + JSON.stringify(params.with_vector), ); + } + + private _setSearchAttributes( + span: Span, + params: qdrant.Schemas["SearchRequest"], + ) { span.setAttribute( - "db.qdrant.search.offset", - JSON.stringify(params.offset), + "db.qdrant.search.query_vector", + JSON.stringify(params.vector), ); + span.setAttribute("db.qdrant.search.limit", JSON.stringify(params.limit)); + span.setAttribute("db.qdrant.search.offset", JSON.stringify(params.offset)); span.setAttribute( "db.qdrant.search.score_threshold", JSON.stringify(params.score_threshold), ); - span.setAttribute("db.qdrant.search.filter", - JSON.stringify(params.filter), - ); + span.setAttribute("db.qdrant.search.filter", JSON.stringify(params.filter)); } private _endSpan({ diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts index 8a8f9554..22cbf463 100755 --- a/packages/instrumentation-qdrant/tests/instrumentation.test.ts +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -32,7 +32,9 @@ describe("Test Qdrant instrumentation", function () { const provider = new BasicTracerProvider(); let instrumentation: QdrantInstrumentation; let contextManager: AsyncHooksContextManager; - const qdrantClient: qdrant.QdrantClient = new qdrant.QdrantClient({ url: 'http://127.0.0.1:6333' }); + const qdrantClient: qdrant.QdrantClient = new qdrant.QdrantClient({ + url: "http://127.0.0.1:6333", + }); before(async () => { provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); @@ -46,13 +48,12 @@ describe("Test Qdrant instrumentation", function () { context.setGlobalContextManager(contextManager); memoryExporter.reset(); - qdrantClient.createCollection(COLLECTION_NAME, { vectors: { size: 3, distance: "Cosine", - } - }) + }, + }); }); afterEach(async () => { @@ -61,10 +62,8 @@ describe("Test Qdrant instrumentation", function () { context.disable(); }); - it("should set span attributes for Upsert", async () => { - const points = - { + const points = { batch: { ids: [32, 23], vectors: [ @@ -72,7 +71,7 @@ describe("Test Qdrant instrumentation", function () { [9.8, 2.3, 2.9], ], payloads: [{ style: "style3" }, { style: "style4" }], - } + }, }; qdrantClient.upsert(COLLECTION_NAME, points); @@ -86,5 +85,4 @@ describe("Test Qdrant instrumentation", function () { // JSON.stringify(points.batch.ids.length), // ); }); - }); From 0329f5311837b8686f4142040a51d6c021a51d47 Mon Sep 17 00:00:00 2001 From: Anush Date: Mon, 3 Jun 2024 16:59:18 +0530 Subject: [PATCH 04/19] ci: Qdrant image for test --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8607705d..03b28312 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,11 @@ jobs: build-and-test: name: Build and test runs-on: ubuntu-latest + services: + qdrant: + image: qdrant/qdrant + ports: + - 6333:6333 permissions: contents: "read" id-token: "write" From 2c4d0e14bfb4355bd4133857669365436c3824bc Mon Sep 17 00:00:00 2001 From: Nir Gazit Date: Thu, 6 Jun 2024 14:05:07 +0200 Subject: [PATCH 05/19] fix: run tests --- .../src/instrumentation.ts | 2 +- .../tests/instrumentation.test.ts | 27 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 9bbd3d76..8be655c8 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -27,7 +27,7 @@ import { safeExecuteInTheMiddle, } from "@opentelemetry/instrumentation"; import { QdrantInstrumentationConfig } from "./types"; -import * as qdrant from "@qdrant/js-client-rest"; +import type * as qdrant from "@qdrant/js-client-rest"; import { version } from "../package.json"; export class QdrantInstrumentation extends InstrumentationBase { diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts index 22cbf463..412b7152 100755 --- a/packages/instrumentation-qdrant/tests/instrumentation.test.ts +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -22,7 +22,8 @@ import { InMemorySpanExporter, SimpleSpanProcessor, } from "@opentelemetry/sdk-trace-base"; -import * as qdrant from "@qdrant/js-client-rest"; +import type * as qdrant_types from "@qdrant/js-client-rest"; +import * as assert from "assert"; const COLLECTION_NAME = "some_collection"; @@ -32,15 +33,17 @@ describe("Test Qdrant instrumentation", function () { const provider = new BasicTracerProvider(); let instrumentation: QdrantInstrumentation; let contextManager: AsyncHooksContextManager; - const qdrantClient: qdrant.QdrantClient = new qdrant.QdrantClient({ - url: "http://127.0.0.1:6333", - }); + let qdrantClient: qdrant_types.QdrantClient; before(async () => { provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); instrumentation = new QdrantInstrumentation({ traceContent: true }); instrumentation.setTracerProvider(provider); - instrumentation.manuallyInstrument(qdrant); + + const qdrant_module = await import("@qdrant/js-client-rest"); + qdrantClient = new qdrant_module.QdrantClient({ + url: "http://127.0.0.1:6333", + }); }); beforeEach(async function () { @@ -74,15 +77,17 @@ describe("Test Qdrant instrumentation", function () { }, }; - qdrantClient.upsert(COLLECTION_NAME, points); + await qdrantClient.upsert(COLLECTION_NAME, points); const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assert.strictEqual(spans[0].name, "qdrant.upsert"); - // const attributes = spans[0].attributes; + const attributes = spans[0].attributes; - // assert.strictEqual( - // attributes["db.qdrant.upsert.points_count"], - // JSON.stringify(points.batch.ids.length), - // ); + assert.strictEqual( + attributes["db.qdrant.upsert.points_count"], + JSON.stringify(points.batch.ids.length), + ); }); }); From 22af190db26d9328887ca89b92a6c22f6d66fc0d Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 10:39:51 +0530 Subject: [PATCH 06/19] test: fix creation --- packages/instrumentation-qdrant/tests/instrumentation.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts index 412b7152..9c757678 100755 --- a/packages/instrumentation-qdrant/tests/instrumentation.test.ts +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -51,7 +51,7 @@ describe("Test Qdrant instrumentation", function () { context.setGlobalContextManager(contextManager); memoryExporter.reset(); - qdrantClient.createCollection(COLLECTION_NAME, { + await qdrantClient.createCollection(COLLECTION_NAME, { vectors: { size: 3, distance: "Cosine", @@ -81,7 +81,7 @@ describe("Test Qdrant instrumentation", function () { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assert.strictEqual(spans[0].name, "qdrant.upsert"); + assert.strictEqual(spans[0].name, `qdrant.${COLLECTION_NAME}.upsert`); const attributes = spans[0].attributes; From fb0698dcd0750d43d1ea2f6cfe57a58043ab8d72 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 14:31:03 +0530 Subject: [PATCH 07/19] refactor: Qdrant instrumentation --- .../src/instrumentation.ts | 269 +++++++++++------- 1 file changed, 165 insertions(+), 104 deletions(-) diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 8be655c8..0019db84 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -29,6 +29,23 @@ import { import { QdrantInstrumentationConfig } from "./types"; import type * as qdrant from "@qdrant/js-client-rest"; import { version } from "../package.json"; +import { + SpanAttributes, + EventAttributes, +} from "@traceloop/ai-semantic-conventions"; + +const UPSERT = "upsert"; +const DELETE = "delete"; +const RETRIEVE = "retrieve"; +const SEARCH = "search"; + +type UpsertRequest = qdrant.Schemas["PointInsertOperations"]; +type DeleteRequest = qdrant.Schemas["PointsSelector"]; +type RetrieveRequest = qdrant.Schemas["PointRequest"]; +type SearchRequest = qdrant.Schemas["SearchRequest"]; +type SearchResponse = Awaited< + ReturnType +>; export class QdrantInstrumentation extends InstrumentationBase { protected declare _config: QdrantInstrumentationConfig; @@ -58,19 +75,19 @@ export class QdrantInstrumentation extends InstrumentationBase { } private wrap(module: typeof qdrant) { - this._wrap(module.QdrantClient.prototype, "upsert", this.wrapperMethod()); - this._wrap(module.QdrantClient.prototype, "retrieve", this.wrapperMethod()); - this._wrap(module.QdrantClient.prototype, "search", this.wrapperMethod()); - this._wrap(module.QdrantClient.prototype, "delete", this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, UPSERT, this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, RETRIEVE, this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, SEARCH, this.wrapperMethod()); + this._wrap(module.QdrantClient.prototype, DELETE, this.wrapperMethod()); return module; } private unwrap(module: typeof qdrant) { - this._unwrap(module.QdrantClient.prototype, "upsert"); - this._unwrap(module.QdrantClient.prototype, "retrieve"); - this._unwrap(module.QdrantClient.prototype, "search"); - this._unwrap(module.QdrantClient.prototype, "delete"); + this._unwrap(module.QdrantClient.prototype, UPSERT); + this._unwrap(module.QdrantClient.prototype, RETRIEVE); + this._unwrap(module.QdrantClient.prototype, SEARCH); + this._unwrap(module.QdrantClient.prototype, DELETE); return module; } @@ -93,95 +110,73 @@ export class QdrantInstrumentation extends InstrumentationBase { return original.apply(this, args); }); }, - () => null, - ); - const wrappedPromise = plugin._wrapPromise( - original.name, - span, - execPromise, + (e) => { + if (e) { + plugin._diag.error(`Error in Qdrant instrumentation`, e); + } + }, ); + const wrappedPromise = execPromise + .then((result: any) => { + return new Promise((resolve) => { + plugin._endSpan({ methodName: original.name, span, result }); + resolve(result); + }); + }) + .catch((error: Error) => { + return new Promise((_, reject) => { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: error.message, + }); + span.end(); + reject(error); + }); + }); return context.bind(execContext, wrappedPromise as any); }; }; } - - private _wrapPromise( - methodName: string, - span: Span, - promise: Promise, - ): Promise { - return promise - .then(async (result) => { - const awaitedResult = await result; - - this._endSpan({ - methodName, - span, - result: awaitedResult, - }); - - return new Promise((resolve) => { - resolve(result); - }); - }) - .catch((error: Error) => { - return new Promise((_, reject) => { - span.setStatus({ - code: SpanStatusCode.ERROR, - message: error.message, - }); - span.recordException(error); - reject(error); - }); - }) - .finally(() => { - span.end(); - }); - } - private _startSpan({ collectionName, params, methodName, }: { collectionName: string; - params: - | qdrant.Schemas["PointInsertOperations"] - | qdrant.Schemas["PointsSelector"] - | qdrant.Schemas["PointRequest"] - | qdrant.Schemas["SearchRequest"]; - + params: UpsertRequest | DeleteRequest | RetrieveRequest | SearchRequest; methodName: string; }): Span { - const span = this.tracer.startSpan( - `qdrant.${collectionName}.${methodName}`, - { - kind: SpanKind.CLIENT, - }, - ); + const spanName = `qdrant.${methodName}`; + const span = this.tracer.startSpan(spanName, { + kind: SpanKind.CLIENT, + }); + span.setAttribute(SpanAttributes.VECTOR_DB_VENDOR, "Qdrant"); try { if (this._config.traceContent) { - if (methodName === "upsert") { + if (methodName === UPSERT) { this._setUpsertAttributes( span, - params as qdrant.Schemas["PointInsertOperations"], - methodName, + collectionName, + params as UpsertRequest, ); - } else if (methodName === "delete") { + } else if (methodName === DELETE) { this._setDeleteAttributes( span, - params as qdrant.Schemas["PointsSelector"], + collectionName, + params as DeleteRequest, ); - } else if (methodName === "retrieve") { + } else if (methodName === RETRIEVE) { this._setRetrieveAttributes( span, - params as qdrant.Schemas["PointRequest"], + collectionName, + params as RetrieveRequest, ); - } else if (methodName === "search") { + } else if (methodName === SEARCH) { this._setSearchAttributes( span, - params as qdrant.Schemas["SearchRequest"], + collectionName, + params as SearchRequest, ); } } @@ -193,28 +188,52 @@ export class QdrantInstrumentation extends InstrumentationBase { return span; } + private _endSpan({ + methodName, + span, + result, + }: { + methodName: string; + span: Span; + result: any; + }) { + try { + if (methodName === SEARCH) { + this._setSearchResultAttributes(span, result as SearchResponse); + } + span.setStatus({ code: SpanStatusCode.OK }); + span.end(); + } catch (e) { + this._diag.debug(e); + this._config.exceptionLogger?.(e); + } + } + private _setUpsertAttributes( span: Span, + collectionName: string, params: qdrant.Schemas["PointInsertOperations"], - method: "add" | "update" | "upsert", ) { + span.setAttribute("db.qdrant.upsert.collection_name", collectionName); if ("batch" in params) { span.setAttribute( - `db.qdrant.${method}.points_count`, - JSON.stringify(params.batch.ids?.length), + `db.qdrant.upsert.points_count`, + params.batch.ids.length, ); } else { span.setAttribute( - `db.qdrant.${method}.points_count`, - JSON.stringify(params.points?.length), + `db.qdrant.upsert.points_count`, + params.points.length, ); } } private _setDeleteAttributes( span: Span, + collectionName: string, params: qdrant.Schemas["PointsSelector"], ) { + span.setAttribute("db.qdrant.delete.collection_name", collectionName); if ("filter" in params) { span.setAttribute( "db.qdrant.delete.filter.must", @@ -240,62 +259,104 @@ export class QdrantInstrumentation extends InstrumentationBase { "db.qdrant.delete.point_ids", JSON.stringify(params.points), ); + span.setAttribute( + "db.qdrant.delete.ids_count", + params.points.length, + ); } } private _setRetrieveAttributes( span: Span, + collectionName: string, params: qdrant.Schemas["PointRequest"], ) { + span.setAttribute("db.qdrant.retrieve.collection_name", collectionName); + span.setAttribute( + "db.qdrant.retrieve.point_ids", + JSON.stringify(params.ids) + ); span.setAttribute( "db.qdrant.retrieve.ids_count", - JSON.stringify(params.ids?.length), + params.ids.length, ); span.setAttribute( "db.qdrant.retrieve.with_payload", - JSON.stringify(params.with_payload), + !!params.with_payload, ); span.setAttribute( "db.qdrant.retrieve.with_vector", - JSON.stringify(params.with_vector), + !!params.with_vector, ); } private _setSearchAttributes( span: Span, + collectionName: string, params: qdrant.Schemas["SearchRequest"], ) { - span.setAttribute( - "db.qdrant.search.query_vector", + span.setAttribute("db.qdrant.search.collection_name", collectionName); + const query_request_event = span.addEvent("qdrant.search.request"); + query_request_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_TOP_K, + params.limit, + ); + query_request_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_INCLUDE_VALUES, + !!params.with_vector, + ); + query_request_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_INCLUDE_METADATA, + !!params.with_payload, + ); + query_request_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_EMBEDDINGS_VECTOR, JSON.stringify(params.vector), ); - span.setAttribute("db.qdrant.search.limit", JSON.stringify(params.limit)); - span.setAttribute("db.qdrant.search.offset", JSON.stringify(params.offset)); - span.setAttribute( - "db.qdrant.search.score_threshold", - JSON.stringify(params.score_threshold), + query_request_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_METADATA_FILTER, + JSON.stringify(params.filter ?? {}), ); - - span.setAttribute("db.qdrant.search.filter", JSON.stringify(params.filter)); } - private _endSpan({ - methodName, - span, - result, - }: { - methodName: string; - span: Span; - result: any; - }): void { - try { - // Pass - } catch (e) { - this._diag.warn(e); - this._config.exceptionLogger?.(e); - } + private _setSearchResultAttributes(span: Span, result: SearchResponse) { + const qdrant_result_event = span.addEvent("qdrant.search.result"); - span.setStatus({ code: SpanStatusCode.OK }); - span.end(); + qdrant_result_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_RESULT_MATCHES_LENGTH, + result.length, + ); + + for (let i = 0; i < result.length; i++) { + const match = result[i]; + const search_result_match_event = qdrant_result_event.addEvent( + `qdrant.search.result.${i}`, + ); + search_result_match_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_RESULT_SCORE.replace( + "{i}", + i.toString(), + ), + match.score, + ); + search_result_match_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_RESULT_ID.replace("{i}", i.toString()), + match.id, + ); + search_result_match_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_RESULT_VALUES.replace( + "{i}", + i.toString(), + ), + JSON.stringify(match.vector), + ); + search_result_match_event.setAttribute( + EventAttributes.VECTOR_DB_QUERY_RESULT_METADATA.replace( + "{i}", + i.toString(), + ), + JSON.stringify(match.payload), + ); + } } } From 90b8b4bfcacd98bd55a60314082804e652ae8aa8 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 14:31:14 +0530 Subject: [PATCH 08/19] test: Qdrant instrumentation --- packages/instrumentation-qdrant/package.json | 3 +- .../src/instrumentation.ts | 27 +--- .../tests/instrumentation.test.ts | 116 +++++++++++++++--- 3 files changed, 110 insertions(+), 36 deletions(-) diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json index 0b8f7dc4..e3be7df5 100644 --- a/packages/instrumentation-qdrant/package.json +++ b/packages/instrumentation-qdrant/package.json @@ -38,7 +38,8 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.22.0" + "@opentelemetry/semantic-conventions": "^1.22.0", + "uuid": "^10.0.0" }, "devDependencies": { "@pollyjs/adapter-node-http": "^6.0.6", diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 0019db84..262ceca5 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -221,10 +221,7 @@ export class QdrantInstrumentation extends InstrumentationBase { params.batch.ids.length, ); } else { - span.setAttribute( - `db.qdrant.upsert.points_count`, - params.points.length, - ); + span.setAttribute(`db.qdrant.upsert.points_count`, params.points.length); } } @@ -259,10 +256,7 @@ export class QdrantInstrumentation extends InstrumentationBase { "db.qdrant.delete.point_ids", JSON.stringify(params.points), ); - span.setAttribute( - "db.qdrant.delete.ids_count", - params.points.length, - ); + span.setAttribute("db.qdrant.delete.ids_count", params.points.length); } } @@ -274,20 +268,11 @@ export class QdrantInstrumentation extends InstrumentationBase { span.setAttribute("db.qdrant.retrieve.collection_name", collectionName); span.setAttribute( "db.qdrant.retrieve.point_ids", - JSON.stringify(params.ids) - ); - span.setAttribute( - "db.qdrant.retrieve.ids_count", - params.ids.length, - ); - span.setAttribute( - "db.qdrant.retrieve.with_payload", - !!params.with_payload, - ); - span.setAttribute( - "db.qdrant.retrieve.with_vector", - !!params.with_vector, + JSON.stringify(params.ids), ); + span.setAttribute("db.qdrant.retrieve.ids_count", params.ids.length); + span.setAttribute("db.qdrant.retrieve.with_payload", !!params.with_payload); + span.setAttribute("db.qdrant.retrieve.with_vector", !!params.with_vector); } private _setSearchAttributes( diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts index 9c757678..00e82d8a 100755 --- a/packages/instrumentation-qdrant/tests/instrumentation.test.ts +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -24,8 +24,10 @@ import { } from "@opentelemetry/sdk-trace-base"; import type * as qdrant_types from "@qdrant/js-client-rest"; import * as assert from "assert"; +import { SpanAttributes } from "@traceloop/ai-semantic-conventions"; +import { v4 as uuidv4 } from "uuid"; -const COLLECTION_NAME = "some_collection"; +const COLLECTION_NAME = uuidv4(); const memoryExporter = new InMemorySpanExporter(); @@ -44,12 +46,6 @@ describe("Test Qdrant instrumentation", function () { qdrantClient = new qdrant_module.QdrantClient({ url: "http://127.0.0.1:6333", }); - }); - - beforeEach(async function () { - contextManager = new AsyncHooksContextManager().enable(); - context.setGlobalContextManager(contextManager); - memoryExporter.reset(); await qdrantClient.createCollection(COLLECTION_NAME, { vectors: { @@ -59,21 +55,41 @@ describe("Test Qdrant instrumentation", function () { }); }); + beforeEach(async function () { + contextManager = new AsyncHooksContextManager().enable(); + context.setGlobalContextManager(contextManager); + memoryExporter.reset(); + }); + afterEach(async () => { - await qdrantClient.deleteCollection(COLLECTION_NAME); memoryExporter.reset(); context.disable(); }); - it("should set span attributes for Upsert", async () => { + this.afterAll(async () => { + await qdrantClient.deleteCollection(COLLECTION_NAME); + }); + + it("should set span attributes for upsert", async () => { const points = { batch: { - ids: [32, 23], + ids: [32, 23, 42, 24, 25, 26], vectors: [ [1.5, 2.9, 3.4], [9.8, 2.3, 2.9], + [0.3, 0.3, 0.3], + [1.5, 2.9, 3.4], + [9.8, 2.3, 2.9], + [0.3, 0.3, 0.3], + ], + payloads: [ + { style: "style3" }, + { style: "style4" }, + { style: "style5" }, + { style: "style6" }, + { style: "style7" }, + { style: "style8" }, ], - payloads: [{ style: "style3" }, { style: "style4" }], }, }; @@ -81,13 +97,85 @@ describe("Test Qdrant instrumentation", function () { const spans = memoryExporter.getFinishedSpans(); assert.strictEqual(spans.length, 1); - assert.strictEqual(spans[0].name, `qdrant.${COLLECTION_NAME}.upsert`); + assert.strictEqual(spans[0].name, `qdrant.upsert`); const attributes = spans[0].attributes; - + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); + assert.strictEqual( + attributes["db.qdrant.upsert.collection_name"], + COLLECTION_NAME, + ); assert.strictEqual( attributes["db.qdrant.upsert.points_count"], - JSON.stringify(points.batch.ids.length), + points.batch.ids.length, + ); + }); + + it("should set attributes in span for search", async () => { + await qdrantClient.search(COLLECTION_NAME, { + vector: [0.3, 0.3, 0.3], + limit: 3, + with_payload: true, + with_vector: true, + }); + + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assert.strictEqual(spans[0].name, `qdrant.search`); + + const attributes = spans[0].attributes; + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); + assert.strictEqual( + attributes["db.qdrant.search.collection_name"], + COLLECTION_NAME, + ); + + const span = spans[0]; + assert.strictEqual(span.events.length, 5); + assert.strictEqual(span.events[0].name, "qdrant.search.request"); + assert.strictEqual(span.events[1].name, "qdrant.search.result"); + assert.strictEqual(span.events[2].name, "qdrant.search.result.0"); + assert.strictEqual(span.events[3].name, "qdrant.search.result.1"); + assert.strictEqual(span.events[4].name, "qdrant.search.result.2"); + }); + + it("should set span attributes for retrieve", async () => { + await qdrantClient.retrieve(COLLECTION_NAME, { + ids: [32, 23, 42], + with_payload: true, + with_vector: true, + }); + + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assert.strictEqual(spans[0].name, `qdrant.retrieve`); + + const attributes = spans[0].attributes; + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); + assert.strictEqual( + attributes["db.qdrant.retrieve.collection_name"], + COLLECTION_NAME, + ); + assert.strictEqual(attributes["db.qdrant.retrieve.ids_count"], 3); + assert.strictEqual(attributes["db.qdrant.retrieve.with_payload"], true); + assert.strictEqual(attributes["db.qdrant.retrieve.with_vector"], true); + }); + + it("should set span attributes for delete", async () => { + await qdrantClient.delete(COLLECTION_NAME, { + points: [32, 23, 42, 24, 25, 26], + }); + + const spans = memoryExporter.getFinishedSpans(); + assert.strictEqual(spans.length, 1); + assert.strictEqual(spans[0].name, `qdrant.delete`); + + const attributes = spans[0].attributes; + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); + assert.strictEqual( + attributes["db.qdrant.delete.collection_name"], + COLLECTION_NAME, ); + assert.strictEqual(attributes["db.qdrant.delete.ids_count"], 6); }); }); From 8b14daac08d16b252f476c74fc73b2560dc8063c Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 15:53:47 +0530 Subject: [PATCH 09/19] chore: Updated lockfile --- package-lock.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 3bd29af1..5af20252 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23511,7 +23511,8 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.22.0" + "@opentelemetry/semantic-conventions": "^1.22.0", + "uuid": "^10.0.0" }, "devDependencies": { "@pollyjs/adapter-node-http": "^6.0.6", @@ -23523,6 +23524,18 @@ "node": ">=14" } }, + "packages/instrumentation-qdrant/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "packages/instrumentation-vertexai": { "name": "@traceloop/instrumentation-vertexai", "version": "0.8.6", From c8e478c26c5bc0b96a573c763aa9c977cd3ecf59 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 16:00:17 +0530 Subject: [PATCH 10/19] chore: Bump version to 0.8.6 --- package-lock.json | 4 ++-- packages/instrumentation-qdrant/package.json | 2 +- packages/traceloop-sdk/package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5af20252..916ce7ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23506,7 +23506,7 @@ }, "packages/instrumentation-qdrant": { "name": "@traceloop/instrumentation-qdrant", - "version": "0.8.1", + "version": "0.8.6", "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", @@ -24191,7 +24191,7 @@ "@traceloop/instrumentation-llamaindex": "^0.8.0", "@traceloop/instrumentation-openai": "^0.8.6", "@traceloop/instrumentation-pinecone": "^0.8.6", - "@traceloop/instrumentation-qdrant": "^0.8.1", + "@traceloop/instrumentation-qdrant": "^0.8.6", "@traceloop/instrumentation-vertexai": "^0.8.6", "@types/nunjucks": "^3.2.5", "cross-fetch": "^4.0.0", diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json index e3be7df5..85d407b6 100644 --- a/packages/instrumentation-qdrant/package.json +++ b/packages/instrumentation-qdrant/package.json @@ -1,6 +1,6 @@ { "name": "@traceloop/instrumentation-qdrant", - "version": "0.8.1", + "version": "0.8.6", "description": "Qdrant Instrumentation", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/packages/traceloop-sdk/package.json b/packages/traceloop-sdk/package.json index cccb8953..60b0274f 100644 --- a/packages/traceloop-sdk/package.json +++ b/packages/traceloop-sdk/package.json @@ -47,7 +47,7 @@ "@traceloop/instrumentation-langchain": "^0.8.6", "@traceloop/instrumentation-llamaindex": "^0.8.0", "@traceloop/instrumentation-openai": "^0.8.6", - "@traceloop/instrumentation-qdrant": "^0.8.1", + "@traceloop/instrumentation-qdrant": "^0.8.6", "@traceloop/instrumentation-pinecone": "^0.8.6", "@traceloop/instrumentation-vertexai": "^0.8.6", "@types/nunjucks": "^3.2.5", From f05df5ee7c067d19769b3005a457a1a17997670e Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 16:40:06 +0530 Subject: [PATCH 11/19] chore: updated lockfile --- package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 916ce7ec..d39f79a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10411,9 +10411,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "dev": true, "engines": { "node": ">= 0.6" @@ -11662,9 +11662,9 @@ "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==" }, "node_modules/express": { - "version": "4.18.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", - "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -11672,7 +11672,7 @@ "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", From 46f6e21429d9d6dcee90e0654dd3b38c13626f1a Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jun 2024 16:49:19 +0530 Subject: [PATCH 12/19] chore: renamed missed type --- .../src/instrumentation.ts | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 262ceca5..ab81bec2 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -154,30 +154,37 @@ export class QdrantInstrumentation extends InstrumentationBase { try { if (this._config.traceContent) { - if (methodName === UPSERT) { - this._setUpsertAttributes( - span, - collectionName, - params as UpsertRequest, - ); - } else if (methodName === DELETE) { - this._setDeleteAttributes( - span, - collectionName, - params as DeleteRequest, - ); - } else if (methodName === RETRIEVE) { - this._setRetrieveAttributes( - span, - collectionName, - params as RetrieveRequest, - ); - } else if (methodName === SEARCH) { - this._setSearchAttributes( - span, - collectionName, - params as SearchRequest, - ); + switch (methodName) { + case UPSERT: + this._setUpsertAttributes( + span, + collectionName, + params as UpsertRequest, + ); + break; + case DELETE: + this._setDeleteAttributes( + span, + collectionName, + params as DeleteRequest, + ); + break; + case RETRIEVE: + this._setRetrieveAttributes( + span, + collectionName, + params as RetrieveRequest, + ); + break; + case SEARCH: + this._setSearchAttributes( + span, + collectionName, + params as SearchRequest, + ); + break; + default: + break; } } } catch (e) { @@ -198,8 +205,10 @@ export class QdrantInstrumentation extends InstrumentationBase { result: any; }) { try { - if (methodName === SEARCH) { - this._setSearchResultAttributes(span, result as SearchResponse); + switch (methodName) { + case SEARCH: this._setSearchResultAttributes(span, result as SearchResponse); + break; + default: break; } span.setStatus({ code: SpanStatusCode.OK }); span.end(); @@ -212,7 +221,7 @@ export class QdrantInstrumentation extends InstrumentationBase { private _setUpsertAttributes( span: Span, collectionName: string, - params: qdrant.Schemas["PointInsertOperations"], + params: UpsertRequest, ) { span.setAttribute("db.qdrant.upsert.collection_name", collectionName); if ("batch" in params) { From 749b7382cefce9f565549a92191ccc8fb6520ef4 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Mon, 17 Jun 2024 13:54:25 +0530 Subject: [PATCH 13/19] chore: uuid to devdeps --- .github/dependabot.yml | 6 ++++++ package-lock.json | 7 ++++--- packages/instrumentation-qdrant/package.json | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 01d2901e..425d305c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -46,6 +46,12 @@ updates: interval: "weekly" labels: - "instrumentation-pinecone" + - package-ecosystem: "npm" + directory: "/packages/instrumentation-qdrant" + schedule: + interval: "weekly" + labels: + - "instrumentation-qdrant" - package-ecosystem: "npm" directory: "/packages/instrumentation-vertexai" schedule: diff --git a/package-lock.json b/package-lock.json index d39f79a7..337bb619 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23511,14 +23511,14 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.22.0", - "uuid": "^10.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@pollyjs/adapter-node-http": "^6.0.6", "@pollyjs/core": "^6.0.6", "@pollyjs/persister-fs": "^6.0.6", - "@qdrant/js-client-rest": "^1.9.0" + "@qdrant/js-client-rest": "^1.9.0", + "uuid": "^10.0.0" }, "engines": { "node": ">=14" @@ -23528,6 +23528,7 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json index 85d407b6..ce1aabd3 100644 --- a/packages/instrumentation-qdrant/package.json +++ b/packages/instrumentation-qdrant/package.json @@ -38,14 +38,14 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.22.0", - "uuid": "^10.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0" }, "devDependencies": { "@pollyjs/adapter-node-http": "^6.0.6", "@pollyjs/core": "^6.0.6", "@pollyjs/persister-fs": "^6.0.6", - "@qdrant/js-client-rest": "^1.9.0" + "@qdrant/js-client-rest": "^1.9.0", + "uuid": "^10.0.0" }, "homepage": "https://github.com/traceloop/openllmetry-js/tree/main/packages/instrumentation-qdrant", "gitHead": "ef1e70d6037f7b5c061056ef2be16e3f55f02ed5" From 5789b739cdb104fc42c79282eb7c91eefb9451ac Mon Sep 17 00:00:00 2001 From: Anush008 Date: Mon, 17 Jun 2024 13:57:59 +0530 Subject: [PATCH 14/19] chore: Bump instrumentation-qdrant 0.8.8 --- package-lock.json | 31 ++++++++++++++++++- packages/instrumentation-qdrant/package.json | 2 +- .../src/instrumentation.ts | 6 ++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec41c3e9..0f0ba197 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23912,7 +23912,7 @@ }, "packages/instrumentation-qdrant": { "name": "@traceloop/instrumentation-qdrant", - "version": "0.8.6", + "version": "0.8.8", "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", @@ -23930,6 +23930,35 @@ "node": ">=14" } }, + "packages/instrumentation-qdrant/node_modules/@opentelemetry/instrumentation": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.44.0.tgz", + "integrity": "sha512-B6OxJTRRCceAhhnPDBshyQO7K07/ltX3quOLu0icEvPK9QZ7r9P1y0RQX8O5DxB4vTv4URRkxkg+aFU/plNtQw==", + "dependencies": { + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.4.2", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "packages/instrumentation-qdrant/node_modules/import-in-the-middle": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", + "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "packages/instrumentation-qdrant/node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json index ce1aabd3..efbfd0f9 100644 --- a/packages/instrumentation-qdrant/package.json +++ b/packages/instrumentation-qdrant/package.json @@ -1,6 +1,6 @@ { "name": "@traceloop/instrumentation-qdrant", - "version": "0.8.6", + "version": "0.8.8", "description": "Qdrant Instrumentation", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index ab81bec2..84d4cfcd 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -206,9 +206,11 @@ export class QdrantInstrumentation extends InstrumentationBase { }) { try { switch (methodName) { - case SEARCH: this._setSearchResultAttributes(span, result as SearchResponse); + case SEARCH: + this._setSearchResultAttributes(span, result as SearchResponse); + break; + default: break; - default: break; } span.setStatus({ code: SpanStatusCode.OK }); span.end(); From 3a04629bf873824840a9c800804c21adedabb62e Mon Sep 17 00:00:00 2001 From: Anush008 Date: Mon, 17 Jun 2024 14:10:55 +0530 Subject: [PATCH 15/19] fix: Updated types --- package-lock.json | 11 ++++++++++- packages/instrumentation-qdrant/package.json | 3 ++- .../instrumentation-qdrant/src/instrumentation.ts | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f0ba197..41d98f38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23917,7 +23917,8 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.22.0" + "@opentelemetry/semantic-conventions": "^1.25.0", + "@traceloop/ai-semantic-conventions": "^0.8.0" }, "devDependencies": { "@pollyjs/adapter-node-http": "^6.0.6", @@ -23948,6 +23949,14 @@ "@opentelemetry/api": "^1.3.0" } }, + "packages/instrumentation-qdrant/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.0.tgz", + "integrity": "sha512-M+kkXKRAIAiAP6qYyesfrC5TOmDpDVtsxuGfPcqd9B/iBrac+E14jYwrgm0yZBUIbIP2OnqC3j+UgkXLm1vxUQ==", + "engines": { + "node": ">=14" + } + }, "packages/instrumentation-qdrant/node_modules/import-in-the-middle": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json index efbfd0f9..b5969d74 100644 --- a/packages/instrumentation-qdrant/package.json +++ b/packages/instrumentation-qdrant/package.json @@ -38,7 +38,8 @@ "dependencies": { "@opentelemetry/core": "^1.8.0", "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.22.0" + "@opentelemetry/semantic-conventions": "^1.25.0", + "@traceloop/ai-semantic-conventions": "^0.8.0" }, "devDependencies": { "@pollyjs/adapter-node-http": "^6.0.6", diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 84d4cfcd..7914d0e8 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -58,8 +58,8 @@ export class QdrantInstrumentation extends InstrumentationBase { super.setConfig(config); } - protected init(): InstrumentationModuleDefinition { - const module = new InstrumentationNodeModuleDefinition( + protected init(): InstrumentationModuleDefinition { + const module = new InstrumentationNodeModuleDefinition( "@qdrant/js-client-rest", ["^1.9"], this.wrap.bind(this), From 88835a2850fa23ba5abd8478a6fdb2008e651bef Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 22 Jun 2024 19:26:12 +0530 Subject: [PATCH 16/19] chore: Bump @opentelemetry/instrumentation to latest --- package-lock.json | 62 ++++---------------- packages/instrumentation-qdrant/package.json | 3 +- 2 files changed, 13 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 91e74de6..c4806cd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6034,13 +6034,13 @@ } }, "node_modules/@opentelemetry/instrumentation": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.0.tgz", - "integrity": "sha512-LPwSIrw+60cheWaXsfGL8stBap/AppKQJFE+qqRvzYrgttXFH2ofoIMxWadeqPTq4BYOXM/C7Bdh/T+B60xnlQ==", + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", "dependencies": { - "@opentelemetry/api-logs": "0.52.0", + "@opentelemetry/api-logs": "0.52.1", "@types/shimmer": "^1.0.2", - "import-in-the-middle": "1.8.0", + "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" @@ -6053,9 +6053,9 @@ } }, "node_modules/@opentelemetry/instrumentation/node_modules/@opentelemetry/api-logs": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.0.tgz", - "integrity": "sha512-HxjD7xH9iAE4OyhNaaSec65i1H6QZYBWSwWkowFfsc5YAcDvJG30/J1sRKXEQqdmUcKTXEAnA66UciqZha/4+Q==", + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", "dependencies": { "@opentelemetry/api": "^1.0.0" }, @@ -13496,9 +13496,9 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.8.0.tgz", - "integrity": "sha512-/xQjze8szLNnJ5rvHSzn+dcVXqCAU6Plbk4P24U/jwPmg1wy7IIp9OjKIO5tYue8GSPhDpPDiApQjvBUmWwhsQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.8.1.tgz", + "integrity": "sha512-yhRwoHtiLGvmSozNOALgjRPFI6uYsds60EoMqqnXyyv+JOIW/BrrLejuTGBt+bq0T5tLzOHrN0T7xYTm4Qt/ng==", "dependencies": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", @@ -23916,8 +23916,7 @@ "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.25.0", + "@opentelemetry/instrumentation": "^0.52.0", "@traceloop/ai-semantic-conventions": "^0.8.0" }, "devDependencies": { @@ -23931,43 +23930,6 @@ "node": ">=14" } }, - "packages/instrumentation-qdrant/node_modules/@opentelemetry/instrumentation": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.44.0.tgz", - "integrity": "sha512-B6OxJTRRCceAhhnPDBshyQO7K07/ltX3quOLu0icEvPK9QZ7r9P1y0RQX8O5DxB4vTv4URRkxkg+aFU/plNtQw==", - "dependencies": { - "@types/shimmer": "^1.0.2", - "import-in-the-middle": "1.4.2", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "packages/instrumentation-qdrant/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.0.tgz", - "integrity": "sha512-M+kkXKRAIAiAP6qYyesfrC5TOmDpDVtsxuGfPcqd9B/iBrac+E14jYwrgm0yZBUIbIP2OnqC3j+UgkXLm1vxUQ==", - "engines": { - "node": ">=14" - } - }, - "packages/instrumentation-qdrant/node_modules/import-in-the-middle": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz", - "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==", - "dependencies": { - "acorn": "^8.8.2", - "acorn-import-assertions": "^1.9.0", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, "packages/instrumentation-qdrant/node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", diff --git a/packages/instrumentation-qdrant/package.json b/packages/instrumentation-qdrant/package.json index b5969d74..e704cd96 100644 --- a/packages/instrumentation-qdrant/package.json +++ b/packages/instrumentation-qdrant/package.json @@ -37,8 +37,7 @@ }, "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.44.0", - "@opentelemetry/semantic-conventions": "^1.25.0", + "@opentelemetry/instrumentation": "^0.52.0", "@traceloop/ai-semantic-conventions": "^0.8.0" }, "devDependencies": { From 886077dac4a49aa3859374d203fdd6809238fce2 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 22 Jun 2024 21:05:05 +0530 Subject: [PATCH 17/19] feat: More SpanAttributes --- .../src/SemanticAttributes.ts | 8 ++++ .../src/instrumentation.ts | 43 ++++++------------- .../tests/instrumentation.test.ts | 18 ++++---- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/packages/ai-semantic-conventions/src/SemanticAttributes.ts b/packages/ai-semantic-conventions/src/SemanticAttributes.ts index 49aeb998..bbaad202 100644 --- a/packages/ai-semantic-conventions/src/SemanticAttributes.ts +++ b/packages/ai-semantic-conventions/src/SemanticAttributes.ts @@ -38,6 +38,14 @@ export const SpanAttributes = { // Vector DB VECTOR_DB_VENDOR: "db.system", VECTOR_DB_QUERY_TOP_K: "db.vector.query.top_k", + VECTOR_DB_TABLE_NAME: "db.vector.table_name", + VECTOR_DB_ADD_COUNT: "db.vector.add.count", + VECTOR_DB_DELETE_SELECTOR: "db.vector.delete.selector", + VECTOR_DB_DELETE_COUNT: "db.vector.delete.count", + VECTOR_DB_GET_SELECTOR: "db.vector.get.selector", + VECTOR_DB_GET_COUNT: "db.vector.get.count", + VECTOR_DB_GET_INCLUDE_METADATA: "db.vector.get.include_metadata", + VECTOR_DB_GET_INCLUDE_VALUES: "db.vector.get.include_values", // LLM Workflows TRACELOOP_SPAN_KIND: "traceloop.span.kind", diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 7914d0e8..e56bedca 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -225,14 +225,14 @@ export class QdrantInstrumentation extends InstrumentationBase { collectionName: string, params: UpsertRequest, ) { - span.setAttribute("db.qdrant.upsert.collection_name", collectionName); + span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); if ("batch" in params) { span.setAttribute( - `db.qdrant.upsert.points_count`, + SpanAttributes.VECTOR_DB_ADD_COUNT, params.batch.ids.length, ); } else { - span.setAttribute(`db.qdrant.upsert.points_count`, params.points.length); + span.setAttribute(SpanAttributes.VECTOR_DB_ADD_COUNT, params.points.length); } } @@ -241,33 +241,18 @@ export class QdrantInstrumentation extends InstrumentationBase { collectionName: string, params: qdrant.Schemas["PointsSelector"], ) { - span.setAttribute("db.qdrant.delete.collection_name", collectionName); + span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); if ("filter" in params) { span.setAttribute( - "db.qdrant.delete.filter.must", - JSON.stringify(params.filter?.must), - ); - - span.setAttribute( - "db.qdrant.delete.filter.should", - JSON.stringify(params.filter?.should), - ); - - span.setAttribute( - "db.qdrant.delete.filter.must_not", - JSON.stringify(params.filter?.must_not), - ); - - span.setAttribute( - "db.qdrant.delete.filter.min_should", - JSON.stringify(params.filter?.min_should), + SpanAttributes.VECTOR_DB_DELETE_SELECTOR, + JSON.stringify(params.filter), ); } else { span.setAttribute( - "db.qdrant.delete.point_ids", + SpanAttributes.VECTOR_DB_DELETE_SELECTOR, JSON.stringify(params.points), ); - span.setAttribute("db.qdrant.delete.ids_count", params.points.length); + span.setAttribute(SpanAttributes.VECTOR_DB_DELETE_COUNT, params.points.length); } } @@ -276,14 +261,14 @@ export class QdrantInstrumentation extends InstrumentationBase { collectionName: string, params: qdrant.Schemas["PointRequest"], ) { - span.setAttribute("db.qdrant.retrieve.collection_name", collectionName); + span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); span.setAttribute( - "db.qdrant.retrieve.point_ids", + SpanAttributes.VECTOR_DB_GET_SELECTOR, JSON.stringify(params.ids), ); - span.setAttribute("db.qdrant.retrieve.ids_count", params.ids.length); - span.setAttribute("db.qdrant.retrieve.with_payload", !!params.with_payload); - span.setAttribute("db.qdrant.retrieve.with_vector", !!params.with_vector); + span.setAttribute(SpanAttributes.VECTOR_DB_GET_COUNT, params.ids.length); + span.setAttribute(SpanAttributes.VECTOR_DB_GET_INCLUDE_METADATA, !!params.with_payload); + span.setAttribute(SpanAttributes.VECTOR_DB_GET_INCLUDE_VALUES, !!params.with_vector); } private _setSearchAttributes( @@ -291,7 +276,7 @@ export class QdrantInstrumentation extends InstrumentationBase { collectionName: string, params: qdrant.Schemas["SearchRequest"], ) { - span.setAttribute("db.qdrant.search.collection_name", collectionName); + span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); const query_request_event = span.addEvent("qdrant.search.request"); query_request_event.setAttribute( EventAttributes.VECTOR_DB_QUERY_TOP_K, diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts index 00e82d8a..e482b37e 100755 --- a/packages/instrumentation-qdrant/tests/instrumentation.test.ts +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -102,11 +102,11 @@ describe("Test Qdrant instrumentation", function () { const attributes = spans[0].attributes; assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); assert.strictEqual( - attributes["db.qdrant.upsert.collection_name"], + attributes[SpanAttributes.VECTOR_DB_TABLE_NAME], COLLECTION_NAME, ); assert.strictEqual( - attributes["db.qdrant.upsert.points_count"], + attributes[SpanAttributes.VECTOR_DB_ADD_COUNT], points.batch.ids.length, ); }); @@ -126,7 +126,7 @@ describe("Test Qdrant instrumentation", function () { const attributes = spans[0].attributes; assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); assert.strictEqual( - attributes["db.qdrant.search.collection_name"], + attributes[SpanAttributes.VECTOR_DB_TABLE_NAME], COLLECTION_NAME, ); @@ -153,12 +153,12 @@ describe("Test Qdrant instrumentation", function () { const attributes = spans[0].attributes; assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); assert.strictEqual( - attributes["db.qdrant.retrieve.collection_name"], + attributes[SpanAttributes.VECTOR_DB_TABLE_NAME], COLLECTION_NAME, ); - assert.strictEqual(attributes["db.qdrant.retrieve.ids_count"], 3); - assert.strictEqual(attributes["db.qdrant.retrieve.with_payload"], true); - assert.strictEqual(attributes["db.qdrant.retrieve.with_vector"], true); + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_GET_COUNT], 3); + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_GET_INCLUDE_METADATA], true); + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_GET_INCLUDE_VALUES], true); }); it("should set span attributes for delete", async () => { @@ -173,9 +173,9 @@ describe("Test Qdrant instrumentation", function () { const attributes = spans[0].attributes; assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_VENDOR], "Qdrant"); assert.strictEqual( - attributes["db.qdrant.delete.collection_name"], + attributes[SpanAttributes.VECTOR_DB_TABLE_NAME], COLLECTION_NAME, ); - assert.strictEqual(attributes["db.qdrant.delete.ids_count"], 6); + assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_DELETE_COUNT], 6); }); }); From 082e23b7b93f867aa602f21da27869c46cc2d4ca Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sun, 23 Jun 2024 08:08:58 +0530 Subject: [PATCH 18/19] chore: style fixes --- .../src/instrumentation.ts | 22 ++++++++++++++----- .../tests/instrumentation.test.ts | 10 +++++++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index e56bedca..96cc561e 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -228,11 +228,14 @@ export class QdrantInstrumentation extends InstrumentationBase { span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); if ("batch" in params) { span.setAttribute( - SpanAttributes.VECTOR_DB_ADD_COUNT, + SpanAttributes.VECTOR_DB_ADD_COUNT, params.batch.ids.length, ); } else { - span.setAttribute(SpanAttributes.VECTOR_DB_ADD_COUNT, params.points.length); + span.setAttribute( + SpanAttributes.VECTOR_DB_ADD_COUNT, + params.points.length, + ); } } @@ -252,7 +255,10 @@ export class QdrantInstrumentation extends InstrumentationBase { SpanAttributes.VECTOR_DB_DELETE_SELECTOR, JSON.stringify(params.points), ); - span.setAttribute(SpanAttributes.VECTOR_DB_DELETE_COUNT, params.points.length); + span.setAttribute( + SpanAttributes.VECTOR_DB_DELETE_COUNT, + params.points.length, + ); } } @@ -267,8 +273,14 @@ export class QdrantInstrumentation extends InstrumentationBase { JSON.stringify(params.ids), ); span.setAttribute(SpanAttributes.VECTOR_DB_GET_COUNT, params.ids.length); - span.setAttribute(SpanAttributes.VECTOR_DB_GET_INCLUDE_METADATA, !!params.with_payload); - span.setAttribute(SpanAttributes.VECTOR_DB_GET_INCLUDE_VALUES, !!params.with_vector); + span.setAttribute( + SpanAttributes.VECTOR_DB_GET_INCLUDE_METADATA, + !!params.with_payload, + ); + span.setAttribute( + SpanAttributes.VECTOR_DB_GET_INCLUDE_VALUES, + !!params.with_vector, + ); } private _setSearchAttributes( diff --git a/packages/instrumentation-qdrant/tests/instrumentation.test.ts b/packages/instrumentation-qdrant/tests/instrumentation.test.ts index e482b37e..c95423af 100755 --- a/packages/instrumentation-qdrant/tests/instrumentation.test.ts +++ b/packages/instrumentation-qdrant/tests/instrumentation.test.ts @@ -157,8 +157,14 @@ describe("Test Qdrant instrumentation", function () { COLLECTION_NAME, ); assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_GET_COUNT], 3); - assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_GET_INCLUDE_METADATA], true); - assert.strictEqual(attributes[SpanAttributes.VECTOR_DB_GET_INCLUDE_VALUES], true); + assert.strictEqual( + attributes[SpanAttributes.VECTOR_DB_GET_INCLUDE_METADATA], + true, + ); + assert.strictEqual( + attributes[SpanAttributes.VECTOR_DB_GET_INCLUDE_VALUES], + true, + ); }); it("should set span attributes for delete", async () => { From 2f28e6862dd5da37433c5f055af359a9c0d172a7 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sun, 23 Jun 2024 11:09:35 +0530 Subject: [PATCH 19/19] chore: type alias --- packages/instrumentation-qdrant/src/instrumentation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/instrumentation-qdrant/src/instrumentation.ts b/packages/instrumentation-qdrant/src/instrumentation.ts index 96cc561e..09bb427e 100644 --- a/packages/instrumentation-qdrant/src/instrumentation.ts +++ b/packages/instrumentation-qdrant/src/instrumentation.ts @@ -242,7 +242,7 @@ export class QdrantInstrumentation extends InstrumentationBase { private _setDeleteAttributes( span: Span, collectionName: string, - params: qdrant.Schemas["PointsSelector"], + params: DeleteRequest, ) { span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); if ("filter" in params) { @@ -265,7 +265,7 @@ export class QdrantInstrumentation extends InstrumentationBase { private _setRetrieveAttributes( span: Span, collectionName: string, - params: qdrant.Schemas["PointRequest"], + params: RetrieveRequest, ) { span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); span.setAttribute( @@ -286,7 +286,7 @@ export class QdrantInstrumentation extends InstrumentationBase { private _setSearchAttributes( span: Span, collectionName: string, - params: qdrant.Schemas["SearchRequest"], + params: SearchRequest, ) { span.setAttribute(SpanAttributes.VECTOR_DB_TABLE_NAME, collectionName); const query_request_event = span.addEvent("qdrant.search.request");