pgvector (tracing)

pgvector adds vector types and similarity operators to PostgreSQL. The Respan-owned pgvector instrumentation traces pgvector registration and psycopg 3 connection and cursor operations, including synchronous and asynchronous execution and fetched results.

Create an account at platform.respan.ai and grab an API key.

Run npx @respan/cli setup to set up with your coding agent.

Setup

1

Install packages

$pip install respan-ai respan-instrumentation-pgvector pgvector "psycopg[binary]"
2

Set environment variables

$export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
$export PGVECTOR_DSN="postgresql://postgres:postgres@localhost:5432/postgres"

The PostgreSQL user must be able to use the vector extension. If it is not already installed in the database, the quickstart also requires permission to run CREATE EXTENSION.

3

Initialize and run

1import os
2
3import pgvector.psycopg as pgvector_psycopg
4import psycopg
5from pgvector import Vector
6from respan import Respan, workflow
7from respan_instrumentation_pgvector import PGVectorInstrumentor
8
9respan = Respan(
10 api_key=os.environ["RESPAN_API_KEY"],
11 instrumentations=[PGVectorInstrumentor()],
12)
13
14
15@workflow(name="pgvector_similarity_queries_workflow")
16def run_pgvector_query():
17 with psycopg.connect(
18 os.environ["PGVECTOR_DSN"],
19 autocommit=True,
20 ) as connection:
21 connection.execute("CREATE EXTENSION IF NOT EXISTS vector")
22 pgvector_psycopg.register_vector(connection)
23 connection.execute(
24 """
25 CREATE TEMP TABLE respan_pgvector_docs (
26 id integer PRIMARY KEY,
27 content text NOT NULL,
28 embedding vector(4) NOT NULL
29 )
30 """
31 )
32
33 with connection.cursor() as cursor:
34 cursor.executemany(
35 """
36 INSERT INTO respan_pgvector_docs (id, content, embedding)
37 VALUES (%s, %s, %s)
38 """,
39 [
40 (
41 1,
42 "Respan traces vector database operations.",
43 Vector([0.9, 0.1, 0.0, 0.0]),
44 ),
45 (
46 2,
47 "PostgreSQL supports pgvector similarity search.",
48 Vector([0.2, 0.8, 0.0, 0.0]),
49 ),
50 ],
51 )
52
53 query = Vector([0.85, 0.15, 0.0, 0.0])
54 return connection.execute(
55 """
56 SELECT id, content, embedding, embedding <-> %s AS distance
57 FROM respan_pgvector_docs
58 ORDER BY embedding <-> %s
59 LIMIT 2
60 """,
61 (query, query),
62 ).fetchall()
63
64
65for row in run_pgvector_query():
66 print(row)
67
68respan.flush()
69respan.shutdown()
4

View your trace

Open the Traces page and search for workflow name pgvector_similarity_queries_workflow.

Covered operations

The instrumentor traces pgvector type registration plus psycopg 3 execute, executemany, fetchone, fetchmany, and fetchall calls for synchronous and asynchronous connections, cursors, and server cursors. This captures dense, half-precision, sparse, and binary vector workflows and PostgreSQL similarity operators. The optional psycopg2 extra also traces pgvector’s psycopg 2 type registration.

Content capture

SQL arguments, vector parameters, operation summaries, and fetched rows are captured by default. Disable content capture when those values should not be attached to spans:

1from respan import Respan
2from respan_instrumentation_pgvector import PGVectorInstrumentor
3
4respan = Respan(
5 instrumentations=[PGVectorInstrumentor(capture_content=False)],
6)

Operation names, status, and PostgreSQL attributes remain available when content capture is disabled.

Configuration

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to the RESPAN_API_KEY environment variable.
base_urlstr | NoneNoneFalls back to the RESPAN_BASE_URL environment variable.
instrumentationslist[]Plugin instrumentations to activate, such as PGVectorInstrumentor().
capture_contentboolTruePGVectorInstrumentor option that controls SQL, vector, and result capture.
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag, such as "production".

Attributes

In Respan()

1from respan import Respan
2from respan_instrumentation_pgvector import PGVectorInstrumentor
3
4respan = Respan(
5 instrumentations=[PGVectorInstrumentor()],
6 customer_identifier="user_123",
7 metadata={"service": "pgvector-rag-api", "version": "1.0.0"},
8)

With propagate_attributes

1from pgvector import Vector
2from respan import propagate_attributes
3
4
5def search(connection, user_id: str, query_vector: list[float]):
6 with propagate_attributes(
7 customer_identifier=user_id,
8 thread_identifier="pgvector_thread",
9 metadata={"table": "respan_pgvector_docs", "plan": "pro"},
10 ):
11 query = Vector(query_vector)
12 return connection.execute(
13 """
14 SELECT id, content
15 FROM respan_pgvector_docs
16 ORDER BY embedding <=> %s
17 LIMIT 2
18 """,
19 (query,),
20 ).fetchall()
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related operations into a thread.
metadatadictCustom key-value pairs merged with default metadata.