@adonis-agora/telescope 0.22.0 → 0.24.0
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 +50 -0
- package/dist/src/ai/index.d.ts +1 -1
- package/dist/src/ai/index.js +1 -1
- package/dist/src/alerts/index.d.ts +1 -1
- package/dist/src/alerts/index.js +1 -1
- package/dist/src/index.d.ts +9 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/metrics/metrics_service.d.ts +5 -0
- package/dist/src/metrics/metrics_service.d.ts.map +1 -1
- package/dist/src/metrics/metrics_service.js +32 -4
- package/dist/src/metrics/metrics_service.js.map +1 -1
- package/dist/src/metrics/pulse.d.ts +8 -0
- package/dist/src/metrics/pulse.d.ts.map +1 -1
- package/dist/src/metrics/pulse.js +125 -37
- package/dist/src/metrics/pulse.js.map +1 -1
- package/dist/src/metrics/stats.d.ts +2 -0
- package/dist/src/metrics/stats.d.ts.map +1 -1
- package/dist/src/metrics/stats.js +8 -3
- package/dist/src/metrics/stats.js.map +1 -1
- package/dist/src/otel/otel_exporting_store.d.ts +1 -1
- package/dist/src/otel/otel_exporting_store.d.ts.map +1 -1
- package/dist/src/otel/otel_exporting_store.js +2 -0
- package/dist/src/otel/otel_exporting_store.js.map +1 -1
- package/dist/src/profiling/index.d.ts +1 -1
- package/dist/src/profiling/index.js +1 -1
- package/dist/src/redaction/redact.d.ts.map +1 -1
- package/dist/src/redaction/redact.js +28 -4
- package/dist/src/redaction/redact.js.map +1 -1
- package/dist/src/redaction/redacting_store.d.ts +1 -1
- package/dist/src/redaction/redacting_store.d.ts.map +1 -1
- package/dist/src/redaction/redacting_store.js +2 -0
- package/dist/src/redaction/redacting_store.js.map +1 -1
- package/dist/src/sampling/sampling_store.d.ts +1 -1
- package/dist/src/sampling/sampling_store.d.ts.map +1 -1
- package/dist/src/sampling/sampling_store.js +6 -1
- package/dist/src/sampling/sampling_store.js.map +1 -1
- package/dist/src/self_scope.d.ts +5 -0
- package/dist/src/self_scope.d.ts.map +1 -0
- package/dist/src/self_scope.js +28 -0
- package/dist/src/self_scope.js.map +1 -0
- package/dist/src/service.d.ts.map +1 -1
- package/dist/src/service.js +9 -2
- package/dist/src/service.js.map +1 -1
- package/dist/src/store.d.ts +46 -0
- package/dist/src/store.d.ts.map +1 -1
- package/dist/src/store.js +16 -1
- package/dist/src/store.js.map +1 -1
- package/dist/src/stores/factory.d.ts +79 -0
- package/dist/src/stores/factory.d.ts.map +1 -1
- package/dist/src/stores/factory.js +71 -0
- package/dist/src/stores/factory.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +73 -28
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +487 -183
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/stores/memory.d.ts +3 -1
- package/dist/src/stores/memory.d.ts.map +1 -1
- package/dist/src/stores/memory.js +29 -0
- package/dist/src/stores/memory.js.map +1 -1
- package/dist/src/stores/parquet.d.ts +184 -0
- package/dist/src/stores/parquet.d.ts.map +1 -0
- package/dist/src/stores/parquet.js +461 -0
- package/dist/src/stores/parquet.js.map +1 -0
- package/dist/src/stores/parquet_duckdb.d.ts +52 -0
- package/dist/src/stores/parquet_duckdb.d.ts.map +1 -0
- package/dist/src/stores/parquet_duckdb.js +266 -0
- package/dist/src/stores/parquet_duckdb.js.map +1 -0
- package/dist/src/stores/parquet_format.d.ts +108 -0
- package/dist/src/stores/parquet_format.d.ts.map +1 -0
- package/dist/src/stores/parquet_format.js +175 -0
- package/dist/src/stores/parquet_format.js.map +1 -0
- package/dist/src/stores/parquet_hyparquet.d.ts +34 -0
- package/dist/src/stores/parquet_hyparquet.d.ts.map +1 -0
- package/dist/src/stores/parquet_hyparquet.js +212 -0
- package/dist/src/stores/parquet_hyparquet.js.map +1 -0
- package/dist/src/stores/parquet_location.d.ts +88 -0
- package/dist/src/stores/parquet_location.d.ts.map +1 -0
- package/dist/src/stores/parquet_location.js +194 -0
- package/dist/src/stores/parquet_location.js.map +1 -0
- package/dist/src/stores/tiered.d.ts +96 -0
- package/dist/src/stores/tiered.d.ts.map +1 -0
- package/dist/src/stores/tiered.js +277 -0
- package/dist/src/stores/tiered.js.map +1 -0
- package/dist/src/stream/streaming_store.d.ts +1 -1
- package/dist/src/stream/streaming_store.d.ts.map +1 -1
- package/dist/src/stream/streaming_store.js +2 -0
- package/dist/src/stream/streaming_store.js.map +1 -1
- package/dist/src/telescope_middleware.d.ts.map +1 -1
- package/dist/src/telescope_middleware.js +20 -11
- package/dist/src/telescope_middleware.js.map +1 -1
- package/dist/src/ui/index.d.ts +1 -1
- package/dist/src/ui/index.js +1 -1
- package/dist/src/watchers/cache_watcher.js +1 -1
- package/dist/src/watchers/cache_watcher.js.map +1 -1
- package/dist/src/watchers/events_watcher.js +1 -1
- package/dist/src/watchers/events_watcher.js.map +1 -1
- package/dist/src/watchers/http_client_watcher.js +1 -1
- package/dist/src/watchers/http_client_watcher.js.map +1 -1
- package/dist/src/watchers/index.d.ts +1 -1
- package/dist/src/watchers/index.js +1 -1
- package/dist/src/watchers/logs_watcher.js +1 -1
- package/dist/src/watchers/logs_watcher.js.map +1 -1
- package/dist/src/watchers/lucid_query_watcher.d.ts.map +1 -1
- package/dist/src/watchers/lucid_query_watcher.js +8 -2
- package/dist/src/watchers/lucid_query_watcher.js.map +1 -1
- package/dist/src/watchers/mail_watcher.js +1 -1
- package/dist/src/watchers/mail_watcher.js.map +1 -1
- package/dist/src/watchers/profiling_watcher.js +1 -1
- package/dist/src/watchers/profiling_watcher.js.map +1 -1
- package/dist/src/watchers/queue_watcher.js +1 -1
- package/dist/src/watchers/queue_watcher.js.map +1 -1
- package/dist/src/watchers/record.d.ts +5 -1
- package/dist/src/watchers/record.d.ts.map +1 -1
- package/dist/src/watchers/record.js +10 -1
- package/dist/src/watchers/record.js.map +1 -1
- package/dist/src/watchers/redis_watcher.js +1 -1
- package/dist/src/watchers/redis_watcher.js.map +1 -1
- package/dist/src/watchers/schedule_watcher.js +1 -1
- package/dist/src/watchers/schedule_watcher.js.map +1 -1
- package/dist/stubs/database/migrations/create_telescope_entries_table.stub +2 -2
- package/package.json +35 -9
- package/skills/telescope-setup/SKILL.md +1 -1
- package/skills/telescope-storage-retention/SKILL.md +13 -7
- package/skills/telescope-watchers/SKILL.md +7 -5
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { hostname } from 'node:os';
|
|
3
|
+
import { compareNewestFirst, HOUR_MS, hourStart, PARQUET_COLUMNS, parsePartition, partitionPrefix, resolvePage, toDate, toParquetRow, typePrefix, } from './parquet_format.js';
|
|
4
|
+
import { importOptionalPeer, isNotFound } from './parquet_location.js';
|
|
5
|
+
/**
|
|
6
|
+
* Entries as hourly-partitioned Parquet files in a {@link ColdObjectStore}:
|
|
7
|
+
*
|
|
8
|
+
* ```
|
|
9
|
+
* type=<type>/dt=<yyyy-mm-dd>/hour=<hh>/<instanceId>-<uuid>.parquet
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Files are append-only and immutable: writing adds files, {@link compact} replaces a
|
|
13
|
+
* closed hour's files with one merged file (written before the inputs are deleted),
|
|
14
|
+
* and retention deletes whole files. Rows inside a file are sorted by `created_at, id`
|
|
15
|
+
* with ~10k-row groups and statistics on, so time-bounded reads skip row groups.
|
|
16
|
+
*
|
|
17
|
+
* This is the cold half of `storage.tiered()`; it is not a {@link TelescopeStore} on its
|
|
18
|
+
* own because recording one entry at a time as Parquet would make one file per entry.
|
|
19
|
+
*/
|
|
20
|
+
export class ParquetColdStore {
|
|
21
|
+
location;
|
|
22
|
+
engine;
|
|
23
|
+
instanceId;
|
|
24
|
+
libs;
|
|
25
|
+
rowGroupSize;
|
|
26
|
+
maxRowsPerFile;
|
|
27
|
+
listingTtlMs;
|
|
28
|
+
metadataCacheSize;
|
|
29
|
+
compactPartitionsPerRun;
|
|
30
|
+
listings = new Map();
|
|
31
|
+
/** Small, per-file stats for every file seen (dropped when the file disappears). */
|
|
32
|
+
stats = new Map();
|
|
33
|
+
/** Parsed footers, LRU-bounded (Map iteration order is insertion order). */
|
|
34
|
+
footers = new Map();
|
|
35
|
+
/** Build a store and its engine (the engine may need async setup, e.g. DuckDB). */
|
|
36
|
+
static async create(options) {
|
|
37
|
+
const store = new ParquetColdStore(options);
|
|
38
|
+
store.engine = await options.engine({
|
|
39
|
+
location: store.location,
|
|
40
|
+
libs: store.libs,
|
|
41
|
+
metadata: (file) => store.metadata(file),
|
|
42
|
+
buffer: (file) => store.buffer(file),
|
|
43
|
+
});
|
|
44
|
+
return store;
|
|
45
|
+
}
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.location = options.location;
|
|
48
|
+
this.libs = options.libs;
|
|
49
|
+
this.instanceId = sanitizeInstanceId(options.instanceId ?? `${hostname()}-${process.pid}`);
|
|
50
|
+
this.rowGroupSize = Math.max(1, options.rowGroupSize ?? 10_000);
|
|
51
|
+
this.maxRowsPerFile = Math.max(this.rowGroupSize, options.maxRowsPerFile ?? 200_000);
|
|
52
|
+
this.listingTtlMs = Math.max(0, options.listingTtlMs ?? 2_000);
|
|
53
|
+
this.metadataCacheSize = Math.max(16, options.metadataCacheSize ?? 2_000);
|
|
54
|
+
this.compactPartitionsPerRun = Math.max(0, options.compactPartitionsPerRun ?? 4);
|
|
55
|
+
}
|
|
56
|
+
// ── Writes ────────────────────────────────────────────────────────────────
|
|
57
|
+
/**
|
|
58
|
+
* Write entries as Parquet, one or more files per `(type, hour)`. Resolves to the keys
|
|
59
|
+
* written, so a caller can delete them again if a later step of its own fails.
|
|
60
|
+
*/
|
|
61
|
+
async write(entries) {
|
|
62
|
+
const groups = new Map();
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
const hs = hourStart(entry.createdAt.getTime());
|
|
65
|
+
const groupKey = `${hs}\u0000${entry.type}`;
|
|
66
|
+
let group = groups.get(groupKey);
|
|
67
|
+
if (!group) {
|
|
68
|
+
group = { type: entry.type, hourStartMs: hs, rows: [] };
|
|
69
|
+
groups.set(groupKey, group);
|
|
70
|
+
}
|
|
71
|
+
group.rows.push(toParquetRow(entry, this.instanceId));
|
|
72
|
+
}
|
|
73
|
+
const written = [];
|
|
74
|
+
try {
|
|
75
|
+
for (const group of groups.values()) {
|
|
76
|
+
group.rows.sort(compareRowsAscending);
|
|
77
|
+
for (let i = 0; i < group.rows.length; i += this.maxRowsPerFile) {
|
|
78
|
+
const key = `${partitionPrefix(group.type, group.hourStartMs)}${this.instanceId}-${randomUUID()}.parquet`;
|
|
79
|
+
await this.location.write(key, this.encode(group.rows.slice(i, i + this.maxRowsPerFile)));
|
|
80
|
+
written.push(key);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
await this.location.delete(written).catch(() => undefined);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
this.listings.clear();
|
|
90
|
+
}
|
|
91
|
+
return written;
|
|
92
|
+
}
|
|
93
|
+
encode(rows) {
|
|
94
|
+
const columnData = PARQUET_COLUMNS.map((column) => ({
|
|
95
|
+
name: column.name,
|
|
96
|
+
type: column.type,
|
|
97
|
+
nullable: column.nullable,
|
|
98
|
+
data: rows.map((row) => row[column.name]),
|
|
99
|
+
...('bloomFilter' in column ? { bloomFilter: column.bloomFilter } : {}),
|
|
100
|
+
}));
|
|
101
|
+
const buffer = this.libs.writer.parquetWriteBuffer({
|
|
102
|
+
// hyparquet-writer types `data` as its DecodedArray union; rows are plain arrays.
|
|
103
|
+
columnData: columnData,
|
|
104
|
+
rowGroupSize: this.rowGroupSize,
|
|
105
|
+
statistics: true,
|
|
106
|
+
kvMetadata: [{ key: 'telescope.layout', value: '1' }],
|
|
107
|
+
createdBy: '@adonis-agora/telescope',
|
|
108
|
+
});
|
|
109
|
+
return new Uint8Array(buffer);
|
|
110
|
+
}
|
|
111
|
+
// ── Reads ─────────────────────────────────────────────────────────────────
|
|
112
|
+
/** Entries matching `query`, newest-first, honouring `{ page, size }`. */
|
|
113
|
+
async list(query = {}) {
|
|
114
|
+
if (query.traceIds !== undefined && query.traceIds.length === 0)
|
|
115
|
+
return [];
|
|
116
|
+
const { offset, size } = resolvePage(query);
|
|
117
|
+
const files = await this.candidates(query);
|
|
118
|
+
const rows = await this.engine.list(files, query, size === undefined ? undefined : offset + size);
|
|
119
|
+
return size === undefined ? rows : rows.slice(offset, offset + size);
|
|
120
|
+
}
|
|
121
|
+
/** The newest `limit` matches with no page offset — what the tiered merge needs. */
|
|
122
|
+
async top(query, limit) {
|
|
123
|
+
if (query.traceIds !== undefined && query.traceIds.length === 0)
|
|
124
|
+
return [];
|
|
125
|
+
return this.engine.list(await this.candidates(query), query, limit);
|
|
126
|
+
}
|
|
127
|
+
async get(id) {
|
|
128
|
+
return this.engine.get(await this.candidates({}), id);
|
|
129
|
+
}
|
|
130
|
+
async listTraceIds(query) {
|
|
131
|
+
const size = Math.max(0, Math.floor(query.size));
|
|
132
|
+
const offset = (Math.max(1, Math.floor(query.page ?? 1)) - 1) * size;
|
|
133
|
+
const rows = await this.topTraceIds(query, offset + size);
|
|
134
|
+
return rows.slice(offset, offset + size);
|
|
135
|
+
}
|
|
136
|
+
/** The `limit` most-recently-seen traces, no offset (for the tiered merge). */
|
|
137
|
+
async topTraceIds(query, limit) {
|
|
138
|
+
if (limit <= 0)
|
|
139
|
+
return [];
|
|
140
|
+
return this.engine.traceIds(await this.candidates(query), query, limit);
|
|
141
|
+
}
|
|
142
|
+
async countByBucket(query) {
|
|
143
|
+
// `after` is exclusive and `before` inclusive here; widen `before` by 1 ms so the
|
|
144
|
+
// exclusive candidate pruning keeps the file holding the boundary row.
|
|
145
|
+
const files = await this.candidates({
|
|
146
|
+
...(query.type !== undefined ? { type: query.type } : {}),
|
|
147
|
+
after: query.after,
|
|
148
|
+
before: new Date(query.before.getTime() + 1),
|
|
149
|
+
});
|
|
150
|
+
return this.engine.countByBucket(files, query);
|
|
151
|
+
}
|
|
152
|
+
/** Rows in the cold tier, from file footers (no rows are read). */
|
|
153
|
+
async count() {
|
|
154
|
+
const files = await this.candidates({});
|
|
155
|
+
return files.reduce((sum, file) => sum + file.numRows, 0);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The newest `created_at` the cold tier could hold for `query`, or `null` when it holds
|
|
159
|
+
* nothing for it. Lets the tiered store skip the cold tier when a page is already
|
|
160
|
+
* filled by hot entries that are all newer.
|
|
161
|
+
*/
|
|
162
|
+
async newestCreatedAt(query) {
|
|
163
|
+
const files = await this.candidates(query);
|
|
164
|
+
return files.length === 0 ? null : new Date(files[0].maxMs);
|
|
165
|
+
}
|
|
166
|
+
// ── Retention + compaction ───────────────────────────────────────────────
|
|
167
|
+
/**
|
|
168
|
+
* Delete every file whose whole hour is older than `olderThan`, keeping the newest
|
|
169
|
+
* files of that doomed set until they hold at least `keepLast` rows. Retention is
|
|
170
|
+
* file-granular: an hour stays until all of it has expired. Resolves to the rows
|
|
171
|
+
* deleted.
|
|
172
|
+
*/
|
|
173
|
+
async expire(olderThan, keepLast) {
|
|
174
|
+
const cutoff = olderThan.getTime();
|
|
175
|
+
const all = await this.listAll(true);
|
|
176
|
+
const doomed = all
|
|
177
|
+
.filter((file) => file.hourStartMs + HOUR_MS <= cutoff)
|
|
178
|
+
.sort((a, b) => b.hourStartMs - a.hourStartMs || b.key.localeCompare(a.key));
|
|
179
|
+
if (doomed.length === 0)
|
|
180
|
+
return 0;
|
|
181
|
+
let kept = 0;
|
|
182
|
+
const toDelete = [];
|
|
183
|
+
for (const file of doomed) {
|
|
184
|
+
if (keepLast !== undefined && kept < keepLast) {
|
|
185
|
+
kept += (await this.withStats(file))?.numRows ?? 0;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
toDelete.push(file);
|
|
189
|
+
}
|
|
190
|
+
let rows = 0;
|
|
191
|
+
for (const file of toDelete)
|
|
192
|
+
rows += (await this.withStats(file))?.numRows ?? 0;
|
|
193
|
+
await this.location.delete(toDelete.map((file) => file.key));
|
|
194
|
+
this.forget(toDelete.map((file) => file.key));
|
|
195
|
+
return rows;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Merge the files of closed hours (hours that ended before `closedBefore`) so each
|
|
199
|
+
* holds one file per {@link ParquetColdStoreOptions.maxRowsPerFile} rows instead of
|
|
200
|
+
* one per prune cycle. The merged file is written before its inputs are deleted, so
|
|
201
|
+
* a reader never loses rows; one that lists in between sees both and the merge on
|
|
202
|
+
* read drops the duplicate ids. Resolves to the number of input files replaced.
|
|
203
|
+
*/
|
|
204
|
+
async compact(closedBefore) {
|
|
205
|
+
if (this.compactPartitionsPerRun === 0)
|
|
206
|
+
return 0;
|
|
207
|
+
const cutoff = closedBefore.getTime();
|
|
208
|
+
const byPartition = new Map();
|
|
209
|
+
for (const file of await this.listAll(true)) {
|
|
210
|
+
if (file.hourStartMs + HOUR_MS > cutoff)
|
|
211
|
+
continue;
|
|
212
|
+
const key = partitionPrefix(file.type, file.hourStartMs);
|
|
213
|
+
const group = byPartition.get(key) ?? [];
|
|
214
|
+
group.push(file);
|
|
215
|
+
byPartition.set(key, group);
|
|
216
|
+
}
|
|
217
|
+
let replaced = 0;
|
|
218
|
+
let partitions = 0;
|
|
219
|
+
for (const files of byPartition.values()) {
|
|
220
|
+
if (partitions >= this.compactPartitionsPerRun)
|
|
221
|
+
break;
|
|
222
|
+
const withStats = (await Promise.all(files.map((file) => this.withStats(file)))).filter((file) => file !== null);
|
|
223
|
+
// Only merge files that are small enough to be worth it, packed up to the file cap.
|
|
224
|
+
const small = withStats
|
|
225
|
+
.filter((file) => file.numRows < this.maxRowsPerFile)
|
|
226
|
+
.sort((a, b) => a.minMs - b.minMs);
|
|
227
|
+
const batches = [];
|
|
228
|
+
let current = [];
|
|
229
|
+
let rows = 0;
|
|
230
|
+
for (const file of small) {
|
|
231
|
+
if (current.length > 0 && rows + file.numRows > this.maxRowsPerFile) {
|
|
232
|
+
batches.push(current);
|
|
233
|
+
current = [];
|
|
234
|
+
rows = 0;
|
|
235
|
+
}
|
|
236
|
+
current.push(file);
|
|
237
|
+
rows += file.numRows;
|
|
238
|
+
}
|
|
239
|
+
if (current.length > 0)
|
|
240
|
+
batches.push(current);
|
|
241
|
+
const toMerge = batches.filter((batch) => batch.length > 1);
|
|
242
|
+
if (toMerge.length === 0)
|
|
243
|
+
continue;
|
|
244
|
+
partitions++;
|
|
245
|
+
for (const batch of toMerge) {
|
|
246
|
+
const entries = await this.engine.list(batch, {}, undefined);
|
|
247
|
+
const unique = dedupeById(entries);
|
|
248
|
+
await this.write(unique);
|
|
249
|
+
await this.location.delete(batch.map((file) => file.key));
|
|
250
|
+
this.forget(batch.map((file) => file.key));
|
|
251
|
+
replaced += batch.length;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return replaced;
|
|
255
|
+
}
|
|
256
|
+
/** Delete every file. */
|
|
257
|
+
async clear() {
|
|
258
|
+
const all = await this.listAll(true);
|
|
259
|
+
await this.location.delete(all.map((file) => file.key));
|
|
260
|
+
this.forget(all.map((file) => file.key));
|
|
261
|
+
}
|
|
262
|
+
async close() {
|
|
263
|
+
await this.engine.close();
|
|
264
|
+
}
|
|
265
|
+
// ── Listing + footers ────────────────────────────────────────────────────
|
|
266
|
+
/**
|
|
267
|
+
* Files that can hold rows for `query`: its type's prefix only, hours outside the
|
|
268
|
+
* time bounds dropped by partition, then files outside them dropped by footer stats.
|
|
269
|
+
* Sorted newest-first by each file's newest row.
|
|
270
|
+
*/
|
|
271
|
+
async candidates(query) {
|
|
272
|
+
const before = query.before?.getTime();
|
|
273
|
+
const after = query.after?.getTime();
|
|
274
|
+
const listed = await this.list_(query.type);
|
|
275
|
+
const byHour = listed.filter((file) => {
|
|
276
|
+
if (query.type !== undefined && file.type !== query.type)
|
|
277
|
+
return false;
|
|
278
|
+
if (before !== undefined && file.hourStartMs >= before)
|
|
279
|
+
return false;
|
|
280
|
+
if (after !== undefined && file.hourStartMs + HOUR_MS - 1 <= after)
|
|
281
|
+
return false;
|
|
282
|
+
return true;
|
|
283
|
+
});
|
|
284
|
+
const resolved = await Promise.all(byHour.map((file) => this.withStats(file)));
|
|
285
|
+
return resolved
|
|
286
|
+
.filter((file) => {
|
|
287
|
+
if (file === null || file.numRows === 0)
|
|
288
|
+
return false;
|
|
289
|
+
if (before !== undefined && file.minMs >= before)
|
|
290
|
+
return false;
|
|
291
|
+
if (after !== undefined && file.maxMs <= after)
|
|
292
|
+
return false;
|
|
293
|
+
return true;
|
|
294
|
+
})
|
|
295
|
+
.sort((a, b) => b.maxMs - a.maxMs || b.key.localeCompare(a.key));
|
|
296
|
+
}
|
|
297
|
+
list_(type) {
|
|
298
|
+
const prefix = type === undefined ? '' : typePrefix(type);
|
|
299
|
+
const now = Date.now();
|
|
300
|
+
const cached = this.listings.get(prefix);
|
|
301
|
+
if (cached && now - cached.at < this.listingTtlMs)
|
|
302
|
+
return cached.files;
|
|
303
|
+
const files = this.location.list(prefix).then((objects) => {
|
|
304
|
+
const out = [];
|
|
305
|
+
for (const object of objects) {
|
|
306
|
+
const partition = parsePartition(object.key);
|
|
307
|
+
if (!partition)
|
|
308
|
+
continue;
|
|
309
|
+
out.push(this.stats.get(object.key) ?? {
|
|
310
|
+
key: object.key,
|
|
311
|
+
size: object.size,
|
|
312
|
+
type: partition.type,
|
|
313
|
+
hourStartMs: partition.hourStartMs,
|
|
314
|
+
numRows: -1,
|
|
315
|
+
minMs: partition.hourStartMs,
|
|
316
|
+
maxMs: partition.hourStartMs + HOUR_MS - 1,
|
|
317
|
+
rowGroups: [],
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
return out;
|
|
321
|
+
});
|
|
322
|
+
files.catch(() => this.listings.delete(prefix));
|
|
323
|
+
this.listings.set(prefix, { at: now, files });
|
|
324
|
+
return files;
|
|
325
|
+
}
|
|
326
|
+
async listAll(fresh) {
|
|
327
|
+
if (fresh)
|
|
328
|
+
this.listings.clear();
|
|
329
|
+
return this.list_(undefined);
|
|
330
|
+
}
|
|
331
|
+
/** The file with footer stats filled in, or `null` when it no longer exists. */
|
|
332
|
+
async withStats(file) {
|
|
333
|
+
if (file.numRows >= 0)
|
|
334
|
+
return file;
|
|
335
|
+
const known = this.stats.get(file.key);
|
|
336
|
+
if (known)
|
|
337
|
+
return known;
|
|
338
|
+
let meta;
|
|
339
|
+
try {
|
|
340
|
+
meta = await this.metadata(file);
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
if (isNotFound(error))
|
|
344
|
+
return null;
|
|
345
|
+
throw error;
|
|
346
|
+
}
|
|
347
|
+
const full = { ...file, ...statsFromFooter(meta, file) };
|
|
348
|
+
this.stats.set(file.key, full);
|
|
349
|
+
return full;
|
|
350
|
+
}
|
|
351
|
+
/** Parsed footer for a file, through a bounded LRU. */
|
|
352
|
+
metadata(file) {
|
|
353
|
+
const hit = this.footers.get(file.key);
|
|
354
|
+
if (hit) {
|
|
355
|
+
this.footers.delete(file.key);
|
|
356
|
+
this.footers.set(file.key, hit);
|
|
357
|
+
return hit;
|
|
358
|
+
}
|
|
359
|
+
const pending = this.libs.hyparquet.parquetMetadataAsync(this.buffer(file));
|
|
360
|
+
pending.catch(() => this.footers.delete(file.key));
|
|
361
|
+
this.footers.set(file.key, pending);
|
|
362
|
+
while (this.footers.size > this.metadataCacheSize) {
|
|
363
|
+
const oldest = this.footers.keys().next().value;
|
|
364
|
+
if (oldest === undefined)
|
|
365
|
+
break;
|
|
366
|
+
this.footers.delete(oldest);
|
|
367
|
+
}
|
|
368
|
+
return pending;
|
|
369
|
+
}
|
|
370
|
+
buffer(file) {
|
|
371
|
+
const location = this.location;
|
|
372
|
+
return {
|
|
373
|
+
byteLength: file.size,
|
|
374
|
+
slice(start, end) {
|
|
375
|
+
const read = location
|
|
376
|
+
.read(file.key, start, end)
|
|
377
|
+
.then((bytes) => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
|
|
378
|
+
// hyparquet starts sibling reads it abandons when one fails, e.g. on a file
|
|
379
|
+
// deleted mid-read. Marking each read handled keeps those from crashing the
|
|
380
|
+
// process; whoever awaits it still gets the error.
|
|
381
|
+
read.catch(() => { });
|
|
382
|
+
return read;
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
forget(keys) {
|
|
387
|
+
for (const key of keys) {
|
|
388
|
+
this.stats.delete(key);
|
|
389
|
+
this.footers.delete(key);
|
|
390
|
+
}
|
|
391
|
+
this.listings.clear();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Load the hyparquet trio. They are optional peers (only `storage.tiered()` needs them),
|
|
396
|
+
* so a missing one fails boot with a message naming it.
|
|
397
|
+
*/
|
|
398
|
+
export async function loadParquetLibs() {
|
|
399
|
+
const neededBy = 'storage.parquet()';
|
|
400
|
+
const [hyparquet, writer, compressorsModule] = await Promise.all([
|
|
401
|
+
importOptionalPeer('hyparquet', neededBy, () => import('hyparquet')),
|
|
402
|
+
importOptionalPeer('hyparquet-writer', neededBy, () => import('hyparquet-writer')),
|
|
403
|
+
importOptionalPeer('hyparquet-compressors', neededBy, () => import('hyparquet-compressors')),
|
|
404
|
+
]);
|
|
405
|
+
return { hyparquet, writer, compressors: compressorsModule.compressors };
|
|
406
|
+
}
|
|
407
|
+
function statsFromFooter(meta, file) {
|
|
408
|
+
const createdAtIndex = meta.schema.slice(1).findIndex((element) => element.name === 'created_at');
|
|
409
|
+
const rowGroups = [];
|
|
410
|
+
let rowStart = 0;
|
|
411
|
+
let minMs = Number.POSITIVE_INFINITY;
|
|
412
|
+
let maxMs = Number.NEGATIVE_INFINITY;
|
|
413
|
+
for (const group of meta.row_groups) {
|
|
414
|
+
const rows = Number(group.num_rows);
|
|
415
|
+
const statistics = group.columns[createdAtIndex]?.meta_data?.statistics;
|
|
416
|
+
const lo = statValue(statistics?.min_value ?? statistics?.min, file.hourStartMs);
|
|
417
|
+
const hi = statValue(statistics?.max_value ?? statistics?.max, file.hourStartMs + HOUR_MS - 1);
|
|
418
|
+
rowGroups.push({ rowStart, rowEnd: rowStart + rows, minMs: lo, maxMs: hi });
|
|
419
|
+
minMs = Math.min(minMs, lo);
|
|
420
|
+
maxMs = Math.max(maxMs, hi);
|
|
421
|
+
rowStart += rows;
|
|
422
|
+
}
|
|
423
|
+
if (rowGroups.length === 0) {
|
|
424
|
+
minMs = file.hourStartMs;
|
|
425
|
+
maxMs = file.hourStartMs;
|
|
426
|
+
}
|
|
427
|
+
return { numRows: Number(meta.num_rows), minMs, maxMs, rowGroups };
|
|
428
|
+
}
|
|
429
|
+
function statValue(value, fallback) {
|
|
430
|
+
if (value === undefined || value === null)
|
|
431
|
+
return fallback;
|
|
432
|
+
const ms = toDate(value).getTime();
|
|
433
|
+
return Number.isFinite(ms) ? ms : fallback;
|
|
434
|
+
}
|
|
435
|
+
function compareRowsAscending(a, b) {
|
|
436
|
+
const t = a.created_at.getTime() - b.created_at.getTime();
|
|
437
|
+
if (t !== 0)
|
|
438
|
+
return t;
|
|
439
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
440
|
+
}
|
|
441
|
+
/** Keep the first occurrence of each id (callers pass newest-first lists). */
|
|
442
|
+
export function dedupeById(entries) {
|
|
443
|
+
const seen = new Set();
|
|
444
|
+
const out = [];
|
|
445
|
+
for (const entry of entries) {
|
|
446
|
+
if (seen.has(entry.id))
|
|
447
|
+
continue;
|
|
448
|
+
seen.add(entry.id);
|
|
449
|
+
out.push(entry);
|
|
450
|
+
}
|
|
451
|
+
return out;
|
|
452
|
+
}
|
|
453
|
+
/** Merge newest-first lists into one newest-first list without duplicate ids. */
|
|
454
|
+
export function mergeNewestFirst(...lists) {
|
|
455
|
+
return dedupeById(lists.flat().sort(compareNewestFirst));
|
|
456
|
+
}
|
|
457
|
+
function sanitizeInstanceId(value) {
|
|
458
|
+
const clean = value.replace(/[^A-Za-z0-9_.-]/g, '_');
|
|
459
|
+
return clean === '' ? 'telescope' : clean;
|
|
460
|
+
}
|
|
461
|
+
//# sourceMappingURL=parquet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parquet.js","sourceRoot":"","sources":["../../../src/stores/parquet.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Entry } from '../entry.js';
|
|
2
|
+
import type { BucketCountQuery, BucketCountRow, EntryQuery, TraceIdRow } from '../store.js';
|
|
3
|
+
import type { ColdEngineContext, ColdFile, ColdReadEngine } from './parquet.js';
|
|
4
|
+
/** Options for the DuckDB cold engine (`engine: { duckdb: { ... } }`). */
|
|
5
|
+
export interface DuckDbEngineOptions {
|
|
6
|
+
/** DuckDB `memory_limit`, e.g. `'512MB'`. Default: DuckDB's own (80% of RAM). */
|
|
7
|
+
memoryLimit?: string;
|
|
8
|
+
/** DuckDB worker threads. Default 2, so a wide scan cannot take every core. */
|
|
9
|
+
threads?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Where remote (S3) files are copied before DuckDB reads them, since DuckDB only reads
|
|
12
|
+
* them by path here. Default `<os tmpdir>/adonis-telescope-parquet`.
|
|
13
|
+
*/
|
|
14
|
+
cacheDir?: string;
|
|
15
|
+
/** Bytes of copied files kept in {@link cacheDir}. Default 1 GiB. */
|
|
16
|
+
cacheBytes?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The optional DuckDB cold engine (`@duckdb/node-api`, an optional peer).
|
|
20
|
+
*
|
|
21
|
+
* It only reads files by local path. A directory location's files are read in place;
|
|
22
|
+
* remote files are fetched through the location (the host's own S3 client) into a
|
|
23
|
+
* bounded local cache first. The instance is locked down at start: extension
|
|
24
|
+
* auto-install/auto-load off, external access off except the data and cache
|
|
25
|
+
* directories, and the configuration locked, so DuckDB can never download or load
|
|
26
|
+
* `httpfs` / `aws` (they are not bundled; DuckDB would fetch them at runtime).
|
|
27
|
+
*/
|
|
28
|
+
export declare class DuckDbEngine implements ColdReadEngine {
|
|
29
|
+
private readonly ctx;
|
|
30
|
+
private readonly instance;
|
|
31
|
+
readonly name: 'duckdb';
|
|
32
|
+
private readonly cache;
|
|
33
|
+
private constructor();
|
|
34
|
+
/** Build the engine. Fails with a clear error when `@duckdb/node-api` is missing. */
|
|
35
|
+
static create(ctx: ColdEngineContext, options?: DuckDbEngineOptions): Promise<DuckDbEngine>;
|
|
36
|
+
list(files: ColdFile[], query: EntryQuery, limit: number | undefined): Promise<Entry[]>;
|
|
37
|
+
get(files: ColdFile[], id: string): Promise<Entry | null>;
|
|
38
|
+
traceIds(files: ColdFile[], query: {
|
|
39
|
+
before?: Date;
|
|
40
|
+
after?: Date;
|
|
41
|
+
}, limit: number): Promise<TraceIdRow[]>;
|
|
42
|
+
countByBucket(files: ColdFile[], query: BucketCountQuery): Promise<BucketCountRow[]>;
|
|
43
|
+
close(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Run one statement over `files`. A file deleted between listing and reading
|
|
46
|
+
* (retention, compaction) makes DuckDB fail the whole scan, so on an IO error the
|
|
47
|
+
* statement is retried once over the files that still exist.
|
|
48
|
+
*/
|
|
49
|
+
private query;
|
|
50
|
+
private paths;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=parquet_duckdb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parquet_duckdb.d.ts","sourceRoot":"","sources":["../../../src/stores/parquet_duckdb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAOhF,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAa,YAAW,cAAc;IAK/C,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAE9C,OAAO,eAMN;IAED,qFAAqF;IACrF,OAAa,MAAM,CACjB,GAAG,EAAE,iBAAiB,EACtB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CAuCvB;IAEK,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CA4B5F;IAEK,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAQ9D;IAEK,QAAQ,CACZ,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,IAAI,CAAA;KAAE,EACtC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,EAAE,CAAC,CAkBvB;IAEK,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAmBzF;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;IAED;;;;OAIG;YACW,KAAK;YAsBL,KAAK;CAYpB"}
|