| 1 | /** |
| 2 | * What a project of a workspace without the g1t plan may send: |
| 3 | * `FREE_TELEMETRY_BYTES_PER_MONTH` (1 GiB, a wrangler var; `0` is no cap), |
| 4 | * held a day at a time as a thirtieth of it, so a burst cannot spend the |
| 5 | * month in an hour. Past a day's share, OTLP is answered `429` until |
| 6 | * midnight UTC, and Cloudflare's tail events of the project's apps keep |
| 7 | * their requests (what the charts are counted from) without their logs. |
| 8 | * |
| 9 | * Bytes are what arrived: an OTLP body once unzipped, and a tail event's |
| 10 | * rows as they are kept. |
| 11 | */ |
| 12 | |
| 13 | export const DEFAULT_FREE_TELEMETRY_BYTES_PER_MONTH = 1024 * 1024 * 1024; |
| 14 | const DAYS_PER_MONTH = 30; |
| 15 | |
| 16 | /** The monthly allowance from its var: the default when unset or not a whole number; 0 is none. */ |
| 17 | export function freeMonthlyBytes(raw: string | undefined): number { |
| 18 | const text = (raw ?? "").trim(); |
| 19 | const value = Number(text); |
| 20 | return text !== "" && Number.isInteger(value) && value >= 0 ? value : DEFAULT_FREE_TELEMETRY_BYTES_PER_MONTH; |
| 21 | } |
| 22 | |
| 23 | /** A day's share of a monthly allowance; null for none. */ |
| 24 | export function dailyCap(monthly: number): number | null { |
| 25 | return monthly > 0 ? Math.ceil(monthly / DAYS_PER_MONTH) : null; |
| 26 | } |
| 27 | |
| 28 | /** |
| 29 | * Whether `adding` more bytes today would go past `cap`. A cap of 0 takes |
| 30 | * nothing: a workspace g1t staff put a hold on (or suspended). |
| 31 | */ |
| 32 | export function overCap(today: number, adding: number, cap: number | null | undefined): boolean { |
| 33 | return cap != null && cap >= 0 && today + adding > cap; |
| 34 | } |
| 35 | |
| 36 | /** The size of a row as it is kept: its JSON. */ |
| 37 | export function sizeOf(value: unknown): number { |
| 38 | return JSON.stringify(value)?.length ?? 0; |
| 39 | } |
| 40 | |
| 41 | /** What OTLP past the day's share is told; with a cap of 0, that the workspace is held. */ |
| 42 | export function overCapMessage(cap: number): string { |
| 43 | if (cap === 0) return "g1t staff put a hold on this project's workspace, so its telemetry is not taken. Write to hey@flagon.io if you think this is a mistake."; |
| 44 | const mb = Math.round(cap / (1024 * 1024)); |
| 45 | return `This project has sent its ${mb} MB for today, a workspace on the free plan's daily share of its monthly observability. Send less, or start the g1t plan; more is taken from 00:00 UTC.`; |
| 46 | } |