Статьи

Log4Play: Log4j Appender и пользовательский интерфейс с Play Framework, Knockout.js и WebSockets


[img_assist | nid = 40327 | title = | desc = | link = none | align = left | width = 100 | height = 29]

Log4Play — это игра! Модуль Framework, предоставляющий приложение
log4j, которое публикует записи журнала в EventStream. Теоретически вы можете использовать его из любого Java-приложения, которое использует log4j, но я протестировал его только с Play! Рамочное приложение.
Log4Play предоставляет пользовательский интерфейс, который использует WebSocket для создания живого потока сообщений журнала. Пользовательский интерфейс позволяет вам
отслеживать журналы вашего приложения без необходимости входа в реальный ящик . Я работал над этим с
Deepthi Rallabandiс кем я работаю над проектом Accenture; Я только что представил ее, чтобы Играть! Было приятно удивиться тому, как быстро она прогрессирует, что еще раз подтверждает,
насколько продуктивна игра! есть . В один прекрасный день она перешла от того, чтобы ничего не знать о WebSockets и не так уж много опыта в Web, к полноценному приложению на основе WebSockets с Play !. Она использовала мою
предыдущую статью о WebSockets, чтобы провести ее через этот процесс. Итак, позвольте мне перейти к реализации.

Сначала мы создали приложение Log4J.

public class PlayWebSocketLogAppender extends WriterAppender implements Appender {

	/**
	 * Publish log event to WebSocket Stream
	 * 
	 * @see org.apache.log4j.WriterAppender#append(org.apache.log4j.spi.LoggingEvent)
	 */
	@Override
	public void append(LoggingEvent event) {
		LogStream.publish(new Log4PlayEvent(event));
	}
}

Затем мы создали плагин для автоматического добавления appender в log4j, поэтому вам не нужно изменять конфигурацию log4j. PlayPlugin позволяет вам настроить поведение фреймворка, я настоятельно рекомендую вам просмотреть исходный код.

public class Log4PlayPlugin extends PlayPlugin {

	/**
	 * On application start.
	 */
	@Override
	public void onApplicationStart() {
		// Add appender that will stream log messages as Log4PlayEvent instances
		// through WebSocket (Log4Play.WebSocket.stream)
		PlayWebSocketLogAppender appender = new PlayWebSocketLogAppender();
		Logger.log4j.addAppender(appender);

		// Add routes for the UI
		Router.addRoute("GET", "/@logs", "Log4Play.index");
		Router.addRoute("WS", "/@logs/stream", "Log4Play.WebSocket.stream");
	}

}

Затем мы создали поток событий, который будет получать сообщения журнала от appender.

public abstract class LogStream {

	/** The stream. */
	public static final ArchivedEventStream<log4playevent> stream = new ArchivedEventStream<log4playevent>(50);

	/**
	 * Gets the stream.
	 * 
	 * @return the stream
	 */
	public static EventStream<log4playevent> getStream() {
		return stream.eventStream();
	}

	/**
	 * Publish.
	 * 
	 * @param event
	 *            the event
	 */
	public static void publish(Log4PlayEvent event) {
		stream.publish(event);
	}

}

Обратите внимание на то, как мы используем
ArchivedEventStream, который мы можем использовать для отображения x номеров сообщений, как только пользователь загрузит пользовательский интерфейс, вместо того, чтобы видеть пустую страницу, на которой затем будут отображаться сообщения журнала по мере их появления с этого момента. В этом главное отличие
ArchivedEventStream от
EventStream, которое я использовал в своей первой статье о
WebSockets — WebSockets с Play Framework 1.2 в действии! ,

Затем мы определили WebSocketController, который прослушивает сообщения, сброшенные в потоке событий, и передает их клиенту.

public class Log4Play extends Controller {

	/**
	 * Index.
	 */
	public static void index() {
		render();
	}

	/**
	 * The Class WebSocket.
	 */
	public static class WebSocket extends WebSocketController {

		/**
		 * Index.
		 */
		public static void index() {
			EventStream<play.modules.log4play.log4playevent> loggingStream = play.modules.log4play.LogStream.getStream();
			while (inbound.isOpen()) {
				try {
					Promise<play.modules.log4play.log4playevent> promise = loggingStream.nextEvent();
					play.modules.log4play.Log4PlayEvent event = await(promise);
					outbound.sendJson(event);

				} catch (Throwable t) {
					Logger.error(play.modules.log4play.ExceptionUtil.getStackTrace(t));
				}
			}
		}

	}

}

Разница между этой реализацией и реализацией из моей предыдущей статьи заключается в том, что в этом случае объект JSON отправляется в представление вместо простой строки.

Затем на стороне просмотра мы использовали Knockout.js .

    // Define Knockout.js Observable
    var viewModel = {};
    viewModel.details = ko.observable();
    ko.applyBindings(viewModel);
    viewModel.details("Log Events will start showing up here...");

    // Create a socket
    var socket = new WebSocket('@@{Log4Play.WebSocket.index()}');
    
    // Display a message
    var data = "";
    var display = function(json) {
		var event = JSON.parse(json);
    	if ( event != null && json != null ) {
	    	var checkLevel = document.getElementById("log4play_level_" + event.level);
	    	if ( checkLevel != null && checkLevel.checked == true ) {
	    		var item = event.level + ' - ' + event.category  + ' - ' + event.date + ' - ' + event.message;
	    		data = item + data;
	    		viewModel.details(data);
	    	}
    	}
    } 
    
    // Message received on the socket
    socket.onmessage = function(event) {
    	display(event.data);
    }

Установка

Под
зависимостями.yml :

require:
– play → log4play 0.0.1

По
маршрутам :

WS      /logstream                    Log4Play.WebSocket.index
GET     /@logs                          Log4Play.index
GET     /public_log4play/          staticDir:public_log4play

Демонстрация в режиме

реального времени Демонстрация в режиме реального времени доступна по адресу
http://log4play.mashup.fm:9030/@logs . Как только вы включите модуль в своем приложении, вы должны иметь такой же доступный интерфейс в / @ logs.

Исходный код

Исходный код доступен на Github по адресу
https://github.com/feliperazeek/log4play .

Теперь иди играть!

Статья изначально размещена по адресу
http://geeks.aretotally.in/log4play-log4j-ui-mashed-up-with-play-framework-knockout-js-and-websockets .