bfi-cli 0.1.108 → 0.1.109
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/cli.mjs +55 -28
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -8714,6 +8714,31 @@ async function runInstall(args, globalOpts) {
|
|
|
8714
8714
|
console.log();
|
|
8715
8715
|
}
|
|
8716
8716
|
const YMC_DEFAULT_BASE = process.env.BFI_YMC_BASE || "https://bfi.yyuap.com/bfi-api/bficli/api/v2";
|
|
8717
|
+
function messageOf(parsed) {
|
|
8718
|
+
const raw = parsed.msg ?? parsed.message;
|
|
8719
|
+
if (typeof raw === "string") return raw;
|
|
8720
|
+
if (raw === void 0 || raw === null) return "";
|
|
8721
|
+
try {
|
|
8722
|
+
return JSON.stringify(raw);
|
|
8723
|
+
} catch {
|
|
8724
|
+
return String(raw);
|
|
8725
|
+
}
|
|
8726
|
+
}
|
|
8727
|
+
function describeApiError(parsed, status, raw = "") {
|
|
8728
|
+
const prefix = status >= 400 ? `HTTP ${status} ` : "";
|
|
8729
|
+
const detail = parsed.detail;
|
|
8730
|
+
if (Array.isArray(detail) && detail.length > 0) return `${prefix}${detail.map((item) => {
|
|
8731
|
+
if (!item || typeof item !== "object") return String(item);
|
|
8732
|
+
const o = item;
|
|
8733
|
+
const loc = Array.isArray(o.loc) ? o.loc.map(String).join(".") : "";
|
|
8734
|
+
const msg = o.msg ?? o.message ?? o.type ?? "参数错误";
|
|
8735
|
+
return loc ? `${loc}: ${String(msg)}` : String(msg);
|
|
8736
|
+
}).join("; ")}`;
|
|
8737
|
+
if (detail !== void 0 && detail !== null) return `${prefix}${typeof detail === "string" ? detail : JSON.stringify(detail)}`;
|
|
8738
|
+
const msg = messageOf(parsed);
|
|
8739
|
+
if (msg.trim()) return `${prefix}${msg}`;
|
|
8740
|
+
return `${prefix}${raw.trim().slice(0, 200) || "服务端未返回错误信息"}`;
|
|
8741
|
+
}
|
|
8717
8742
|
var YmcApi = class {
|
|
8718
8743
|
baseUrl;
|
|
8719
8744
|
token;
|
|
@@ -8732,12 +8757,12 @@ var YmcApi = class {
|
|
|
8732
8757
|
if (body !== void 0 && Object.keys(body).length > 0) console.log(JSON.stringify(body, null, 2));
|
|
8733
8758
|
process.exit(0);
|
|
8734
8759
|
}
|
|
8735
|
-
async call(path, body = {}, timeoutMs =
|
|
8760
|
+
async call(path, body = {}, timeoutMs = 12e4) {
|
|
8736
8761
|
if (this.dryRun) this._dryRunExit("POST", path, body);
|
|
8737
8762
|
const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
|
|
8738
8763
|
const payload = JSON.stringify(body);
|
|
8739
8764
|
const mod = url.startsWith("https://") ? https : http;
|
|
8740
|
-
const raw = await new Promise((resolve, reject) => {
|
|
8765
|
+
const { status, text: raw } = await new Promise((resolve, reject) => {
|
|
8741
8766
|
const req = mod.request(url, {
|
|
8742
8767
|
method: "POST",
|
|
8743
8768
|
headers: {
|
|
@@ -8750,7 +8775,10 @@ var YmcApi = class {
|
|
|
8750
8775
|
}, (res) => {
|
|
8751
8776
|
const chunks = [];
|
|
8752
8777
|
res.on("data", (c) => chunks.push(c));
|
|
8753
|
-
res.on("end", () => resolve(
|
|
8778
|
+
res.on("end", () => resolve({
|
|
8779
|
+
status: res.statusCode ?? 0,
|
|
8780
|
+
text: Buffer.concat(chunks).toString("utf-8")
|
|
8781
|
+
}));
|
|
8754
8782
|
});
|
|
8755
8783
|
req.on("timeout", () => {
|
|
8756
8784
|
req.destroy(/* @__PURE__ */ new Error(`请求超时(${timeoutMs}ms)`));
|
|
@@ -8763,12 +8791,13 @@ var YmcApi = class {
|
|
|
8763
8791
|
try {
|
|
8764
8792
|
parsed = JSON.parse(raw);
|
|
8765
8793
|
} catch {
|
|
8766
|
-
throw new Error(
|
|
8794
|
+
throw new Error(`HTTP ${status} 非 JSON 响应:${raw.slice(0, 200)}`);
|
|
8767
8795
|
}
|
|
8768
|
-
if (parsed.detail && parsed.code === void 0) throw new Error(
|
|
8796
|
+
if (parsed.detail !== void 0 && parsed.code === void 0) throw new Error(describeApiError(parsed, status, raw));
|
|
8797
|
+
if (status >= 400 && parsed.code === void 0 && parsed.msg === void 0) throw new Error(describeApiError(parsed, status, raw));
|
|
8769
8798
|
return {
|
|
8770
8799
|
code: typeof parsed.code === "number" ? parsed.code : -1,
|
|
8771
|
-
msg:
|
|
8800
|
+
msg: messageOf(parsed),
|
|
8772
8801
|
data: parsed.data ?? null,
|
|
8773
8802
|
raw: parsed
|
|
8774
8803
|
};
|
|
@@ -8816,7 +8845,7 @@ var YmcApi = class {
|
|
|
8816
8845
|
if (this.dryRun) this._dryRunExit("GET", path);
|
|
8817
8846
|
const url = `${this.baseUrl}/${path.replace(/^\//, "")}`;
|
|
8818
8847
|
const mod = url.startsWith("https://") ? https : http;
|
|
8819
|
-
const raw = await new Promise((resolve, reject) => {
|
|
8848
|
+
const { status, text: raw } = await new Promise((resolve, reject) => {
|
|
8820
8849
|
const req = mod.request(url, {
|
|
8821
8850
|
method: "GET",
|
|
8822
8851
|
headers: {
|
|
@@ -8827,7 +8856,10 @@ var YmcApi = class {
|
|
|
8827
8856
|
}, (res) => {
|
|
8828
8857
|
const chunks = [];
|
|
8829
8858
|
res.on("data", (c) => chunks.push(c));
|
|
8830
|
-
res.on("end", () => resolve(
|
|
8859
|
+
res.on("end", () => resolve({
|
|
8860
|
+
status: res.statusCode ?? 0,
|
|
8861
|
+
text: Buffer.concat(chunks).toString("utf-8")
|
|
8862
|
+
}));
|
|
8831
8863
|
});
|
|
8832
8864
|
req.on("timeout", () => {
|
|
8833
8865
|
req.destroy(/* @__PURE__ */ new Error(`请求超时(${timeoutMs}ms)`));
|
|
@@ -8835,11 +8867,16 @@ var YmcApi = class {
|
|
|
8835
8867
|
req.on("error", reject);
|
|
8836
8868
|
req.end();
|
|
8837
8869
|
});
|
|
8838
|
-
|
|
8839
|
-
|
|
8870
|
+
let parsed;
|
|
8871
|
+
try {
|
|
8872
|
+
parsed = JSON.parse(raw);
|
|
8873
|
+
} catch {
|
|
8874
|
+
throw new Error(`HTTP ${status} 非 JSON 响应:${raw.slice(0, 200)}`);
|
|
8875
|
+
}
|
|
8876
|
+
if (parsed.detail !== void 0 && parsed.code === void 0) throw new Error(describeApiError(parsed, status, raw));
|
|
8840
8877
|
return {
|
|
8841
8878
|
code: typeof parsed.code === "number" ? parsed.code : -1,
|
|
8842
|
-
msg:
|
|
8879
|
+
msg: messageOf(parsed),
|
|
8843
8880
|
data: parsed.data ?? null,
|
|
8844
8881
|
raw: parsed
|
|
8845
8882
|
};
|
|
@@ -8921,7 +8958,6 @@ const F_ENV = [
|
|
|
8921
8958
|
"--env",
|
|
8922
8959
|
"--env-name"
|
|
8923
8960
|
];
|
|
8924
|
-
const F_TIME = ["-t", "--time"];
|
|
8925
8961
|
const F_RANGE = [
|
|
8926
8962
|
"-t",
|
|
8927
8963
|
"--time",
|
|
@@ -8941,7 +8977,7 @@ const ALLOWED_FLAGS = {
|
|
|
8941
8977
|
],
|
|
8942
8978
|
"sls-grep": [
|
|
8943
8979
|
...F_ENV,
|
|
8944
|
-
...
|
|
8980
|
+
...F_RANGE,
|
|
8945
8981
|
"--group-by",
|
|
8946
8982
|
"--line",
|
|
8947
8983
|
"--app"
|
|
@@ -9091,15 +9127,6 @@ function requireEnv(args) {
|
|
|
9091
9127
|
}
|
|
9092
9128
|
return { env_name: env };
|
|
9093
9129
|
}
|
|
9094
|
-
function timeOf(args, required = true) {
|
|
9095
|
-
const t = opt(args, "-t", "--time");
|
|
9096
|
-
const err = timeError(t);
|
|
9097
|
-
if (err && required) {
|
|
9098
|
-
console.error(err);
|
|
9099
|
-
process.exit(1);
|
|
9100
|
-
}
|
|
9101
|
-
return t ? { time: t } : {};
|
|
9102
|
-
}
|
|
9103
9130
|
function timeOpts(args) {
|
|
9104
9131
|
const out = {};
|
|
9105
9132
|
const t = opt(args, "-t", "--time");
|
|
@@ -9192,7 +9219,7 @@ async function runYmc(args, globalOpts) {
|
|
|
9192
9219
|
trace_id: id,
|
|
9193
9220
|
...requireEnv(rest),
|
|
9194
9221
|
...opt(rest, "--ts") ? { ts: Number(opt(rest, "--ts")) } : {}
|
|
9195
|
-
}), jsonMode, (data) => {
|
|
9222
|
+
}, 18e4), jsonMode, (data) => {
|
|
9196
9223
|
const d = data;
|
|
9197
9224
|
const lines = [];
|
|
9198
9225
|
const wc = d.warning_chain;
|
|
@@ -9277,7 +9304,7 @@ async function runYmc(args, globalOpts) {
|
|
|
9277
9304
|
case "sls-grep": {
|
|
9278
9305
|
const kw = positionals(rest)[0];
|
|
9279
9306
|
if (!kw) {
|
|
9280
|
-
console.error("用法:bfi ymc sls-grep \"<关键词>\" -e <env> [-t time] [--app <appCode>] [--group-by applicationName|message|requestURL]");
|
|
9307
|
+
console.error("用法:bfi ymc sls-grep \"<关键词>\" -e <env> [-t <time> | --start-time <s> --end-time <e>] [--app <appCode>] [--group-by applicationName|message|requestURL]");
|
|
9281
9308
|
console.error("例:bfi ymc sls-grep \"ClassCastException\" -e daily -t 3d");
|
|
9282
9309
|
console.error("⚠️ 关键词按「整值」匹配:类名/全限定异常名必须整串加引号");
|
|
9283
9310
|
console.error(" (\"java.lang.OutOfMemoryError\" 命中;简写 \"OutOfMemoryError\" 恒 0 且不报错)——sls-discipline §3");
|
|
@@ -9292,7 +9319,7 @@ async function runYmc(args, globalOpts) {
|
|
|
9292
9319
|
emit(await api.call("sls/raw", {
|
|
9293
9320
|
query,
|
|
9294
9321
|
...requireEnv(rest),
|
|
9295
|
-
...
|
|
9322
|
+
...timeOpts(rest),
|
|
9296
9323
|
line: Number(opt(rest, "--line") || 50)
|
|
9297
9324
|
}), jsonMode, aggSummary(`SLS 全文检索 "${kw}"`));
|
|
9298
9325
|
break;
|
|
@@ -9404,7 +9431,7 @@ async function runYmc(args, globalOpts) {
|
|
|
9404
9431
|
};
|
|
9405
9432
|
const app = opt(rest, "--app");
|
|
9406
9433
|
if (app) body.filters = { service_name: app };
|
|
9407
|
-
emit(await api.call("kibana/stats", body), jsonMode, (data) => {
|
|
9434
|
+
emit(await api.call("kibana/stats", body, 18e4), jsonMode, (data) => {
|
|
9408
9435
|
const d = data;
|
|
9409
9436
|
const a = d.aggs;
|
|
9410
9437
|
return `✓ URL 统计${app ? ` [${app}]` : "(⚠️ 未限定服务,共享路径为全平台混合)"}: QPS=${a.qps} avg=${a.avg_rt?.value ?? "-"} 慢请求Top=${Array.isArray(d.slow_top) ? d.slow_top.length : 0}`;
|
|
@@ -9429,7 +9456,7 @@ async function runYmc(args, globalOpts) {
|
|
|
9429
9456
|
console.error("用法:bfi ymc ingress --trace-id <id> | --uri </path> [-app <service_name>] -e <env> [-t time]");
|
|
9430
9457
|
process.exit(1);
|
|
9431
9458
|
}
|
|
9432
|
-
emit(await api.call("kibana/search", body), jsonMode, rowsSummary("ingress 日志"));
|
|
9459
|
+
emit(await api.call("kibana/search", body, 18e4), jsonMode, rowsSummary("ingress 日志"));
|
|
9433
9460
|
break;
|
|
9434
9461
|
}
|
|
9435
9462
|
case "dump-list": {
|
|
@@ -9721,7 +9748,7 @@ const HELP = {
|
|
|
9721
9748
|
bfi ymc sls-raw 'applicationname: yonbip-scm-scmmp AND "unaudit" | SELECT traceid, time LIMIT 10' -e core3 -t 1d
|
|
9722
9749
|
注意:业务关键词检索必须 applicationname: 限定目标服务(共享路径 URL 全平台都有);
|
|
9723
9750
|
traceid/spanid 检索例外(全局唯一)。非索引字段(logger/requesturl)不能进检索语法,只能在 SELECT 里引用。`,
|
|
9724
|
-
"sls-grep": `bfi ymc sls-grep "<关键词>" -e <env> -t <time> [--app <appCode>] [--group-by <字段>] [--json]
|
|
9751
|
+
"sls-grep": `bfi ymc sls-grep "<关键词>" -e <env> [-t <time> | --start-time <s> --end-time <e>] [--app <appCode>] [--group-by <字段>] [--json]
|
|
9725
9752
|
SLS 全文检索聚合(每组计数精确不封顶;组数上限 500——实测 2026-09-17:计数不受限,仅组数受 SLS 默认 LIMIT 约束,服务端已放宽)。
|
|
9726
9753
|
⚠️ 关键词按「整值」匹配:类名/全限定异常名必须整串加引号
|
|
9727
9754
|
("java.lang.OutOfMemoryError" 命中;简写 "OutOfMemoryError" 恒 0 命中且不报错)——sls-discipline §3
|