Skip to content

Commit

Permalink
✨ feat: v1 히스토리 관리를 위한 k6 그라파나 태깅 (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
yanggwangseong committed Dec 24, 2024
1 parent f77b862 commit 5673f17
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 37 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,7 @@ uploads/
# docker
Dockerfile.dev
docker-compose-dev.yml
docker-compose-dev.yml
docker-compose.dev-bak.yml
grafana
prometheus

4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ docker-compose-dev.yml
docker-compose.yml
Dockerfile
mysql-data

grafana/**
prometheus/prometheus.yml
docker-compose.dev-bak.yml
15 changes: 11 additions & 4 deletions k6/scripts/articles-performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,30 @@ export const options = {
/* 일정한 RPS(Request Per Second)를 유지하는 실행기 타입 */
executor: "constant-arrival-rate",
/* 초당 실행할 반복 횟수 */
rate: 1,
rate: 4,
/* rate의 시간 단위 (1s, 1m, 1h 등) */
timeUnit: "1s",
/* 전체 테스트 실행 시간 */
duration: "1m",
/* 테스트 시작 시 미리 할당할 가상 사용자 수 */
preAllocatedVUs: 5,
preAllocatedVUs: 10,
/* 최대 가상 사용자 수 (필요시 추가 할당) */
maxVUs: 10,
maxVUs: 30,
},
},
// 태그 추가
tags: {
testName: "articles-api-test",
testType: "performance",
component: "articles",
version: "1.0",
},
thresholds: {
/* HTTP 요청 실패율이 5% 미만이어야 함 */
http_req_failed: [{ threshold: "rate<0.05", abortOnFail: true }],
/* 부하로 인한 요청 누락률이 5% 미만이어야 함 */
dropped_iterations: [{ threshold: "rate<0.05", abortOnFail: true }],
/* 95%의 요청이 3초 이내에 완료되어야 함 */
// /* 95%의 요청이 3초 이내에 완료되어야 함 */
http_req_duration: [{ threshold: "p(95)<3000", abortOnFail: true }],
},
};
Expand Down
13 changes: 10 additions & 3 deletions k6/scripts/participations-performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ export const options = {
scenarios: {
simple_rps_test: {
executor: "constant-arrival-rate",
rate: 10, // 초당 10개의 요청 (RPS)
rate: 450, // 초당 10개의 요청 (RPS)
timeUnit: "1s", // RPS 단위 설정
duration: "1m", // 테스트 지속 시간: 5분
preAllocatedVUs: 20, // 미리 할당할 VU 수
maxVUs: 50, // 최대 VU 수
preAllocatedVUs: 1000, // 미리 할당할 VU 수
maxVUs: 2000, // 최대 VU 수
},
},
// 태그 추가
tags: {
testName: "participations-api-test",
testType: "performance",
component: "participations",
version: "1.0",
},
thresholds: {
http_req_failed: [{ threshold: "rate<0.05", abortOnFail: true }],
dropped_iterations: [{ threshold: "rate<0.05", abortOnFail: true }],
Expand Down
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@
"-------------------------------------------": "",
"k6:run:articles": "docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/articles-performance.js",
"k6:run:participations": "docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/participations-performance.js",
"k6:run:signup": "docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/signup-performance.js"
"k6:run:signup": "docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/signup-performance.js",
"clinic:doctor-participations": "cross-env NODE_ENV=development clinic doctor --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/participations-performance.js' -- node dist/main.js",
"clinic:doctor-articles": "cross-env NODE_ENV=development clinic doctor --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/articles-performance.js' -- node dist/main.js",
"clinic:doctor-signup": "cross-env NODE_ENV=development clinic doctor --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/signup-performance.js' -- node dist/main.js",
"clinic:flame-participations": "cross-env NODE_ENV=development clinic flame --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/participations-performance.js' -- node dist/main.js",
"clinic:flame-articles": "cross-env NODE_ENV=development clinic flame --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/articles-performance.js' -- node dist/main.js",
"clinic:flame-signup": "cross-env NODE_ENV=development clinic flame --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/signup-performance.js' -- node dist/main.js",
"clinic:bubbleprof-participations": "cross-env NODE_ENV=development clinic bubbleprof --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/participations-performance.js' -- node dist/main.js",
"clinic:bubbleprof-articles": "cross-env NODE_ENV=development clinic bubbleprof --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/articles-performance.js' -- node dist/main.js",
"clinic:bubbleprof-signup": "cross-env NODE_ENV=development clinic bubbleprof --on-port 'docker-compose -f docker-compose-dev.yml run --rm k6 run /scripts/signup-performance.js' -- node dist/main.js"
},
"dependencies": {
"@nestjs-modules/mailer": "^2.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/common/typeorm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const TypeOrmModuleOptions = {
poolSize: 30,
connectTimeout: 120000,
...(configService.get("NODE_ENV") === "development"
? { retryAttempts: 10, logging: true }
? { retryAttempts: 10, logging: false }
: { logging: false }),
};

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/articles.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class ArticlesController {
@Query("limit", new ParseIntPipe()) limit: number,
@CurrentMemberDecorator("id") _currentMemberId: number,
) {
return this.articlesService.findAll2(cursor, limit);
return this.articlesService.findAll(cursor, limit, _currentMemberId);
}

@Get(":articleId")
Expand Down
18 changes: 12 additions & 6 deletions src/controllers/participations.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ export class ParticipationsController {
@Query("cursor", new ParseIntPipe()) cursor: number,
@Query("limit", new ParseIntPipe()) limit: number,
) {
await this.articlesService.findById(articleId);
const [article, participation] = await Promise.all([
this.articlesService.findById(articleId),
this.participationsService.getParticipationsByArticleId(
articleId,
cursor,
limit,
),
]);

return this.participationsService.getParticipationsByArticleId(
articleId,
cursor,
limit,
);
return {
...participation,
article,
};
}

@Get()
Expand Down
21 changes: 21 additions & 0 deletions src/repositories/participations.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { QueryRunner, Repository } from "typeorm";

import { ParticipationStatus } from "@APP/common/enum/participation-status.enum";
import { ParticipationEntity } from "@APP/entities/participation.entity";

@Injectable()
Expand All @@ -18,4 +19,24 @@ export class ParticipationsRepository extends Repository<ParticipationEntity> {
? qr.manager.getRepository<ParticipationEntity>(ParticipationEntity)
: this.repository;
}

findAllParticipationsByArticleId(
articleId: number,
cursor: number,
limit: number,
) {
const query = this.repository
.createQueryBuilder("participation")
.where(cursor ? "participation.id > :cursor" : "1=1", { cursor })
.andWhere("participation.articleId = :articleId", {
articleId,
})
.andWhere("participation.status = :status", {
status: ParticipationStatus.ACTIVE,
})
.orderBy("participation.id", "ASC")
.limit(limit + 1);

return query.getRawMany();
}
}
15 changes: 9 additions & 6 deletions src/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import { RegisterMemberDto } from "@APP/dtos/register-member.dto";
import { VerifyEmailDto } from "@APP/dtos/verify-email.dto";
import { MemberEntity } from "@APP/entities/member.entity";

import { MailsService } from "./mails.service";
//import { MailsService } from "./mails.service";
import { MembersService } from "./members.service";

@Injectable()
export class AuthService {
constructor(
private readonly jwtService: JwtService,
private readonly membersService: MembersService,
private readonly mailsService: MailsService,
//private readonly mailsService: MailsService,
private readonly configService: ConfigService,
) {}

Expand Down Expand Up @@ -98,10 +98,13 @@ export class AuthService {
verificationCode,
);

void this.mailsService.sendVerificationEmail(
newMember.email,
verificationCode,
);
/**
* 테스트를 위해서 잠시 보류
*/
// void this.mailsService.sendVerificationEmail(
// newMember.email,
// verificationCode,
// );

return this.signInMember(newMember);
}
Expand Down
19 changes: 5 additions & 14 deletions src/services/participations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,13 @@ export class ParticipationsService {
cursor: number,
limit: number,
) {
const query = this.participationsRepository
.createQueryBuilder("participation")
.where("participation.articleId = :articleId", {
const participations =
await this.participationsRepository.findAllParticipationsByArticleId(
articleId,
})
.andWhere("participation.status = :status", {
status: ParticipationStatus.ACTIVE,
})
.orderBy("participation.id", "ASC")
.limit(limit + 1);

if (cursor) {
query.andWhere("participation.id > :cursor", { cursor });
}
cursor,
limit,
);

const participations = await query.getRawMany();
const hasNextPage = participations.length > limit;
const results = hasNextPage
? participations.slice(0, -1)
Expand Down

0 comments on commit 5673f17

Please sign in to comment.