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 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 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()); } } }