tracksiy 0.9.0 → 0.9.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/dist/tracksiy.mjs +29 -9
- package/package.json +1 -1
package/dist/tracksiy.mjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
|
-
var VERSION = true ? "0.9.
|
|
7
|
+
var VERSION = true ? "0.9.1" : "0.0.0-dev";
|
|
8
8
|
var USER_AGENT = `tracksiy-cli/${VERSION} (node ${process.versions.node}; ${process.platform})`;
|
|
9
9
|
|
|
10
10
|
// src/core/errors.ts
|
|
@@ -822,7 +822,7 @@ var monitorsList = {
|
|
|
822
822
|
status: { type: "string", enum: ["all", "up", "down", "never"], description: "Filter by state. Default all." },
|
|
823
823
|
type: { type: "string", enum: ["heartbeat", "get", "ping", "ssl", "ingest"], description: "Only this monitor type." }
|
|
824
824
|
},
|
|
825
|
-
output: "{summary{total, up, down, never, unalertable}, monitors:[{id, name, project, monitorType, url, upNow, lastCheck, overdue, alertable, checkInUrl, downReason, lastCheckDetail{status, expectedStatus, bytes, truncated, expectedTextFound, forbiddenTextFound, error, ms}}], notes[]}",
|
|
825
|
+
output: "{summary{total, up, down, never, unalertable}, monitors:[{id, name, slug, project, monitorType, url, upNow, lastCheck, overdue, alertable, checkInUrl, downReason, lastCheckDetail{status, expectedStatus, bytes, truncated, expectedTextFound, forbiddenTextFound, error, ms}}], notes[]}",
|
|
826
826
|
text: (d) => `${kv(d.summary ?? {})}
|
|
827
827
|
|
|
828
828
|
${table(d.monitors ?? [], [
|
|
@@ -1141,6 +1141,22 @@ var BUDGET_KEYS = {
|
|
|
1141
1141
|
minSamples: "minSamples"
|
|
1142
1142
|
};
|
|
1143
1143
|
var NUMERIC = /* @__PURE__ */ new Set(["max", "windowMinutes", "minSamples"]);
|
|
1144
|
+
BUDGET_KEYS["window_minutes"] = "windowMinutes";
|
|
1145
|
+
BUDGET_KEYS["min_samples"] = "minSamples";
|
|
1146
|
+
function normalizeBudget(raw) {
|
|
1147
|
+
const out = {};
|
|
1148
|
+
for (const [key, value] of Object.entries(raw ?? {})) {
|
|
1149
|
+
out[BUDGET_KEYS[key] ?? key] = value;
|
|
1150
|
+
}
|
|
1151
|
+
return out;
|
|
1152
|
+
}
|
|
1153
|
+
function budgetsBody(body) {
|
|
1154
|
+
const wrapped = Array.isArray(body) ? { budgets: body } : body;
|
|
1155
|
+
if (!wrapped || !Array.isArray(wrapped.budgets)) {
|
|
1156
|
+
throw usageError("bad_value", '--body must be {"budgets": [...]} or a list of budgets.', `e.g. --body '{"budgets": [{"name": "init", "transaction": "GET /api/v1/init", "metric": "p95", "max": 800, "windowMinutes": 60}]}'`);
|
|
1157
|
+
}
|
|
1158
|
+
return { ...wrapped, budgets: wrapped.budgets.map(normalizeBudget) };
|
|
1159
|
+
}
|
|
1144
1160
|
function parseBudget(raw) {
|
|
1145
1161
|
const out = {};
|
|
1146
1162
|
for (const part of String(raw).split(/,(?=\s*[\w-]+=)/)) {
|
|
@@ -1192,7 +1208,7 @@ var budgetsGet = {
|
|
|
1192
1208
|
var budgetsSet = {
|
|
1193
1209
|
path: ["budgets", "set"],
|
|
1194
1210
|
summary: "Declare performance budgets: told once when one is crossed and once when it is met again.",
|
|
1195
|
-
description: `The list replaces the stored one, by name (--merge keeps the others). Metrics: ${METRICS}. max is an upper bound: ms, a 0..1 ratio for failure_rate, unitless for cls. Below min-samples the verdict is unknown, never pass. Alerts go through the project's rules with performance on (the default).`,
|
|
1211
|
+
description: `The list replaces the stored one, by name (--merge keeps the others). Metrics: ${METRICS}. max is an upper bound: ms, a 0..1 ratio for failure_rate, unitless for cls. Below min-samples the verdict is unknown, never pass. Alerts go through the project's rules with performance on (the default). --body takes the API's shape, {"budgets": [{"name", "metric", "max", "transaction"?, "op"?, "monitor"? (slug or id), "windowMinutes"?, "minSamples"?}]}, or a bare list; the flag spellings window and min-samples are accepted there too, and --dry-run and --merge apply to it.`,
|
|
1196
1212
|
context: "project",
|
|
1197
1213
|
effect: "write",
|
|
1198
1214
|
idempotent: true,
|
|
@@ -1211,23 +1227,27 @@ var budgetsSet = {
|
|
|
1211
1227
|
examples: [
|
|
1212
1228
|
{ command: "tracksiy budgets set --budget 'name=init,transaction=GET /api/v1/init,metric=p95,max=800'", description: "Told when the init call's p95 passes 800 ms over an hour." },
|
|
1213
1229
|
{ command: "tracksiy budgets set --merge --budget 'name=inp,op=ui.interaction,metric=inp,max=200,window=1440'", description: "INP p75 over a day, across every route; keeps the other budgets." },
|
|
1214
|
-
{ command: "tracksiy budgets set --merge --budget 'name=backup,monitor=db-backup-s3,metric=duration_p95,max=1200000,window=10080,min-samples=3'", description: "Told before the nightly backup gets near its max runtime." }
|
|
1230
|
+
{ command: "tracksiy budgets set --merge --budget 'name=backup,monitor=db-backup-s3,metric=duration_p95,max=1200000,window=10080,min-samples=3'", description: "Told before the nightly backup gets near its max runtime." },
|
|
1231
|
+
{ command: "tracksiy budgets set --body @tools/tracksiy/budgets.json --dry-run", description: "The whole declaration from a file; shows the changes, writes nothing." },
|
|
1232
|
+
{ command: "tracksiy budgets set --merge --budget 'name=site-ttfb,monitor=41,metric=ttfb_p95,max=800'", description: "A monitor by its id (from `monitors list`), for one whose name has spaces." }
|
|
1215
1233
|
],
|
|
1216
1234
|
output: "The stored budgets and `changes` [{name, action}], same shape as `budgets get`.",
|
|
1217
1235
|
text: budgetsText,
|
|
1218
1236
|
async run(ctx) {
|
|
1219
1237
|
const path = await projectPath(ctx, "budgets");
|
|
1220
1238
|
const i = ctx.input;
|
|
1221
|
-
if (i.body
|
|
1222
|
-
|
|
1223
|
-
let budgets = (i.budget ?? []).map(parseBudget);
|
|
1239
|
+
if (!i.body && !i.budget?.length && !i.merge) throw usageError("missing_flag", "No --budget given.", `Pass --budget ... (repeatable), or --body. To delete every budget: --body '{"budgets": []}'.`);
|
|
1240
|
+
const fromBody = i.body ? budgetsBody(i.body) : void 0;
|
|
1241
|
+
let budgets = fromBody ? fromBody.budgets : (i.budget ?? []).map(parseBudget);
|
|
1242
|
+
if (fromBody && i.budget?.length) budgets = [...budgets, ...i.budget.map(parseBudget)];
|
|
1224
1243
|
if (i.merge) {
|
|
1225
1244
|
const current = await ctx.api.get(path);
|
|
1226
1245
|
const named = new Set(budgets.map((b) => b.name));
|
|
1227
1246
|
const kept = (current.budgets ?? []).filter((b) => !named.has(b.name)).map((b) => compact({ name: b.name, transaction: b.transaction ?? void 0, op: b.op ?? void 0, monitor: b.monitor ?? void 0, metric: b.metric, max: b.max, windowMinutes: b.windowMinutes, minSamples: b.minSamples }));
|
|
1228
1247
|
budgets = [...kept, ...budgets];
|
|
1229
1248
|
}
|
|
1230
|
-
|
|
1249
|
+
const dryRun = i.dryRun || fromBody?.dryRun || void 0;
|
|
1250
|
+
return ctx.api.send("PUT", path, compact({ budgets, dryRun }));
|
|
1231
1251
|
}
|
|
1232
1252
|
};
|
|
1233
1253
|
var budgetsCheck = {
|
|
@@ -1294,7 +1314,7 @@ var monitorsTiming = {
|
|
|
1294
1314
|
context: "project",
|
|
1295
1315
|
effect: "read",
|
|
1296
1316
|
endpoint: { method: "GET", path: "/api/agent/v1/projects/{org}/{project}/monitors/{slug}/timing" },
|
|
1297
|
-
args: [{ name: "slug", required: true, description: "The monitor's slug (its name)
|
|
1317
|
+
args: [{ name: "slug", required: true, description: "The monitor's slug (its name; quote it when it has spaces), or its id from `monitors list`." }],
|
|
1298
1318
|
flags: { since: { type: "string", value: TIME, description: "Default 24h for HTTP, 7d for jobs; compared with the window before." } },
|
|
1299
1319
|
examples: [
|
|
1300
1320
|
{ command: "tracksiy monitors timing home", description: "Is the home page slow at the server, or on the wire?" },
|