@mastra/duckdb 1.2.0 → 1.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/dist/docs/SKILL.md +2 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-duckdb.md +150 -0
- package/dist/index.cjs +13 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/{observability-AILZGFQT.cjs → observability-2PJ44OVC.cjs} +307 -33
- package/dist/observability-2PJ44OVC.cjs.map +1 -0
- package/dist/{observability-YJBOVLPV.js → observability-7LL4LLXY.js} +308 -34
- package/dist/observability-7LL4LLXY.js.map +1 -0
- package/dist/storage/domains/observability/index.d.ts +4 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/metrics.d.ts.map +1 -1
- package/dist/storage/domains/observability/scores.d.ts +2 -1
- package/dist/storage/domains/observability/scores.d.ts.map +1 -1
- package/dist/storage/domains/observability/tracing.d.ts +41 -2
- package/dist/storage/domains/observability/tracing.d.ts.map +1 -1
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/observability-AILZGFQT.cjs.map +0 -1
- package/dist/observability-YJBOVLPV.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# @mastra/duckdb
|
|
2
2
|
|
|
3
|
+
## 1.3.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Improved performance of `listTraces` and `listBranches` on DuckDB. The Traces and Branches lists in the observability UI now load noticeably faster, especially on large span tables, because filtering and pagination happen up front and the store only assembles full span data for the rows on the page being viewed. ([#16165](https://github.com/mastra-ai/mastra/pull/16165))
|
|
8
|
+
|
|
9
|
+
No API or behavior changes — return shapes and filter semantics are unchanged, and no migration is required.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`ca28c23`](https://github.com/mastra-ai/mastra/commit/ca28c232a2f18801a6cf20fe053479237b4d4fb0)]:
|
|
12
|
+
- @mastra/core@1.32.0-alpha.3
|
|
13
|
+
|
|
14
|
+
## 1.3.0-alpha.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- - **Added** `listBranches` and `getSpans` implementations. ([#16154](https://github.com/mastra-ai/mastra/pull/16154))
|
|
19
|
+
- Historical span data is queryable immediately; no migration required.
|
|
20
|
+
|
|
21
|
+
- Added `count_distinct` aggregation and server-side TopK to the metrics storage API so dashboards built on high-cardinality fields (like `threadId` or `resourceId`) stay fast and bounded. ([#16137](https://github.com/mastra-ai/mastra/pull/16137))
|
|
22
|
+
|
|
23
|
+
**New aggregation**
|
|
24
|
+
|
|
25
|
+
`getMetricAggregate`, `getMetricBreakdown`, and `getMetricTimeSeries` accept `aggregation: 'count_distinct'` with a `distinctColumn`. Backends pick the most efficient native implementation — `uniq` on ClickHouse, `approx_count_distinct` on DuckDB.
|
|
26
|
+
|
|
27
|
+
`distinctColumn` is restricted to a low/medium-cardinality categorical allowlist (`entityType`, `entityName`, `parentEntityType`, `parentEntityName`, `rootEntityType`, `rootEntityName`, `name`, `provider`, `model`, `environment`, `executionSource`, `serviceName`). ID columns are not allowed — distinct counts over near-unique values converge to the row count and are rarely useful.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
await store.getMetricAggregate({
|
|
31
|
+
name: ['mastra_llm_tokens_total'],
|
|
32
|
+
aggregation: 'count_distinct',
|
|
33
|
+
distinctColumn: 'model',
|
|
34
|
+
filters: { timestamp: { start, end } },
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Server-side TopK**
|
|
39
|
+
|
|
40
|
+
`getMetricBreakdown` accepts `limit` and `orderDirection`, so breakdowns never return the full cardinality of a column from the database. Ordering is always by the aggregated `value`; `orderDirection` flips between top-N (`DESC`, default) and bottom-N (`ASC`).
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
await store.getMetricBreakdown({
|
|
44
|
+
name: ['mastra_agent_duration_ms'],
|
|
45
|
+
aggregation: 'sum',
|
|
46
|
+
groupBy: ['threadId'],
|
|
47
|
+
limit: 20,
|
|
48
|
+
orderDirection: 'DESC',
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Patch Changes
|
|
53
|
+
|
|
54
|
+
- Added direct score lookup support to observability storage so score records can be fetched by `scoreId` without scanning paginated score lists, including DuckDB and ClickHouse vNext observability stores. ([#16162](https://github.com/mastra-ai/mastra/pull/16162))
|
|
55
|
+
|
|
56
|
+
- Updated dependencies [[`86c0298`](https://github.com/mastra-ai/mastra/commit/86c0298e647306423c842f9d5ac827bd616bd13d), [`7fce309`](https://github.com/mastra-ai/mastra/commit/7fce30912b14170bfc41f0ac736cca0f39fe0cd4), [`7997c2e`](https://github.com/mastra-ai/mastra/commit/7997c2e55ddd121562a4098cd8d2b89c68433bf1), [`e97ccb9`](https://github.com/mastra-ai/mastra/commit/e97ccb900f8b7a390ce82c9f8eb8d6eb2c5e3777), [`c5daf48`](https://github.com/mastra-ai/mastra/commit/c5daf48556e98c46ae06caf00f92c249912007e9), [`cd96779`](https://github.com/mastra-ai/mastra/commit/cd9677937f113b2856dc8b9f3d4bdabcee58bb2e)]:
|
|
57
|
+
- @mastra/core@1.32.0-alpha.2
|
|
58
|
+
|
|
3
59
|
## 1.2.0
|
|
4
60
|
|
|
5
61
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-duckdb
|
|
|
3
3
|
description: Documentation for @mastra/duckdb. Use when working with @mastra/duckdb APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/duckdb"
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.3.0-alpha.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -16,6 +16,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
16
16
|
|
|
17
17
|
### Reference
|
|
18
18
|
|
|
19
|
+
- [Reference: DuckDB storage](references/reference-storage-duckdb.md) - Documentation for the DuckDB storage implementation in Mastra, an embedded analytical backend for local observability development.
|
|
19
20
|
- [Reference: DuckDB vector store](references/reference-vectors-duckdb.md) - Documentation for the DuckDBVector class in Mastra, which provides embedded high-performance vector search using DuckDB with HNSW indexing.
|
|
20
21
|
|
|
21
22
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# DuckDB storage
|
|
2
|
+
|
|
3
|
+
[DuckDB](https://duckdb.org/) is an embedded, in-process analytical database. The `@mastra/duckdb` package provides an OLAP-backed observability store for local development, suitable for traces, logs, metrics, scores, and feedback without running an external service.
|
|
4
|
+
|
|
5
|
+
For vector search, see the [DuckDB vector store reference](https://mastra.ai/reference/vectors/duckdb), which is a separate API in the same package.
|
|
6
|
+
|
|
7
|
+
## When to use DuckDB
|
|
8
|
+
|
|
9
|
+
Local development of observability features. DuckDB is embedded and file-based, so it does not require a server and starts instantly. It supports the same observability signals as ClickHouse, which makes it useful for testing dashboards and trace exploration before deploying to a production backend.
|
|
10
|
+
|
|
11
|
+
DuckDB currently implements only the `observability` domain. Pair it with another storage adapter (such as [LibSQL](https://mastra.ai/reference/storage/libsql)) for `memory` and `workflows` in a [composite storage](https://mastra.ai/reference/storage/composite) setup.
|
|
12
|
+
|
|
13
|
+
> **Warning:** DuckDB is for development and not recommended for production. It runs in-process, persists to a single local file, and does not work on platforms with ephemeral filesystems (such as Railway, Fly.io, Render, Heroku, or serverless containers). For production observability, use [ClickHouse](https://mastra.ai/reference/storage/clickhouse).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
**npm**:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @mastra/duckdb@latest
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**pnpm**:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add @mastra/duckdb@latest
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Yarn**:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn add @mastra/duckdb@latest
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Bun**:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bun add @mastra/duckdb@latest
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
### As the observability domain in a composite store
|
|
44
|
+
|
|
45
|
+
This is the standard local-development setup. LibSQL handles the other domains, and DuckDB handles observability.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Mastra } from '@mastra/core'
|
|
49
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
50
|
+
import { LibSQLStore } from '@mastra/libsql'
|
|
51
|
+
import { DuckDBStore } from '@mastra/duckdb'
|
|
52
|
+
import { Observability, DefaultExporter } from '@mastra/observability'
|
|
53
|
+
|
|
54
|
+
export const mastra = new Mastra({
|
|
55
|
+
storage: new MastraCompositeStore({
|
|
56
|
+
id: 'composite-storage',
|
|
57
|
+
default: new LibSQLStore({
|
|
58
|
+
id: 'mastra-storage',
|
|
59
|
+
url: 'file:./mastra.db',
|
|
60
|
+
}),
|
|
61
|
+
domains: {
|
|
62
|
+
observability: new DuckDBStore().observability,
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
observability: new Observability({
|
|
66
|
+
configs: {
|
|
67
|
+
default: {
|
|
68
|
+
serviceName: 'mastra',
|
|
69
|
+
exporters: [new DefaultExporter()],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The `.observability` accessor returns the observability domain store directly. The equivalent generic form uses `getStore()`, which works for any composite-style storage adapter:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const observability = await new DuckDBStore().getStore('observability')
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Standalone
|
|
83
|
+
|
|
84
|
+
When you need only observability storage outside the `Mastra` composite, instantiate `DuckDBStore` directly and access the observability domain:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { DuckDBStore } from '@mastra/duckdb'
|
|
88
|
+
|
|
89
|
+
const duckdb = new DuckDBStore({ path: './traces.duckdb' })
|
|
90
|
+
const observability = duckdb.observability
|
|
91
|
+
|
|
92
|
+
await observability.init()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### In-memory database
|
|
96
|
+
|
|
97
|
+
Pass `:memory:` to use an ephemeral DuckDB instance. Data is lost when the process exits, which is appropriate for unit tests and short-lived scripts.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const duckdb = new DuckDBStore({ path: ':memory:' })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
### `DuckDBStore` options
|
|
106
|
+
|
|
107
|
+
**id** (`string`): Unique identifier for this storage instance. (Default: `'duckdb'`)
|
|
108
|
+
|
|
109
|
+
**path** (`string`): Path to the DuckDB database file. Use \`:memory:\` for an ephemeral in-memory database. (Default: `'mastra.duckdb'`)
|
|
110
|
+
|
|
111
|
+
### Lower-level types
|
|
112
|
+
|
|
113
|
+
`@mastra/duckdb` also exports `DuckDBConnection` for sharing a single underlying database across multiple Mastra storage instances, and the corresponding `DuckDBStorageConfig` type. Most applications will not need these directly.
|
|
114
|
+
|
|
115
|
+
## Supported domains
|
|
116
|
+
|
|
117
|
+
DuckDB currently implements one storage domain:
|
|
118
|
+
|
|
119
|
+
| Domain | Supported |
|
|
120
|
+
| --------------- | --------- |
|
|
121
|
+
| `observability` | Yes |
|
|
122
|
+
| `memory` | No |
|
|
123
|
+
| `workflows` | No |
|
|
124
|
+
| `scores` | No |
|
|
125
|
+
| `agents` | No |
|
|
126
|
+
|
|
127
|
+
For a full storage solution, compose `DuckDBStore` with an adapter that covers the missing domains (most commonly [LibSQL](https://mastra.ai/reference/storage/libsql) for local development).
|
|
128
|
+
|
|
129
|
+
## Initialization
|
|
130
|
+
|
|
131
|
+
When passed to `Mastra` through `MastraCompositeStore`, the observability domain initializes itself on first use. To run initialization explicitly outside of `Mastra`, call `init()` on the observability store:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { DuckDBStore } from '@mastra/duckdb'
|
|
135
|
+
|
|
136
|
+
const duckdb = new DuckDBStore({ path: './traces.duckdb' })
|
|
137
|
+
await duckdb.observability.init()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Observability strategy
|
|
141
|
+
|
|
142
|
+
DuckDB supports the `event-sourced` strategy used by `DefaultExporter`, which buffers spans in memory and writes completed events in batches. This is appropriate for development-scale traffic. For high-volume production workloads, see [`DefaultExporter` storage provider support](https://mastra.ai/docs/observability/tracing/exporters/default).
|
|
143
|
+
|
|
144
|
+
## Related
|
|
145
|
+
|
|
146
|
+
- [Storage overview](https://mastra.ai/reference/storage/overview)
|
|
147
|
+
- [Composite storage](https://mastra.ai/reference/storage/composite)
|
|
148
|
+
- [ClickHouse storage](https://mastra.ai/reference/storage/clickhouse): Production observability backend
|
|
149
|
+
- [DuckDB vector store](https://mastra.ai/reference/vectors/duckdb): Vector search using the same package
|
|
150
|
+
- [Observability overview](https://mastra.ai/docs/observability/overview)
|
package/dist/index.cjs
CHANGED
|
@@ -583,7 +583,7 @@ var ObservabilityStorageDuckDB = class extends storage.ObservabilityStorage {
|
|
|
583
583
|
return null;
|
|
584
584
|
}
|
|
585
585
|
if (!this.loadPromise) {
|
|
586
|
-
this.loadPromise = import('./observability-
|
|
586
|
+
this.loadPromise = import('./observability-2PJ44OVC.cjs').then(({ ObservabilityStorageDuckDB: ObservabilityStorageDuckDB2 }) => {
|
|
587
587
|
const delegate = new ObservabilityStorageDuckDB2({ db: this.db });
|
|
588
588
|
this.delegate = delegate;
|
|
589
589
|
return delegate;
|
|
@@ -640,6 +640,10 @@ var ObservabilityStorageDuckDB = class extends storage.ObservabilityStorage {
|
|
|
640
640
|
const delegate = await this.requireDelegate();
|
|
641
641
|
return delegate.getSpan(...args);
|
|
642
642
|
}
|
|
643
|
+
async getSpans(...args) {
|
|
644
|
+
const delegate = await this.requireDelegate();
|
|
645
|
+
return delegate.getSpans(...args);
|
|
646
|
+
}
|
|
643
647
|
async getRootSpan(...args) {
|
|
644
648
|
const delegate = await this.requireDelegate();
|
|
645
649
|
return delegate.getRootSpan(...args);
|
|
@@ -656,6 +660,10 @@ var ObservabilityStorageDuckDB = class extends storage.ObservabilityStorage {
|
|
|
656
660
|
const delegate = await this.requireDelegate();
|
|
657
661
|
return delegate.listTraces(...args);
|
|
658
662
|
}
|
|
663
|
+
async listBranches(...args) {
|
|
664
|
+
const delegate = await this.requireDelegate();
|
|
665
|
+
return delegate.listBranches(...args);
|
|
666
|
+
}
|
|
659
667
|
async batchCreateSpans(...args) {
|
|
660
668
|
const delegate = await this.requireDelegate();
|
|
661
669
|
return delegate.batchCreateSpans(...args);
|
|
@@ -744,6 +752,10 @@ var ObservabilityStorageDuckDB = class extends storage.ObservabilityStorage {
|
|
|
744
752
|
const delegate = await this.requireDelegate();
|
|
745
753
|
return delegate.listScores(...args);
|
|
746
754
|
}
|
|
755
|
+
async getScoreById(...args) {
|
|
756
|
+
const delegate = await this.requireDelegate();
|
|
757
|
+
return delegate.getScoreById(...args);
|
|
758
|
+
}
|
|
747
759
|
async getScoreAggregate(...args) {
|
|
748
760
|
const delegate = await this.requireDelegate();
|
|
749
761
|
return delegate.getScoreAggregate(...args);
|