report-sync.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import http from 'k6/http';
  2. import { check, sleep } from 'k6';
  3. import { Rate, Trend } from 'k6/metrics';
  4. const BASE_URL = __ENV.BASE_URL;
  5. const SCENARIO = __ENV.SCENARIO || 'mixed';
  6. const MODE = __ENV.MODE || 'duration';
  7. const OUTLOOK_PAYLOAD = __ENV.OUTLOOK_PAYLOAD || '../payloads/outlook.json';
  8. const ACHIEVEMENT_PAYLOAD = __ENV.ACHIEVEMENT_PAYLOAD || '../payloads/achievement.json';
  9. const REQUEST_TIMEOUT = __ENV.REQUEST_TIMEOUT || '120s';
  10. const outlookPayload = open(OUTLOOK_PAYLOAD);
  11. const achievementPayload = open(ACHIEVEMENT_PAYLOAD);
  12. const businessSuccess = new Rate('business_success');
  13. const outlookDuration = new Trend('outlook_sync_duration');
  14. const achievementDuration = new Trend('achievement_sync_duration');
  15. function scenarioOptions() {
  16. if (MODE === 'burst') {
  17. return {
  18. scenarios: {
  19. burst_once: {
  20. executor: 'per-vu-iterations',
  21. vus: Number(__ENV.VUS || 20),
  22. iterations: Number(__ENV.ITERATIONS_PER_VU || 1),
  23. maxDuration: __ENV.MAX_DURATION || '2m',
  24. },
  25. },
  26. };
  27. }
  28. return {
  29. vus: Number(__ENV.VUS || 20),
  30. duration: __ENV.DURATION || '3m',
  31. };
  32. }
  33. export const options = {
  34. ...scenarioOptions(),
  35. thresholds: {
  36. http_req_failed: ['rate==0'],
  37. business_success: ['rate==1'],
  38. },
  39. };
  40. function requireBaseUrl() {
  41. if (!BASE_URL) {
  42. throw new Error('BASE_URL is required, for example: BASE_URL=https://test-host k6 run loadtest/k6/report-sync.js');
  43. }
  44. }
  45. function postSync(path, payload, apiName) {
  46. const response = http.post(`${BASE_URL}${path}`, payload, {
  47. headers: {
  48. 'Content-Type': 'application/json',
  49. ...( __ENV.TOKEN ? { Authorization: `Bearer ${__ENV.TOKEN}` } : {} ),
  50. },
  51. tags: { api: apiName },
  52. timeout: REQUEST_TIMEOUT,
  53. });
  54. const ok = check(response, {
  55. [`${apiName} status is 200`]: (res) => res.status === 200,
  56. [`${apiName} has downloadUrl`]: (res) => {
  57. try {
  58. return Boolean(res.json('data.downloadUrl'));
  59. } catch (error) {
  60. return false;
  61. }
  62. },
  63. });
  64. businessSuccess.add(ok, { api: apiName });
  65. if (apiName === 'outlook_sync') {
  66. outlookDuration.add(response.timings.duration);
  67. }
  68. if (apiName === 'achievement_sync') {
  69. achievementDuration.add(response.timings.duration);
  70. }
  71. }
  72. export default function () {
  73. requireBaseUrl();
  74. if (SCENARIO === 'outlook') {
  75. postSync('/api/exam-sprint/outlook-reports/sync', outlookPayload, 'outlook_sync');
  76. } else if (SCENARIO === 'achievement') {
  77. postSync('/api/exam-sprint/achievement-reports/sync', achievementPayload, 'achievement_sync');
  78. } else {
  79. if ((__VU + __ITER) % 2 === 0) {
  80. postSync('/api/exam-sprint/outlook-reports/sync', outlookPayload, 'outlook_sync');
  81. } else {
  82. postSync('/api/exam-sprint/achievement-reports/sync', achievementPayload, 'achievement_sync');
  83. }
  84. }
  85. sleep(Number(__ENV.SLEEP_SECONDS || 0.2));
  86. }