Observability
vectlite ships with two complementary observability features:
search_with_stats()— per-call timings, candidate counts, fusion strategy, andexplainpayloads for individual searches.- OpenTelemetry tracing — span-based instrumentation that integrates with your existing OTel collector / backend.
The OpenTelemetry SDK is loaded lazily and is not a runtime dependency. Install it only if you want tracing.
OpenTelemetry
Setup (Python)
pip install opentelemetry-api opentelemetry-sdk
import vectlite
# Auto-detect: uses the default tracer from opentelemetry.trace if installed
vectlite.configure_opentelemetry()
# Or supply your own tracer
vectlite.configure_opentelemetry({"tracer": my_tracer})
# Custom tracer name (default: "vectlite")
vectlite.configure_opentelemetry({"tracer_name": "my-app"})
# Disable
vectlite.configure_opentelemetry(False)
Setup (Node.js)
npm install @opentelemetry/api @opentelemetry/sdk-node
const vectlite = require('vectlite')
vectlite.configureOpenTelemetry() // auto-detect
vectlite.configureOpenTelemetry({ tracer: myTracer }) // explicit tracer
vectlite.configureOpenTelemetry({ tracerName: 'my-app' }) // rename
vectlite.configureOpenTelemetry({ enabled: false }) // disable
What gets traced
Each search_text() and search_text_with_stats() call creates a vectlite.search span with:
| Attribute | Description |
|---|---|
db.system | Always "vectlite" |
db.operation.name | Always "search" |
vectlite.search.k | Requested result count |
vectlite.search.namespace | Target namespace |
vectlite.search.has_dense | Whether a dense query vector was provided |
vectlite.search.has_sparse | Whether sparse terms were provided |
vectlite.search.fusion | Fusion strategy ("linear" or "rrf") |
vectlite.search.used_ann | Whether HNSW was used (set after completion) |
vectlite.search.result_count | Number of results returned |
vectlite.search.total_us | Total search time in microseconds |
If a search raises, the span records the exception and sets an error status before re-raising.
Search diagnostics
For per-call inspection (without standing up an OTel pipeline), use search_with_stats():
Python
outcome = db.search_with_stats(query, k=5, sparse=terms, explain=True)
print(outcome["stats"]["timings"]) # {"dense_us": 120, "sparse_us": 45, ...}
print(outcome["stats"]["used_ann"]) # True
print(outcome["results"][0]["explain"]) # detailed scoring breakdown
Node.js
const outcome = db.searchWithStats(query, { k: 5, sparse: terms, explain: true })
console.log(outcome.stats.timings)
console.log(outcome.stats.used_ann)
console.log(outcome.results[0].explain)
See the Diagnostics guide for the full SearchStats reference.
Recommended setup
- Local dev / quick checks →
search_with_stats()withexplain=True. - Production aggregate metrics → OpenTelemetry, exported to your backend (Tempo, Jaeger, Honeycomb, Datadog, etc.).
- One-off perf investigation → both. OTel gives the trend;
search_with_statsgives the per-call breakdown.