aboutsummaryrefslogtreecommitdiffstats
path: root/vespalog/src/main/java/com/yahoo/log/LogMessage.java
diff options
context:
space:
mode:
Diffstat (limited to 'vespalog/src/main/java/com/yahoo/log/LogMessage.java')
-rw-r--r--vespalog/src/main/java/com/yahoo/log/LogMessage.java151
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();
+ }
+}