- 浏览: 1080806 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (399)
- C++ (39)
- Java (74)
- Java界面开发学习笔记 (4)
- Java用户的c++之旅 (0)
- 自言自语 (12)
- DSP (1)
- MCU (0)
- CG (0)
- Jabber (0)
- Gloox (0)
- Linux (11)
- Windows (19)
- Networks (4)
- Jobs (0)
- PHP (1)
- JSP (2)
- 生活 (35)
- C (2)
- Qt4 (2)
- C# (50)
- WPF (5)
- ASP (2)
- FLEX (47)
- SQL (20)
- JavaScript (12)
- SharePoint (6)
- GWT (1)
- Dojo (9)
- HTML (11)
- Others (7)
- 如何安装配置系列 (7)
- UML (2)
- Android (3)
- alibaba (1)
最新评论
-
zxjlwt:
学习了http://surenpi.com
Firefox插件开发: Hello World! -
ylldzz:
楼主知道MVEL怎么调试么
MVEL简介及快速使用 -
blueman2012:
您好,可否提供源码下载,我把您的代码贴过来后,好多报错的,谢谢 ...
Log4J日志解析 -
svygh123:
你的游标都没有关闭呢!
MYSQL游标嵌套循环示例 -
dizh:
写的很好啊
MVEL简介及快速使用
在有些场景下,需要解析Log4J的日志,以为己用。比如,根据关键字查询日志,用以定位问题等。就查询日志这个问题而论,通常的做法是登陆线上机器,grep一把日志目录,得到相关信息。这种做法有两个不好或者说不便捷的问题:首先要登陆线上机器,二来就是若有多台服务器,必须人肉的挨个儿查找,比较费时费力。
下面给出的解决方法是,分析log4j的配置文件,得到所有的Appender,然后再根据Appender中的日志路径、ConversionPattern等信息,去解析相应的日志文件,继而得到我们想要的信息,如Level,Logger、Message等信息。
闲话上说,直接上代码啦。
public final class ConversionRule { private boolean followedByQuotedString; private int beginIndex; private int length; private int minWidth = -1; private int maxWidth = -1; private String placeholderName; private String modifier; private Map<String, Object> properties = new HashMap<String, Object>(); public boolean isFollowedByQuotedString() { return followedByQuotedString; } public void setFollowedByQuotedString(boolean followedByQuotedString) { this.followedByQuotedString = followedByQuotedString; } public int getBeginIndex() { return beginIndex; } public void setBeginIndex(int beginIndex) { this.beginIndex = beginIndex; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public int getMinWidth() { return minWidth; } public void setMinWidth(int minWidth) { this.minWidth = minWidth; } public int getMaxWidth() { return maxWidth; } public void setMaxWidth(int maxWidth) { this.maxWidth = maxWidth; } public String getPlaceholderName() { return placeholderName; } public void setPlaceholderName(String placeholderName) { this.placeholderName = placeholderName; } public String getModifier() { return modifier; } public void setModifier(String modifier) { this.modifier = modifier; } public void putProperty(String key, Object value) { properties.put(key, value); } @SuppressWarnings("unchecked") public <T> T getProperty(String key, Class<T> clazz) { return (T) properties.get(key); } @Override public String toString() { return "ConversionRule [modifier=" + modifier + ", placeholderName=" + placeholderName + "]"; }
public class ConversionRuleParser { private static final Pattern EXTRACTION_PATTERN = Pattern.compile("%(-?(\\d+))?(\\.(\\d+))?([a-zA-Z])(\\{([^\\}]+)\\})?"); public static final String PROP_DATEFORMAT = "dateFormat"; protected Pattern getInternalPattern(String externalPattern) throws Exception { List<ConversionRule> rules = extractRules(externalPattern); return Pattern.compile(toRegexPattern(prepare(externalPattern), rules)); } protected List<ConversionRule> extractRules(String externalPattern) throws Exception { externalPattern = prepare(externalPattern); Matcher m = EXTRACTION_PATTERN.matcher(externalPattern); List<ConversionRule> ret = new ArrayList<ConversionRule>(); while (m.find()) { String minWidthModifier = m.group(2); String maxWidthModifier = m.group(4); String conversionName = m.group(5); String conversionModifier = m.group(7); int minWidth = -1; if ((minWidthModifier != null) && (minWidthModifier.length() > 0)) { minWidth = Integer.parseInt(minWidthModifier); } int maxWidth = -1; if ((maxWidthModifier != null) && (maxWidthModifier.length() > 0)) { maxWidth = Integer.parseInt(maxWidthModifier); } ConversionRule rule = new ConversionRule(); rule.setBeginIndex(m.start()); rule.setLength(m.end() - m.start()); rule.setMaxWidth(maxWidth); rule.setMinWidth(minWidth); rule.setPlaceholderName(conversionName); rule.setModifier(conversionModifier); rewrite(rule); ret.add(rule); } return ret; } public String prepare(String externalPattern) throws Exception { if (!externalPattern.endsWith("%n")) { return externalPattern; } // Pattern without %n externalPattern = externalPattern.substring(0, externalPattern.length() - 2); if (externalPattern.contains("%n")) { throw new Exception("ConversionPattern不合法!"); } return externalPattern; } private void rewrite(ConversionRule rule) throws Exception { if (rule.getPlaceholderName().equals("d")) { applyDefaults(rule); if (rule.getModifier().equals("ABSOLUTE")) { rule.setModifier("HH:mm:ss,SSS"); } else if (rule.getModifier().equals("DATE")) { rule.setModifier("dd MMM yyyy HH:mm:ss,SSS"); } else if (rule.getModifier().equals("ISO8601")) { rule.setModifier("yyyy-MM-dd HH:mm:ss,SSS"); } try { // Cache date format rule.putProperty(PROP_DATEFORMAT, new SimpleDateFormat(rule.getModifier())); } catch (IllegalArgumentException e) { throw new Exception(e); } } } private void applyDefaults(ConversionRule rule) throws Exception { if (rule.getModifier() == null) { // ISO8601 is the default rule.setModifier("ISO8601"); } } private String getRegexPatternForRule(ConversionRule rule) throws Exception { if (rule.getPlaceholderName().equals("d")) { // Pattern is dynamic return "(" + RegexUtils.getRegexForSimpleDateFormat(rule.getModifier()) + ")"; } else if (rule.getPlaceholderName().equals("p")) { String lnHint = RegexUtils.getLengthHint(rule); if (lnHint.length() > 0) { return "([ A-Z]" + lnHint + ")"; } // Default: Length is limited by the levels available return "([A-Z]{4,5})"; } else if (rule.getPlaceholderName().equals("c")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } else if (rule.getPlaceholderName().equals("t")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } else if (rule.getPlaceholderName().equals("m")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } else if (rule.getPlaceholderName().equals("F")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } else if (rule.getPlaceholderName().equals("C")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } else if (rule.getPlaceholderName().equals("M")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } else if (rule.getPlaceholderName().equals("L")) { return "([0-9]*" + RegexUtils.getLengthHint(rule) + ")"; } else if (rule.getPlaceholderName().equals("x")) { return "(.*" + RegexUtils.getLengthHint(rule) + RegexUtils.getLazySuffix(rule) + ")"; } throw new Exception("无法找到对应的表达式描述!"); } protected String toRegexPattern(String externalPattern, List<ConversionRule> rules) throws Exception { // Determine whether rules are followed by quoted string, allowing use of special Regex lazy modifiers int idx = 0; ConversionRule prevRule = null; for (ConversionRule rule : rules) { if ((rule.getBeginIndex() > idx) && (prevRule != null)) { // Previous rule is followed by a quoted string, allowing special regex flags prevRule.setFollowedByQuotedString(true); } idx = rule.getBeginIndex(); idx += rule.getLength(); prevRule = rule; } if ((externalPattern.length() > idx) && (prevRule != null)) { // Previous rule is followed by a quoted string, allowing special regex flags prevRule.setFollowedByQuotedString(true); } // Build the internal Regex pattern StringBuilder sb = new StringBuilder(); idx = 0; for (ConversionRule rule : rules) { if (rule.getBeginIndex() > idx) { // Escape chars with special meaning sb.append(Pattern.quote(externalPattern.substring(idx, rule.getBeginIndex()))); } idx = rule.getBeginIndex(); String regex = this.getRegexPatternForRule(rule); sb.append(regex); idx += rule.getLength(); } if (externalPattern.length() > idx) { // Append suffix sb.append(Pattern.quote(externalPattern.substring(idx))); } return sb.toString(); } }
public class ConversionPatternParser { private Map<String, Appender> appenderBag; public static String CONVERSION_JUST_4TEST = "%d [] %-5p %c{2} - %m%n"; public ConversionPatternParser() {} public void parseConfiguration(String configFilePath) throws Exception { AppenderParser config = new AppenderParser(); config.parse(configFilePath); setAppenderBag(config.getAppenderBag()); } public String getConversionPattern(Appender appender) { Layout layout = appender.getLayout(); if (layout instanceof PatternLayout) { PatternLayout patternLayout = (PatternLayout) layout; return patternLayout.getConversionPattern(); } return null; } public void setAppenderBag(Map<String, Appender> appenderBag) { this.appenderBag = appenderBag; } public Map<String, Appender> getAppenderBag() { return appenderBag; } }
/** * @author Philipp Nanz */ public class RegexUtils { private static transient Logger logger = LoggerFactory.getLogger(RegexUtils.class); /** * Returns the Regex lazy suffix for the given rule. * @param rule the conversion rule * @return the Regex lazy suffix */ public static String getLazySuffix(ConversionRule rule) { if (rule.isFollowedByQuotedString()) { return "?"; } else { return ""; } } /** * Returns the Regex length hint for the given rule. * @param rule the conversion rule * @return the Regex length hint */ public static String getLengthHint(ConversionRule rule) { if ((rule.getMaxWidth() > 0) && (rule.getMaxWidth() == rule.getMinWidth())) { // Exact length specified return "{" + rule.getMaxWidth() + "}"; } else if (rule.getMaxWidth() > 0) { // Both min and max are specified return "{" + Math.max(0, rule.getMinWidth()) + "," + rule.getMaxWidth() + "}"; //$NON-NLS-3$ } else if (rule.getMinWidth() > 0) { // Only min is specified return "{" + rule.getMinWidth() + ",}"; } return ""; } /** * Converts a given <code>java.lang.SimpleDateFormat</code> pattern into * a regular expression * @param format the pattern * @return the translated pattern * @throws Exception if an error occurred */ public static String getRegexForSimpleDateFormat(String format) throws Exception { RegexUtils utils = new RegexUtils(); return utils.doGetRegexForSimpleDateFormat(format); } private String doGetRegexForSimpleDateFormat(String format) throws Exception { try { new SimpleDateFormat(format); } catch (Exception e) { // Pattern is invalid throw new Exception(e); } // Initialize ReplacementContext ctx = new ReplacementContext(); ctx.setBits(new BitSet(format.length())); ctx.setBuffer(new StringBuffer(format)); // Unquote unquote(ctx); // G - Era designator replace(ctx, "G+", "[ADBC]{2}"); // y - Year replace(ctx, "[y]{3,}", "\\d{4}"); replace(ctx, "[y]{2}", "\\d{2}"); replace(ctx, "y", "\\d{4}"); // M - Month in year replace(ctx, "[M]{3,}", "[a-zA-Z]*"); replace(ctx, "[M]{2}", "\\d{2}"); replace(ctx, "M", "\\d{1,2}"); // w - Week in year replace(ctx, "w+", "\\d{1,2}"); // W - Week in month replace(ctx, "W+", "\\d"); // D - Day in year replace(ctx, "D+", "\\d{1,3}"); // d - Day in month replace(ctx, "d+", "\\d{1,2}"); // F - Day of week in month replace(ctx, "F+", "\\d"); // E - Day in week replace(ctx, "E+", "[a-zA-Z]*"); // a - Am/pm marker replace(ctx, "a+", "[AMPM]{2}"); // H - Hour in day (0-23) replace(ctx, "H+", "\\d{1,2}"); // k - Hour in day (1-24) replace(ctx, "k+", "\\d{1,2}"); // K - Hour in am/pm (0-11) replace(ctx, "K+", "\\d{1,2}"); // h - Hour in am/pm (1-12) replace(ctx, "h+", "\\d{1,2}"); // m - Minute in hour replace(ctx, "m+", "\\d{1,2}"); // s - Second in minute replace(ctx, "s+", "\\d{1,2}"); // S - Millisecond replace(ctx, "S+", "\\d{1,3}"); // z - Time zone replace(ctx, "z+", "[a-zA-Z-+:0-9]*"); // Z - Time zone replace(ctx, "Z+", "[-+]\\d{4}"); return ctx.getBuffer().toString(); } private void unquote(ReplacementContext ctx) { Pattern p = Pattern.compile("'[^']+'"); Matcher m = p.matcher(ctx.getBuffer().toString()); while (m.find()) { logger.trace(ctx.toString()); // Match is valid int offset = -2; // Copy all bits after the match for (int i = m.end(); i < ctx.getBuffer().length(); i++) { ctx.getBits().set(i + offset, ctx.getBits().get(i)); } for (int i = m.start(); i < m.end() + offset; i++) { ctx.getBits().set(i); } ctx.getBuffer().replace(m.start(), m.start() + 1, ""); ctx.getBuffer().replace(m.end() - 2, m.end() - 1, ""); logger.trace(ctx.toString()); } p = Pattern.compile("''"); m = p.matcher(ctx.getBuffer().toString()); while (m.find()) { logger.trace(ctx.toString()); // Match is valid int offset = -1; // Copy all bits after the match for (int i = m.end(); i < ctx.getBuffer().length(); i++) { ctx.getBits().set(i + offset, ctx.getBits().get(i)); } for (int i = m.start(); i < m.end() + offset; i++) { ctx.getBits().set(i); } ctx.getBuffer().replace(m.start(), m.start() + 1, ""); logger.trace(ctx.toString()); } } private void replace(ReplacementContext ctx, String regex, String replacement) { Pattern p = Pattern.compile(regex); Matcher m = p.matcher(ctx.getBuffer().toString()); while (m.find()) { logger.trace(regex); logger.trace(ctx.toString()); int idx = ctx.getBits().nextSetBit(m.start()); if ((idx == -1) || (idx > m.end() - 1)) { // Match is valid int len = m.end() - m.start(); int offset = replacement.length() - len; if (offset > 0) { // Copy all bits after the match, in reverse order for (int i = ctx.getBuffer().length() - 1; i > m.end(); i--) { ctx.getBits().set(i + offset, ctx.getBits().get(i)); } } else if (offset < 0) { // Copy all bits after the match for (int i = m.end(); i < ctx.getBuffer().length(); i++) { ctx.getBits().set(i + offset, ctx.getBits().get(i)); } } for (int i = m.start(); i < m.end() + offset; i++) { ctx.getBits().set(i); } ctx.getBuffer().replace(m.start(), m.end(), replacement); logger.trace(ctx.toString()); } } } private class ReplacementContext { private BitSet bits; private StringBuffer buffer; /** * @return the bits */ public BitSet getBits() { return bits; } /** * @param bits the bits to set */ public void setBits(BitSet bits) { this.bits = bits; } /** * @return the buffer */ public StringBuffer getBuffer() { return buffer; } /** * @param buffer the buffer to set */ public void setBuffer(StringBuffer buffer) { this.buffer = buffer; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("ReplacementContext [bits="); for (int i = 0; i < buffer.length(); i++) { sb.append(bits.get(i) ? '1' : '0'); } sb.append(", buffer="); sb.append(buffer); sb.append(']'); return sb.toString(); } } }
public class LogEntry { private Map<String, Object> map = new HashMap<String, Object>(); public final <VT> void put(String key, VT value) { map.put(key, value); } @SuppressWarnings("unchecked") public final <VT> VT get(String key) { return (VT) map.get(key); } public final <VT> boolean contains(String key) { return map.containsKey(key); } public String toString() { return map.toString(); } }
public class LogFileParser { public static final String FIELD_LOGGER = "logger"; public static final String FIELD_TIMESTAMP = "timestamp"; public static final String FIELD_LEVEL = "level"; public static final String FIELD_THREAD = "thread"; public static final String FIELD_MESSAGE = "message"; public static final String FIELD_CURRENT_LINE = "currLine"; public static final String FIELD_IS_HIT = "isHit"; public static final String FIELD_NDC = "ndc"; public static final String FIELD_THROWABLE = "throwable"; public static final String FIELD_LOC_FILENAME = "locFilename"; public static final String FIELD_LOC_CLASS = "locClass"; public static final String FIELD_LOC_METHOD = "locMethod"; public static final String FIELD_LOC_LINE = "locLine"; private static Logger logger = Logger.getLogger(LogFileParser.class); private ConversionRuleParser conversionRuleParser; public LogFileParser() { conversionRuleParser = new ConversionRuleParser(); } public List<LogEntry> parse(String fileName, String conversionPattern, String content, Integer upperLogNum, Integer lowerLogNum) throws Exception { List<ConversionRule> extractRules = conversionRuleParser.extractRules(conversionPattern); FileInputStream fis = new FileInputStream(new File(fileName)); LineIterator iter = IOUtils.lineIterator(fis, "GBK"); try { List<LogEntry> logLines = iterateLogLines(conversionPattern, extractRules, iter, upperLogNum, lowerLogNum, content); return logLines; } finally { LineIterator.closeQuietly(iter); } } @SuppressWarnings("unchecked") private List<LogEntry> iterateLogLines(String conversionPattern, List<ConversionRule> extractRules, LineIterator iter, Integer upperLogNum, Integer lowerLogNum, String content) throws Exception { boolean flag = true; List<LogEntry> result = new ArrayList<LogEntry>(); BoundedFifoBuffer upperLogEntries = null; if (upperLogNum != null && upperLogNum > 0) upperLogEntries = new BoundedFifoBuffer(upperLogNum); BoundedFifoBuffer lowerLogEntries = null; if (lowerLogNum != null && lowerLogNum > 0) lowerLogEntries = new BoundedFifoBuffer(lowerLogNum); LogEntry unfinishedEntry = null; LogEntry currentEntry = fetchARecord(iter, conversionPattern, extractRules, unfinishedEntry); while (currentEntry != null) { String msg = currentEntry.get(FIELD_MESSAGE); boolean isHit = msg.contains(content); if (flag) { if (isHit) { //命中 flag = false; if (upperLogEntries != null) { result.addAll(upperLogEntries); upperLogEntries.clear(); } currentEntry.put(FIELD_IS_HIT, true); result.add(currentEntry); } else { if (upperLogEntries != null) { if (upperLogEntries.isFull()) { upperLogEntries.remove(); } upperLogEntries.add(currentEntry); } } currentEntry = fetchARecord(iter, conversionPattern, extractRules, unfinishedEntry); continue; } else { if (!isHit) { if (lowerLogNum != 0) { //未命中 if (lowerLogEntries != null) { lowerLogEntries.add(currentEntry); if (lowerLogEntries.isFull()) { //转移Lower中的记录到LogList中 flag = true; result.addAll(lowerLogEntries); lowerLogEntries.clear(); } } } else { flag = true; } } else { if (lowerLogEntries != null) { result.addAll(lowerLogEntries); lowerLogEntries.clear(); } currentEntry.put(FIELD_IS_HIT, true); result.add(currentEntry); } currentEntry = fetchARecord(iter, conversionPattern, extractRules, unfinishedEntry); continue; } } return result; } private long lineNo = 1; private LogEntry fetchARecord(LineIterator iter, String conversionPattern, List<ConversionRule> extractRules, LogEntry unfinishedEntry) throws Exception { LogEntry currentEntry = null; boolean found = true; if (unfinishedEntry == null) { found = false; } if (!iter.hasNext()) { return null; } while (iter.hasNext()) { // Error handling String line = iter.nextLine(); while (StringUtils.isBlank(line) && iter.hasNext()) { line = iter.nextLine(); } Matcher m = conversionRuleParser.getInternalPattern(conversionPattern).matcher(line); if (m.find()) { //It's next entry, unfinished if (found) { currentEntry = unfinishedEntry; unfinishedEntry = new LogEntry(); for (int i = 0; i < m.groupCount(); i++) { try { this.extractField(unfinishedEntry, extractRules.get(i), m.group(i + 1)); } catch (Exception e) { // Mark for interruption logger.warn(e); } } currentEntry.put(FIELD_CURRENT_LINE, lineNo++); return currentEntry; } else { unfinishedEntry = new LogEntry(); found = true; for (int i = 0; i < m.groupCount(); i++) { try { this.extractField(unfinishedEntry, extractRules.get(i), m.group(i + 1)); } catch (Exception e) { // Mark for interruption logger.warn(e); } } } } else if (unfinishedEntry != null) { String msg = unfinishedEntry.get(FIELD_MESSAGE); msg += '\n' + line; unfinishedEntry.put(FIELD_MESSAGE, msg); } } if (unfinishedEntry != null) { currentEntry = unfinishedEntry; } if (currentEntry != null) currentEntry.put(FIELD_CURRENT_LINE, lineNo++); return currentEntry; } private void extractField(LogEntry entry, ConversionRule rule, String val) throws Exception { if (rule.getPlaceholderName().equals("d")) { DateFormat df = rule.getProperty(ConversionRuleParser.PROP_DATEFORMAT, DateFormat.class); entry.put(FIELD_TIMESTAMP, df.parse(val.trim())); } else if (rule.getPlaceholderName().equals("p")) { Level lvl = Level.toLevel(val.trim()); entry.put(FIELD_LEVEL, lvl); } else if (rule.getPlaceholderName().equals("c")) { entry.put(FIELD_LOGGER, val.trim()); } else if (rule.getPlaceholderName().equals("t")) { entry.put(FIELD_THREAD, val.trim()); } else if (rule.getPlaceholderName().equals("m")) { entry.put(FIELD_MESSAGE, val.trim()); } else if (rule.getPlaceholderName().equals("F")) { entry.put(FIELD_LOC_FILENAME, val.trim()); } else if (rule.getPlaceholderName().equals("C")) { entry.put(FIELD_LOC_CLASS, val.trim()); } else if (rule.getPlaceholderName().equals("M")) { entry.put(FIELD_LOC_METHOD, val.trim()); } else if (rule.getPlaceholderName().equals("L")) { entry.put(FIELD_LOC_LINE, val.trim()); } else if (rule.getPlaceholderName().equals("x")) { entry.put(FIELD_NDC, val.trim()); } else { throw new Exception("异常消息暂未设置"); } } }
LogFileParser的活动图:
public class AppenderParser extends DOMConfigurator { private Map<String, Appender> appenderBag = new HashMap<String, Appender>(); private Document doc = null; private DocumentBuilderFactory dbf; private DocumentBuilder db = null; public AppenderParser() {} public void parse(String configFile) throws Exception { doc = getDocument(configFile); NodeList appenderList = doc.getElementsByTagName("appender"); for (int t = 0; t < appenderList.getLength(); t++) { Node node = appenderList.item(t); NamedNodeMap map = node.getAttributes(); Node attrNode = map.getNamedItem("name"); if (getAppenderBag().get(attrNode.getNodeValue()) == null) { Appender appender = parseAppender((Element) node); getAppenderBag().put(attrNode.getNodeValue(), appender); } } } private Document getDocument(String configFile) throws ParserConfigurationException, SAXException, IOException { dbf = DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); return db.parse(new File(configFile)); } public static void main(String[] args) throws Exception { String configFile = "D:\\log4j.xml"; AppenderParser config = new AppenderParser(); config.parse(configFile); System.out.println(SerializeUtil.serialize(config.getAppenderBag())); } public void setAppenderBag(Map<String, Appender> appenderBag) { this.appenderBag = appenderBag; } public Map<String, Appender> getAppenderBag() { return appenderBag; } }
@Component public class LoggerSearch { private AppenderParser appenderParser; private LogFileParser logParser; private Map<String, Appender> appenders; private String configFilePath = "log4j.xml"; List<LogEntry> logEntries; Map<String, List<LogEntry>> allLogEntries; @PostConstruct public void init() throws Exception { appenderParser = new AppenderParser(); logParser = new LogFileParser(); appenderParser.parse(getConfigFilePath()); appenders = appenderParser.getAppenderBag(); allLogEntries = new HashMap<String, List<LogEntry>>(); } public Map<String, List<LogEntry>> searchAll(String content, Integer upperLogNum, Integer lowerLogNum) throws Exception { for (Appender appender : appenders.values()) { if (appender instanceof FileAppender) { FileAppender fileAppender = (FileAppender) appender; if (appender instanceof DailyRollingFileAppender) { Layout layout = fileAppender.getLayout(); if (layout instanceof PatternLayout) { PatternLayout patternLayout = (PatternLayout) layout; String conversionPattern = patternLayout.getConversionPattern(); String fileName = fileAppender.getFile(); logEntries = logParser.parse(fileName, conversionPattern, content, upperLogNum, lowerLogNum); allLogEntries.put(new File(fileName).getName(), logEntries); } } } } return allLogEntries; } public void setConfigFilePath(String configFilePath) { this.configFilePath = configFilePath; } public String getConfigFilePath() { return LoggerSearch.class.getClassLoader().getResource(configFilePath).getFile(); } }
上述部分代码参考了LogSaw,其中仅实现了简单的功能,如果有需要可自行扩展。
另附上一个JMX查询接口:
@Component @JmxClass public class Log4jGrep { @Resource private LoggerSearch loggerSearch; @JmxMethod public String searchAll(String content, Integer upperLogNum, Integer lowerLogNum) { try { StringBuilder sb = new StringBuilder(); Map<String, List<LogEntry>> logEntries = loggerSearch.searchAll(content, upperLogNum, lowerLogNum); String color = "#cccccc"; for (String logName : logEntries.keySet()) { List<LogEntry> logs = logEntries.get(logName); if (logs != null && logs.size() > 0) { sb.append("<p style=\"\font-weight: bold;color: #FF0000;font-family: Geneva, Arial, Helvetica, sans-serif;font-size: x-large;\">" + logName + "</p>"); sb.append("<table height=\"100\" border=\"1\">"); sb.append("<tr>"); sb.append("<td width=\"45\">行号</td>"); sb.append("<td width=\"55\">等级</td>"); sb.append("<td width=\"88\">类名</td>"); sb.append("<td width=\"763\">信息</td>"); sb.append("</tr>"); for (LogEntry log : logs) { if (log.get(LogFileParser.FIELD_IS_HIT) != null) { color = "#cccccc"; } else { color = ""; } sb.append("<tr bgcolor=" + color + ">"); sb.append("<td>" + log.get(LogFileParser.FIELD_CURRENT_LINE) + "</td>"); sb.append("<td>" + log.get(LogFileParser.FIELD_LEVEL) + "</td>"); sb.append("<td>" + log.get(LogFileParser.FIELD_LOGGER) + "</td>"); String msg = log.get(LogFileParser.FIELD_MESSAGE); msg = msg.replaceAll(content, "<span style=\"color: #FFFFFF;background: #FF0000;\">" + content + "</span>"); sb.append("<td style=\"word-wrap:break-word;\">" + msg + "</td>"); sb.append("</tr>"); } sb.append("<table/>"); } } return sb.toString(); } catch (Exception e) { return ExceptionUtils.getFullStackTrace(e); } } }
发表评论
-
Interesting interview question…
2011-06-23 19:10 1470Today I was asked this questi ... -
简单易用的Web框架:SummerCool介绍
2011-05-10 19:01 4756SummerCool是国内某大型电子商务平台的架构师自 ... -
[转]Eclipse插件:Java AST View
2011-05-06 16:03 4624转载:http://www.blogjava.net/life ... -
Eclipse之Debug技巧
2011-05-02 15:30 1573你认为你的eclipse debug技能都学会了吗?能够熟 ... -
AccessController.doPrivileged 小记
2011-04-29 20:29 2094原文:http://blog.csdn.net/tea ... -
推荐一个下载源码的网站
2011-04-29 20:26 1261http://olex.openlogic.com/ 这个网 ... -
Java解析xml禁止校验dtd
2011-04-27 21:34 8417今天在做log4j.xml解析的时候,指定了如下的dtd声明: ... -
区分getName、getCanonicalName与getSimpleName
2011-04-27 18:34 5772举例,现有一个类如下: package com.sha ... -
分享个不错的网站:看JSON字符串的利器
2011-04-20 20:09 1321分享个不错的网站:看JSON字符串的利器or胸器 http: ... -
Regex:密码验证
2011-04-13 18:45 20194.当且仅当含数字和字母的密码验证 如果密码当且仅当 ... -
JDBC操作数据库时切记关闭资源
2011-04-08 18:14 1894Error: No ManagedConnectio ... -
JDBC:如何将resultset的信息自动封装到pojo里面
2011-04-08 10:32 4320不多说了 直接上代码 Java代码 p ... -
Maven自动升级版本号并打包上传的脚本
2011-04-02 09:52 7538同事写的自动升级版本并打包上传的脚本: echo of ... -
在ibatis中使用$value$引入变量会引入SQLInjection漏洞
2011-04-01 16:26 2321(1)sql语法中的_关键字_.如果sql语句中出现存在用户输 ... -
EqualsBuilder和HashCodeBuilder
2011-03-31 19:30 2230自动化hashCode()和equals() 问题产生:当需 ... -
Eclipse中的Stack Trace Console的使用
2011-03-15 14:47 3035很多的Java程序员(特别是开发Web程序的时候),通常在 ... -
System.out.format的使用
2011-01-21 12:34 4804JDK5.0允许象C语言那样直接用printf()方法来格式化 ... -
jhat的简单使用
2011-01-18 19:41 2896leak一般会发生在容器类保存对象引用而不删除的时候,替代方法 ... -
关于变更eclipse中maven插件的repository路径
2011-01-10 10:02 17091.打开eclipse 2.window-->ref ... -
Spring 出错:java.lang.NoSuchMethodError: org.springframework.util.ReflectionUtils.
2010-12-13 19:19 2619今天在跑单元测试,使用的是Maven。得到如下Excepti ...
相关推荐
本文将详细讨论如何解决Log4j日志文件出现的乱码问题。 首先,我们要理解Log4j的工作原理。Log4j允许开发者自定义日志输出的方式,包括输出到控制台、文件、数据库等。它使用了`QuietWriter`类来写入日志,`...
当我们遇到“无法打出log4j日志的问题”,这通常是由于配置、环境或代码实现中的某些错误导致的。这篇长文将深入探讨如何排查和解决这类问题。 首先,我们要理解Log4j的基本工作原理。Log4j通过配置文件(通常是log...
总结来说,Log4j的动态配置日志输出路径主要涉及对配置文件的解析和重新加载,以及在运行时使用API直接调整日志设置。理解并熟练运用这些方法,可以帮助我们在开发过程中更灵活地管理和监控日志,提高开发效率和问题...
在实际操作中,可能还需要结合其他工具,如Logstash用于日志解析和Elasticsearch进行日志存储与搜索,形成ELK(Elasticsearch, Logstash, Kibana)或EFK(Elasticsearch, Fluentd, Kibana)栈,以提供更强大的日志...
《深入理解Log4j:构建高效...以上就是关于Log4j日志打印的全面解析,希望能对你自定义的日志记录工具提供有价值的参考和启示。在实际使用中,不断学习和实践,才能更好地发挥Log4j的优势,提升日志记录的质量和效率。
### 配置Log4j的详细指南:最佳的日志管理工具 #### 一、引言 在软件开发过程中,良好的日志记录对于调试、维护和性能优化等方面具有至关重要的作用。Log4j作为Apache下的一个开源项目,因其高度灵活性、易配置性...
这个库实现了log4j-api中定义的接口,提供了具体的功能,比如各种Appender(控制台输出、文件写入、网络传输等)、Layout(日志格式化)、Filter(日志过滤)和Lookup(动态配置变量解析)。例如,`org.apache....
《深入解析Log4j 2.11.0源码》 Log4j,作为Java领域最常用的日志框架之一,其2.11.0版本的发布为开发者提供了更加强大、高效和灵活的日志处理能力。源码包的获取,对于开发者深入理解其工作原理、定制化需求以及...
标题提及的是"log4j-API-最新稳定版本log4j-1.2.17",这表明我们关注的是日志框架Log4j的一个特定版本,即1.2.17。Log4j是Apache软件基金会开发的一个用于Java应用程序的日志记录工具,它提供了灵活的日志记录功能,...
四、Log4j的使用 在Java代码中,我们可以使用以下方式创建和使用Logger: ```java import org.apache.log4j.Logger; public class MyClass { private static final Logger logger = Logger.getLogger(MyClass....
在提供的`log4j-core-2.11.2.jar`和`log4j-api-2.11.2.jar`中,`log4j-core`是实现部分,包含了各种日志记录功能,如配置解析、日志事件的处理等;而`log4j-api`则包含API接口,供开发者在代码中调用,定义日志级别...
### 教你更简单的使用log4j日志 在日常的软件开发过程中,日志记录是必不可少的一个环节,它能够帮助我们追踪程序运行时的状态、定位问题所在,并且为后期维护提供重要的参考依据。Log4j作为Apache组织下的一个开源...
Log4j是Apache的一个开源项目,主要用于日志记录,提供了灵活的日志配置,允许开发者根据需求调整日志输出的级别和格式。Log4j2作为Log4j的升级版本,它在性能、可配置性和可扩展性上有了显著提升,同时也修复了Log4...
Log4j是一款广泛使用的Java日志框架,但有时候我们可能需要根据特定需求创建一个类似Log4j的配置系统。这篇博客“日志组件-仿log4j的配置”探讨了如何设计和实现一个模仿Log4j的日志解决方案。 首先,我们需要理解...
Log4Shell漏洞的核心在于log4j2的Lookup功能,该功能允许在日志消息中动态解析变量。攻击者可以利用此功能,将恶意的JNDI链接注入到日志记录中,当log4j2尝试解析这些链接时,就会执行攻击者控制的代码。由于很多...
在IT行业中,日志记录是系统调试、性能分析和故障排查的重要工具,而Log4j则是Java编程语言中广泛使用的日志框架之一。本工程基于Eclipse IDE,配置了一个简单的Log4j设置,实现了每天自动将日志输出到一个特定命名...
"Log4j记录压缩日记" 指的是使用Log4j日志框架来记录并压缩日志文件。Log4j是Apache的一个开源项目,它为应用程序提供了灵活的日志记录功能,包括输出格式、日志级别管理以及日志文件的滚动策略等。在某些场景下,...
本文将详细解析Log4j 1.2.15.jar这个版本的核心概念、使用方法以及重要特性。 一、Log4j简介 Log4j是由Apache软件基金会开发的一个开源日志组件,主要为Java应用程序提供日志服务。它的设计理念是让日志输出变得...
《深入理解Log4j 2.15.0-rc2:日志处理的关键技术解析》 Log4j,作为Java领域广泛使用的日志记录框架,一直以来都是开发者们的重要工具。这次我们关注的是其最新版本——logging-log4j2-log4j-2.15.0-rc2。这个版本...