Sentry — трекинг java exception в Java

    Sentry — трекинг java exception в Java


    Стандартно Java разработчики мониторят ошибки, exception через логи. Но есть и другой способ, а именно отправка exception в Sentry.


    Sentry — инструмент мониторинга исключений (exception), ошибок в ваших приложениях.


    Преимущества использования Sentry:


    • не нервничать при размещении приложений на боевом сервере,
    • быстро находить причины возникших проблем,
    • устранять баги раньше, чем о них вам сообщат тестировщики, коллеги из саппорта, пользователи, ПМ или директор,
    • выявлять незаметные остальной команде проблемы, которые портят жизнь пользователям и снижают эффективность вашего продукта,
    • бесплатен,
    • легко интегрируется в проект,
    • ловит ошибки и в браузере пользователя, и на вашем сервере.
    • Если в ELK один и тот же exception происходит несколько раз, то они идут как отдельные записи, занимают место на диске и в ОЗУ. Если в Sentry один и тот же exception происходит несколько раз, то поле EVENTS увеличивается, тем самым экономя место на диске и в ОЗУ.

      Пример


    Основные возможности:


    • Список ошибок обновляется в режиме реального времени,
    • Если ошибка была помечена как решенная и появилась снова, то она снова создается и учитывается в отдельном потоке,
    • Ошибки группируются и отображаются в порядке частоты появления,
    • Ошибки можно фильтровать по статусам, источнику логгирования, уровню логгирования, имени сервера и т.д.

    Sentry поддерживает большую часть языков программирования. Подробнее здесь.


    Устанавливаем Sentry


    • через скрипт, который в docker-compose поднимет все компоненты (скрипт и репо находятся здесь https://github.com/getsentry/onpremise/)
    • собираем RPM пакеты все зависимостей Sentry и устанавливаем через RPM пакеты https://habr.com/ru/post/500632/

    После установки Sentry у вас должен быть DSN



    Здесь будет обзор основных примеров отправки java exception в Sentry. Примеры будем брать из официального репозитория https://github.com/getsentry/examples/tree/master/java.


    Зависимости


    На машине где будете запускать эти примеры необходимо иметь установленными JDK и Maven.


    # Пример для CentOS
    wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
    yum install -y apache-maven java-1.8.0-openjdk-devel git

    Скачиваем репозиторий


    git clone https://github.com/getsentry/examples.git
    cd examples/java/

    Sentry Basic Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/basic


    cd basic

    Запускаем компилирование проекта


    mvn compile exec:java

    Запускаем Java приложение и передаем ему SENTRY_DSN


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 mvn exec:java

    Как выглядят exception в Sentry








    Запустим приложение несколько раз:


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 mvn exec:java

    Видно что счетчик EVENTS для этого конкретного exception увеличился. Скриншот в начале поста.


    Sentry Grails Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/grails-3.x


    Устанавливаем зависимости для SDK


    yum install -y unzip zip

    Устанавливаем grails используя SDK https://grails.org/download.html


    curl -s https://get.sdkman.io | bash
    source "$HOME/.sdkman/bin/sdkman-init.sh"
    sdk install grails

    Запускаем grails c SENTRY_DSN


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 grails run-app

    Открываем в браузере http://localhost:8080/hello/index и exception отправляются в Sentry


    Как выглядят exception в Sentry












    Запустим приложение несколько раз:


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 grails run-app

    Видно что счетчик EVENTS для этого конкретного exception увеличился.


    Sentry java.util.logging Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/java.util.logging


    Собираем пакет JAR


    mvn clean package

    Запускаем JAR


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 \
    java \
    -Djava.util.logging.config.file=src/main/resources/logging.properties \
    -cp ./target/sentry-java-jul-example-1.0-SNAPSHOT-jar-with-dependencies.jar \
    io.sentry.example.Application

    Как выглядят exception в Sentry







    Sentry Log4j 1.x Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/log4j-1.x


    Компилируем


    mvn compile exec:java

    Запускаем


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 mvn exec:java

    Как выглядят exception в Sentry







    Sentry Log4j 2.x Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/log4j-2.x


    Компилируем


    mvn compile exec:java

    Запускаем


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 mvn exec:java

    Как выглядят exception в Sentry







    Sentry Logback Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/logback


    Компилируем


    mvn compile exec:java

    Запускаем


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 mvn exec:java

    Как выглядят exception в Sentry







    Sentry Spring Boot Example


    Переходим к https://github.com/getsentry/examples/tree/master/java/spring-boot


    Запускаем


    SENTRY_DSN=http://31bc93d7d64e4fd6b2e77d6d7780be6c@172.26.10.64:9000/1 mvn spring-boot:run

    Открываем в браузере http://localhost:8080/ и exception отправляются в Sentry


    В логах мы видим
    2020-06-20 12:35:47.249 ERROR 13939 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ArithmeticException: / by zero] with root cause
    
    java.lang.ArithmeticException: / by zero
        at io.sentry.example.Application.home(Application.java:44) ~[classes/:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_252]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_252]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_252]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_252]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_252]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_252]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_252]

    В http://localhost:8080/ мы видим:



    Как выглядят exception в Sentry








    Телеграм чат по Sentry https://t.me/sentry_ru

    Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

    Используете ли вы трекинг exception, как например Sentry?

    • 18,2%Да, использую локальный вариант4
    • 31,8%Да, использую облачный вариант7
    • 13,6%Да, планирую ипользовать3
    • 9,1%Нет, я думал Sentry платный и только в облаке2
    • 27,3%Нет, мне хватает логов в Kibana6
    • 18,2%Нет, я не знал о трекинге exception как направление4

    Попробуете ли вы трекинг exception Sentry?

    • 83,3%Да, мне это интересно15
    • 11,1%Нет, мне хватает логов в Kibana2
    • 5,6%Я не понял как подключать Sentry SDK к своему коду1
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 3

      0
      Sentry не бесплатен. Бесплатно до 5к эксепшенов в месяц
        +1

        Sentry это OpenSource cross-platform application monitoring, with a focus on error reporting.


        Исходный код находится здесь https://github.com/getsentry/sentry


        Sentry On-Premise находится здесь https://github.com/getsentry/onpremise


        Чтобы установить Sentry On-Premise на ваши сервер можно пойти 2 путями


        1) Собрать rpm и установить их — https://habr.com/ru/post/500632/


        2) Воспользоваться официальным установщиком


        установить на сервер docker и docker-compose


        git clone https://github.com/getsentry/onpremise.git
        ./install.sh
          0
          спасибо!

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое