Skip to content

Commit

Permalink
Merge pull request #62 from boostcampwm-2024/be-feat#57
Browse files Browse the repository at this point in the history
[BE] 로그 로직 변경 및 clickhouse 설정 변경
  • Loading branch information
sjy2335 authored Nov 13, 2024
2 parents c8da51d + ca2ccf7 commit 7175a69
Show file tree
Hide file tree
Showing 23 changed files with 225 additions and 677 deletions.
19 changes: 19 additions & 0 deletions backend/proxy-server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/proxy-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"typescript": "^5.6.3"
},
"dependencies": {
"@clickhouse/client": "^1.8.0",
"@fastify/reply-from": "^11.0.1",
"clickhouse": "^2.6.0",
"dotenv": "^16.4.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from 'path';
import fs from 'fs';
import { ErrorLog } from './logger.interface';
import type { ErrorLog } from './logger.interface';

export class ErrorLogRepository {
private readonly logDir = 'logs';
Expand Down
5 changes: 2 additions & 3 deletions backend/proxy-server/src/common/logger/fastify.logger.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type { FastifyInstance } from 'fastify';
import type { ErrorLog, Logger } from './logger.interface';
import { RequestLogEntity } from '../../domain/log/request-log.entity';
import { ResponseLogEntity } from '../../domain/log/response-log.entity';
import type { HttpLogEntity } from '../../domain/log/http-log.entity';

export class FastifyLogger implements Logger {
constructor(private readonly server: FastifyInstance) {}

public info(log: RequestLogEntity | ResponseLogEntity | { message: string }): void {
public info(log: HttpLogEntity | { message: string }): void {
this.server.log.info(log);
}

Expand Down
7 changes: 3 additions & 4 deletions backend/proxy-server/src/common/logger/logger.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { RequestLogEntity } from '../../domain/log/request-log.entity';
import { ResponseLogEntity } from '../../domain/log/response-log.entity';
import { BaseLog } from '../../domain/core/base-log';
import type { HttpLogEntity } from '../../domain/log/http-log.entity';
import type { BaseLog } from '../../domain/core/base-log';

export interface ErrorLog extends BaseLog {
request: {
Expand All @@ -22,6 +21,6 @@ export interface ErrorLog extends BaseLog {
}

export interface Logger {
info(log: RequestLogEntity | ResponseLogEntity | { message: string }): void;
info(log: HttpLogEntity | { message: string }): void;
error(log: ErrorLog): void;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ClickHouse } from 'clickhouse';
import { createClient, ClickHouseClient } from '@clickhouse/client';
import { clickhouseConfig } from './config/clickhouse.config';

export class ClickhouseDatabase {
private static instance: ClickHouse;
private static instance: ClickHouseClient;

public static getInstance(): ClickHouse {
public static getInstance(): ClickHouseClient {
if (!ClickhouseDatabase.instance) {
ClickhouseDatabase.instance = new ClickHouse(clickhouseConfig);
ClickhouseDatabase.instance = createClient(clickhouseConfig);
}
return ClickhouseDatabase.instance;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
export const clickhouseConfig = {
url: process.env.CLICKHOUSE_URL || 'http://localhost',
port: Number(process.env.CLICKHOUSE_PORT) || 8123,
debug: false,
basicAuth: process.env.CLICKHOUSE_AUTH
? {
username: process.env.CLICKHOUSE_USERNAME || 'default',
password: process.env.CLICKHOUSE_PASSWORD || '',
}
: null,
format: 'json',
config: {
session_timeout: 60,
database: process.env.CLICKHOUSE_DATABASE,
},
import { ClickHouseClientConfigOptions } from '@clickhouse/client';

export const clickhouseConfig: ClickHouseClientConfigOptions = {
url: process.env.CLICKHOUSE_URL || 'http://localhost:8123',
username: process.env.CLICKHOUSE_USERNAME || 'default',
password: process.env.CLICKHOUSE_PASSWORD || '',
database: process.env.CLICKHOUSE_DATABASE,
};
Original file line number Diff line number Diff line change
@@ -1,38 +1,17 @@
import type { ClickHouse } from 'clickhouse';
import { ClickhouseDatabase } from '../clickhouse/clickhouse-database';
import { DatabaseQueryError } from '../../common/error/database-query.error';
import { LogRepository } from '../../domain/log/log.repository';
import { RequestLogEntity } from '../../domain/log/request-log.entity';
import { ResponseLogEntity } from '../../domain/log/response-log.entity';
import { HttpLogEntity } from '../../domain/log/http-log.entity';
import { ClickHouseClient } from '@clickhouse/client';

export class LogRepositoryClickhouse implements LogRepository {
private readonly clickhouse: ClickHouse;
private readonly clickhouse: ClickHouseClient;

constructor() {
this.clickhouse = ClickhouseDatabase.getInstance();
}

public async insertRequestLog(log: RequestLogEntity): Promise<void> {
const values = [
{
method: log.method,
path: log.path || '',
host: log.host,
timestamp: this.formatDate(new Date()),
},
];

try {
const query = `\nINSERT INTO request_log FORMAT JSONEachRow ${JSON.stringify(values)}`;

await this.clickhouse.insert(query).toPromise();
} catch (error) {
console.error('ClickHouse Error:', error);
throw new DatabaseQueryError(error as Error);
}
}

public async insertResponseLog(log: ResponseLogEntity): Promise<void> {
public async insertHttpLog(log: HttpLogEntity): Promise<void> {
const values = [
{
method: log.method,
Expand All @@ -45,19 +24,17 @@ export class LogRepositoryClickhouse implements LogRepository {
];

try {
const query = `\nINSERT INTO response_log FORMAT JSONEachRow ${this.formatValues(values)}`;

await this.clickhouse.query(query).toPromise();
await this.clickhouse.insert({
table: 'http_log',
values: values,
format: 'JSONEachRow',
});
} catch (error) {
console.error('ClickHouse Error:', error);
throw new DatabaseQueryError(error as Error);
}
}

private formatValues(values: any): string {
return JSON.stringify(values[0]);
}

private formatDate(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { BaseLog } from '../core/base-log';
import type { BaseLog } from '../core/base-log';

interface ResponseLog extends BaseLog {
interface HttpLog extends BaseLog {
statusCode: number;
responseTime: number;
}

export class ResponseLogEntity {
export class HttpLogEntity {
readonly method: string;
readonly host: string;
readonly path: string | undefined;
readonly statusCode: number;
readonly responseTime: number;

constructor(log: ResponseLog) {
constructor(log: HttpLog) {
this.method = log.method;
this.host = log.host;
this.path = log.path;
Expand Down
6 changes: 2 additions & 4 deletions backend/proxy-server/src/domain/log/log.repository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { RequestLogEntity } from './request-log.entity';
import { ResponseLogEntity } from './response-log.entity';
import type { HttpLogEntity } from './http-log.entity';

export interface LogRepository {
insertRequestLog(log: RequestLogEntity): Promise<void>;
insertResponseLog(log: ResponseLogEntity): Promise<void>;
insertHttpLog(log: HttpLogEntity): Promise<void>;
}
21 changes: 4 additions & 17 deletions backend/proxy-server/src/domain/log/log.service.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
import { DatabaseQueryError } from '../../common/error/database-query.error';
import { RequestLogEntity } from './request-log.entity';
import { ResponseLogEntity } from './response-log.entity';
import { LogRepository } from './log.repository';

import type { HttpLogEntity } from './http-log.entity';
import type { LogRepository } from './log.repository';
export class LogService {
constructor(private readonly logRepository: LogRepository) {}

public async saveRequestLog(log: RequestLogEntity): Promise<void> {
try {
await this.logRepository.insertRequestLog(log);
} catch (error) {
if (error instanceof DatabaseQueryError) {
throw error;
}
throw new DatabaseQueryError(error as Error);
}
}

public async saveResponseLog(log: ResponseLogEntity): Promise<void> {
public async saveHttpLog(log: HttpLogEntity): Promise<void> {
try {
await this.logRepository.insertResponseLog(log);
await this.logRepository.insertHttpLog(log);
} catch (error) {
if (error instanceof DatabaseQueryError) {
throw error;
Expand Down
15 changes: 0 additions & 15 deletions backend/proxy-server/src/domain/log/request-log.entity.ts

This file was deleted.

4 changes: 2 additions & 2 deletions backend/proxy-server/src/domain/project/project.entity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProjectRow } from '../../database/query/project.repository.mysql';
import type { ProjectRow } from '../../database/query/project.repository.mysql';

interface Project extends ProjectRow {}
type Project = ProjectRow;

export class ProjectEntity {
readonly ip: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ProjectEntity } from './project.entity';
import type { ProjectEntity } from './project.entity';

export interface ProjectRepository {
findIpByDomain(domain: string): Promise<ProjectEntity>;
Expand Down
2 changes: 1 addition & 1 deletion backend/proxy-server/src/domain/project/project.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ProjectRepository } from './project.repository';
import type { ProjectRepository } from './project.repository';

export class ProjectService {
constructor(private readonly projectRepository: ProjectRepository) {}
Expand Down
4 changes: 2 additions & 2 deletions backend/proxy-server/src/server/error.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import type { FastifyLogger } from '../common/logger/fastify.logger';
import { ProxyError } from '../common/core/proxy.error';
import { isProxyError } from '../common/core/proxy-error.type.guard';
import type { IncomingHttpHeaders } from 'node:http';
import { ErrorLogRepository } from '../common/logger/error-log.repository';
import { ErrorLog } from '../common/logger/logger.interface';
import type { ErrorLogRepository } from '../common/logger/error-log.repository';
import type { ErrorLog } from '../common/logger/logger.interface';

interface ProxyErrorHandlerOptions {
logger: FastifyLogger;
Expand Down
33 changes: 7 additions & 26 deletions backend/proxy-server/src/server/proxy-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ import { fastifyConfig } from './config/fastify.config';
import { HOST_HEADER } from '../common/constant/http.constant';
import { ErrorHandler } from './error.handler';
import { FastifyLogger } from '../common/logger/fastify.logger';
import { LogService } from '../domain/log/log.service';
import { RequestLogEntity } from '../domain/log/request-log.entity';
import { ResponseLogEntity } from '../domain/log/response-log.entity';
import { ProjectService } from '../domain/project/project.service';
import type { LogService } from '../domain/log/log.service';
import type { HttpLogEntity } from '../domain/log/http-log.entity';
import type { ProjectService } from '../domain/project/project.service';
import { DatabaseQueryError } from '../common/error/database-query.error';
import { ErrorLog } from '../common/logger/logger.interface';
import { ErrorLogRepository } from '../common/logger/error-log.repository';
import type { ErrorLogRepository } from '../common/logger/error-log.repository';

export class ProxyServer {
private readonly server: FastifyInstance;
Expand Down Expand Up @@ -50,40 +48,23 @@ export class ProxyServer {
}

private initializeHooks(): void {
this.server.addHook('onRequest', (request, reply, done) => {
this.logRequest(request);
done();
});

this.server.addHook('onResponse', (request, reply, done) => {
this.logResponse(request, reply);
done();
});
}

private async logRequest(request: FastifyRequest): Promise<void> {
const requestLog: RequestLogEntity = {
method: request.method,
host: request.host,
path: request.raw.url,
};

this.logger.info(requestLog);

await this.logService.saveRequestLog(requestLog);
}

private async logResponse(request: FastifyRequest, reply: FastifyReply): Promise<void> {
const responseLog: ResponseLogEntity = {
const httpLog: HttpLogEntity = {
method: request.method,
host: request.host,
path: request.raw.url,
statusCode: reply.statusCode,
responseTime: reply.elapsedTime,
};

this.logger.info(responseLog);
await this.logService.saveResponseLog(responseLog);
this.logger.info(httpLog);
await this.logService.saveHttpLog(httpLog);
}

private initializeErrorHandler(): void {
Expand Down
Loading

0 comments on commit 7175a69

Please sign in to comment.