로그 조회 추가

master
mjkhan21 6 months ago
parent f01c7d8d24
commit b926330ea1

@ -55,6 +55,12 @@
<version>23.04.01-SNAPSHOT</version> <version>23.04.01-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>cokr.xit.base</groupId>
<artifactId>xit-docs</artifactId>
<version>23.04.01-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -0,0 +1,81 @@
package cokr.xit.base.syslog;
import cokr.xit.foundation.component.QueryRequest;
public class LogQuery extends QueryRequest {
private static final long serialVersionUID = 1L;
private String[]
logTypes,
userIDs,
userAccounts;
private String
userName,
fromDate,
toDate;
public String[] getLogTypes() {
return ifEmpty(logTypes, null);
}
public void setLogTypes(String... logTypes) {
this.logTypes = logTypes;
}
public String[] getUserIDs() {
return ifEmpty(userIDs, null);
}
public void setUserIDs(String... userIDs) {
this.userIDs = userIDs;
}
public String[] getUserAccounts() {
return ifEmpty(userAccounts, null);
}
public void setUserAccounts(String[] userAccounts) {
this.userAccounts = userAccounts;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getFromDate() {
return fromDate;
}
public void setFromDate(String fromDate) {
this.fromDate = fromDate;
}
public String getToDate() {
return toDate;
}
public void setToDate(String toDate) {
this.toDate = toDate;
}
@Override
public String getOrderBy() {
String orderBy = blankIfEmpty(super.getOrderBy());
if (isEmpty(orderBy)) {
if (!isEmpty(logTypes))
orderBy += "LOG_TYPE, ";
if (!isEmpty(userIDs))
orderBy += "USER_ID, ";
if (!isEmpty(userAccounts))
orderBy += "USER_ACNT, ";
if (!isEmpty(userName))
orderBy += "USER_NM, ";
orderBy += "LOG_ID DESC";
}
return orderBy;
}
}

@ -1,15 +1,25 @@
package cokr.xit.base.syslog.dao; package cokr.xit.base.syslog.dao;
import java.util.List;
import org.egovframe.rte.psl.dataaccess.mapper.Mapper; import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
import cokr.xit.base.syslog.LogQuery;
import cokr.xit.base.syslog.ServiceLog; import cokr.xit.base.syslog.ServiceLog;
import cokr.xit.foundation.component.AbstractMapper; import cokr.xit.foundation.component.AbstractMapper;
import cokr.xit.foundation.data.DataObject;
/** DAO /** DAO
* @author mjkhan * @author mjkhan
*/ */
@Mapper("loggingMapper") @Mapper("loggingMapper")
public interface LoggingMapper extends AbstractMapper { public interface LoggingMapper extends AbstractMapper {
/** .
* @param req
* @return
*/
public List<DataObject> getLogs(LogQuery req);
/** . /** .
* @param log * @param log
* @return * @return

@ -1,6 +1,13 @@
package cokr.xit.base.syslog.service; package cokr.xit.base.syslog.service;
import java.util.List;
import cokr.xit.base.syslog.LogQuery;
import cokr.xit.foundation.data.DataObject;
/** /**
* @author mjkhan * @author mjkhan
*/ */
public interface LoggingService {} public interface LoggingService {
List<DataObject> getLogs(LogQuery req);
}

@ -70,7 +70,9 @@ public class LogFilter extends AbstractComponent {
UserInfo current = UserInfo.current(); UserInfo current = UserInfo.current();
if (!current.isAuthenticated()) { if (!current.isAuthenticated()) {
Object[] args = log.getArgs(); Object[] args = log.getArgs();
log.setUserId(current.getId(args.length > 0 ? args[0] : null)); Object arg = args.length > 0 ? args[0] : null;
if (!"onFailure".equals(log.getMethodName()))
log.setUserId(current.getId(arg));
} }
return true; return true;
default: return false; default: return false;

@ -1,12 +1,16 @@
package cokr.xit.base.syslog.service.bean; package cokr.xit.base.syslog.service.bean;
import java.util.List;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import cokr.xit.base.syslog.LogQuery;
import cokr.xit.base.syslog.ServiceLog; import cokr.xit.base.syslog.ServiceLog;
import cokr.xit.base.syslog.dao.LoggingMapper; import cokr.xit.base.syslog.dao.LoggingMapper;
import cokr.xit.foundation.component.AbstractBean; import cokr.xit.foundation.component.AbstractBean;
import cokr.xit.foundation.data.DataObject;
/** /**
* @author mjkhan * @author mjkhan
@ -16,6 +20,14 @@ public class LoggingBean extends AbstractBean {
@Resource(name = "loggingMapper") @Resource(name = "loggingMapper")
private LoggingMapper loggingMapper; private LoggingMapper loggingMapper;
/** .
* @param req
* @return
*/
public List<DataObject> getLogs(LogQuery req) {
return loggingMapper.getLogs(req);
}
/** . /** .
* @param log * @param log
* @return * @return

@ -8,11 +8,13 @@ import org.aspectj.lang.JoinPoint;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import cokr.xit.base.syslog.LogQuery;
import cokr.xit.base.syslog.ServiceCall; import cokr.xit.base.syslog.ServiceCall;
import cokr.xit.base.syslog.ServiceLog; import cokr.xit.base.syslog.ServiceLog;
import cokr.xit.base.syslog.service.LoggingService; import cokr.xit.base.syslog.service.LoggingService;
import cokr.xit.foundation.Access; import cokr.xit.foundation.Access;
import cokr.xit.foundation.component.AspectServiceBean; import cokr.xit.foundation.component.AspectServiceBean;
import cokr.xit.foundation.data.DataObject;
/** /**
* @author mjkhan * @author mjkhan
@ -24,6 +26,11 @@ public class LoggingServiceBean extends AspectServiceBean implements LoggingServ
@Resource(name = "loggingBean") @Resource(name = "loggingBean")
private LoggingBean loggingBean; private LoggingBean loggingBean;
@Override
public List<DataObject> getLogs(LogQuery req) {
return loggingBean.getLogs(req);
}
@Override @Override
public void beforeController(JoinPoint joinPoint) { public void beforeController(JoinPoint joinPoint) {
ServiceLog log = ServiceLog.create(joinPoint); ServiceLog log = ServiceLog.create(joinPoint);

@ -0,0 +1,130 @@
package cokr.xit.base.syslog.web;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import cokr.xit.base.docs.xls.CellDef;
import cokr.xit.base.docs.xls.XLSWriter;
import cokr.xit.base.syslog.LogQuery;
import cokr.xit.base.syslog.service.LoggingService;
import cokr.xit.foundation.data.DataFormat;
import cokr.xit.foundation.data.DataObject;
import cokr.xit.foundation.web.AbstractController;
import cokr.xit.foundation.web.RequestHandlerReader;
@RequestMapping(name = "시스템 로그", value = "/syslog")
public class LoggingController extends AbstractController {
@Resource(name = "loggingService")
private LoggingService loggingService;
@Autowired
private RequestMappingHandlerMapping requestHandlers;
private RequestHandlerReader requestReader = new RequestHandlerReader();
/** (user/user-main) .
* {@link #getUserList(UserQuery) } .
* @return base/user/user-main
*/
@GetMapping(name="시스템 로그 메인", value="/main.do")
public ModelAndView main() {
ModelAndView mav = getLogs(new LogQuery().setPageNum(1));
mav.setViewName("base/syslog/syslog-main");
return mav.addObject("syslogList", toJson(mav.getModel().remove("syslogList")));
}
@GetMapping(name = "시스템 로그 조회", value = "/list.do")
public ModelAndView getLogs(LogQuery req) {
boolean download = !isEmpty(req.getDownload());
if (!download)
setFetchSize(req);
else
req.setPageNum(0).setFetchSize(0);
String
toDate = req.getToDate(),
fromDate = req.getFromDate();
if (isEmpty(toDate)) {
Date date = new Date();
toDate = DataFormat.yyyy_mm_dd(date);
req.setToDate(toDate.replace("-", ""));
if (isEmpty(fromDate)) {
fromDate = DataFormat.yyyy_mm_dd(new Date(date.getTime() - 1000L * 60L * 60L * 24L * 30L));
req.setFromDate(fromDate.replace("-", ""));
}
}
List<DataObject>
list = loggingService.getLogs(req),
web = list.stream()
.filter(row -> "web".equals(row.get("LOG_TYPE")))
.toList();
if (!list.isEmpty()) {
Map<String, DataObject> reqs = requestReader.asTree(requestHandlers).getIndex();
list.forEach(row -> {
Object obj = row.get("REG_DT");
row.set("REG_DT", DataFormat.yyyy_mm_dd_hh_mm_ss(obj));
obj = row.get("URL");
if (isEmpty(obj)) return;
DataObject reqInfo = reqs.get(obj);
row.set("DSCRP", reqInfo != null ? reqInfo.get("name") : "");
});
}
if (!download)
return setCollectionInfo(
new ModelAndView("jsonView")
.addObject("fromDate", fromDate)
.addObject("toDate", toDate),
list,
"syslog"
);
else
return download(list);
}
private ModelAndView download(List<DataObject> list) {
List<CellDef> cellDefs = List.of(
new CellDef().setLabel("계정").setField("USER_ACNT"),
new CellDef().setLabel("사용자이름").setField("USER_NM"),
new CellDef().setLabel("IP 주소").setField("IP_ADDR"),
new CellDef().setLabel("로그유형").setField("LOG_TYPE_NM"),
new CellDef().setLabel("접속일시").setField("REG_DT"),
new CellDef().setLabel("URL").setField("URL"),
new CellDef().setLabel("설명").setField("DSCRP"),
new CellDef().setLabel("파일이름").setField("FILE_NM"),
new CellDef().setLabel("민감정보").setField("PSNL_INFO")
);
XLSWriter xlsx = new XLSWriter()
.worksheet(0)
.trackWidth(IntStream.range(0, cellDefs.size()).toArray())
.cell(0, 0)
.value("시스템 로그 목록").merge(0, cellDefs.size() - 1)
.cell(2, 0)
.rowValues(CellDef.header(cellDefs, null))
.cell(3, 0)
.values(
list,
CellDef.values(cellDefs)
)
.autoWidth();
return new ModelAndView("downloadView")
.addObject("download",
xlsx.getDownloadable()
.setFilename("시스템 로그 목록.xlsx")
);
}
}

@ -16,6 +16,46 @@
<result property="ipAddress" column="IP_ADDR"/> <!-- 등록 일시 --> <result property="ipAddress" column="IP_ADDR"/> <!-- 등록 일시 -->
</resultMap> </resultMap>
<select id="getLogs" parameterType="map" resultType="dataobject">/* 시스템 로그 조회(loggingMapper.getLogs) */
<include refid="utility.paging-prefix" />
SELECT LOG_ID
, A.LOG_TYPE
, CASE MTD_NM WHEN 'onLogin' THEN '로그인'
WHEN 'onLogout' THEN '로그아웃'
WHEN 'onFailure' THEN '로그인 실패'
ELSE LOG_TYPE_NM
END LOG_TYPE_NM
, URL
, CLS_NM
, MTD_NM
, NULL DSCRP
, FILE_NM
, DATA_CNT
, DATA_NM
, PSNL_INFO
, A.USER_ID
, USER_ACNT
, USER_NM
, NSTT_CD
, IP_ADDR
, A.REG_DT
FROM TB_SYS_LOG A LEFT OUTER JOIN
TB_USER B ON A.USER_ID = B.USER_ID,
(SELECT 'log-inout' LOG_TYPE, '로그인아웃' LOG_TYPE_NM FROM DUAL UNION
SELECT 'download' LOG_TYPE, '다운로드' LOG_TYPE_NM FROM DUAL UNION
SELECT 'service' LOG_TYPE, '서비스' LOG_TYPE_NM FROM DUAL UNION
SELECT 'web' LOG_TYPE, '웹' LOG_TYPE_NM FROM DUAL
) C
<where><if test="fromDate != null"> AND LOG_ID >= CONCAT(#{fromDate}, LPAD(0, 16, '0'))</if>
<if test="toDate != null"> AND LOG_ID &lt;= CONCAT(#{toDate}, LPAD(9, 16, '9'))</if>
<if test="logTypes != null"> AND A.LOG_TYPE IN (<foreach collection="logTypes" item="logType" separator=",">#{logType}</foreach>)</if>
<if test="userIDs != null"> AND USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)</if>
<if test="userAccounts != null"> AND USER_ACNT IN (<foreach collection="userAccounts" item="userAccount" separator=",">#{userAccount}</foreach>)</if>
<if test="userName != null"> AND USER_NM LIKE CONCAT('%', #{userName}, '%')</if>
AND A.LOG_TYPE = C.LOG_TYPE</where>
<include refid="utility.sortBy" />
<include refid="utility.paging-suffix" /></select>
<insert id="insertLog" parameterType="cokr.xit.base.syslog.ServiceLog">/* 시스템 로그 등록(loggingMapper.insertLog) */ <insert id="insertLog" parameterType="cokr.xit.base.syslog.ServiceLog">/* 시스템 로그 등록(loggingMapper.insertLog) */
<selectKey keyProperty="id" keyColumn="NEW_ID" resultType="string" order="BEFORE"> <selectKey keyProperty="id" keyColumn="NEW_ID" resultType="string" order="BEFORE">
SELECT CONCAT(TODAY, LPAD(NVL(SUBSTR(MAX(LOG_ID), 9) + 1, 1), 16, '0')) NEW_ID SELECT CONCAT(TODAY, LPAD(NVL(SUBSTR(MAX(LOG_ID), 9) + 1, 1), 16, '0')) NEW_ID

Loading…
Cancel
Save