package com.eactive.eai.common.logger; import java.util.List; import java.util.Properties; import org.apache.commons.lang3.SerializationUtils; import com.eactive.eai.common.logger.async.AsyncLoggingPoolManager; import com.eactive.eai.common.message.EAIMessage; import com.eactive.eai.common.message.EAIMessageKeys; import com.eactive.eai.common.monitor.EAIServiceMonitor; import com.eactive.eai.common.util.Logger; import com.eactive.eai.common.util.MessageUtil; import com.eactive.eai.env.ElinkConfig; /** * 1. 기능 : EAI에서 처리되는 모든 On-Line 거래를 데이터베이스에 로깅하기 위한 운영관리 Logger Sender * 2. 처리 개요 : - RequestProcessor에서 받은 로깅 정보를 로그 Queue로 전달 * 3. 주의사항 */ public class EAILogSender { static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); static TransactionLogger txLogger; static { try { txLogger = (TransactionLogger) Class.forName("com.eactive.eai.common.logger.DBLogTransactionLogger").newInstance(); } catch(Exception e) { logger.error(e.getMessage(), e); } } private EAILogSender() { } public static int logCount() { return txLogger.logCount(); } public static int errCount() { return txLogger.errCount(); } public static void resetCount() { txLogger.resetCount(); } public static void send(EAIMessage message, Properties prop) throws Exception { if(message == null) { if(logger.isWarn()) { logger.warn("EAIMessage is null, skip async logging."); } } else { String guidLogPrefix = "EAILogSender] GUID[" + message.getMapper().getGuid(message.getStandardMessage()) + "] UUID[" + message.getSvcOgNo() + "] "; boolean isLogging = false; int svcLogLvl = message.getSvcLogLvl(); int logPssSno = message.getLogPssSno(); String svcTsmtUsgTp = message.getSvcTsmtUsgTp(); if(svcLogLvl >= 3) { isLogging = true; } else if(svcLogLvl == 2) { if( EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTp) && (logPssSno == 100 || logPssSno == 400) ) { isLogging = true; } if( EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && (logPssSno == 200 || logPssSno == 400) ) { isLogging = true; } } else if(svcLogLvl == 1) { isLogging = ! MessageUtil.checkRspErrCd(message.getLogRspErrCd()); } else { isLogging = false; } if(logger.isDebug()) { logger.debug(guidLogPrefix + " svcLogLvl="+ svcLogLvl + ",isLogging="+ isLogging+ ", logPssSno="+ logPssSno); } long logTime = System.currentTimeMillis(); message.setMsgPssTm(logTime); if(isLogging) { if(ElinkConfig.isUseAsyncLogging()) { try { EAIMessage cloned = null; // cloned = (EAIMessage) ObjectUtil.deepCopy(message); // cloned = (EAIMessage) SerializationUtils.clone(message); // performance issue, use clone -> shallow copy bug -> fix cloned = (EAIMessage) message.clone(); Properties clonedProp = null; if(prop != null) clonedProp = (Properties) prop.clone(); AsyncLoggingPoolManager.getInstance().publish(cloned, clonedProp); } catch (Exception e) { logger.warn("AsyncLogging error", e); logDirect(message, prop); // throw e; } } else { logDirect(message, prop); } } // 실시간 모니터링 로그 EAIServiceMonitor servicemonitor = EAIServiceMonitor.getInstance(); servicemonitor.receiveLogMessage(message); // if(EAIMessageKeys.EAI_BLOCKED_CODE.equals(message.getRspErrCd())) { // if(logger.isWarn()) { // logger.warn(guidLogPrefix + " 거래통제 실시간 모니터링 SKIP - " + message.getEAISvcCd() // + ", "+message.getMapper().getGuid(message.getStandardMessage()) ); // } // }else if (EAIMessageKeys.EAI_INFLOW_BLOCKED_CODE.equals(message.getRspErrCd())) { // if(logger.isWarn()) { // logger.warn(guidLogPrefix + " 유량제어 실시간 모니터링 SKIP - " + message.getEAISvcCd() // + ", "+ message.getMapper().getGuid(message.getStandardMessage()) ); // } // }else { // servicemonitor.receiveLogMessage(message); // } } } public static void logDirect(EAIMessage message, Properties prop) throws EAILogException { txLogger.log(message, prop); } /** * 여러 건을 한 트랜잭션(COMMIT 1회)으로 적재한다. * 비동기 로깅 컨슈머(CustomEventHandler)가 모아둔 배치를 넘길 때 사용한다. * * @param items {EAIMessage, Properties} 쌍의 목록 */ public static void logDirectBatch(List items) { if (items == null || items.isEmpty()) return; if (txLogger instanceof DBLogTransactionLogger) { ((DBLogTransactionLogger) txLogger).logBatch(items); return; } // 배치를 지원하지 않는 TransactionLogger 구현이면 건별 처리로 폴백한다. for (Object[] item : items) { try { txLogger.log((EAIMessage) item[0], (Properties) item[1]); } catch (Exception e) { logger.error("logDirectBatch fallback failed.", e); } } } }