@vitalscope/cli 0.0.0-stage → 0.1.0
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/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +60 -2
- package/SECURITY.md +16 -0
- package/dist/app.js +70 -0
- package/dist/app.js.map +1 -0
- package/dist/buffer.js +115 -0
- package/dist/buffer.js.map +1 -0
- package/dist/cli.js +12 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.js +92 -0
- package/dist/commands.js.map +1 -0
- package/dist/fingerprint.js +56 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/live.js +37 -0
- package/dist/live.js.map +1 -0
- package/dist/node-version.js +7 -0
- package/dist/node-version.js.map +1 -0
- package/dist/origin.js +26 -0
- package/dist/origin.js.map +1 -0
- package/dist/panel/assets/index-BMlDnoZj.css +1 -0
- package/dist/panel/assets/index-D-PRDDvW.js +12 -0
- package/dist/panel/index.html +14 -0
- package/dist/panel.js +108 -0
- package/dist/panel.js.map +1 -0
- package/dist/queries.js +290 -0
- package/dist/queries.js.map +1 -0
- package/dist/report.js +99 -0
- package/dist/report.js.map +1 -0
- package/dist/rows.js +57 -0
- package/dist/rows.js.map +1 -0
- package/dist/server.js +33 -0
- package/dist/server.js.map +1 -0
- package/dist/sqlite.js +99 -0
- package/dist/sqlite.js.map +1 -0
- package/dist/start.js +48 -0
- package/dist/start.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta name="color-scheme" content="light dark" />
|
|
7
|
+
<title>Vitalscope</title>
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-D-PRDDvW.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BMlDnoZj.css">
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="root"></div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
package/dist/panel.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { extname, join } from "node:path";
|
|
3
|
+
import { METRIC_NAMES } from "@vitalscope/protocol";
|
|
4
|
+
import { ENVIRONMENTS, getComparison, getErrorDetail, getErrorList, getMetricDetail, getOptions, getOverview, getReleases } from "./queries.js";
|
|
5
|
+
const CONTENT_TYPES = {
|
|
6
|
+
".html": "text/html; charset=utf-8",
|
|
7
|
+
".js": "text/javascript; charset=utf-8",
|
|
8
|
+
".css": "text/css; charset=utf-8",
|
|
9
|
+
".svg": "image/svg+xml",
|
|
10
|
+
};
|
|
11
|
+
const ERROR_ID = /^[0-9a-f]{16}$/;
|
|
12
|
+
const RANGES = { "1h": 3_600_000, "24h": 86_400_000, "7d": 604_800_000, "30d": 2_592_000_000 };
|
|
13
|
+
const CSP = "default-src 'none'; script-src 'self'; style-src 'self'; connect-src 'self'; img-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";
|
|
14
|
+
/** Tarayıcı dışı istemcide başlık yoktur; adres çubuğundan açılış `none` gönderir. */
|
|
15
|
+
const SAME_SITE_REQUESTS = new Set(["same-origin", "none"]);
|
|
16
|
+
/**
|
|
17
|
+
* Build çıktısı açılışta belleğe alınır. İstek sadece bu tabloya bakar, dosya sistemine dokunmaz:
|
|
18
|
+
* yol aşımı (`/../`) ve sonradan eklenen dosyalar sunulamaz. Panel paketlenmemişse tablo boş kalır.
|
|
19
|
+
*/
|
|
20
|
+
export function loadPanelAssets(dir) {
|
|
21
|
+
const assets = new Map();
|
|
22
|
+
if (!existsSync(dir))
|
|
23
|
+
return assets;
|
|
24
|
+
for (const entry of readdirSync(dir, { recursive: true, withFileTypes: true })) {
|
|
25
|
+
const type = CONTENT_TYPES[extname(entry.name)];
|
|
26
|
+
if (!entry.isFile() || !type)
|
|
27
|
+
continue;
|
|
28
|
+
const path = join(entry.parentPath, entry.name);
|
|
29
|
+
const route = `/${path.slice(dir.length).replace(/\\/g, "/").replace(/^\/+/, "")}`;
|
|
30
|
+
assets.set(route, { body: new Uint8Array(readFileSync(path)), type });
|
|
31
|
+
}
|
|
32
|
+
return assets;
|
|
33
|
+
}
|
|
34
|
+
function parseFilters(c, now) {
|
|
35
|
+
const { env, page, device, range } = c.req.query();
|
|
36
|
+
if (!ENVIRONMENTS.includes(env))
|
|
37
|
+
return null;
|
|
38
|
+
if (range !== undefined && !Object.hasOwn(RANGES, range))
|
|
39
|
+
return null;
|
|
40
|
+
return {
|
|
41
|
+
env: env,
|
|
42
|
+
...(page !== undefined ? { page } : {}),
|
|
43
|
+
...(device !== undefined ? { device } : {}),
|
|
44
|
+
...(range !== undefined ? { since: now - RANGES[range] } : {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function addPanelRoutes(app, { db, assets, live, now }) {
|
|
48
|
+
// Ölçümler sayfa adresleri ve hata izleri içerir. CORS başlığı yok; başka sitelere yanıt hiç verilmez.
|
|
49
|
+
app.use("/api/*", async (c, next) => {
|
|
50
|
+
const site = c.req.header("Sec-Fetch-Site");
|
|
51
|
+
if (site !== undefined && !SAME_SITE_REQUESTS.has(site))
|
|
52
|
+
return new Response(null, { status: 403 });
|
|
53
|
+
await next();
|
|
54
|
+
c.res.headers.set("Cache-Control", "no-store");
|
|
55
|
+
});
|
|
56
|
+
app.get("/api/live", () => live.stream());
|
|
57
|
+
app.get("/api/options", (c) => c.json(getOptions(db)));
|
|
58
|
+
app.get("/api/overview", (c) => {
|
|
59
|
+
const filters = parseFilters(c, now());
|
|
60
|
+
return filters ? c.json(getOverview(db, filters)) : new Response(null, { status: 400 });
|
|
61
|
+
});
|
|
62
|
+
app.get("/api/metrics/:name", (c) => {
|
|
63
|
+
const name = c.req.param("name");
|
|
64
|
+
if (!METRIC_NAMES.includes(name))
|
|
65
|
+
return new Response(null, { status: 404 });
|
|
66
|
+
const filters = parseFilters(c, now());
|
|
67
|
+
return filters ? c.json(getMetricDetail(db, name, filters)) : new Response(null, { status: 400 });
|
|
68
|
+
});
|
|
69
|
+
app.get("/api/errors", (c) => {
|
|
70
|
+
const filters = parseFilters(c, now());
|
|
71
|
+
return filters ? c.json(getErrorList(db, filters)) : new Response(null, { status: 400 });
|
|
72
|
+
});
|
|
73
|
+
app.get("/api/errors/:id", (c) => {
|
|
74
|
+
const id = c.req.param("id");
|
|
75
|
+
if (!ERROR_ID.test(id))
|
|
76
|
+
return new Response(null, { status: 404 });
|
|
77
|
+
const filters = parseFilters(c, now());
|
|
78
|
+
return filters ? c.json(getErrorDetail(db, id, filters)) : new Response(null, { status: 400 });
|
|
79
|
+
});
|
|
80
|
+
app.get("/api/releases", (c) => {
|
|
81
|
+
const filters = parseFilters(c, now());
|
|
82
|
+
return filters ? c.json(getReleases(db, filters)) : new Response(null, { status: 400 });
|
|
83
|
+
});
|
|
84
|
+
app.get("/api/compare", (c) => {
|
|
85
|
+
const filters = parseFilters(c, now());
|
|
86
|
+
const { a, b } = c.req.query();
|
|
87
|
+
if (!filters || !a || !b)
|
|
88
|
+
return new Response(null, { status: 400 });
|
|
89
|
+
return c.json(getComparison(db, filters, a, b));
|
|
90
|
+
});
|
|
91
|
+
const serve = (route) => {
|
|
92
|
+
const asset = assets.get(route);
|
|
93
|
+
if (!asset)
|
|
94
|
+
return new Response(null, { status: 404 });
|
|
95
|
+
return new Response(asset.body, {
|
|
96
|
+
headers: {
|
|
97
|
+
"Content-Type": asset.type,
|
|
98
|
+
// Dosya adları içerik özeti taşır; sayfanın kendisi her açılışta yeniden istenir.
|
|
99
|
+
"Cache-Control": route === "/index.html" ? "no-cache" : "public, max-age=31536000, immutable",
|
|
100
|
+
"Content-Security-Policy": CSP,
|
|
101
|
+
"Referrer-Policy": "no-referrer",
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
app.get("/", () => serve("/index.html"));
|
|
106
|
+
app.get("/assets/*", (c) => serve(c.req.path));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAmB,MAAM,sBAAsB,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAkC,MAAM,cAAc,CAAC;AAEhL,MAAM,aAAa,GAA2B;IAC5C,OAAO,EAAE,0BAA0B;IACnC,KAAK,EAAE,gCAAgC;IACvC,MAAM,EAAE,yBAAyB;IACjC,MAAM,EAAE,eAAe;CACxB,CAAC;AACF,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAClC,MAAM,MAAM,GAA2B,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AACvH,MAAM,GAAG,GAAG,0JAA0J,CAAC;AACvK,sFAAsF;AACtF,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAI5D;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2D,CAAC;IAClF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/E,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI;YAAE,SAAS;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;QACnF,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,CAAU,EAAE,GAAW;IAC3C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAkB,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,OAAO;QACL,GAAG,EAAE,GAAkB;QACvB,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,GAAG,MAAM,CAAC,KAAK,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAS,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAA4E;IAC3I,uGAAuG;IACvG,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC5C,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpG,MAAM,IAAI,EAAE,CAAC;QACb,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1C,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEvD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAkB,CAAC;YAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3F,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,IAAkB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAClH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC/B,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE;YAC9B,OAAO,EAAE;gBACP,cAAc,EAAE,KAAK,CAAC,IAAI;gBAC1B,kFAAkF;gBAClF,eAAe,EAAE,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,qCAAqC;gBAC7F,yBAAyB,EAAE,GAAG;gBAC9B,iBAAiB,EAAE,aAAa;aACjC;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
package/dist/queries.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { METRIC_NAMES, THRESHOLDS, getRating } from "@vitalscope/protocol";
|
|
2
|
+
import { errorGroup } from "./fingerprint.js";
|
|
3
|
+
export const ENVIRONMENTS = ["production", "preview", "development"];
|
|
4
|
+
/** Aralık genişliği eşiklerin katı: her aralık tek bir değerlendirmeye düşer, eşik çizgisi aralık sınırındadır. */
|
|
5
|
+
const BIN_WIDTH = { LCP: 500, INP: 50, CLS: 0.05, FCP: 300, TTFB: 200 };
|
|
6
|
+
const MAX_BINS = 40;
|
|
7
|
+
const MAX_BUCKETS = 60;
|
|
8
|
+
const MIN_BUCKET_SAMPLES = 5;
|
|
9
|
+
const MINUTE = 60_000;
|
|
10
|
+
const BUCKETS = [MINUTE, 5 * MINUTE, 15 * MINUTE, 60 * MINUTE, 360 * MINUTE, 1440 * MINUTE, 10_080 * MINUTE];
|
|
11
|
+
const MAX_ROWS = 100;
|
|
12
|
+
const PAGE = 0;
|
|
13
|
+
const DEVICE = 1;
|
|
14
|
+
const NAME = 2;
|
|
15
|
+
const VALUE = 3;
|
|
16
|
+
const TS = 4;
|
|
17
|
+
/** En yakın sıra yöntemi; `sorted` küçükten büyüğe sıralı ve boş olmamalı. */
|
|
18
|
+
export function sortedPercentile(sorted, q) {
|
|
19
|
+
return sorted[Math.ceil(sorted.length * q) - 1];
|
|
20
|
+
}
|
|
21
|
+
function where({ env, page, device, since, release }) {
|
|
22
|
+
const clauses = ["1"];
|
|
23
|
+
const params = [];
|
|
24
|
+
if (env !== undefined) {
|
|
25
|
+
clauses.push("env = ?");
|
|
26
|
+
params.push(env);
|
|
27
|
+
}
|
|
28
|
+
if (release !== undefined) {
|
|
29
|
+
clauses.push("release = ?");
|
|
30
|
+
params.push(release);
|
|
31
|
+
}
|
|
32
|
+
if (page !== undefined) {
|
|
33
|
+
clauses.push("COALESCE(route, path) = ?");
|
|
34
|
+
params.push(page);
|
|
35
|
+
}
|
|
36
|
+
if (device !== undefined) {
|
|
37
|
+
clauses.push("device = ?");
|
|
38
|
+
params.push(device);
|
|
39
|
+
}
|
|
40
|
+
if (since !== undefined) {
|
|
41
|
+
clauses.push("ts >= ?");
|
|
42
|
+
params.push(since);
|
|
43
|
+
}
|
|
44
|
+
return { sql: clauses.join(" AND "), params };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Değere göre sıralı gelir: gruplar da sıralı kalır, yüzdelik için yeniden sıralanmaz.
|
|
48
|
+
* Satırların çoğu okunur; index'ten gidip her satır için tabloya bakmak sırayla taramadan katlarca yavaş.
|
|
49
|
+
*/
|
|
50
|
+
function samples(db, filters, name) {
|
|
51
|
+
const { sql, params } = where(filters);
|
|
52
|
+
const metric = name ? " AND name = ?" : "";
|
|
53
|
+
const statement = db.prepare(`SELECT COALESCE(route, path), device, name, value, ts FROM vitals NOT INDEXED WHERE ${sql}${metric} ORDER BY value`);
|
|
54
|
+
statement.setReturnArrays(true);
|
|
55
|
+
return statement.all(...params, ...(name ? [name] : []));
|
|
56
|
+
}
|
|
57
|
+
const valuesOf = (items) => items.map((item) => item[VALUE]);
|
|
58
|
+
/** `values` sıralı olmalı. */
|
|
59
|
+
function summarize(name, values) {
|
|
60
|
+
const counts = { good: 0, needsImprovement: 0, poor: 0 };
|
|
61
|
+
for (const value of values) {
|
|
62
|
+
const rating = getRating(name, value);
|
|
63
|
+
counts[rating === "needs-improvement" ? "needsImprovement" : rating]++;
|
|
64
|
+
}
|
|
65
|
+
if (values.length === 0)
|
|
66
|
+
return { name, count: 0, p75: null, rating: null, counts };
|
|
67
|
+
const p75 = sortedPercentile(values, 0.75);
|
|
68
|
+
return { name, count: values.length, p75, rating: getRating(name, p75), counts };
|
|
69
|
+
}
|
|
70
|
+
function groupBy(items, key) {
|
|
71
|
+
const groups = new Map();
|
|
72
|
+
for (const item of items) {
|
|
73
|
+
const group = groups.get(key(item));
|
|
74
|
+
if (group)
|
|
75
|
+
group.push(item);
|
|
76
|
+
else
|
|
77
|
+
groups.set(key(item), [item]);
|
|
78
|
+
}
|
|
79
|
+
return groups;
|
|
80
|
+
}
|
|
81
|
+
/** SDK her sayfa açılışında metriklerden önce pageview gönderir; seçenekler çok daha küçük `pageviews` ve `errors`'tan okunur. */
|
|
82
|
+
export function getOptions(db) {
|
|
83
|
+
const column = (sql) => db.prepare(sql).all().map((row) => row.value);
|
|
84
|
+
const pages = "SELECT COALESCE(route, path) AS value FROM pageviews UNION SELECT COALESCE(route, path) FROM errors ORDER BY 1 LIMIT 200";
|
|
85
|
+
const devices = "SELECT device AS value FROM pageviews UNION SELECT device FROM errors ORDER BY 1";
|
|
86
|
+
const environments = new Set(column("SELECT env AS value FROM pageviews UNION SELECT env FROM errors"));
|
|
87
|
+
return { environments: ENVIRONMENTS.filter((env) => environments.has(env)), pages: column(pages), devices: column(devices) };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Satırlar JS'e taşınmaz: sayılar ve yüzdelikler index üzerinde bulunur (`vitals_metric`, `vitals_page`).
|
|
91
|
+
* Yüzdelik, değere göre sıralı index'te en yakın sıradaki satırdır; `sortedPercentile` ile aynı sonucu verir.
|
|
92
|
+
*/
|
|
93
|
+
export function getOverview(db, filters) {
|
|
94
|
+
const { sql, params } = where(filters);
|
|
95
|
+
const p75At = (extra, extraParams, count) => db.prepare(`SELECT value FROM vitals WHERE ${sql}${extra} ORDER BY value LIMIT 1 OFFSET ?`).get(...params, ...extraParams, Math.ceil(count * 0.75) - 1).value;
|
|
96
|
+
const metrics = METRIC_NAMES.map((name) => {
|
|
97
|
+
const { good, poor } = THRESHOLDS[name];
|
|
98
|
+
const row = db.prepare(`SELECT COUNT(*) AS count, TOTAL(value <= ?) AS good, TOTAL(value > ?) AS poor FROM vitals WHERE ${sql} AND name = ?`).get(good, poor, ...params, name);
|
|
99
|
+
const count = row.count;
|
|
100
|
+
const counts = { good: row.good, needsImprovement: count - row.good - row.poor, poor: row.poor };
|
|
101
|
+
if (count === 0)
|
|
102
|
+
return { name, count, p75: null, rating: null, counts };
|
|
103
|
+
const p75 = p75At(" AND name = ?", [name], count);
|
|
104
|
+
return { name, count, p75, rating: getRating(name, p75), counts };
|
|
105
|
+
});
|
|
106
|
+
const views = new Map(db
|
|
107
|
+
.prepare(`SELECT COALESCE(route, path) AS page, SUM(1.0 / sample_rate) AS views FROM pageviews WHERE ${sql} GROUP BY page`)
|
|
108
|
+
.all(...params)
|
|
109
|
+
.map((row) => [row.page, Math.round(row.views)]));
|
|
110
|
+
// Sayfa seçiliyse sayılar metriklerinkiyle aynı. Sorgu sayfa ifadesini her satırda tablodan okur, 1 milyon olayda ≈ 0,8 sn.
|
|
111
|
+
const counts = filters.page === undefined
|
|
112
|
+
? db.prepare(`SELECT COALESCE(route, path) AS page, name, COUNT(*) AS count FROM vitals WHERE ${sql} GROUP BY page, name`).all(...params)
|
|
113
|
+
: metrics.filter(({ count }) => count > 0).map(({ name, count }) => ({ page: filters.page, name, count }));
|
|
114
|
+
const groups = groupBy(counts, (group) => group.page);
|
|
115
|
+
const names = [...new Set([...views.keys(), ...groups.keys()])].sort((a, b) => (views.get(b) ?? 0) - (views.get(a) ?? 0) || a.localeCompare(b));
|
|
116
|
+
return {
|
|
117
|
+
metrics,
|
|
118
|
+
// Yüzdelik sadece gösterilen sayfalar için aranır.
|
|
119
|
+
pages: names.slice(0, MAX_ROWS).map((page) => {
|
|
120
|
+
const p75 = Object.fromEntries((groups.get(page) ?? []).map(({ name, count }) => [name, p75At(" AND COALESCE(route, path) = ? AND name = ?", [page, name], count)]));
|
|
121
|
+
return { page, views: views.get(page) ?? 0, p75 };
|
|
122
|
+
}),
|
|
123
|
+
morePages: Math.max(0, names.length - MAX_ROWS),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function timeSeries(items) {
|
|
127
|
+
const series = { x: [], p50: [], p75: [], p95: [] };
|
|
128
|
+
if (items.length === 0)
|
|
129
|
+
return series;
|
|
130
|
+
const times = items.map((item) => item[TS]);
|
|
131
|
+
const span = maxOf(times) - minOf(times);
|
|
132
|
+
// İki ölçümden yüzdelik çıkmaz: az veride kovalar büyür, p75 ile p95 aynı çizgiye düşmez.
|
|
133
|
+
const maxBuckets = Math.max(1, Math.min(MAX_BUCKETS, Math.floor(items.length / MIN_BUCKET_SAMPLES)));
|
|
134
|
+
const step = BUCKETS.find((bucket) => span / bucket <= maxBuckets) ?? BUCKETS.at(-1);
|
|
135
|
+
const buckets = [...groupBy(items, (item) => String(Math.floor(item[TS] / step) * step))].sort(([a], [b]) => Number(a) - Number(b));
|
|
136
|
+
for (const [time, group] of buckets) {
|
|
137
|
+
const values = valuesOf(group);
|
|
138
|
+
series.x.push(Number(time));
|
|
139
|
+
series.p50.push(sortedPercentile(values, 0.5));
|
|
140
|
+
series.p75.push(sortedPercentile(values, 0.75));
|
|
141
|
+
series.p95.push(sortedPercentile(values, 0.95));
|
|
142
|
+
}
|
|
143
|
+
return series;
|
|
144
|
+
}
|
|
145
|
+
/** `values` sıralı olmalı. */
|
|
146
|
+
function histogram(name, values) {
|
|
147
|
+
const width = BIN_WIDTH[name];
|
|
148
|
+
// Değerler eşiğin çok altında olsa da eşikler görünsün; değerlendirme nerede durduğunuzu göstermeli.
|
|
149
|
+
const needed = Math.ceil(Math.max(THRESHOLDS[name].poor + width, values.at(-1) ?? 0) / width - 1e-9);
|
|
150
|
+
const count = Math.min(MAX_BINS, needed);
|
|
151
|
+
const round = (value) => Number(value.toFixed(6));
|
|
152
|
+
const bins = Array.from({ length: count }, (_, i) => ({ start: round(i * width), end: round((i + 1) * width), count: 0 }));
|
|
153
|
+
let above = 0;
|
|
154
|
+
for (const value of values) {
|
|
155
|
+
// `getRating` eşiği iyi sayar: aralıklar üstten kapalı, 2500 ms son iyi aralıkta.
|
|
156
|
+
const index = Math.max(0, Math.ceil(value / width - 1e-9) - 1);
|
|
157
|
+
if (index < count)
|
|
158
|
+
bins[index].count++;
|
|
159
|
+
else
|
|
160
|
+
above++;
|
|
161
|
+
}
|
|
162
|
+
const percentiles = values.length === 0 ? null : { p50: sortedPercentile(values, 0.5), p75: sortedPercentile(values, 0.75), p95: sortedPercentile(values, 0.95) };
|
|
163
|
+
return { bins, above, percentiles };
|
|
164
|
+
}
|
|
165
|
+
function breakdown(name, items, key) {
|
|
166
|
+
return [...groupBy(items, key)]
|
|
167
|
+
.map(([group, rows]) => {
|
|
168
|
+
const p75 = sortedPercentile(valuesOf(rows), 0.75);
|
|
169
|
+
return { key: group, count: rows.length, p75, rating: getRating(name, p75) };
|
|
170
|
+
})
|
|
171
|
+
.sort((a, b) => b.count - a.count || a.key.localeCompare(b.key))
|
|
172
|
+
.slice(0, MAX_ROWS);
|
|
173
|
+
}
|
|
174
|
+
export function getMetricDetail(db, name, filters) {
|
|
175
|
+
const items = samples(db, filters, name);
|
|
176
|
+
const values = valuesOf(items);
|
|
177
|
+
return {
|
|
178
|
+
summary: summarize(name, values),
|
|
179
|
+
series: timeSeries(items),
|
|
180
|
+
histogram: histogram(name, values),
|
|
181
|
+
pages: breakdown(name, items, (item) => item[PAGE]),
|
|
182
|
+
devices: breakdown(name, items, (item) => item[DEVICE]),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** En yeni olay önce; her grubun ilk satırı son mesajı ve son stack'i taşır. */
|
|
186
|
+
function errorRows(db, filters) {
|
|
187
|
+
const { sql, params } = where(filters);
|
|
188
|
+
const rows = db
|
|
189
|
+
.prepare(`SELECT type, message, stack, handled, COALESCE(route, path) AS page, device, release, ts, sample_rate FROM errors WHERE ${sql} ORDER BY ts DESC, rowid DESC`)
|
|
190
|
+
.all(...params);
|
|
191
|
+
return rows.map(({ stack, sample_rate, ...row }) => {
|
|
192
|
+
const frames = JSON.parse(stack);
|
|
193
|
+
const { id, location } = errorGroup(row.type, row.message, frames);
|
|
194
|
+
return { ...row, id, location, stack: frames, weight: 1 / sample_rate };
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function toGroup(rows) {
|
|
198
|
+
const { id, type, message, location, ts: lastSeen } = rows[0];
|
|
199
|
+
const count = Math.round(rows.reduce((sum, row) => sum + row.weight, 0));
|
|
200
|
+
return { id, type, message, location, count, firstSeen: rows.at(-1).ts, lastSeen };
|
|
201
|
+
}
|
|
202
|
+
/** Rapor ve panel aynı gruplamayı kullanır: aynı hata ikisinde de aynı sayılır. */
|
|
203
|
+
export function getErrorGroups(db, filters) {
|
|
204
|
+
const groups = [...groupBy(errorRows(db, filters), (row) => row.id).values()].map(toGroup);
|
|
205
|
+
return groups.sort((a, b) => b.count - a.count || b.lastSeen - a.lastSeen);
|
|
206
|
+
}
|
|
207
|
+
export function getErrorList(db, filters) {
|
|
208
|
+
const groups = getErrorGroups(db, filters);
|
|
209
|
+
return { errors: groups.slice(0, MAX_ROWS), moreErrors: Math.max(0, groups.length - MAX_ROWS) };
|
|
210
|
+
}
|
|
211
|
+
function countBy(rows, key) {
|
|
212
|
+
return [...groupBy(rows, key)]
|
|
213
|
+
.map(([group, items]) => ({ key: group, count: Math.round(items.reduce((sum, item) => sum + item.weight, 0)) }))
|
|
214
|
+
.sort((a, b) => b.count - a.count || a.key.localeCompare(b.key))
|
|
215
|
+
.slice(0, MAX_ROWS);
|
|
216
|
+
}
|
|
217
|
+
/** Boş kovalar sıfırla doldurulur: hatasız geçen süre çizgide görünmeli. */
|
|
218
|
+
function occurrences(rows) {
|
|
219
|
+
const times = rows.map((row) => row.ts);
|
|
220
|
+
const first = minOf(times);
|
|
221
|
+
const last = maxOf(times);
|
|
222
|
+
const step = BUCKETS.find((bucket) => (last - first) / bucket <= MAX_BUCKETS) ?? BUCKETS.at(-1);
|
|
223
|
+
const start = Math.floor(first / step) * step;
|
|
224
|
+
const x = Array.from({ length: Math.floor((last - start) / step) + 1 }, (_, i) => start + i * step);
|
|
225
|
+
const totals = x.map(() => 0);
|
|
226
|
+
for (const { ts, weight } of rows)
|
|
227
|
+
totals[Math.floor((ts - start) / step)] += weight;
|
|
228
|
+
return { x, counts: totals.map(Math.round) };
|
|
229
|
+
}
|
|
230
|
+
/** Bu filtrelerde hatası yoksa `null`. */
|
|
231
|
+
export function getErrorDetail(db, id, filters) {
|
|
232
|
+
const rows = errorRows(db, filters).filter((row) => row.id === id);
|
|
233
|
+
if (rows.length === 0)
|
|
234
|
+
return null;
|
|
235
|
+
return {
|
|
236
|
+
...toGroup(rows),
|
|
237
|
+
stack: rows[0].stack,
|
|
238
|
+
handled: rows[0].handled === 1,
|
|
239
|
+
series: occurrences(rows),
|
|
240
|
+
pages: countBy(rows, (row) => row.page),
|
|
241
|
+
devices: countBy(rows, (row) => row.device),
|
|
242
|
+
releases: countBy(rows, (row) => row.release ?? ""),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/** Son görülen önce. */
|
|
246
|
+
export function getReleases(db, filters) {
|
|
247
|
+
const { sql, params } = where(filters);
|
|
248
|
+
// `vitals`'ın index'leri `release` taşımaz; sırayla taramak her satırda tabloya dönmekten hızlı.
|
|
249
|
+
const union = ["vitals NOT INDEXED", "pageviews", "errors"].map((table) => `SELECT release, ts FROM ${table} WHERE ${sql}`).join(" UNION ALL ");
|
|
250
|
+
return db
|
|
251
|
+
.prepare(`SELECT release FROM (${union}) WHERE release IS NOT NULL GROUP BY release ORDER BY MAX(ts) DESC LIMIT ${MAX_ROWS}`)
|
|
252
|
+
.all(...params, ...params, ...params)
|
|
253
|
+
.map((row) => row.release);
|
|
254
|
+
}
|
|
255
|
+
export function getComparison(db, filters, a, b) {
|
|
256
|
+
const views = (release) => {
|
|
257
|
+
const { sql, params } = where({ ...filters, release });
|
|
258
|
+
const row = db.prepare(`SELECT SUM(1.0 / sample_rate) AS views FROM pageviews WHERE ${sql}`).get(...params);
|
|
259
|
+
return Math.round(row?.views ?? 0);
|
|
260
|
+
};
|
|
261
|
+
const side = (release) => groupBy(samples(db, { ...filters, release }), (sample) => sample[NAME]);
|
|
262
|
+
const metricsA = side(a);
|
|
263
|
+
const metricsB = side(b);
|
|
264
|
+
const pick = (name, groups) => {
|
|
265
|
+
const { count, p75, rating } = summarize(name, valuesOf(groups.get(name) ?? []));
|
|
266
|
+
return { count, p75, rating };
|
|
267
|
+
};
|
|
268
|
+
const errorsA = new Map(getErrorGroups(db, { ...filters, release: a }).map((group) => [group.id, group]));
|
|
269
|
+
const errorsB = new Map(getErrorGroups(db, { ...filters, release: b }).map((group) => [group.id, group]));
|
|
270
|
+
const errors = [...new Set([...errorsB.keys(), ...errorsA.keys()])]
|
|
271
|
+
.map((id) => {
|
|
272
|
+
const { type, message, location } = (errorsB.get(id) ?? errorsA.get(id));
|
|
273
|
+
return { id, type, message, location, a: errorsA.get(id)?.count ?? 0, b: errorsB.get(id)?.count ?? 0 };
|
|
274
|
+
})
|
|
275
|
+
// Yeni release'te en çok görülen önce.
|
|
276
|
+
.sort((x, y) => y.b - x.b || y.a - x.a);
|
|
277
|
+
return {
|
|
278
|
+
views: { a: views(a), b: views(b) },
|
|
279
|
+
metrics: METRIC_NAMES.map((name) => ({ name, a: pick(name, metricsA), b: pick(name, metricsB) })),
|
|
280
|
+
errors: errors.slice(0, MAX_ROWS),
|
|
281
|
+
moreErrors: Math.max(0, errors.length - MAX_ROWS),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function minOf(values) {
|
|
285
|
+
return values.reduce((min, value) => Math.min(min, value), Infinity);
|
|
286
|
+
}
|
|
287
|
+
function maxOf(values) {
|
|
288
|
+
return values.reduce((max, value) => Math.max(max, value), -Infinity);
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"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"}
|
package/dist/report.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { DatabaseSync } from "node:sqlite";
|
|
4
|
+
import { styleText } from "node:util";
|
|
5
|
+
import { METRIC_NAMES, getRating } from "@vitalscope/protocol";
|
|
6
|
+
import { ENVIRONMENTS, getErrorGroups, getOverview } from "./queries.js";
|
|
7
|
+
import { DB_FILE } from "./sqlite.js";
|
|
8
|
+
const MAX_PAGES = 30;
|
|
9
|
+
const MAX_ERRORS = 20;
|
|
10
|
+
const PAGE_WIDTH = 40;
|
|
11
|
+
const ERROR_WIDTH = 80;
|
|
12
|
+
/** Renksiz çıktıda da (dosyaya yönlendirme, `NO_COLOR`) okunabilsin diye değerin yanında işaret. */
|
|
13
|
+
const MARKS = { good: "", "needs-improvement": " ~", poor: " !" };
|
|
14
|
+
const COLORS = { good: "green", "needs-improvement": "yellow", poor: "red" };
|
|
15
|
+
/** Geliştirme sunucusu ile build'in sayıları tek p75'te karışmasın diye her ortamın kendi tablosu var. */
|
|
16
|
+
const DEV_WARNING = "Development servers run unminified code with HMR, so these numbers differ from a production build.";
|
|
17
|
+
/**
|
|
18
|
+
* Yollar ve hata mesajları tarayıcıdan gelir, sayfadaki herhangi bir betik belirleyebilir.
|
|
19
|
+
* Kontrol karakterleri temizlenmezse bir hata mesajı terminale kaçış dizisi basabilir.
|
|
20
|
+
*/
|
|
21
|
+
function clean(text, width) {
|
|
22
|
+
const safe = text.toWellFormed().replace(/[\p{Cc}\p{Cf}]/gu, " ");
|
|
23
|
+
return safe.length > width ? `${safe.slice(0, width - 1)}…` : safe;
|
|
24
|
+
}
|
|
25
|
+
function formatValue(name, value) {
|
|
26
|
+
if (name === "CLS")
|
|
27
|
+
return value.toFixed(2);
|
|
28
|
+
return value < 1000 ? `${Math.round(value)} ms` : `${(value / 1000).toFixed(2)} s`;
|
|
29
|
+
}
|
|
30
|
+
function more(total, shown, label) {
|
|
31
|
+
return total > shown ? [`…and ${total - shown} more ${label}`] : [];
|
|
32
|
+
}
|
|
33
|
+
/** Panelin genel bakışıyla aynı sorgu: sayılar ikisinde de aynı. */
|
|
34
|
+
function pagesTable(db, env) {
|
|
35
|
+
const { pages, morePages } = getOverview(db, { env });
|
|
36
|
+
if (pages.length === 0)
|
|
37
|
+
return [];
|
|
38
|
+
const rows = pages.slice(0, MAX_PAGES).map(({ page, views, p75 }) => ({
|
|
39
|
+
page: clean(page, PAGE_WIDTH),
|
|
40
|
+
views: String(views),
|
|
41
|
+
cells: METRIC_NAMES.map((name) => {
|
|
42
|
+
const value = p75[name];
|
|
43
|
+
if (value === undefined)
|
|
44
|
+
return { text: "-", rating: undefined };
|
|
45
|
+
const rating = getRating(name, value);
|
|
46
|
+
return { text: formatValue(name, value) + MARKS[rating], rating };
|
|
47
|
+
}),
|
|
48
|
+
}));
|
|
49
|
+
const pageWidth = Math.max("Page".length, ...rows.map((row) => row.page.length));
|
|
50
|
+
const viewsWidth = Math.max("Views".length, ...rows.map((row) => row.views.length));
|
|
51
|
+
const widths = METRIC_NAMES.map((name, i) => Math.max(name.length, ...rows.map((row) => row.cells[i].text.length)));
|
|
52
|
+
const header = ["Page".padEnd(pageWidth), "Views".padStart(viewsWidth), ...METRIC_NAMES.map((name, i) => name.padStart(widths[i]))].join(" ");
|
|
53
|
+
const lines = rows.map((row) => [
|
|
54
|
+
row.page.padEnd(pageWidth),
|
|
55
|
+
row.views.padStart(viewsWidth),
|
|
56
|
+
// Hizalama rengi etkilemesin: önce doldurulur, sonra renklenir.
|
|
57
|
+
...row.cells.map(({ text, rating }, i) => {
|
|
58
|
+
const padded = text.padStart(widths[i]);
|
|
59
|
+
return rating ? styleText(COLORS[rating], padded, { stream: process.stdout }) : padded;
|
|
60
|
+
}),
|
|
61
|
+
].join(" "));
|
|
62
|
+
return [header, ...lines, ...more(pages.length + morePages, rows.length, "pages")];
|
|
63
|
+
}
|
|
64
|
+
function errorsList(db) {
|
|
65
|
+
const errors = getErrorGroups(db, {});
|
|
66
|
+
return [
|
|
67
|
+
...errors.slice(0, MAX_ERRORS).flatMap(({ type, message, location, count }) => [
|
|
68
|
+
`${String(count).padStart(5)}× ${clean(`${type}: ${message}`, ERROR_WIDTH)}`,
|
|
69
|
+
...(location ? [` at ${clean(location, ERROR_WIDTH)}`] : []),
|
|
70
|
+
]),
|
|
71
|
+
...more(errors.length, MAX_ERRORS, "errors"),
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
/** Toplanan veriden terminal raporu üretir. Veri yoksa klasör oluşturmaz, ne yapılacağını söyler. */
|
|
75
|
+
export function buildReport(dir) {
|
|
76
|
+
const file = join(dir, DB_FILE);
|
|
77
|
+
const empty = `No measurements yet. Run "vitalscope dev" and open your site.`;
|
|
78
|
+
if (!existsSync(file))
|
|
79
|
+
return empty;
|
|
80
|
+
const db = new DatabaseSync(file, { readOnly: true });
|
|
81
|
+
try {
|
|
82
|
+
const sections = ENVIRONMENTS.flatMap((env) => {
|
|
83
|
+
const pages = pagesTable(db, env);
|
|
84
|
+
if (pages.length === 0)
|
|
85
|
+
return [];
|
|
86
|
+
return [[`p75 by page, ${env} (~ needs improvement, ! poor)`, ...(env === "development" ? [DEV_WARNING] : []), "", ...pages]];
|
|
87
|
+
});
|
|
88
|
+
const errors = errorsList(db);
|
|
89
|
+
if (errors.length > 0)
|
|
90
|
+
sections.push(["Errors", "", ...errors]);
|
|
91
|
+
if (sections.length === 0)
|
|
92
|
+
return empty;
|
|
93
|
+
return sections.map((section) => section.join("\n")).join("\n\n");
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
db.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAgC,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAoB,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,oGAAoG;AACpG,MAAM,KAAK,GAA2B,EAAE,IAAI,EAAE,EAAE,EAAE,mBAAmB,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC1F,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAW,CAAC;AACtF,0GAA0G;AAC1G,MAAM,WAAW,GAAG,oGAAoG,CAAC;AAEzH;;;GAGG;AACH,SAAS,KAAK,CAAC,IAAY,EAAE,KAAa;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IAClE,OAAO,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC;AAED,SAAS,WAAW,CAAC,IAAgB,EAAE,KAAa;IAClD,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACrF,CAAC;AAED,SAAS,IAAI,CAAC,KAAa,EAAE,KAAa,EAAE,KAAa;IACvD,OAAO,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,KAAK,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,oEAAoE;AACpE,SAAS,UAAU,CAAC,EAAgB,EAAE,GAAgB;IACpD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QACpE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC;QAC7B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QACpB,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACjE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACtC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QACpE,CAAC,CAAC;KACH,CAAC,CAAC,CAAC;IAEJ,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACjF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAErH,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChJ,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAC7B;QACE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAC1B,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC9B,gEAAgE;QAChE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACzF,CAAC,CAAC;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,UAAU,CAAC,EAAgB;IAClC,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACtC,OAAO;QACL,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YAC7E,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,EAAE,WAAW,CAAC,EAAE;YAC7E,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACpE,CAAC;QACF,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,+DAA+D,CAAC;IAC9E,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpC,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAClC,OAAO,CAAC,CAAC,gBAAgB,GAAG,iCAAiC,EAAE,GAAG,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;QACjI,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;QAChE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACxC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpE,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
|
package/dist/rows.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const MAX_EVENT_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
2
|
+
const MAX_CLOCK_SKEW_MS = 60 * 60 * 1000;
|
|
3
|
+
/** İstemci saatine güvenilmez: uç değerli `ts`'ler zaman serilerini bozar. Makul aralık dışında alınma zamanı kullanılır. */
|
|
4
|
+
function eventTime(ts, receivedAt) {
|
|
5
|
+
return ts >= receivedAt - MAX_EVENT_AGE_MS && ts <= receivedAt + MAX_CLOCK_SKEW_MS ? ts : receivedAt;
|
|
6
|
+
}
|
|
7
|
+
function timings({ ttfb, loadDelay, loadTime, renderDelay, inputDelay, processing, presentation, time }) {
|
|
8
|
+
const all = { ttfb, loadDelay, loadTime, renderDelay, inputDelay, processing, presentation, time };
|
|
9
|
+
return Object.fromEntries(Object.entries(all).filter(([, value]) => value !== undefined));
|
|
10
|
+
}
|
|
11
|
+
/** Olayları türüne göre tablo satırlarına ayırır; verilmeyen sütunlar `NULL` kalır. */
|
|
12
|
+
export function toRows(events) {
|
|
13
|
+
const rows = { vitals: [], errors: [], pageviews: [], custom_events: [] };
|
|
14
|
+
for (const { receivedAt, sdk, ctx, event } of events) {
|
|
15
|
+
const common = {
|
|
16
|
+
ts: eventTime(event.ts, receivedAt),
|
|
17
|
+
received_at: receivedAt,
|
|
18
|
+
sample_rate: ctx.sr,
|
|
19
|
+
sdk,
|
|
20
|
+
path: ctx.path,
|
|
21
|
+
route: ctx.route,
|
|
22
|
+
release: ctx.release,
|
|
23
|
+
env: ctx.env,
|
|
24
|
+
device: ctx.device,
|
|
25
|
+
conn: ctx.conn,
|
|
26
|
+
nav_type: ctx.nav,
|
|
27
|
+
session_id: ctx.sid,
|
|
28
|
+
};
|
|
29
|
+
switch (event.t) {
|
|
30
|
+
case "vital":
|
|
31
|
+
rows.vitals.push({
|
|
32
|
+
...common,
|
|
33
|
+
name: event.name,
|
|
34
|
+
metric_id: event.id,
|
|
35
|
+
value: event.value,
|
|
36
|
+
rating: event.rating,
|
|
37
|
+
attr_target: event.attr?.target,
|
|
38
|
+
attr_url: event.attr?.url,
|
|
39
|
+
attr_script: event.attr?.script,
|
|
40
|
+
attr_type: event.attr?.type,
|
|
41
|
+
attr: event.attr ? JSON.stringify(timings(event.attr)) : undefined,
|
|
42
|
+
});
|
|
43
|
+
break;
|
|
44
|
+
case "error":
|
|
45
|
+
rows.errors.push({ ...common, type: event.type, message: event.msg, stack: JSON.stringify(event.stack), handled: event.handled ? 1 : 0 });
|
|
46
|
+
break;
|
|
47
|
+
case "pageview":
|
|
48
|
+
rows.pageviews.push({ ...common, path: event.path ?? ctx.path });
|
|
49
|
+
break;
|
|
50
|
+
case "custom":
|
|
51
|
+
rows.custom_events.push({ ...common, name: event.name, value: event.value });
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return rows;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=rows.js.map
|
package/dist/rows.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rows.js","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"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"}
|