diff options
Diffstat (limited to 'vespalog/src/main/java/com/yahoo/log/LogMessage.java')
-rw-r--r-- | vespalog/src/main/java/com/yahoo/log/LogMessage.java | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/vespalog/src/main/java/com/yahoo/log/LogMessage.java b/vespalog/src/main/java/com/yahoo/log/LogMessage.java new file mode 100644 index 00000000000..123c10d0d95 --- /dev/null +++ b/vespalog/src/main/java/com/yahoo/log/LogMessage.java @@ -0,0 +1,151 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.log; + +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.yahoo.log.event.Event; +import com.yahoo.log.event.MalformedEventException; + +/** + * This class implements the common ground log message used by + * the logserver. A LogMessage is immutable. Note that we have + * chosen the name LogMessage to avoid confusion with LogRecord + * which is used in java.util.logging. + * + * @author <a href="mailto:borud@yahoo-inc.com">Bjorn Borud</a> + */ +public class LogMessage +{ + private static Logger log = Logger.getLogger(LogMessage.class.getName()); + + private static Pattern nativeFormat = + Pattern.compile("^(\\d[^\t]+)\t" + // time + "([^\t]+)\t" + // host + "([^\t]+)\t" + // threadProcess + "([^\t]+)\t" + // service + "([^\t]+)\t" + // component + "([^\t]+)\t" + // level + "(.+)$" // payload + ); + + private long time; + private String timeStr; + private String host; + private String threadProcess; + private String service; + private String component; + private Level level; + private String payload; + private Event event; + + /** + * Private constructor. Log messages should never be instantiated + * directly; only as the result of a static factory method. + */ + private LogMessage (String timeStr, Long time, String host, String threadProcess, + String service, String component, Level level, + String payload) + { + this.timeStr = timeStr; + this.time = time; + this.host = host; + this.threadProcess = threadProcess; + this.service = service; + this.component = component; + this.level = level; + this.payload = payload; + } + + public long getTime () {return time;} + public long getTimeInSeconds () {return time / 1000;} + public String getHost () {return host;} + public String getThreadProcess () {return threadProcess;} + public String getService () {return service;} + public String getComponent () {return component;} + public Level getLevel () {return level;} + public String getPayload () {return payload;} + + /** + * Make a log message from the native format of the logging + * package. + * + * @param msg The log message + * @return Returns a LogMessage instance + * @throws InvalidLogFormatException if the log message + * can not be parsed, ie. is invalid, we throw this + * exception. + */ + public static LogMessage parseNativeFormat(String msg) throws InvalidLogFormatException { + Matcher m = nativeFormat.matcher(msg); + if (! m.matches()) { + throw new InvalidLogFormatException(msg); + } + + Level msgLevel = LogLevel.parse(m.group(6)); + Long timestamp = parseTimestamp(m.group(1)); + + return new LogMessage(m.group(1), timestamp, m.group(2), m.group(3), + m.group(4), m.group(5), msgLevel, + m.group(7)); + } + + private static long parseTimestamp(String timeStr) throws InvalidLogFormatException { + try { + return (long) (Double.parseDouble(timeStr) * 1000); + } catch (NumberFormatException e) { + throw new InvalidLogFormatException("Invalid time string:" + timeStr); + } + } + + /** + * If the LogMessage was an EVENT then this method can + * be used to get the Event instance representing the + * event. The event instance created the first time + * this method is called and then cached. + * + * TODO: make sure this throws exception! + * + * @return Returns Event instance if this is an event message + * and the payload is correctly formatted. Otherwise + * it will return <code>null</code>. + * + */ + public Event getEvent () throws MalformedEventException { + if ((level == LogLevel.EVENT) && (event == null)) { + try { + event = Event.parse(getPayload()); + event.setTime(time); + } + catch (MalformedEventException e) { + log.log(LogLevel.DEBUG, "Got malformed event: " + getPayload()); + throw e; + } + } + return event; + } + + /** + * Return valid representation of log message. + */ + public String toString () { + return new StringBuilder(timeStr.length() + + host.length() + + threadProcess.length() + + service.length() + + component.length() + + level.toString().length() + + payload.length() + + 1) + .append(timeStr).append("\t") + .append(host).append("\t") + .append(threadProcess).append("\t") + .append(service).append("\t") + .append(component).append("\t") + .append(level.toString().toLowerCase()).append("\t") + .append(payload).append("\n") + .toString(); + } +} |