Java tutorial
/* Copyright (C) 2011 NTT DATA Corporation This program is free software; you can redistribute it and/or Modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package com.clustercontrol.agent.log; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.clustercontrol.agent.util.MonitorStringUtil; import com.clustercontrol.bean.PriorityConstant; import com.clustercontrol.util.HinemosTime; import com.clustercontrol.util.MessageConstant; /** * <BR> */ public class LogfileMonitor { // Syslog? private LoggerSyslog m_syslog = null; // private static Log m_log = LogFactory.getLog(LogfileMonitor.class); /** ????????????????????internal?? */ private boolean m_initFlag = true; private long m_lastDataCheck = HinemosTime.currentTimeMillis(); // ? private ReadingStatusRoot.ReadingStatus status; private FileChannel fileChannel; private long m_unchanged_stats = 0; // ????????? private MonitorInfoWrapper m_wrapper = null; /** * * * @param monitorInfo * @param runInstructionInfo */ public LogfileMonitor(MonitorInfoWrapper monitorInfo, ReadingStatusRoot.ReadingStatus status) { this.status = status; m_syslog = new LoggerSyslog(); setMonitor(monitorInfo); } public void clean() { m_log.info("clean dir=" + m_wrapper.monitorInfo.getLogfileCheckInfo().getDirectory() + ", filepath=" + status.rsFilePath); closeFile(); } private String getFilePath() { return status.filePath.getPath(); } /** * ?<BR> * */ public void run() { m_log.debug("monitor start. logfile : " + getFilePath() + " file encoding : " + System.getProperty("file.encoding")); if (!status.isInitialized()) return; // if (fileChannel == null) { // ?????? if (!openFile()) { return; } } boolean readSuccessFlg = true; // ??? long currentFilesize = 0; try { currentFilesize = fileChannel.size(); // ?????? if (status.prevSize == currentFilesize) { /** ? */ boolean logrotateFlag = false; // int runInterval = LogfileMonitorManager.getRunInterval(); // ?m_unchangedStatsPeriod???????? if ((++m_unchanged_stats * runInterval) < LogfileMonitorConfig.unchangedStatsPeriod) { return; } m_log.debug("run() : " + getFilePath() + " check log rotation"); // ?????? // ?? // ??????????????????? // mv?????? File file = new File(getFilePath()); if (fileChannel.size() != file.length()) { // m_log.debug("run() : " + getFilePath() + " file size not match"); logrotateFlag = true; m_log.debug("run() : m_logrotate set true .1");// rm?????????rotate?????? m_log.debug("run() : m_fr.length()=" + fileChannel.size()); m_log.debug("run() : file.length()=" + file.length()); } else if (currentFilesize > 0 && LogfileMonitorConfig.firstPartDataCheckPeriod > 0 && (HinemosTime.currentTimeMillis() - m_lastDataCheck) > LogfileMonitorConfig.firstPartDataCheckPeriod) { m_log.debug("run() : " + getFilePath() + " check first part of file"); // ?? // ???????????????????? // mv??????? // ????????????? logrotateFlag = checkPrefix(); // ? m_lastDataCheck = HinemosTime.currentTimeMillis(); } // ?????? if (logrotateFlag) { // ???? // ?????????????? // ??????????????filesize???????? // ???????????????? // ?? if (currentFilesize == fileChannel.size()) { m_log.info(getFilePath() + " : file changed"); closeFile(); status.rotate(); // if (!openFile()) { return; } currentFilesize = fileChannel.size(); } } m_unchanged_stats = 0; } m_unchanged_stats = 0; if (status.prevSize < currentFilesize) { // ? m_log.debug("run() : " + getFilePath() + " filesize " + status.prevSize + " tmp_filesize " + currentFilesize); char[] cbuf = new char[1024]; try (Reader fr = new InputStreamReader(Channels.newInputStream(fileChannel), m_wrapper.monitorInfo.getLogfileCheckInfo().getFileEncoding()) { @Override public void close() { // ???????? } }) { LineSeparator separator = new LineSeparator(m_wrapper.monitorInfo.getLogfileCheckInfo()); int maxBytes = m_wrapper.monitorInfo.getLogfileCheckInfo().getMaxBytes() != null ? m_wrapper.monitorInfo.getLogfileCheckInfo().getMaxBytes() : LogfileMonitorConfig.logfilMessageLength; int maxLines = LogfileMonitorConfig.logfilMessageLine; long start = System.currentTimeMillis(); boolean logFlag = true; while (true) { readSuccessFlg = false; int read = fr.read(cbuf); readSuccessFlg = true; if (read == -1) break; // ????? // ?????????? // ????? String appendedBuf = new StringBuilder(status.carryover.length() + read) .append(status.carryover).append(cbuf, 0, read).toString(); List<String> lines = new LinkedList<String>(); while (lines.size() <= maxLines) { int pos = separator.search(appendedBuf); if (pos != -1) { lines.add(appendedBuf.substring(0, pos)); appendedBuf = appendedBuf.substring(pos, appendedBuf.length()); } else { break; } } if (!appendedBuf.isEmpty()) { status.carryover = appendedBuf; // ???????? if (status.carryover.length() > maxBytes) { String message = "run() : " + getFilePath() + " carryOverBuf size = " + status.carryover.length() + ". carryOverBuf is too long. it cut down .(see monitor.logfile.message.length)"; if (logFlag) { m_log.info(message); logFlag = false; } else { m_log.debug(message); } status.carryover = status.carryover.substring(0, maxBytes); } // ? if (m_log.isDebugEnabled()) { m_log.debug("run() : " + getFilePath() + " carryOverBuf size " + status.carryover.length()); } } else { status.carryover = ""; logFlag = true; } for (String line : lines) { // ????????syslog?????? if (m_syslog.isValid()) { // v3.2 mode String logPrefix = LogfileMonitorConfig.program + "(" + getFilePath() + "):"; m_syslog.log(logPrefix + line); } else { // v4.0 mode MonitorStringUtil.patternMatch( LogfileMonitorConfig.formatLine(line, m_wrapper.monitorInfo), m_wrapper.monitorInfo, m_wrapper.runInstructionInfo, getFilePath()); } } //Copytruncate???????Position? //?????Position?????????????? //????????????????? //??????????????? currentFilesize = fileChannel.size(); if (status.prevSize <= currentFilesize) { // ?? status.position = fileChannel.position(); status.prevSize = currentFilesize; if (status.prefix == null || status.prefix.isEmpty()) { status.prefix = new String(cbuf, 0, Math.min(read, LogfileMonitorConfig.firstPartDataCheckSize)); } else if (status.prefix.length() < LogfileMonitorConfig.firstPartDataCheckSize) { status.prefix = status.prefix + new String(cbuf, 0, Math.min(read, LogfileMonitorConfig.firstPartDataCheckSize - status.prefix.length())); } status.store(); } else { fileChannel.position(0); status.rotate(); } } m_log.info(String.format("run() : elapsed=%d ms.", System.currentTimeMillis() - start)); } if (m_log.isDebugEnabled()) { m_log.debug("run() : " + getFilePath() + " filesize = " + status.prevSize + ", FilePointer = " + fileChannel.position()); } } else if (status.prevSize > currentFilesize) { // ???? m_log.info("run() : " + getFilePath() + " : file size becomes small"); fileChannel.position(0); status.rotate(); } } catch (IOException e) { if (readSuccessFlg) { m_log.error("run() : " + e.getMessage()); String[] args = { getFilePath() }; // message.log.agent.1={0}? // message.log.agent.4=???????? sendMessage(PriorityConstant.TYPE_WARNING, MessageConstant.AGENT.getMessage(), MessageConstant.MESSAGE_LOG_FAILED_TO_READ_FILE.getMessage(), MessageConstant.MESSAGE_LOG_FILE.getMessage(args) + "\n" + e.getMessage()); // ????? closeFile(); } else { m_log.warn("run() : " + e.getMessage()); // ????????????? try { fileChannel.position(status.prevSize); } catch (IOException e1) { m_log.error("run() set file-pointer error : " + e1.getMessage()); } } } } /** * ?? * * @param priority * ?? * @param app * * @param msg * * @param msgOrg * */ private void sendMessage(int priority, String app, String msg, String msgOrg) { LogfileMonitorManager.sendMessage(getFilePath(), priority, app, msg, msgOrg, m_wrapper.monitorInfo.getMonitorId(), m_wrapper.runInstructionInfo); } /** * ? * */ private void closeFile() { if (fileChannel != null) { try { fileChannel.close(); fileChannel = null; } catch (IOException e) { m_log.debug("run() : " + e.getMessage()); } } } /** * ? */ private boolean openFile() { m_log.info("openFile : filename=" + status.rsFilePath.getName()); closeFile(); FileChannel fc = null; // try { if (checkPrefix()) status.rotate(); fc = FileChannel.open(Paths.get(getFilePath()), StandardOpenOption.READ); long filesize = fc.size(); if (filesize > LogfileMonitorConfig.fileMaxSize) { // ???????? // message.log.agent.1={0}? // message.log.agent.3=?????? // message.log.agent.5={0} byte? String[] args1 = { getFilePath() }; String[] args2 = { String.valueOf(filesize) }; sendMessage(PriorityConstant.TYPE_INFO, MessageConstant.AGENT.getMessage(), MessageConstant.MESSAGE_LOG_FILE_SIZE_EXCEEDED_UPPER_BOUND.getMessage(), MessageConstant.MESSAGE_LOG_FILE.getMessage(args1) + ", " + MessageConstant.MESSAGE_LOG_FILE_SIZE_BYTE.getMessage(args2)); } // ?? // ?open?init=true?? // ??open?init=false??? fc.position(status.position); fileChannel = fc; return true; } catch (FileNotFoundException e) { m_log.info("openFile : " + e.getMessage()); if (m_initFlag) { // ???????? // message.log.agent.1={0}? // message.log.agent.2=??????? String[] args = { getFilePath() }; sendMessage(PriorityConstant.TYPE_INFO, MessageConstant.AGENT.getMessage(), MessageConstant.MESSAGE_LOG_FILE_NOT_FOUND.getMessage(), MessageConstant.MESSAGE_LOG_FILE.getMessage(args)); } return false; } catch (SecurityException e) { m_log.info("openFile : " + e.getMessage()); if (m_initFlag) { // ?? // message.log.agent.1={0}? // message.log.agent.4=???????? String[] args = { getFilePath() }; sendMessage(PriorityConstant.TYPE_WARNING, MessageConstant.AGENT.getMessage(), MessageConstant.MESSAGE_LOG_FAILED_TO_READ_FILE.getMessage(), MessageConstant.MESSAGE_LOG_FILE.getMessage(args) + "\n" + e.getMessage()); } return false; } catch (IOException e) { m_log.info("openFile : " + e.getMessage()); if (m_initFlag) { // ?? // message.log.agent.1={0}? // message.log.agent.4=???????? String[] args = { getFilePath() }; sendMessage(PriorityConstant.TYPE_INFO, MessageConstant.AGENT.getMessage(), MessageConstant.MESSAGE_LOG_FAILED_TO_READ_FILE.getMessage(), MessageConstant.MESSAGE_LOG_FILE.getMessage(args)); } return false; } finally { // ?????????????? if (fc != null && fileChannel == null) { try { fc.close(); } catch (IOException e) { m_log.warn(e.getMessage(), e); } } m_initFlag = false; } } private boolean checkPrefix() throws IOException { boolean logrotateFlag = false; try { char[] newFirstPartOfFile = new char[LogfileMonitorConfig.firstPartDataCheckSize]; Arrays.fill(newFirstPartOfFile, '\0'); // ???0?? if (status.prefix.length() > 0) { // ?????? try (BufferedReader newFile = new BufferedReader( new InputStreamReader(new FileInputStream(getFilePath()), this.m_wrapper.monitorInfo.getLogfileCheckInfo().getFileEncoding()))) { if (newFile.read(newFirstPartOfFile) >= status.prefix.length()) { String firstPart = new String(newFirstPartOfFile, 0, status.prefix.length()); if (m_log.isDebugEnabled()) { try { m_log.debug("run() : " + getFilePath() + " newFirstPartOfFile : " + firstPart); } catch (Exception e) { m_log.error("run() : " + getFilePath() + " " + e.getMessage(), e); } } // ????? if (!firstPart.equals(status.prefix)) { m_log.debug("run() : " + getFilePath() + " log rotation detected"); logrotateFlag = true; m_log.debug("run() : m_logrotate set true .2"); } } } } } catch (RuntimeException e) { m_log.error("run() : " + getFilePath() + " " + e.getMessage(), e); } return logrotateFlag; } public void setMonitor(MonitorInfoWrapper monitorInfo) { this.m_wrapper = monitorInfo; } }