apiblaze 0.20.5 → 0.20.6

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.
Files changed (2) hide show
  1. package/dist/index.js +39 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -932,7 +932,7 @@ var import_commander = require("commander");
932
932
  var import_chalk51 = __toESM(require("chalk"));
933
933
 
934
934
  // package.json
935
- var version = "0.20.5";
935
+ var version = "0.20.6";
936
936
 
937
937
  // src/index.ts
938
938
  init_types();
@@ -9834,6 +9834,7 @@ var OP_COMMANDS = [
9834
9834
  { cmd: "op latency", blurb: "which FEATURE is slow, and what inside it", extra: "--hours N --team T --project P" },
9835
9835
  { cmd: "op latency slow", blurb: "slowest requests, each with a request id you can look up", extra: "--min-ms N" },
9836
9836
  { cmd: "op latency llm", blurb: "chat timing by provider/model, tokens, credit-reserve cost" },
9837
+ { cmd: "op latency grades", blurb: "daily %% excellent / okay / bad / terrible, and who to blame", extra: "--days N" },
9837
9838
  { cmd: "op mark", blurb: 'record "I changed something significant just now"', extra: 'apiblaze op mark "cached tenant count"' },
9838
9839
  { cmd: "op latency compare", blurb: "latency before vs after the last mark, equal windows", extra: "--hours N" },
9839
9840
  { cmd: "op credits", blurb: "list credit wallets across all teams" },
@@ -10014,7 +10015,11 @@ async function runOp(sub, opts = {}, view) {
10014
10015
  ["route", "route"],
10015
10016
  ["environment", "environment"],
10016
10017
  ["statusClass", "status_class"],
10017
- ["minMs", "min_ms"]
10018
+ ["minMs", "min_ms"],
10019
+ ["days", "days"],
10020
+ ["excellent", "excellent"],
10021
+ ["okay", "okay"],
10022
+ ["bad", "bad"]
10018
10023
  ];
10019
10024
  for (const [optKey, queryKey] of FILTERS) {
10020
10025
  const v = opts[optKey];
@@ -10022,6 +10027,37 @@ async function runOp(sub, opts = {}, view) {
10022
10027
  }
10023
10028
  const q = qs.toString() ? `?${qs}` : "";
10024
10029
  const which = view;
10030
+ if (which === "grades") {
10031
+ const data = await opCall({ method: "GET", path: `/operator/latency/grades${q}`, summary: "latency grades" });
10032
+ if (opts.json) return void console.log(JSON.stringify(data, null, 2));
10033
+ const t = data.thresholds_ms;
10034
+ console.log(import_chalk50.default.bold("\nHow good was apiblaze itself?") + import_chalk50.default.dim(" (our overhead only \u2014 a slow customer API never counts against us)"));
10035
+ console.log(import_chalk50.default.dim(` excellent <${t.excellent.replace("<", "")}ms \xB7 okay ${t.okay}ms \xB7 bad ${t.bad}ms \xB7 terrible ${t.terrible.replace(">=", "")}ms+
10036
+ `));
10037
+ console.log(import_chalk50.default.dim(" date reqs excellent okay bad terrible"));
10038
+ for (const d of data.days ?? []) {
10039
+ const p = d.pct;
10040
+ const cell = (v, colour) => v > 0 ? colour(`${String(v).padStart(5)}%`) : import_chalk50.default.dim(`${String(v).padStart(5)}%`);
10041
+ console.log(
10042
+ ` ${d.date} ${String(d.total).padStart(5)} ${cell(p.excellent, import_chalk50.default.green)} ${cell(p.okay, import_chalk50.default.cyan)} ${cell(p.bad, import_chalk50.default.yellow)} ${cell(p.terrible, import_chalk50.default.red)}`
10043
+ );
10044
+ }
10045
+ const cul = data.culprits ?? [];
10046
+ if (cul.length) {
10047
+ console.log(import_chalk50.default.bold("\n Who caused the bad and terrible ones\n"));
10048
+ console.log(import_chalk50.default.dim(" bad terrible feature \u2192 dependency"));
10049
+ for (const r of cul.slice(0, 12)) {
10050
+ if (!r.bad && !r.terrible) continue;
10051
+ console.log(
10052
+ ` ${String(r.bad).padStart(6)} ${import_chalk50.default.red(String(r.terrible).padStart(8))} ${import_chalk50.default.yellow(r.feature)} ${import_chalk50.default.dim("\u2192")} ${import_chalk50.default.cyan(r.dep)}`
10053
+ );
10054
+ }
10055
+ }
10056
+ if (data.caveat) console.log(import_chalk50.default.dim(`
10057
+ \u26A0 ${data.caveat}
10058
+ `));
10059
+ return;
10060
+ }
10025
10061
  if (which === "compare") {
10026
10062
  const data = await opCall({ method: "GET", path: `/operator/latency/compare${q}`, summary: "latency before/after" });
10027
10063
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
@@ -10274,7 +10310,7 @@ apikeys.command("list").description("List control-plane API keys in your team").
10274
10310
  apikeys.command("mint").description("Create a control-plane API key (secret shown once)").option("--desc <text>", "Description").option("--expires-days <n>", "Expiry in days (default 90 server-side)").option("--team <id|name>", "Team (defaults to active team)").option("--json", "Output machine-readable JSON").action(action((opts, cmd) => runKeyMint({ ...cmd.parent?.opts(), ...opts })));
10275
10311
  apikeys.command("revoke").description("Revoke a control-plane API key").argument("<keyId>", "Key id (see `apikeys list`)").option("--team <id|name>", "Team (defaults to active team)").action(action((keyId, opts, cmd) => runKeyRevoke(keyId, { ...cmd.parent?.opts(), ...opts })));
10276
10312
  program.addCommand(apikeys, { hidden: true });
10277
- var op = new import_commander.Command("op").description("Operator menu (platform operators only)").argument("[action]", "latency | mark | credits | residue | sweep (omit for the menu)").argument("[view]", "for `latency`: slow | llm | compare \xB7 for `mark`: the change name, quoted").option("-y, --yes", "Skip the sweep confirmation prompt").option("--json", "Output machine-readable JSON").option("--hours <n>", "Look-back window in hours (default 1)").option("--team <id>", "Filter to one team").option("--project <name>", "Filter to one proxy").option("--api-version <v>", "Filter to one API version").option("--tenant <name>", "Filter to one tenant").option("--route <path>", "Filter to one route").option("--environment <env>", "Filter to one environment").option("--status-class <c>", "Filter to a status class (2xx/4xx/5xx)").option("--min-ms <n>", "For `latency slow`: minimum duration (default 1000)").action(action((sub, view, opts) => runOp(sub, opts, view))).addHelpText("after", () => `
10313
+ var op = new import_commander.Command("op").description("Operator menu (platform operators only)").argument("[action]", "latency | mark | credits | residue | sweep (omit for the menu)").argument("[view]", "for `latency`: slow | llm | compare | grades \xB7 for `mark`: the change name, quoted").option("-y, --yes", "Skip the sweep confirmation prompt").option("--json", "Output machine-readable JSON").option("--hours <n>", "Look-back window in hours (default 1)").option("--team <id>", "Filter to one team").option("--project <name>", "Filter to one proxy").option("--api-version <v>", "Filter to one API version").option("--tenant <name>", "Filter to one tenant").option("--route <path>", "Filter to one route").option("--environment <env>", "Filter to one environment").option("--status-class <c>", "Filter to a status class (2xx/4xx/5xx)").option("--min-ms <n>", "For `latency slow`: minimum duration (default 1000)").option("--days <n>", "For `latency grades`: how many days back (default 7)").option("--excellent <ms>", "Grade threshold: under this is excellent (default 250)").option("--okay <ms>", "Grade threshold: under this is okay (default 500)").option("--bad <ms>", "Grade threshold: under this is bad, at/over is terrible (default 1000)").action(action((sub, view, opts) => runOp(sub, opts, view))).addHelpText("after", () => `
10278
10314
  ${renderOpCommands()}
10279
10315
  `);
10280
10316
  program.addCommand(op, { hidden: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.20.5",
3
+ "version": "0.20.6",
4
4
  "description": "APIblaze CLI — Chat with your APIs, Manage your API keys, users and groups with the APIblaze serverless proxy",
5
5
  "keywords": [
6
6
  "apiblaze",