Статьи

Логирование на стороне сервера из JavaScript-кода на стороне браузера

Регистрация приложений — это то, что мы все делаем в наших приложениях, которые развертываются на сервере приложений, верно? Использование фреймворков, таких как Log4J или Logback, для большинства разработчиков Java кажется легким. Но как насчет кода, который мы написали, который работает в этих надоедливых браузерах? Я предполагаю, что, кроме случайного оператора console.log (), используемого во время отладки, мы не уделяем много внимания логированию JavaScript. Я нахожу эту ситуацию очень прискорбной, поскольку в настоящее время наблюдается тенденция переноса логики нашего приложения в браузер. И с этим, интересные события, происходящие в браузере, могут остаться незамеченными, или любые ошибки, которые будут происходить, независимо от того, насколько хорошо мы разработали и протестировали наш код на стороне клиента, могут оказаться излишне трудными для воспроизведения и, следовательно, исправления. В этой записи блога я продемонстрирую очень простую настройку для регистрации сообщений из браузера на сервере с использованием базового JavaScript-кода с jQuery и простого контроллера Spring с Slf4J.

Серверный код

Предполагая, что у вас уже есть существующее веб-приложение Spring и вы используете SLF4J для регистрации вашего приложения, все, что нам нужно сделать, это добавить дополнительный @Controller, который позаботится о регистрации любых входящих сообщений.

Наш контроллер JSLogger

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package it.jdev.demo;
 
import java.lang.invoke.MethodHandles;
 
import javax.servlet.http.HttpServletRequest;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
 
@Controller
@RequestMapping(value = "/js-log")
public class JSLogger {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.Lookup.class);
 
    @RequestMapping(method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void logError(final HttpServletRequest request, @RequestBody(required = true) final String logMessage) {
        final String ipAddress = request.getRemoteAddr();
        final String hostname = request.getRemoteHost();
        LOGGER.warn("Received client-side logmessage (" + ipAddress + "/" + hostname + "): " + logMessage);
    }
 
}

Код JavaScript

Для JavaScript-части нашего решения по протоколированию мы добавим JS-файл с именем jdev.js. В нем мы определим модуль с именем JDEV.logging, который будет содержать метод с именем logToServer () . Этот метод отправит Ajax-сообщение нашему контроллеру с небольшой помощью jQuery. Просто убедитесь, что переменная url указывает на конечную точку, настроенную в @RequestMapping нашего контроллера.

Наш модуль логирования JavaScript

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var JDEV = JDEV || {};
 
 
JDEV.namespace = function(ns_string) {
    var parts = ns_string.split('.');
    var parent = JDEV;
 
    // strip redundant leading global
    if (parts[0] === "JDEV") {
        parts = parts.slice(1);
    }
    for (var i = 0; i < parts.length; i += 1) {
        // create a property if it doesn't exist
        if (typeof parent[parts[i]] === "undefined") {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
};
 
 
JDEV.namespace('logging');
JDEV.logging = (function() {
 
    var logToServer = function(logMessage) {
        var logEventObject = {
            "message" : logMessage,
            "location" : location.href,
            "browser" : navigator.userAgent,
        };
        var logMsg = JSON.stringify(logEventObject);
        var url = "js-log";
        $.ajax({
            type : "POST",
            url : url,
            data : logMsg,
            contentType : "application/json",
            cache : "false",
        });
    }
     
    return {
        logToServer : logToServer,
    }
 
})();

Все, что осталось сделать, это включить jQuery и наш файл jdev.js в наши html-страницы и вместо вызова console.log () использовать наш новый метод ведения журнала:

Подключение кода JS

1
2
3
4
5
6
7
8
9
    <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
    <script type="text/javascript" src="js/jdev.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            JDEV.logging.logToServer("Hi from the browser...");
        });
    </script>
</body>
</html>

Если все настроено правильно, вы должны получить похожую запись в журнале:
WARN : Received client-side logmessage (127.0.0.1/localhost): {"message":"Hi from the browser...","location":"http://localhost:8080/demo/","browser":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"}

Завершение

Я продемонстрировал очень простой дизайн, позволяющий регистрировать записи в журнале на стороне сервера, которые происходят из кода JavaScript на стороне браузера. Конечно, вы можете уточнить этот пример, например, добавив возможность отправки по Log Level с помощью вызова Ajax.