From 7a0f792fdca96d58459e794eee530db2aeff0df8 Mon Sep 17 00:00:00 2001 From: mjkhan21 Date: Mon, 26 Feb 2024 14:52:34 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cokr/xit/base/syslog/ServiceCall.java | 20 ++++++ .../java/cokr/xit/base/syslog/ServiceLog.java | 31 +++++++-- .../xit/base/syslog/dao/LoggingMapper.java | 8 +++ .../base/syslog/service/bean/LogFilter.java | 63 ++++++++++++++++++- .../base/syslog/service/bean/LoggingBean.java | 13 +++- 5 files changed, 126 insertions(+), 9 deletions(-) diff --git a/src/main/java/cokr/xit/base/syslog/ServiceCall.java b/src/main/java/cokr/xit/base/syslog/ServiceCall.java index c2a506e..0cf811f 100644 --- a/src/main/java/cokr/xit/base/syslog/ServiceCall.java +++ b/src/main/java/cokr/xit/base/syslog/ServiceCall.java @@ -8,9 +8,15 @@ import cokr.xit.foundation.Access; import cokr.xit.foundation.Assert; import cokr.xit.foundation.UserInfo; +/**서비스 요청 객체 + * @author mjkhan + */ public class ServiceCall { private static final ThreadLocal cache = new ThreadLocal<>(); + /**현재 스레드의 서비스 요청 객체를 반환한다. + * @return 현재 스레드의 서비스 요청 객체 + */ public static final ServiceCall get() { ServiceCall call = cache.get(); if (call == null) { @@ -21,6 +27,9 @@ public class ServiceCall { return call; } + /**현재 스레드의 서비스 요청 중 컨트롤러에서 생성한 로그를 반환한다. + * @return ServiceLog + */ public static final ServiceLog controllerLog() { ServiceCall call = get(); @@ -31,16 +40,27 @@ public class ServiceCall { return !Assert.isEmpty(url) ? log : null; } + /**현재 스레드의 서비스 요청이 컨트롤러에서 시작한 것인지 반환한다. + * @return 서비스 요청의 컨트롤러 시작 여부 + * + */ public static final boolean controllerStarted() { return controllerLog() != null; } + /**주어진 ServiceLog를 현재 스레드의 서비스 요청에 추가한다. + * @param log ServiceLog + */ public static final void set(ServiceLog log) { if (log == null) return; get().add(log); } + /**현재 스레드의 서비스 요청을 비우고 제거한다. + */ public static final void remove() { ServiceCall call = cache.get(); if (call != null) { diff --git a/src/main/java/cokr/xit/base/syslog/ServiceLog.java b/src/main/java/cokr/xit/base/syslog/ServiceLog.java index 2356221..ddbc80f 100644 --- a/src/main/java/cokr/xit/base/syslog/ServiceLog.java +++ b/src/main/java/cokr/xit/base/syslog/ServiceLog.java @@ -22,23 +22,33 @@ public class ServiceLog { private static final Config conf; static { - try (InputStream input = new ClassPathResource("conf/xit-syslog.conf").getInputStream();) { + try (InputStream input = new ClassPathResource("xit-syslog.conf").getInputStream();) { conf = new JSON().parse(input, Config.class); } catch (Exception e) { throw Assert.runtimeException(e); } } + /**시스템 로그 설정을 반영한다. + * @return 시스템 로그 설정 + */ public static final Config config() { return conf; } - public static final String - LOG_INOUT = "log-inout", - DOWNLOAD = "download", - WEB = "web", - SERVICE = "service"; + /** 로그유형 - 로그인/아웃 */ + public static final String LOG_INOUT = "log-inout"; + /** 로그유형 - 다운로드 */ + public static final String DOWNLOAD = "download"; + /** 로그유형 - 컨트롤러 */ + public static final String WEB = "web"; + /** 로그유형 - 서비스 */ + public static final String SERVICE = "service"; + /**joinPoint에서 ServiceLog를 생성하여 반환한다. + * @param joinPoint JoinPoint + * @return ServiceLog + */ public static ServiceLog create(JoinPoint joinPoint) { ServiceLog log = new ServiceLog(); @@ -326,6 +336,9 @@ public class ServiceLog { ); } + /**서비스 로그 설정. 설정 정보는 xit-syslog.conf 파일에서 읽어들인다. + * @author mjkhan + */ public static class Config { private Exclude exclude; private List personalFields; @@ -359,6 +372,9 @@ public class ServiceLog { } } + /**로그 대상 제외 설정 + * @author mjkhan + */ public static class Exclude { private Set classes, @@ -393,6 +409,9 @@ public class ServiceLog { } } + /**개인정보 필드 설정 + * @author mjkhan + */ public static class PersonalField { private String name, diff --git a/src/main/java/cokr/xit/base/syslog/dao/LoggingMapper.java b/src/main/java/cokr/xit/base/syslog/dao/LoggingMapper.java index 63e8216..5fc746d 100644 --- a/src/main/java/cokr/xit/base/syslog/dao/LoggingMapper.java +++ b/src/main/java/cokr/xit/base/syslog/dao/LoggingMapper.java @@ -10,8 +10,16 @@ import cokr.xit.foundation.component.AbstractMapper; */ @Mapper("loggingMapper") public interface LoggingMapper extends AbstractMapper { + /**서비스 로그를 등록한다. + * @param log 서비스 로그 + * @return 저장된 정보수 + */ int insertLog(ServiceLog log); + /**서비스 로그를 등록한다. + * @param log 서비스 로그 + * @return 저장된 정보수 + */ default int insertLogs(Iterable logs) { if (isEmpty(logs)) return 0; diff --git a/src/main/java/cokr/xit/base/syslog/service/bean/LogFilter.java b/src/main/java/cokr/xit/base/syslog/service/bean/LogFilter.java index 5b26c2b..fdbc0bf 100644 --- a/src/main/java/cokr/xit/base/syslog/service/bean/LogFilter.java +++ b/src/main/java/cokr/xit/base/syslog/service/bean/LogFilter.java @@ -13,18 +13,33 @@ import cokr.xit.base.syslog.ServiceLog; import cokr.xit.foundation.AbstractComponent; import cokr.xit.foundation.data.DataObject; +/**서비스 로그 필터. + * 서비스 로그의 저장여부를 반환하고, 필요할 경우 서비스 로그를 수정한다. + * @author mjkhan + */ public class LogFilter extends AbstractComponent { private PersonalInfo personalInfo = new PersonalInfo(); - public boolean filter(ServiceLog svcLog) { + /**서비스 로그에 필터를 적용, 저장여부를 반환한다. + * 서비스 로그를 저장할 경우, 필요에 따라 서비스 로그의 필드를 수정한다. + * @param log 서비스 로그. + * @return 서비스 로그 저장여부 + *
  • 저장할 경우 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ + public boolean filter(ServiceLog log) { for (Predicate filter: getFilters()) { - if (!filter.test(svcLog)) + if (!filter.test(log)) return false; } return true; } + /**서비스 로그 필터를 반환한다. + * @return 서비스 로그 필터 + */ protected List> getFilters() { ArrayList> filters = new ArrayList<>(); @@ -36,6 +51,13 @@ public class LogFilter extends AbstractComponent { return filters; } + /**인증서비스 중 로그인/아웃일 경우 저장한다. + * @param log 서비스 로그 + * @return 서비스 로그 저장여부 + *
  • 저장할 경우 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ protected boolean authenticationFilter(ServiceLog log) { if (!log.getClassName().contains("AuthenticationService")) return true; @@ -50,6 +72,13 @@ public class LogFilter extends AbstractComponent { } } + /**설정파일의 내용에 따라 필터를 적용한다. + * @param log 서비스 로그 + * @return 서비스 로그 저장여부 + *
  • 저장할 경우 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ protected boolean configuredFilter(ServiceLog log) { String name = log.getClassName(); for (String exclude: ServiceLog.config().getExclude().getClasses()) { @@ -65,6 +94,24 @@ public class LogFilter extends AbstractComponent { return true; } + /**파일 다운로드 서비스에 필터를 적용한다. 다운로드 로그에는 + *
  • 파일이름
  • + *
  • 데이터 갯수
  • + *
  • 파일에 포함된 모든 필드이름
  • + *
  • 파일에 포함된 개인정보 필드이름
  • + *
+ * 등이 포함된다. 위 내용을 추출하기위해 ModelAndView에 + *
  • viewName은 'downloadView' 또는 'xlsView'
  • + *
  • 파일이 사용한 데이터는 'downloadData'
  • + *
  • 파일에 포함된 모든 필드이름은 'dataNames'
  • + *
+ * 로 설정한다. + * @param log 서비스 로그 + * @return 서비스 로그 저장여부 + *
  • 저장할 경우 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ protected boolean downloadFilter(ServiceLog log) { Object returned = log.getReturned(); if (returned instanceof ModelAndView) { @@ -80,6 +127,11 @@ public class LogFilter extends AbstractComponent { return true; } + /**ModelAndView의 'downloadData'로 설정한 데이터에서 + * 데이터 갯수, 포함된 모든 필드이름, 개인정보 필드이름들을 추출한다. + * @param log 서비스 로그 + * @param model ModelAndView의 model + */ protected void setDownloadData(ServiceLog log, Map model) { Object obj = model.get("downloadData"); if (!(obj instanceof List)) return; @@ -103,6 +155,13 @@ public class LogFilter extends AbstractComponent { log.setDataNames(model.get("dataNames")); } + /**커스텀 필터를 정의한다. + * @param log 서비스 로그 + * @return 서비스 로그 저장여부 + *
  • 저장할 경우 true
  • + *
  • 그렇지 않으면 false
  • + *
+ */ protected boolean customFilter(ServiceLog log) { return true; } diff --git a/src/main/java/cokr/xit/base/syslog/service/bean/LoggingBean.java b/src/main/java/cokr/xit/base/syslog/service/bean/LoggingBean.java index 18b244f..a33324e 100644 --- a/src/main/java/cokr/xit/base/syslog/service/bean/LoggingBean.java +++ b/src/main/java/cokr/xit/base/syslog/service/bean/LoggingBean.java @@ -8,15 +8,26 @@ import cokr.xit.base.syslog.ServiceLog; import cokr.xit.base.syslog.dao.LoggingMapper; import cokr.xit.foundation.component.AbstractBean; -@Component("loggingBean") +/**서비스 로깅 빈 + * @author mjkhan + */ +@Component public class LoggingBean extends AbstractBean { @Resource(name = "loggingMapper") private LoggingMapper loggingMapper; + /**서비스 로그를 등록한다. + * @param log 서비스 로그 + * @return 저장된 정보수 + */ public int create(ServiceLog log) { return log != null ? loggingMapper.insertLog(log) : 0; } + /**서비스 로그를 등록한다. + * @param logs 서비스 로그 + * @return 저장된 정보수 + */ public int create(Iterable logs) { return loggingMapper.insertLogs(logs); }