Java tutorial
/* * Copyright 2012 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.netflix.exhibitor.core.activity; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.netflix.exhibitor.core.ExhibitorArguments; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.util.Date; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; public class ActivityLog { private final Queue<Message> queue = new ConcurrentLinkedQueue<Message>(); private final int windowSizeLines; private static final Logger log = LoggerFactory.getLogger(ActivityLog.class); private static class Message { final Date date = new Date(); final String text; final Type type; private Message(String text, Type type) { this.text = text; this.type = type; } } /** * @param windowSizeLines max lines to keep in memory */ public ActivityLog(int windowSizeLines) { this.windowSizeLines = windowSizeLines; add(Type.INFO, "Exhibitor started"); } /** * Return the current window lines * * * @param separator line separator * @param logDirection display direction * @return lines */ public List<String> toDisplayList(final String separator, ExhibitorArguments.LogDirection logDirection) { Iterable<String> transformed = Iterables.transform(queue, new Function<Message, String>() { public String apply(Message message) { return message.date + separator + message.type + separator + message.text; } }); ImmutableList<String> list = ImmutableList.copyOf(transformed); return (logDirection == ExhibitorArguments.LogDirection.NATURAL) ? list : Lists.reverse(list); } /** * Supported line types */ public enum Type { ERROR() { @Override protected void log(String message, Throwable exception) { if (exception != null) { log.error(message, exception); } else { log.error(message); } } @Override protected boolean addToUI() { return true; } }, INFO() { @Override protected void log(String message, Throwable exception) { if (exception != null) { log.info(message, exception); } else { log.info(message); } } @Override protected boolean addToUI() { return true; } }, DEBUG() { @Override protected void log(String message, Throwable exception) { if (exception != null) { log.debug(message, exception); } else { log.debug(message); } } @Override protected boolean addToUI() { return Boolean.getBoolean("log-debug"); } } ; protected abstract void log(String message, Throwable exception); protected abstract boolean addToUI(); } /** * Add a log message * * @param type message type * @param message the messqage */ public void add(Type type, String message) { add(type, message, null); } /** * Add a log message with an exception * * @param type message type * @param message the messqage * @param exception the exception */ public void add(Type type, String message, Throwable exception) { String queueMessage = message; if ((type == Type.ERROR) && (exception != null)) { queueMessage += " (" + getExceptionMessage(exception) + ")"; } if (type.addToUI()) { while (queue.size() > windowSizeLines) // NOTE: due to concurrency, this may make the queue shorter than MAX - that's OK (and in some cases longer) { queue.remove(); } queue.add(new Message(queueMessage, type)); } type.log(message, exception); } /** * Convert an exception into a log message * * @param exception the exception * @return message */ public static String getExceptionMessage(Throwable exception) { StringWriter out = new StringWriter(); exception.printStackTrace(new PrintWriter(out)); BufferedReader in = new BufferedReader(new StringReader(out.toString())); try { StringBuilder str = new StringBuilder(); for (;;) { String line = in.readLine(); if (line == null) { break; } if (str.length() > 0) { str.append(", "); } str.append(line); } return str.toString(); } catch (IOException e) { // ignore } return "n/a"; } }