| 1 | /** |
| 2 | * The tables of a project's store, in the Durable Object's own SQLite. |
| 3 | * Each step runs once, in order; the store keeps how many have run. |
| 4 | * |
| 5 | * Raw rows (requests, logs, spans, metric points) are kept for the |
| 6 | * project's retention. `rollups` are per-minute counts of requests by |
| 7 | * service, environment, deployment and route, with latency and CPU as |
| 8 | * histograms (./histogram.ts): what the overview's charts read, kept for |
| 9 | * `ROLLUP_DAYS` whatever the retention. Each minute also has one row of |
| 10 | * all routes together (method and route `*`), which the charts read. |
| 11 | */ |
| 12 | export const ROLLUP_DAYS = 90; |
| 13 | |
| 14 | export const MIGRATIONS: string[] = [ |
| 15 | ` |
| 16 | CREATE TABLE requests ( |
| 17 | id TEXT PRIMARY KEY, |
| 18 | time_us INTEGER NOT NULL, |
| 19 | duration_us INTEGER NOT NULL DEFAULT 0, |
| 20 | trigger TEXT NOT NULL DEFAULT 'fetch', |
| 21 | method TEXT, |
| 22 | url TEXT, |
| 23 | route TEXT, |
| 24 | status INTEGER, |
| 25 | outcome TEXT NOT NULL DEFAULT 'ok', |
| 26 | cpu_ms REAL, |
| 27 | region TEXT, |
| 28 | country TEXT, |
| 29 | trace_id TEXT, |
| 30 | log_count INTEGER NOT NULL DEFAULT 0, |
| 31 | error_name TEXT, |
| 32 | error_message TEXT, |
| 33 | service TEXT NOT NULL DEFAULT '', |
| 34 | environment TEXT, |
| 35 | deployment_id TEXT, |
| 36 | commit_sha TEXT, |
| 37 | source TEXT NOT NULL, |
| 38 | -- Which halves have arrived: the dispatcher's (edge) and the app's. |
| 39 | edge INTEGER NOT NULL DEFAULT 0, |
| 40 | app INTEGER NOT NULL DEFAULT 0, |
| 41 | -- Counted into rollups yet. |
| 42 | rolled INTEGER NOT NULL DEFAULT 0 |
| 43 | ); |
| 44 | CREATE INDEX requests_by_time ON requests (time_us); |
| 45 | CREATE INDEX requests_by_trace ON requests (trace_id); |
| 46 | CREATE INDEX requests_to_roll ON requests (rolled, time_us); |
| 47 | |
| 48 | CREATE TABLE logs ( |
| 49 | id TEXT PRIMARY KEY, |
| 50 | time_us INTEGER NOT NULL, |
| 51 | severity_number INTEGER NOT NULL, |
| 52 | body TEXT NOT NULL, |
| 53 | trace_id TEXT, |
| 54 | span_id TEXT, |
| 55 | request_id TEXT, |
| 56 | attributes TEXT NOT NULL DEFAULT '{}', |
| 57 | service TEXT NOT NULL DEFAULT '', |
| 58 | environment TEXT, |
| 59 | deployment_id TEXT, |
| 60 | commit_sha TEXT, |
| 61 | source TEXT NOT NULL |
| 62 | ); |
| 63 | CREATE INDEX logs_by_time ON logs (time_us); |
| 64 | CREATE INDEX logs_by_trace ON logs (trace_id); |
| 65 | CREATE INDEX logs_by_request ON logs (request_id); |
| 66 | |
| 67 | CREATE TABLE spans ( |
| 68 | trace_id TEXT NOT NULL, |
| 69 | span_id TEXT NOT NULL, |
| 70 | parent_span_id TEXT, |
| 71 | name TEXT NOT NULL, |
| 72 | kind TEXT NOT NULL, |
| 73 | start_us INTEGER NOT NULL, |
| 74 | duration_us INTEGER NOT NULL, |
| 75 | status TEXT NOT NULL, |
| 76 | status_message TEXT, |
| 77 | attributes TEXT NOT NULL DEFAULT '{}', |
| 78 | resource TEXT NOT NULL DEFAULT '{}', |
| 79 | events TEXT NOT NULL DEFAULT '[]', |
| 80 | links TEXT NOT NULL DEFAULT '[]', |
| 81 | service TEXT NOT NULL DEFAULT '', |
| 82 | environment TEXT, |
| 83 | deployment_id TEXT, |
| 84 | commit_sha TEXT, |
| 85 | source TEXT NOT NULL, |
| 86 | PRIMARY KEY (trace_id, span_id) |
| 87 | ); |
| 88 | CREATE INDEX spans_by_time ON spans (start_us); |
| 89 | |
| 90 | CREATE TABLE metric_points ( |
| 91 | name TEXT NOT NULL, |
| 92 | kind TEXT NOT NULL, |
| 93 | time_us INTEGER NOT NULL, |
| 94 | value REAL, |
| 95 | count REAL, |
| 96 | sum REAL, |
| 97 | min REAL, |
| 98 | max REAL, |
| 99 | bounds TEXT, |
| 100 | counts TEXT, |
| 101 | quantiles TEXT, |
| 102 | monotonic INTEGER NOT NULL DEFAULT 0, |
| 103 | attributes TEXT NOT NULL DEFAULT '{}', |
| 104 | service TEXT NOT NULL DEFAULT '', |
| 105 | environment TEXT, |
| 106 | deployment_id TEXT, |
| 107 | source TEXT NOT NULL |
| 108 | ); |
| 109 | CREATE INDEX metric_points_by_name ON metric_points (name, time_us); |
| 110 | CREATE INDEX metric_points_by_time ON metric_points (time_us); |
| 111 | |
| 112 | CREATE TABLE metric_names ( |
| 113 | name TEXT PRIMARY KEY, |
| 114 | kind TEXT NOT NULL, |
| 115 | unit TEXT NOT NULL DEFAULT '', |
| 116 | description TEXT NOT NULL DEFAULT '', |
| 117 | services TEXT NOT NULL DEFAULT '[]', |
| 118 | last_us INTEGER NOT NULL |
| 119 | ); |
| 120 | |
| 121 | CREATE TABLE rollups ( |
| 122 | minute INTEGER NOT NULL, |
| 123 | service TEXT NOT NULL, |
| 124 | environment TEXT NOT NULL DEFAULT '', |
| 125 | deployment_id TEXT NOT NULL DEFAULT '', |
| 126 | commit_sha TEXT, |
| 127 | source TEXT NOT NULL, |
| 128 | method TEXT NOT NULL DEFAULT '', |
| 129 | route TEXT NOT NULL DEFAULT '', |
| 130 | requests INTEGER NOT NULL DEFAULT 0, |
| 131 | errors INTEGER NOT NULL DEFAULT 0, |
| 132 | s2 INTEGER NOT NULL DEFAULT 0, |
| 133 | s3 INTEGER NOT NULL DEFAULT 0, |
| 134 | s4 INTEGER NOT NULL DEFAULT 0, |
| 135 | s5 INTEGER NOT NULL DEFAULT 0, |
| 136 | latency TEXT NOT NULL DEFAULT '', |
| 137 | cpu TEXT NOT NULL DEFAULT '', |
| 138 | PRIMARY KEY (minute, service, environment, deployment_id, method, route) |
| 139 | ); |
| 140 | |
| 141 | CREATE TABLE error_groups ( |
| 142 | fingerprint TEXT PRIMARY KEY, |
| 143 | name TEXT NOT NULL, |
| 144 | message TEXT NOT NULL, |
| 145 | stack TEXT, |
| 146 | service TEXT NOT NULL, |
| 147 | environment TEXT, |
| 148 | first_us INTEGER NOT NULL, |
| 149 | last_us INTEGER NOT NULL, |
| 150 | count INTEGER NOT NULL DEFAULT 0, |
| 151 | first_deployment_id TEXT, |
| 152 | last_request_id TEXT, |
| 153 | last_trace_id TEXT, |
| 154 | state TEXT NOT NULL DEFAULT 'open', |
| 155 | issue_number INTEGER |
| 156 | ); |
| 157 | CREATE INDEX error_groups_by_last ON error_groups (last_us); |
| 158 | |
| 159 | CREATE TABLE tokens ( |
| 160 | id TEXT PRIMARY KEY, |
| 161 | name TEXT NOT NULL, |
| 162 | hash TEXT NOT NULL UNIQUE, |
| 163 | hint TEXT NOT NULL, |
| 164 | created_by TEXT, |
| 165 | created_us INTEGER NOT NULL, |
| 166 | last_used_us INTEGER, |
| 167 | managed INTEGER NOT NULL DEFAULT 0, |
| 168 | -- The deployments' own token is kept so each upload can bind it. |
| 169 | secret TEXT |
| 170 | ); |
| 171 | |
| 172 | CREATE TABLE exports ( |
| 173 | id TEXT PRIMARY KEY, |
| 174 | name TEXT NOT NULL, |
| 175 | endpoint TEXT NOT NULL, |
| 176 | signals TEXT NOT NULL, |
| 177 | headers TEXT NOT NULL DEFAULT '{}', |
| 178 | enabled INTEGER NOT NULL DEFAULT 1, |
| 179 | last_error TEXT, |
| 180 | last_sent_us INTEGER |
| 181 | ); |
| 182 | |
| 183 | CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT NOT NULL); |
| 184 | |
| 185 | CREATE TABLE usage ( |
| 186 | month TEXT PRIMARY KEY, |
| 187 | ingested_bytes INTEGER NOT NULL DEFAULT 0, |
| 188 | requests INTEGER NOT NULL DEFAULT 0, |
| 189 | logs INTEGER NOT NULL DEFAULT 0, |
| 190 | spans INTEGER NOT NULL DEFAULT 0, |
| 191 | metric_points INTEGER NOT NULL DEFAULT 0 |
| 192 | ); |
| 193 | `, |
| 194 | ]; |
| 195 | |
| 196 | /** |
| 197 | * Full-text search over log bodies, made apart from the tables: SQLite |
| 198 | * builds without FTS5 exist, and logs are still searched (more slowly, |
| 199 | * with LIKE) without it. |
| 200 | */ |
| 201 | export const FTS = ` |
| 202 | CREATE VIRTUAL TABLE IF NOT EXISTS logs_fts USING fts5(body, content='logs', content_rowid='rowid'); |
| 203 | CREATE TRIGGER IF NOT EXISTS logs_fts_insert AFTER INSERT ON logs BEGIN |
| 204 | INSERT INTO logs_fts (rowid, body) VALUES (new.rowid, new.body); |
| 205 | END; |
| 206 | CREATE TRIGGER IF NOT EXISTS logs_fts_delete AFTER DELETE ON logs BEGIN |
| 207 | INSERT INTO logs_fts (logs_fts, rowid, body) VALUES ('delete', old.rowid, old.body); |
| 208 | END; |
| 209 | `; |