mirror of https://github.com/zulip/zulip.git
katex_server: Add Prometheus metrics.
This commit is contained in:
parent
c13e3dee24
commit
bfe4017663
|
@ -69,6 +69,7 @@
|
|||
"postcss-prefixwrap": "^1.24.0",
|
||||
"postcss-preset-env": "^9.0.0",
|
||||
"postcss-simple-vars": "^7.0.0",
|
||||
"prom-client": "^15.1.0",
|
||||
"regenerator-runtime": "^0.14.0",
|
||||
"shebang-loader": "^0.0.1",
|
||||
"simplebar": "^6.2.0",
|
||||
|
|
|
@ -214,6 +214,9 @@ dependencies:
|
|||
postcss-simple-vars:
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.1(postcss@8.4.35)
|
||||
prom-client:
|
||||
specifier: ^15.1.0
|
||||
version: 15.1.0
|
||||
regenerator-runtime:
|
||||
specifier: ^0.14.0
|
||||
version: 0.14.1
|
||||
|
@ -2727,6 +2730,11 @@ packages:
|
|||
rimraf: 3.0.2
|
||||
dev: false
|
||||
|
||||
/@opentelemetry/api@1.8.0:
|
||||
resolution: {integrity: sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
dev: false
|
||||
|
||||
/@pkgjs/parseargs@0.11.0:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
@ -4360,6 +4368,10 @@ packages:
|
|||
file-uri-to-path: 1.0.0
|
||||
dev: false
|
||||
|
||||
/bintrees@1.0.2:
|
||||
resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==}
|
||||
dev: false
|
||||
|
||||
/bit-twiddle@1.0.2:
|
||||
resolution: {integrity: sha512-B9UhK0DKFZhoTFcfvAzhqsjStvGJp9vYWf3+6SNTtdSQnvIgfkHbgHrg/e4+TH71N2GDu8tpmCVoyfrL1d7ntA==}
|
||||
dev: false
|
||||
|
@ -10573,6 +10585,14 @@ packages:
|
|||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/prom-client@15.1.0:
|
||||
resolution: {integrity: sha512-cCD7jLTqyPdjEPBo/Xk4Iu8jxjuZgZJ3e/oET3L+ZwOuap/7Cw3dH/TJSsZKs1TQLZ2IHpIlRAKw82ef06kmMw==}
|
||||
engines: {node: ^16 || ^18 || >=20}
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.8.0
|
||||
tdigest: 0.1.2
|
||||
dev: false
|
||||
|
||||
/promise-inflight@1.0.1:
|
||||
resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==}
|
||||
peerDependencies:
|
||||
|
@ -12002,6 +12022,12 @@ packages:
|
|||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/tdigest@0.1.2:
|
||||
resolution: {integrity: sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==}
|
||||
dependencies:
|
||||
bintrees: 1.0.2
|
||||
dev: false
|
||||
|
||||
/terser-webpack-plugin@5.3.10(webpack@5.90.3):
|
||||
resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
|
|
|
@ -3,6 +3,7 @@ import crypto from "node:crypto";
|
|||
import bodyParser from "@koa/bodyparser";
|
||||
import katex from "katex";
|
||||
import Koa from "koa";
|
||||
import Prometheus from "prom-client";
|
||||
|
||||
const host = "localhost";
|
||||
const port = Number(process.argv[2] ?? "9700");
|
||||
|
@ -30,6 +31,43 @@ const compare_secret = (given_secret: string): boolean => {
|
|||
const app = new Koa();
|
||||
app.use(bodyParser());
|
||||
|
||||
Prometheus.collectDefaultMetrics();
|
||||
const httpRequestDurationSeconds = new Prometheus.Histogram({
|
||||
name: "katex_http_request_duration_seconds",
|
||||
help: "Duration of HTTP requests in seconds",
|
||||
labelNames: ["method", "path", "status"] as const,
|
||||
buckets: [
|
||||
0.00001, 0.00002, 0.00005, 0.0001, 0.0002, 0.0005, 0.001, 0.002, 0.005, 0.01, 0.02, 0.05,
|
||||
0.1,
|
||||
],
|
||||
});
|
||||
|
||||
const httpRequestSizeBytes = new Prometheus.Histogram({
|
||||
name: "katex_request_size_bytes",
|
||||
help: "Size of successful KaTeX input in bytes",
|
||||
labelNames: ["display_mode"] as const,
|
||||
buckets: [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000],
|
||||
});
|
||||
|
||||
const httpResponseSizeBytes = new Prometheus.Histogram({
|
||||
name: "katex_response_size_bytes",
|
||||
help: "Size of successful KaTeX output in bytes",
|
||||
labelNames: ["display_mode"] as const,
|
||||
buckets: [100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000],
|
||||
});
|
||||
|
||||
app.use(async (ctx, next) => {
|
||||
if (ctx.request.method === "GET" && ctx.request.path === "/metrics") {
|
||||
ctx.body = await Prometheus.register.metrics();
|
||||
return;
|
||||
}
|
||||
const endTimer = httpRequestDurationSeconds.startTimer();
|
||||
await next();
|
||||
const {method, path} = ctx.request;
|
||||
const {status} = ctx.response;
|
||||
httpRequestDurationSeconds.labels({method, path, status: String(status)}).observe(endTimer());
|
||||
});
|
||||
|
||||
app.use((ctx, _next) => {
|
||||
if (ctx.request.method !== "POST" || ctx.request.path !== "/") {
|
||||
ctx.status = 404;
|
||||
|
@ -59,8 +97,12 @@ app.use((ctx, _next) => {
|
|||
return;
|
||||
}
|
||||
|
||||
httpRequestSizeBytes.labels(String(is_display)).observe(Buffer.byteLength(content, "utf8"));
|
||||
try {
|
||||
ctx.body = katex.renderToString(content, {displayMode: is_display});
|
||||
httpResponseSizeBytes
|
||||
.labels(String(is_display))
|
||||
.observe(Buffer.byteLength(ctx.body, "utf8"));
|
||||
} catch (error) {
|
||||
if (error instanceof katex.ParseError) {
|
||||
ctx.status = 400;
|
||||
|
|
Loading…
Reference in New Issue