NOTE: This code was refactored a bit and exists in MochiKit 1.0+ as MochiKit.LoggingPane?!

Here's code to create an inline or popup-window log viewer for the default logger. Current dependencies are MochiKit.Base and MochiKit.Logging.

Allows regex-based filtering of the message level and info, and can view all logged messages or only new ones as they come.

function createDebugPane(inline) {
    /* Use a div if inline, pop up a window if not */
    if(logger) {
        /* Create the elements */
        var doc = document;
        if(!inline) {
            var win = window.open("", "", "dependent,resizable,height=200");
            doc = win.document;
        }
        var debugPane = doc.createElement("div");
        var levelFilterField = doc.createElement("input");
        var infoFilterField = doc.createElement("input");
        var filterButton = doc.createElement("button");
        var loadButton = doc.createElement("button");
        var clearButton = doc.createElement("button");
        var closeButton = doc.createElement("button");
        var logPane = doc.createElement("div");

        /* Set up the functions */
        var listenerId = "_debugPaneListener";
        var colorTable = {"ERROR": "orange","FATAL": "red","WARNING": "blue","INFO": "green","DEBUG": "silver"};
        var messages = [];
        var messageFilter = null;

        var messageLevel = function(msg) {
            var level = msg.level;
            if(typeof(level) == "number")
                level = LogLevel[level];
            return level;
        };

        var messageText = function(msg) {
            var text = "";
            for(var i = 0; i < msg.info.length; i++)
                text += msg.info[i];
            return text;
        };

        var addMessageText = function(msg) {
            var level = messageLevel(msg);
            var text = messageText(msg);
            var c = colorTable[level];
            var p = doc.createElement("p");
            p.style.color = c;
            p.style.margin = "0";
            p.appendChild(doc.createTextNode(level + ": " + text));
            logPane.appendChild(p);
            p.scrollIntoView();
        };

        var addMessage = function(msg) {
            messages[messages.length] = msg;
            addMessageText(msg);
        };

        var buildMessageFilter = function() {
            var levelre, infore;
            try {
                /* Catch any exceptions that might arise due to invalid regexes */
                var levelre = new RegExp(levelFilterField.value);
                var infore = new RegExp(infoFilterField.value);
            } catch(e) {
                /* If there was an error with the regexes, do no filtering */
                logDebug("Error in filter regex: " + e.message);
                return null;
            }

            return function(msg) {
                return (levelre.test(messageLevel(msg)) && infore.test(messageText(msg)));
            };
        }

        var clearMessagePane = function() {
            while(logPane.firstChild)
                logPane.removeChild(logPane.firstChild);
        };

        var clearMessages = function() {
            messages = [];
            clearMessagePane();
        }

        var closePane = function() {
            logger.removeListener(listenerId);

            if(inline)
                debugPane.parentNode.removeChild(debugPane);
            else
                win.close();
        };

        var filterMessages = function() {
            clearMessagePane();

            for(var i = 0; i < messages.length; i++) {
                var msg = messages[i];
                if(messageFilter == null || messageFilter(msg))
                    addMessageText(msg);
            }
        };

        var buildAndApplyFilter = function() {
            messageFilter = buildMessageFilter();

            filterMessages();

            logger.removeListener(listenerId);
            logger.addListener(listenerId, messageFilter, addMessage);
        };


        var loadMessages = function() {
            messages = logger.getMessages();
            filterMessages();
        };

        var filterOnEnter = function(event) {
            event = event || window.event;
            key = event.which || event.keyCode;
            if(key == 13)
                buildAndApplyFilter();
        };

        /* Create the debug pane */
        debugPane.style.display = "block";
        debugPane.style.position = "fixed";
        debugPane.style.left = "0px";
        debugPane.style.bottom = "0px";
        debugPane.style.font = "8pt Verdana,sans-serif";
        debugPane.style.width = "100%";
        if(inline) {
            debugPane.style.height = "10em";
            debugPane.style.borderTop = "2px solid black";
        } else {
            debugPane.style.height = "100%";
        }
        debugPane.style.backgroundColor = "white";
        doc.body.appendChild(debugPane);

        /* Create the filter fields */
        levelFilterField.value = "FATAL|ERROR|WARNING|INFO|DEBUG";
        levelFilterField.style.width = "33%";
        levelFilterField.style.display = "inline";
        levelFilterField.style.font = "8pt Verdana,sans-serif";
        levelFilterField.onkeypress = filterOnEnter;
        debugPane.appendChild(levelFilterField);

        infoFilterField.value = ".*";
        infoFilterField.style.width = "33%";
        infoFilterField.style.display = "inline";
        infoFilterField.style.font = "8pt Verdana,sans-serif";
        infoFilterField.onkeypress = filterOnEnter;
        debugPane.appendChild(infoFilterField);

        /* Create the buttons */
        filterButton.appendChild(doc.createTextNode("Filter"));
        filterButton.style.width = "8%";
        filterButton.style.display = "inline";
        filterButton.onclick = buildAndApplyFilter;
        filterButton.style.font = "8pt Verdana,sans-serif";
        debugPane.appendChild(filterButton);

        loadButton.appendChild(doc.createTextNode("Load"));
        loadButton.style.width = "8%";
        loadButton.style.display = "inline";
        loadButton.onclick = loadMessages;
        loadButton.style.font = "8pt Verdana,sans-serif";
        debugPane.appendChild(loadButton);

        clearButton.appendChild(doc.createTextNode("Clear"));
        clearButton.style.width = "8%";
        clearButton.style.display = "inline";
        clearButton.onclick = clearMessages;
        clearButton.style.font = "8pt Verdana,sans-serif";
        debugPane.appendChild(clearButton);

        closeButton.appendChild(doc.createTextNode("Close"));
        closeButton.style.width = "8%";
        closeButton.style.display = "inline";
        closeButton.onclick = closePane;
        closeButton.style.font = "8pt Verdana,sans-serif";
        debugPane.appendChild(closeButton);

        /* Create the logging pane */
        debugPane.style.display = "block";
        logPane.style.whitespace = "preserve";
        logPane.style.overflow = "auto";
        logPane.style.width = "100%";
        logPane.style.height = "8em";

        debugPane.appendChild(logPane);

        buildAndApplyFilter();
    } else {

        alert("logger not found!");
    }
}