diff options
| author | Adam Soltys <[email protected]> | 2026-06-04 00:42:15 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-06-04 00:42:15 -0700 |
| commit | 3db24424438322c3b341623456bd235ae64f98a1 (patch) | |
| tree | 2f3064847d018aa559a32d8f1bad79578e4ab044 /scripts/analytics.ts | |
| parent | 183a3cb03e9ca04a0b1433fa2850a47747de00d6 (diff) | |
| download | coinos-server-3db24424438322c3b341623456bd235ae64f98a1.tar.gz coinos-server-3db24424438322c3b341623456bd235ae64f98a1.zip | |
analytics: --csv flag for month-over-month trend tracking
Appends one metrics row per run to a CSV (header written if file is new):
date, users, MAU/WAU, payments, volume, custody, fee revenue, bolt12
recipients, and per-type volume/txn columns. Notice goes to stderr so it
doesn't pollute the saved stdout report or --json output. Drives the new
monthly snapshot cron (~/scripts/analytics-cron.sh).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'scripts/analytics.ts')
| -rw-r--r-- | scripts/analytics.ts | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/scripts/analytics.ts b/scripts/analytics.ts index d4c8ea54..7cefa3d4 100644 --- a/scripts/analytics.ts +++ b/scripts/analytics.ts @@ -3,16 +3,21 @@ // aggregates payment + balance + user data into an insight report. // // Usage: -// bun scripts/analytics.ts [--days N] [--top N] [--json] +// bun scripts/analytics.ts [--days N] [--top N] [--json] [--csv PATH] // // Defaults: --days 30, --top 20. Reads only the live db (redis://127.0.0.1:6379); // archived payments (older, in `arc`) are out of scope for the trailing window. +// --csv appends one metrics row to PATH (writing a header if the file is new), +// for month-over-month trend tracking; the human report still prints to stdout. import { createClient } from "redis"; +import { appendFileSync, existsSync } from "fs"; const argDays = Number(process.argv[process.argv.indexOf("--days") + 1]) || 30; const TOP = Number(process.argv[process.argv.indexOf("--top") + 1]) || 20; const asJson = process.argv.includes("--json"); +const csvIdx = process.argv.indexOf("--csv"); +const csvPath = csvIdx >= 0 ? process.argv[csvIdx + 1] : null; const now = Date.now(); const cutoff = now - argDays * 24 * 60 * 60 * 1000; @@ -169,6 +174,50 @@ regularBolt12.sort((a, b) => b[1] - a[1]); const totalVolume = Object.values(byType).reduce((s, a) => s + a.volume, 0); +// ---- CSV append (trend tracking) ------------------------------------------- +// One row per run. Stable column set so months line up; per-type volume/count +// columns let us chart the lightning/liquid/bitcoin/internal/bolt12 mix over +// time. Written before stdout output so it happens in both text and --json modes. +if (csvPath) { + const typeCols = ["lightning", "liquid", "bitcoin", "internal", "bolt12", "fund"]; + const header = [ + "date", + "window_days", + "users_total", + "new_users", + "mau", + "wau", + "payments", + "total_volume_sats", + "custodied_sats", + "holders", + "fee_revenue_sats", + "bolt12_recipients", + "regular_bolt12", + ...typeCols.flatMap((t) => [`${t}_vol`, `${t}_txns`]), + ]; + const row = [ + new Date(now).toISOString().slice(0, 10), + argDays, + userRecords, + newUsers, + activeUids.size, + weekActive.size, + paymentsInWindow, + totalVolume, + totalCustodied, + holders.length, + feeRevenue, + bolt12Recipients.size, + regularBolt12.length, + ...typeCols.flatMap((t) => [byType[t]?.volume || 0, byType[t]?.count || 0]), + ]; + const fresh = !existsSync(csvPath); + appendFileSync(csvPath, (fresh ? header.join(",") + "\n" : "") + row.join(",") + "\n"); + // To stderr so it doesn't pollute the saved stdout report / --json output. + console.error(`[csv] appended row to ${csvPath}`); +} + // ---- output ---------------------------------------------------------------- if (asJson) { |
