Skip to content

Commit f9c30ab

Browse files
docs: add OpenTelemetry monitoring guide
1 parent 6ca19f6 commit f9c30ab

2 files changed

Lines changed: 115 additions & 0 deletions

File tree

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@
217217
"group": "Support",
218218
"pages": [
219219
"troubleshooting",
220+
"monitoring",
220221
{
221222
"group": "FAQ",
222223
"pages": [

docs/monitoring.mdx

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
title: "Monitor LanceDB with OpenTelemetry"
3+
sidebarTitle: "Monitoring"
4+
description: "Export LanceDB object store request counts, bytes, latency, errors, and throttles to any OpenTelemetry backend."
5+
icon: "chart-line"
6+
keywords: ["monitoring", "observability", "opentelemetry", "otel", "metrics", "prometheus", "object store"]
7+
---
8+
9+
LanceDB emits internal metrics — currently object store request counts, bytes transferred, request latency, retryable errors, and throttles — and can bridge them into any [OpenTelemetry](https://opentelemetry.io/) backend. Use this to watch how your application interacts with S3, GCS, Azure Blob, or the local filesystem in production: spot latency regressions, catch retry storms, and size your storage tier from real workload data.
10+
11+
The bridge is available in the Python and TypeScript SDKs. It is a thin wrapper over LanceDB's `metrics` recorder; your application supplies and configures the OpenTelemetry SDK.
12+
13+
<Note>
14+
This page covers LanceDB OSS. LanceDB Enterprise clusters emit their own Prometheus/OpenTelemetry metrics from the server side — see the [Enterprise overview](/enterprise/) for that flow.
15+
</Note>
16+
17+
## What you get
18+
19+
Once instrumented, LanceDB registers one observable instrument per metric on your `MeterProvider`. The current catalog covers the object store layer:
20+
21+
| Metric | Kind | Description |
22+
|--------|------|-------------|
23+
| `lance_object_store_requests_total` | Counter | Total object store requests, labelled by `operation` and `base` (store scheme). |
24+
| `lance_object_store_request_duration_seconds` | Histogram | Request latency in seconds. |
25+
| `lance_object_store_bytes_transferred_total` | Counter | Bytes read from or written to the store. |
26+
| `lance_object_store_retryable_responses_total` | Counter | Requests that returned a retryable error (throttles, transient failures). |
27+
| `lance_object_store_in_flight_requests` | Gauge | Currently outstanding object store requests. |
28+
29+
The recorder is process-global and pull-based: your configured `MetricReader` collects on its own schedule, so there is no hot-path overhead beyond the atomic aggregation that LanceDB does anyway.
30+
31+
<Note>
32+
**Histograms are exported Prometheus-style.** OpenTelemetry has no asynchronous histogram instrument, so each histogram surfaces as three observable counters: `<name>_bucket` (with an `le` attribute per bucket boundary, including `+Inf`), `<name>_count`, and `<name>_sum`. Only `_sum` carries the histogram's unit; `_bucket` and `_count` are cumulative sample counts.
33+
</Note>
34+
35+
## Python
36+
37+
Install LanceDB with the `otel` extra to pull in the OpenTelemetry API, plus an OpenTelemetry SDK of your choice. The SDK is intentionally not bundled — you configure it, its readers, and its exporters however your platform expects.
38+
39+
```bash
40+
pip install "lancedb[otel]" opentelemetry-sdk
41+
```
42+
43+
Call `instrument_lancedb_metrics()` once at startup, before opening any tables. It returns `True` when the recorder is installed and instruments are registered.
44+
45+
```python Python icon="python"
46+
import lancedb
47+
from lancedb.otel import instrument_lancedb_metrics
48+
from opentelemetry.sdk.metrics import MeterProvider
49+
from opentelemetry.sdk.metrics.export import (
50+
PeriodicExportingMetricReader,
51+
)
52+
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
53+
OTLPMetricExporter,
54+
)
55+
56+
reader = PeriodicExportingMetricReader(OTLPMetricExporter())
57+
provider = MeterProvider(metric_readers=[reader])
58+
59+
instrument_lancedb_metrics(provider)
60+
61+
# Any object store activity from this point on is now recorded.
62+
db = lancedb.connect("s3://my-bucket/lancedb")
63+
```
64+
65+
If you omit `meter_provider`, LanceDB uses the global provider returned by `opentelemetry.metrics.get_meter_provider()`.
66+
67+
<Warning>
68+
`instrument_lancedb_metrics()` returns `False` and emits a warning if another `metrics`-crate recorder is already installed in the process. Only one global recorder is permitted, so instrument LanceDB before any other library that installs its own recorder.
69+
</Warning>
70+
71+
## TypeScript
72+
73+
The Node SDK depends on `@opentelemetry/api` directly, so no extra install step is needed to expose the entry point. You still need an OpenTelemetry SDK to actually export.
74+
75+
```bash
76+
npm install @opentelemetry/sdk-metrics @opentelemetry/exporter-metrics-otlp-grpc
77+
```
78+
79+
```typescript TypeScript icon="square-js"
80+
import { connect, instrumentLanceDbMetrics } from "@lancedb/lancedb";
81+
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
82+
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
83+
84+
const reader = new PeriodicExportingMetricReader({
85+
exporter: new OTLPMetricExporter(),
86+
});
87+
const provider = new MeterProvider({ readers: [reader] });
88+
89+
instrumentLanceDbMetrics(provider);
90+
91+
const db = await connect("s3://my-bucket/lancedb");
92+
```
93+
94+
`instrumentLanceDbMetrics()` also accepts no arguments, in which case it uses the global provider from `@opentelemetry/api`. Calling it more than once is safe: instruments are created only on the first successful call.
95+
96+
## What to watch
97+
98+
A few starting points for dashboards and alerts:
99+
100+
- **Request rate by operation**`rate(lance_object_store_requests_total[1m])` broken down by `operation` shows read vs. write pressure and helps size ingestion vs. serving traffic separately.
101+
- **Tail latency** — histogram quantiles over `lance_object_store_request_duration_seconds_bucket` catch object store slowdowns before they surface as query timeouts.
102+
- **Retryable responses** — a rising `lance_object_store_retryable_responses_total` typically means you are being throttled and should back off or shard writes.
103+
- **In-flight requests** — a growing `lance_object_store_in_flight_requests` gauge without a matching rise in throughput indicates queueing.
104+
105+
## Where to go next
106+
107+
<Columns cols={2}>
108+
<Card title="Performance tips" icon="gauge-high" href="/performance">
109+
Tune ingestion, indexing, and query patterns once metrics highlight a hot spot.
110+
</Card>
111+
<Card title="Storage configuration" icon="wrench" href="/storage/configuration">
112+
Configure the object store backends whose requests these metrics measure.
113+
</Card>
114+
</Columns>

0 commit comments

Comments
 (0)