diff --git a/apps/user-service/build.gradle b/apps/user-service/build.gradle index 624067f6..d2ffcb1e 100644 --- a/apps/user-service/build.gradle +++ b/apps/user-service/build.gradle @@ -54,6 +54,11 @@ dependencies { implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.22.1' implementation 'org.apache.logging.log4j:log4j-jul:2.22.1' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml' + implementation 'org.apache.logging.log4j:log4j-layout-template-json:2.22.1' + + implementation 'org.apache.httpcomponents:httpclient:4.5.14' + implementation 'org.apache.httpcomponents:httpcore:4.4.16' + implementation 'pl.tkowalcz.tjahzi:log4j2-appender-nodep:0.9.17' // 비동기 로깅 implementation 'com.lmax:disruptor:3.4.4' diff --git a/apps/user-service/src/main/java/site/icebang/global/filter/LoggingFilter.java b/apps/user-service/src/main/java/site/icebang/global/filter/LoggingFilter.java index e89f2d80..0a782839 100644 --- a/apps/user-service/src/main/java/site/icebang/global/filter/LoggingFilter.java +++ b/apps/user-service/src/main/java/site/icebang/global/filter/LoggingFilter.java @@ -30,7 +30,8 @@ protected void doFilterInternal( traceId = UUID.randomUUID().toString(); } - MDC.put("traceId", traceId.substring(0, 8)); + // MDC.put("traceId", traceId.substring(0, 8)); + MDC.put("traceId", traceId); // ⭐️ 요청 객체에 attribute로 traceId를 저장하여 컨트롤러 등에서 사용할 수 있게 함 request.setAttribute("X-Request-ID", traceId); diff --git a/apps/user-service/src/main/resources/application-test-integration.yml b/apps/user-service/src/main/resources/application-test-integration.yml index 0ed34f36..526cf151 100644 --- a/apps/user-service/src/main/resources/application-test-integration.yml +++ b/apps/user-service/src/main/resources/application-test-integration.yml @@ -39,4 +39,4 @@ mybatis: map-underscore-to-camel-case: true logging: - config: classpath:log4j2-develop.yml \ No newline at end of file + config: classpath:log4j2-test-unit.yml \ No newline at end of file diff --git a/apps/user-service/src/main/resources/log4j2-develop.yml b/apps/user-service/src/main/resources/log4j2-develop.yml index f900c3b1..5303e6ff 100644 --- a/apps/user-service/src/main/resources/log4j2-develop.yml +++ b/apps/user-service/src/main/resources/log4j2-develop.yml @@ -1,133 +1,50 @@ Configuration: + status: DEBUG name: develop properties: property: - - name: "log-path" - value: "./logs" - - name: "charset-UTF-8" - value: "UTF-8" - # 통일된 콘솔 패턴 - 모든 로그에 RequestId 포함 - - name: "console-layout-pattern" - value: "%highlight{[%-5level]} [%X{traceId}] %d{MM-dd HH:mm:ss} [%t] %n %msg%n%n" - # 파일용 상세 패턴 - RequestId 포함 - - name: "file-layout-pattern" - value: "[%X{traceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" - # 로그 파일 경로들 - - name: "info-log" - value: ${log-path}/user-service/info.log - - name: "error-log" - value: ${log-path}/user-service/error.log - - name: "auth-log" - value: ${log-path}/user-service/auth.log - - name: "json-log" - value: ${log-path}/user-service/json-info.log + - name: "app-name" + value: "${env:APP_NAME:-user-service-app}" - # [Appenders] 로그 기록방식 정의 Appenders: - # 통일된 콘솔 출력 + # 콘솔 appender Console: name: console-appender target: SYSTEM_OUT PatternLayout: - pattern: ${console-layout-pattern} + pattern: "[%-5level] [%X{traceId}] %d{MM-dd HH:mm:ss} [%t] %msg%n" - # 롤링 파일 로그 - RollingFile: - name: rolling-file-appender - fileName: ${log-path}/rolling-file.log - filePattern: "logs/archive/rolling-file.log.%d{yyyy-MM-dd-hh-mm}_%i.gz" + # Tjahzi Loki Appender (올바른 문법) + Loki: + name: loki-appender + host: localhost + port: 3100 PatternLayout: - charset: ${charset-UTF-8} - pattern: ${file-layout-pattern} - Policies: - SizeBasedTriggeringPolicy: - size: "200KB" - TimeBasedTriggeringPolicy: - interval: "1" - DefaultRollOverStrategy: - max: "30" - fileIndex: "max" + pattern: "[%-5level] [%X{traceId}] %d{MM-dd HH:mm:ss} [%t] %msg%n" + Label: + - name: "app" + value: "${app-name}" # 고정 값 + - name: "service" + value: "user-service" # 고정 값 + - name: "traceId" + value: "${ctx:traceId}" # MDC에서 가져올 값만 넣음 - # 파일 로그들 - File: - - name: file-info-appender - fileName: ${info-log} - PatternLayout: - pattern: ${file-layout-pattern} - - name: file-error-appender - fileName: ${error-log} - PatternLayout: - pattern: ${file-layout-pattern} - - name: file-auth-appender - fileName: ${auth-log} - PatternLayout: - pattern: ${file-layout-pattern} - - name: file-json-info-appender - fileName: ${json-log} - PatternLayout: - pattern: ${file-layout-pattern} - - # [Loggers] 로그 출력 범위를 정의 Loggers: - # [Loggers - Root] 모든 로그를 기록하는 최상위 로그를 정의 Root: - level: OFF + level: INFO AppenderRef: - ref: console-appender - - ref: rolling-file-appender - # [Loggers - Loggers] 특정 패키지나 클래스에 대한 로그를 정의 Logger: - # 1. Spring Framework 로그 - - name: org.springframework - additivity: "false" - level: DEBUG - AppenderRef: - - ref: console-appender - - ref: file-info-appender - - ref: file-error-appender - - # 2. 애플리케이션 로그 + # 애플리케이션 로그만 Loki로 전송 (additivity 문법 수정) - name: site.icebang - additivity: "false" - level: TRACE + additivity: false + level: INFO AppenderRef: - ref: console-appender - - ref: file-info-appender - - ref: file-error-appender + - ref: loki-appender - # 3. HikariCP 로그 비활성화 + # HikariCP 로그 비활성화 - name: com.zaxxer.hikari - level: OFF - - # 4. Spring Security 로그 - 인증/인가 추적에 중요 - - name: org.springframework.security - level: DEBUG - additivity: "false" - AppenderRef: - - ref: console-appender - - ref: file-auth-appender - - # 5. 웹 요청 로그 - 요청 처리 과정 추적 - - name: org.springframework.web - level: DEBUG - additivity: "false" - AppenderRef: - - ref: console-appender - - ref: file-info-appender - - # 6. 트랜잭션 로그 - DB 작업 추적 - - name: org.springframework.transaction - level: DEBUG - additivity: "false" - AppenderRef: - - ref: console-appender - - ref: file-info-appender - - - name: site.icebang.domain.auth.mapper - level: DEBUG - additivity: "false" - AppenderRef: - - ref: console-appender - - ref: file-info-appender \ No newline at end of file + level: OFF \ No newline at end of file diff --git a/apps/user-service/src/main/resources/sql/01-schema.sql b/apps/user-service/src/main/resources/sql/01-schema.sql index 2f1d4655..31242c33 100644 --- a/apps/user-service/src/main/resources/sql/01-schema.sql +++ b/apps/user-service/src/main/resources/sql/01-schema.sql @@ -308,37 +308,28 @@ ALTER TABLE `department` -- v0.4 -- 기존 execution_log 테이블 수정 -ALTER TABLE `execution_log` --- 새로운 컬럼 추가 - ADD COLUMN `run_id` bigint unsigned NULL COMMENT 'workflow_run_id, job_run_id, task_run_id' AFTER `source_id`, -ADD COLUMN `status` varchar(20) NULL COMMENT 'success, failed, warning, running' AFTER `log_level`, -ADD COLUMN `duration_ms` int unsigned NULL COMMENT '실행 시간 (밀리초)' AFTER `executed_at`, -ADD COLUMN `error_code` varchar(50) NULL COMMENT '에러 코드' AFTER `duration_ms`, - --- 예비 컬럼 (향후 확장용) -ADD COLUMN `reserved1` varchar(100) NULL COMMENT '예비 컬럼 1', -ADD COLUMN `reserved2` varchar(100) NULL COMMENT '예비 컬럼 2', -ADD COLUMN `reserved3` int NULL COMMENT '예비 컬럼 3', -ADD COLUMN `reserved4` json NULL COMMENT '예비 컬럼 4', -ADD COLUMN `reserved5` timestamp NULL COMMENT '예비 컬럼 5'; - --- 기존 컬럼 수정 -ALTER TABLE `execution_log` - MODIFY COLUMN `log_message` varchar(500) NOT NULL COMMENT '요약 메시지', - MODIFY COLUMN `executed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '실행 시간'; - --- 기존 불필요한 컬럼 제거 (있다면) -ALTER TABLE `execution_log` -DROP COLUMN IF EXISTS `config_snapshot`; - --- 새로운 인덱스 추가 -ALTER TABLE `execution_log` - ADD INDEX `idx_run_id` (`run_id`), -ADD INDEX `idx_log_level_status` (`log_level`, `status`), -ADD INDEX `idx_error_code` (`error_code`), -ADD INDEX `idx_duration` (`duration_ms`); - --- 기존 인덱스 수정 (복합 인덱스 최적화) -ALTER TABLE `execution_log` -DROP INDEX IF EXISTS `idx_source_id_type`, -ADD INDEX `idx_execution_type_source` (`execution_type`, `source_id`); \ No newline at end of file +-- 컬럼 추가 (한 번에 하나씩) +-- 컬럼 추가 +ALTER TABLE execution_log ADD COLUMN run_id BIGINT NULL; +ALTER TABLE execution_log ADD COLUMN status VARCHAR(20) NULL; +ALTER TABLE execution_log ADD COLUMN duration_ms INT NULL; +ALTER TABLE execution_log ADD COLUMN error_code VARCHAR(50) NULL; +ALTER TABLE execution_log ADD COLUMN reserved1 VARCHAR(100) NULL; +ALTER TABLE execution_log ADD COLUMN reserved2 VARCHAR(100) NULL; +ALTER TABLE execution_log ADD COLUMN reserved3 INT NULL; +ALTER TABLE execution_log ADD COLUMN reserved4 json NULL; +ALTER TABLE execution_log ADD COLUMN reserved5 TIMESTAMP NULL; + +-- 컬럼 수정 +ALTER TABLE execution_log MODIFY COLUMN log_message VARCHAR(500) NOT NULL; +ALTER TABLE execution_log MODIFY COLUMN executed_at TIMESTAMP NOT NULL; + +-- 컬럼 삭제 +ALTER TABLE execution_log DROP COLUMN config_snapshot; + +-- 인덱스 생성 (CREATE INDEX 별도) +CREATE INDEX idx_run_id ON execution_log(run_id); +CREATE INDEX idx_log_level_status ON execution_log(log_level, status); +CREATE INDEX idx_error_code ON execution_log(error_code); +CREATE INDEX idx_duration ON execution_log(duration_ms); +CREATE INDEX idx_execution_type_source ON execution_log(execution_type, source_id); diff --git a/docker/local/docker-compose.yml b/docker/local/docker-compose.yml index c0bf14fd..c69ea697 100644 --- a/docker/local/docker-compose.yml +++ b/docker/local/docker-compose.yml @@ -33,5 +33,40 @@ services: depends_on: - mariadb + loki: + image: grafana/loki:2.9.0 + container_name: loki + restart: unless-stopped + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + volumes: + - loki_data:/loki + healthcheck: + test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1"] + interval: 10s + timeout: 5s + retries: 5 + + grafana: + image: grafana/grafana:10.1.0 + container_name: grafana + restart: unless-stopped + environment: + - GF_SECURITY_ADMIN_PASSWORD=admin + ports: + - "3030:3000" + volumes: + - grafana_data:/var/lib/grafana + depends_on: + - loki + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:3000/api/health || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + volumes: - mariadb_data: \ No newline at end of file + mariadb_data: + loki_data: + grafana_data: \ No newline at end of file