184 lines
6.0 KiB
JavaScript
184 lines
6.0 KiB
JavaScript
/**
|
|
* SCENARIO: timeline-query.js
|
|
* Timeline analytics endpoints — Guardian dashboard, location history, activity logs.
|
|
*
|
|
* Simulasi Guardian yang aktif monitoring: buka dashboard, lihat peta,
|
|
* scroll history, cek obstacle logs. Query-heavy read scenario.
|
|
*
|
|
* Target: p95 < 1000ms (analytics boleh lebih lambat), error rate < 1%
|
|
*/
|
|
import { sleep, check } from "k6";
|
|
import {
|
|
DEFAULT_THRESHOLDS,
|
|
handleSummary,
|
|
} from "../modules/metrics-helper.js";
|
|
import * as api from "../modules/api-client.js";
|
|
import { testData } from "../modules/test-data.js";
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
timeline_analytics: {
|
|
executor: "ramping-vus",
|
|
startVUs: 0,
|
|
stages: [
|
|
{ duration: "20s", target: 10 },
|
|
{ duration: "90s", target: 30 },
|
|
{ duration: "30s", target: 0 },
|
|
],
|
|
gracefulRampDown: "15s",
|
|
},
|
|
},
|
|
thresholds: {
|
|
...DEFAULT_THRESHOLDS,
|
|
walkguide_timeline_latency_ms: ["p(95)<1000", "p(99)<2000"],
|
|
http_req_duration: ["p(95)<1000"],
|
|
},
|
|
};
|
|
|
|
// ── Per-VU state ──────────────────────────────────────────────────────────────
|
|
let guardianToken = null;
|
|
let userToken = null;
|
|
|
|
export default function timelineQuery() {
|
|
// ── Init: setup both roles ─────────────────────────────────────────────────
|
|
if (!guardianToken || !userToken) {
|
|
const suffix = `tl_${__VU}_${Date.now()}`;
|
|
|
|
const gRes = api.register(testData.guardianRegisterPayload(suffix));
|
|
if (gRes.status === 200) {
|
|
const b = api.parseBody(gRes);
|
|
if (b && b.data) guardianToken = b.data.accessToken;
|
|
}
|
|
|
|
const uRes = api.register(testData.userRegisterPayload(suffix));
|
|
if (uRes.status === 200) {
|
|
const b = api.parseBody(uRes);
|
|
if (b && b.data) userToken = b.data.accessToken;
|
|
}
|
|
|
|
if (!guardianToken || !userToken) {
|
|
sleep(2);
|
|
return;
|
|
}
|
|
|
|
// Seed beberapa location updates agar ada data untuk query
|
|
for (let i = 0; i < 3; i++) {
|
|
const coord = testData.randomSurabayaCoord(0.02);
|
|
api.updateLocation(userToken, coord.lat, coord.lng, 5.0, 1.2, 90.0);
|
|
sleep(0.1);
|
|
}
|
|
|
|
// Seed obstacle logs
|
|
for (let i = 0; i < 5; i++) {
|
|
api.logObstacle(userToken, testData.obstacleLogPayload());
|
|
sleep(0.1);
|
|
}
|
|
|
|
sleep(0.5);
|
|
}
|
|
|
|
// ── Guardian Dashboard Simulation ─────────────────────────────────────────
|
|
|
|
// Step 1: Guardian dashboard (overview semua data)
|
|
const dashRes = api.getGuardianDashboard(guardianToken);
|
|
check(dashRes, {
|
|
"dashboard: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"dashboard: fast": (r) => r.timings.duration < 1000,
|
|
"dashboard: has data": (r) => {
|
|
const b = api.parseBody(r);
|
|
return b && b.data !== undefined;
|
|
},
|
|
});
|
|
sleep(0.5);
|
|
|
|
// Step 2: Get user location (paling sering dipanggil di Guardian map screen)
|
|
const locRes = api.getUserLocation(guardianToken);
|
|
check(locRes, {
|
|
"user-location: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"user-location: fast": (r) => r.timings.duration < 500,
|
|
});
|
|
sleep(0.3);
|
|
|
|
// Step 3: Location history (scroll timeline peta seperti Google Maps Timeline)
|
|
const pages = [0, 1, 2];
|
|
const pageSizes = [20, 50, 100];
|
|
|
|
for (const page of pages) {
|
|
const size = pageSizes[page % pageSizes.length];
|
|
const histRes = api.getLocationHistory(guardianToken, page, size);
|
|
check(histRes, {
|
|
[`location-history page${page}: 2xx`]: (r) =>
|
|
r.status >= 200 && r.status < 300,
|
|
[`location-history page${page}: latency`]: (r) =>
|
|
r.timings.duration < 1500,
|
|
});
|
|
sleep(0.3);
|
|
}
|
|
|
|
// Step 4: Obstacle logs (Guardian ingin tahu apa saja yang terdeteksi)
|
|
const obsRes = api.getObstacleLogs(guardianToken, 0, 20);
|
|
check(obsRes, {
|
|
"obstacle-logs: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"obstacle-logs: fast": (r) => r.timings.duration < 800,
|
|
});
|
|
sleep(0.3);
|
|
|
|
// Step 5: Activity logs (timeline aktivitas User)
|
|
const actRes = api.getActivityLogsGuardian(guardianToken, 0, 20);
|
|
check(actRes, {
|
|
"activity-logs: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"activity-logs: fast": (r) => r.timings.duration < 1000,
|
|
});
|
|
sleep(0.3);
|
|
|
|
// Step 6: SOS events history
|
|
const sosRes = api.getSosEvents(guardianToken, 0, 10);
|
|
check(sosRes, {
|
|
"sos-events: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
sleep(0.2);
|
|
|
|
// Step 7: AI config (Guardian mau lihat setting YOLO)
|
|
const aiRes = api.getAiConfig(guardianToken);
|
|
check(aiRes, {
|
|
"ai-config: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
sleep(0.2);
|
|
|
|
// Step 8: Geofence config
|
|
const geoRes = api.getGeofenceConfig(guardianToken);
|
|
check(geoRes, {
|
|
"geofence: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
|
|
// ── User side: check own activity ─────────────────────────────────────────
|
|
sleep(0.5);
|
|
|
|
const uActRes = api.getActivityLogs(userToken, 0, 10);
|
|
check(uActRes, {
|
|
"user-activity: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
|
|
const uSettRes = api.getUserSettings(userToken);
|
|
check(uSettRes, {
|
|
"user-settings: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
|
|
const uAiRes = api.getUserAiConfig(userToken);
|
|
check(uAiRes, {
|
|
"user-ai-config: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
|
|
// Think time — Guardian tidak refresh setiap detik
|
|
sleep(testData.randomFloat(2.0, 5.0, 1));
|
|
}
|
|
|
|
export function setup() {
|
|
const res = api.ping();
|
|
if (res.status !== 200)
|
|
throw new Error(`Backend not reachable: ${res.status}`);
|
|
console.log("📊 Timeline analytics test starting.");
|
|
}
|
|
|
|
export { handleSummary };
|