e9fbffa87e
- 오류 발생 시 AdapterErrorMessageHandler가 처리하여도 400 오류로 출력되도록 수정 - 업무 오류 발생 시 AdapterErrorMessageHandler가 처리하여도 에러 RECEAIINA001 출력
291 lines
11 KiB
Java
291 lines
11 KiB
Java
package com.eactive.eai.common.logger;
|
|
|
|
|
|
import java.util.List;
|
|
import java.util.Properties;
|
|
|
|
import com.eactive.eai.adapter.ElinkAdapter;
|
|
import com.eactive.eai.adapter.ElinkAdapterFactory;
|
|
import com.eactive.eai.common.dao.DAOFactory;
|
|
import com.eactive.eai.common.message.EAIMessage;
|
|
import com.eactive.eai.common.message.EAIMessageKeys;
|
|
import com.eactive.eai.common.property.PropManager;
|
|
import com.eactive.eai.common.util.ApplicationContextProvider;
|
|
import com.eactive.eai.common.util.Logger;
|
|
import com.eactive.eai.common.util.MessageUtil;
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
|
|
|
/**
|
|
* 1. 기능 : EAI에서 처리되는 모든 On-Line 거래를 데이터베이스에 로깅하기 위한 운영관리 Logger Sender
|
|
* 2. 처리 개요 :
|
|
* - Processor에서 받은 거래로그 정보를 저장
|
|
* 3. 주의사항
|
|
*
|
|
* @author :
|
|
* @version : v 3.0.0
|
|
* @see :
|
|
* @since :JDK v1.5.0
|
|
*/
|
|
public class DBLogTransactionLogger implements TransactionLogger {
|
|
// 거래 로그 Count
|
|
private int logCount;
|
|
|
|
// 에러 로그 Count
|
|
private int errCount;
|
|
|
|
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
|
|
|
/**
|
|
* 1. 기능 : EAI 거래 로그 Count를 반환
|
|
* 2. 처리 개요 :
|
|
* - EAI 거래 로그 Count를 반환한다.
|
|
* 3. 주의사항
|
|
*
|
|
* @return int 거래 로그 Count
|
|
**/
|
|
public int logCount() {
|
|
return logCount;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : EAI 에러 로그 Count를 반환
|
|
* 2. 처리 개요 :
|
|
* - EAI 거래 에러 Count를 반환한다.
|
|
* 3. 주의사항
|
|
*
|
|
* @return int 에러 로그 Count
|
|
**/
|
|
public int errCount() {
|
|
return errCount;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 거래 로그 및 에러 로그 초기화
|
|
* 2. 처리 개요 :
|
|
* - 거래 및 에러 로그를 초기화 한다.
|
|
* 3. 주의사항
|
|
*
|
|
**/
|
|
public void resetCount() {
|
|
logCount = 0;
|
|
errCount = 0;
|
|
}
|
|
|
|
private byte[] callAdapter(String adapterGroupName, Properties prop, Object message)
|
|
throws java.lang.Exception {
|
|
byte[] resBytes;
|
|
try {
|
|
|
|
ElinkAdapterFactory factory = ElinkAdapterFactory.newInstance();
|
|
ElinkAdapter adapter = null;
|
|
adapter = factory.getElinkAdapter(com.eactive.eai.adapter.Keys.TYPE_NET2);
|
|
|
|
if(prop==null) {
|
|
prop = new Properties();
|
|
}
|
|
if(prop.getProperty("ADAPTER_GROUP_NAME") == null) {
|
|
prop.setProperty("ADAPTER_GROUP_NAME", adapterGroupName);
|
|
}
|
|
resBytes = (byte[])adapter.callService(adapterGroupName, prop, message, prop);
|
|
} catch(Exception e) {
|
|
logger.error("callSocketAdapter error", e);
|
|
//throw new Exception(ExceptionUtil.getErrorCode(e, SOCK_CONTROL_ERROR));
|
|
throw e;
|
|
}
|
|
return resBytes;
|
|
}
|
|
|
|
private byte[] getItsmSMSMesage(EAIMessage eaimessage) {
|
|
byte[] itsmSMSMessage = null;
|
|
StringBuilder sb = new StringBuilder();
|
|
try {
|
|
// make message from EAIMessage
|
|
sb.append(eaimessage.getEAISvcCd());
|
|
itsmSMSMessage = sb.toString().getBytes();
|
|
}
|
|
catch(Exception e) {
|
|
itsmSMSMessage = sb.toString().getBytes();
|
|
}
|
|
return itsmSMSMessage;
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 로깅 정보를 로그 Queue로 전달
|
|
* 2. 처리 개요 :
|
|
* - 로깅 정보를 로그 Queue로 전달
|
|
* - 실시간 거래 정보 통계를 위해 EAIServiceMonitor로 전달
|
|
* 3. 주의사항
|
|
*
|
|
* @param message EAIMessage
|
|
* @param prop logging 관련 Properties
|
|
* @exception EAILogException
|
|
**/
|
|
public void log(EAIMessage message, Properties prop) throws EAILogException {
|
|
++logCount;
|
|
int svcLogLvl = message.getSvcLogLvl();
|
|
String svcTsmtUsgTp = message.getSvcTsmtUsgTp();
|
|
int logPssSno = message.getLogPssSno();
|
|
boolean isLogging = false;
|
|
|
|
String guidLogPrefix = "DBLogTransactionLogger] GUID["
|
|
+ message.getMapper().getGuid(message.getStandardMessage())
|
|
+ "] UUID[" + message.getSvcOgNo() + "] ";
|
|
|
|
try {
|
|
// Direct DB Logging
|
|
String logType = "DB";
|
|
String setLogType = PropManager.getInstance().getProperty("LOG_TYPE");
|
|
if(setLogType != null) {
|
|
logType = setLogType;
|
|
}
|
|
|
|
if("DB".equals(logType)) {
|
|
insertLog(message, prop);
|
|
}
|
|
else {
|
|
EAIFileLogger.getInstance().setLog(message, prop);
|
|
}
|
|
//---------------------------------------------------->
|
|
// ITSM ERROR Log 전송
|
|
// 템플릿만 남겨두고, 나머지는 사이트에 맞게 수정 필요함.
|
|
//---------------------------------------------------->
|
|
boolean itsmEnabled = false;
|
|
if((itsmEnabled) && !MessageUtil.checkRspErrCd(message.getLogRspErrCd())) {
|
|
if(logger.isDebug()) {
|
|
logger.debug(guidLogPrefix + " ITSM Error Message Notify! ");
|
|
}
|
|
if(( EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTp) && logPssSno == 400 ) ||
|
|
( EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && (logPssSno == 200 || logPssSno == 400))) {
|
|
String itsmErrorAdapterName = "";
|
|
itsmErrorAdapterName = PropManager.getInstance().getProperty("ITSM_CONFIG","ADAPTER_GROUP_NAME_ERROR"); /* Properties 추가 및 어뎁터 등록 */
|
|
if (logger.isDebug()) {
|
|
logger.debug(guidLogPrefix + " ITSM ERROR Send Message Adapter Name[" + itsmErrorAdapterName + "]");
|
|
}
|
|
|
|
if(itsmErrorAdapterName != null && itsmErrorAdapterName.length() > 0) {
|
|
byte[] itsmSMSMessage = getItsmSMSMesage(message); /* ITSM 전송 메시지 포맷 결정 */
|
|
Properties itsmProp = new Properties();
|
|
callAdapter(itsmErrorAdapterName, itsmProp, itsmSMSMessage);
|
|
}
|
|
}
|
|
}
|
|
} catch(Exception e) {
|
|
if (logger.isError()) logger.error(guidLogPrefix + " ITSM ERROR Send ERROR " + e.getMessage(),e);
|
|
errCount++;
|
|
//throw new EAILogException(ExceptionUtil.getErrorCode(e, "RECEAICLG005"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 1. 기능 : 여러 건의 로깅 정보를 한 트랜잭션으로 적재 (COMMIT 1회)
|
|
* 2. 처리 개요 :
|
|
* - log()의 건별 처리와 달리 COMMIT 횟수를 배치 크기만큼 줄인다.
|
|
* - LOG_TYPE 판정 규칙은 log()과 동일하게 유지한다.
|
|
* 3. 주의사항
|
|
* - 실시간 모니터링(EAIServiceMonitor) 전달은 발행측 EAILogSender.send()에서
|
|
* 이미 처리하므로 여기서는 다루지 않는다.
|
|
*
|
|
* @param items {EAIMessage, Properties} 쌍의 목록
|
|
**/
|
|
public void logBatch(List<Object[]> items) {
|
|
if (items == null || items.isEmpty()) return;
|
|
logCount += items.size();
|
|
try {
|
|
insertLogBatch(items);
|
|
} catch (Exception e) {
|
|
errCount++;
|
|
if (logger.isError()) logger.error("DBLogTransactionLogger] logBatch ERROR. - " + e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
public static void insertLogBatch(List<Object[]> items) {
|
|
if (items == null || items.isEmpty()) return;
|
|
|
|
// Direct DB Logging - 판정 규칙은 log()과 동일
|
|
String logType = "DB";
|
|
String setLogType = PropManager.getInstance().getProperty("LOG_TYPE");
|
|
if (setLogType != null) {
|
|
logType = setLogType;
|
|
}
|
|
|
|
if (!"DB".equals(logType) || !EAIDBLogControl.isEnable()) {
|
|
for (Object[] item : items) {
|
|
writeFileLog((EAIMessage) item[0], (Properties) item[1]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
EAILogBatchWriter writer = ApplicationContextProvider.getContext().getBean(EAILogBatchWriter.class);
|
|
try {
|
|
writer.writeBatch(items);
|
|
} catch (Exception be) {
|
|
// 배치는 한 건만 실패해도 트랜잭션 전체가 롤백된다.
|
|
// 정상 건까지 유실되지 않도록 건별 독립 트랜잭션으로 재시도한다.
|
|
if (logger.isError()) {
|
|
logger.error("DBLogTransactionLogger] insertLogBatch failed, retry one by one. size=" + items.size(), be);
|
|
}
|
|
for (Object[] item : items) {
|
|
EAIMessage eaiMessage = (EAIMessage) item[0];
|
|
Properties prop = (Properties) item[1];
|
|
try {
|
|
writer.writeOne(eaiMessage, prop);
|
|
} catch (Exception e) {
|
|
String message = e.getMessage();
|
|
// DB Connection Error일 경우에만 DB 로깅을 중단한다.
|
|
if ("ConnectionError".equals(message) || StringUtils.contains(message, "JDBCConnectionException")
|
|
|| StringUtils.contains(message, "Unable to acquire JDBC Connection")) {
|
|
EAIDBLogControl.setEnable(false);
|
|
}
|
|
if (logger.isError()) {
|
|
logger.error("DBLogTransactionLogger] insertLogBatch single retry failed. - " + message, e);
|
|
}
|
|
writeFileLog(eaiMessage, prop);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void writeFileLog(EAIMessage eaiMessage, Properties prop) {
|
|
try {
|
|
EAIFileLogger.getInstance().setLog(eaiMessage, prop);
|
|
} catch (Exception fe) {
|
|
if (logger.isError()) logger.error("DBLogTransactionLogger] file log failed. - " + fe.getMessage(), fe);
|
|
}
|
|
}
|
|
|
|
public static void insertLog(EAIMessage eaiMessage, Properties prop) throws EAILogException {
|
|
String guidLogPrefix = "DBLogTransactionLogger] GUID["+ eaiMessage.getMapper().getGuid(eaiMessage.getStandardMessage())
|
|
+"] UUID["+eaiMessage.getSvcOgNo()+"] ";
|
|
try {
|
|
if (EAIDBLogControl.isEnable()){
|
|
try {
|
|
EAILogDAO dao = ApplicationContextProvider.getContext().getBean(EAILogDAO.class);
|
|
dao.addEAISvcLog(eaiMessage, prop);
|
|
} catch(Exception e) {
|
|
if (logger.isError()) logger.error(guidLogPrefix +" insertLog DB ERROR. - " + e.getMessage(),e);
|
|
// DB Connection Error일 경우에만 설정하도록 수정
|
|
String message = e.getMessage();
|
|
// 오류 메시지 추가 - Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
|
|
// 오류 메시지 추가 - Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Unable to acquire JDBC Connection
|
|
if( "ConnectionError".equals(message) || StringUtils.contains(message, "JDBCConnectionException")
|
|
|| StringUtils.contains(message, "Unable to acquire JDBC Connection") ) {
|
|
EAIDBLogControl.setEnable(false);
|
|
}
|
|
//file log
|
|
EAIFileLogger.getInstance().setLog(eaiMessage, prop);
|
|
throw e;
|
|
}
|
|
}
|
|
else{
|
|
//file log
|
|
EAIFileLogger.getInstance().setLog(eaiMessage, prop);
|
|
}
|
|
|
|
} catch(Exception e) {
|
|
if (logger.isError()) logger.error(guidLogPrefix + " insertLog ERROR. - " + e.getMessage(), e);
|
|
throw new EAILogException("insertLog ERROR."+ e.getMessage());
|
|
}
|
|
}
|
|
}
|