Files
zwitschi 33b6296c5e
CI / test (push) Successful in 2m50s
CI / docker (push) Successful in 5m12s
Refactor load testing scripts to support Bash and PowerShell
- Updated README.md to reflect changes in load testing commands and added usage examples for Bash scripts.
- Converted PowerShell load testing scripts to Bash equivalents for better cross-platform compatibility.
- Added new Bash scripts: run-loadtests.sh, summarize-artillery.sh, and summarize-k6.sh to mirror existing PowerShell functionality.
- Updated admin-api.js and ws-chat.yml for consistency and improved performance metrics reporting.
- Enhanced error handling and output formatting in summary scripts for better readability.
2026-09-02 19:47:34 +02:00

107 lines
3.5 KiB
JavaScript

#!/usr/bin/env node
const apiToken = process.env.CLOUDFLARE_API_TOKEN;
const zoneTag = process.env.CLOUDFLARE_ZONE_TAG;
const hostname = process.env.CLOUDFLARE_HOSTNAME || "linearvoid.tv";
const windowMinutes = Number.parseInt(process.env.CLOUDFLARE_CACHE_HIT_RATIO_WINDOW_MINUTES || "60", 10);
const endpoint = process.env.CLOUDFLARE_GRAPHQL_ENDPOINT || "https://api.cloudflare.com/client/v4/graphql";
if (!apiToken || !zoneTag) {
console.error("Missing required environment variables: CLOUDFLARE_API_TOKEN, CLOUDFLARE_ZONE_TAG");
process.exit(1);
}
const end = new Date();
const start = new Date(end.getTime() - windowMinutes * 60 * 1000);
const iso = (value) => value.toISOString();
const query = `
query CacheHitRatio($zoneTag: string, $start: Time, $end: Time, $hostname: String) {
viewer {
zones(filter: { zoneTag: $zoneTag }) {
requests: httpRequestsAdaptiveGroups(
limit: 1000
filter: {
datetime_geq: $start
datetime_lt: $end
clientRequestHTTPHost: $hostname
requestSource: "eyeball"
}
) {
count
dimensions {
cacheStatus
}
}
}
}
}
`;
async function main() {
const response = await fetch(endpoint, {
method: "POST",
headers: {
Authorization: `Bearer ${apiToken}`,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
query,
variables: {
zoneTag,
hostname,
start: iso(start),
end: iso(end),
},
}),
});
const payload = await response.json();
if (!response.ok || payload.errors) {
const message = payload.errors ? JSON.stringify(payload.errors) : `HTTP ${response.status}`;
throw new Error(message);
}
const groups = payload?.data?.viewer?.zones?.[0]?.requests || [];
let totalRequests = 0;
let hitRequests = 0;
for (const group of groups) {
const count = Number(group?.count || 0);
const status = String(group?.dimensions?.cacheStatus || "").toUpperCase();
totalRequests += count;
if (status === "HIT") {
hitRequests += count;
}
}
const ratio = totalRequests > 0 ? hitRequests / totalRequests : 0;
console.log(
`# HELP linearvoid_cache_hit_ratio Cloudflare cache hit ratio for the selected hostname and time window.`,
);
console.log(`# TYPE linearvoid_cache_hit_ratio gauge`);
console.log(
`linearvoid_cache_hit_ratio{zone="${zoneTag}",hostname="${hostname}",window_minutes="${windowMinutes}"} ${ratio.toFixed(6)}`,
);
console.log(`# HELP linearvoid_cache_hit_requests_total Cloudflare cache HIT requests counted in the time window.`);
console.log(`# TYPE linearvoid_cache_hit_requests_total counter`);
console.log(
`linearvoid_cache_hit_requests_total{zone="${zoneTag}",hostname="${hostname}",window_minutes="${windowMinutes}"} ${hitRequests}`,
);
console.log(
`# HELP linearvoid_cache_total_requests_total Cloudflare total eyeball requests counted in the time window.`,
);
console.log(`# TYPE linearvoid_cache_total_requests_total counter`);
console.log(
`linearvoid_cache_total_requests_total{zone="${zoneTag}",hostname="${hostname}",window_minutes="${windowMinutes}"} ${totalRequests}`,
);
}
main().catch((error) => {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
});