Мониторинг Apache Tomcat с помощью Proto Observability
На этой странице:
- Сбор метрик Tomcat
- Сбор логов Tomcat
Сбор метрик Tomcat
Интеграция tomcat собирает метрики Apache Tomcat через JMX. Проверка опрашивает
MBean’ы в домене Catalina (или Tomcat — у некоторых сборок) и стандартные
java.lang:* / java.nio:* beans JVM. Из коробки покрываются:
- пулы потоков коннекторов (
Catalina:type=ThreadPool); - глобальные счётчики запросов коннектора (
Catalina:type=GlobalRequestProcessor); - сервлеты каждого веб-модуля (
Catalina:j2eeType=Servlet); - JSP-мониторы веб-модулей (
Catalina:type=JspMonitor); - строковый кэш (
Catalina:type=StringCache) и кэш веб-ресурсов (Catalina:type=WebResourceRoot,name=Cache); - пул JDBC-соединений Tomcat, если он используется (
Catalina:type=DataSource); - стандартные метрики JVM (heap/non-heap, GC, потоки, классы, буферы, дескрипторы).
Образ агента для JMX
Если ProtoOBP Агент работает в контейнере (Docker, Kubernetes), используйте образ с суффиксом-jmx, например protoobp-agent:7.40.3-jmx. Без этого
суффикса в образе нет JRE и интеграция падает с ошибкой запуска JMX-проверки.Конфигурация Tomcat
JMX Remote должен быть включён и доступен с хоста, на котором работает агент.
catalina.sh уважает переменные окружения CATALINA_OPTS и JAVA_OPTS, поэтому
отдельный JmxRemoteLifecycleListener в server.xml не нужен — достаточно
передать JVM-флаги.
Создайте (или дополните) файл <CATALINA_BASE>/bin/setenv.sh — catalina.sh
подхватывает его автоматически:
# <CATALINA_BASE>/bin/setenv.sh
export CATALINA_OPTS="$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9010 \
-Dcom.sun.management.jmxremote.rmi.port=9010 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.local.only=false \
-Djava.rmi.server.hostname=<имя_хоста_или_адрес_интерфейса>"
Закрепление jmxremote.rmi.port на том же значении, что и jmxremote.port,
даёт один порт для RMI-реестра и для RMI-объектов — удобно для проброса через
firewall / docker. На проде включите аутентификацию JMX
(-Dcom.sun.management.jmxremote.authenticate=true + password/access файлы)
и TLS вместо ssl=false.
После правок перезапустите Tomcat.
Те же флаги пробрасываются через environment: (значение CATALINA_OPTS
автоматически попадает в JVM):
services:
tomcat:
image: tomcat:9.0-jdk17-temurin
environment:
CATALINA_OPTS: >-
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=tomcat # имя сервиса в docker network
ports:
- "8080:8080" # HTTP-коннектор
- "9010:9010" # JMX
Образы Tomcat: webapps.dist
В современных образах <code>tomcat</code> примеры (<code>ROOT/</code>, <code>examples/</code>, <code>docs/</code>, …) лежат
в /usr/local/tomcat/webapps.dist/, а каталог webapps/ пуст — поэтому
«из коробки» Tomcat ничего не отдаёт, и beans Servlet / JspMonitor /
WebResourceRoot отсутствуют. Если нужно, чтобы интеграция видела
per-servlet / JSP / cache метрики, разверните хотя бы одно веб-приложение
(перенесите содержимое webapps.dist/ в webapps/ или задеплойте свой WAR).
`java.rmi.server.hostname`
JMX RMI отдаёт клиенту адрес второго сокета через значение
java.rmi.server.hostname. Этот адрес должен резолвиться и быть достижим
из контейнера (или с хоста) агента:
- В Docker Compose — указывайте имя сервиса (например,
tomcat), оно резолвится через embedded DNS docker network. - На хосте — FQDN или адрес интерфейса, на который смотрит агент.
- Не указывайте
0.0.0.0илиlocalhost— это распространённая ошибка, агент получит этот адрес и упадёт сConnection refused.
Конфигурация ProtoOBP агента
Если агент запускается в виде службы на хосте
Создайте файл
/etc/protoobp-agent/conf.d/tomcat.d/conf.yaml:init_config: is_jmx: true collect_default_metrics: true # Современные имена GC-метрик: jvm_gc_minor_collection_count и т.п. # вместо jvm_gc_parnew_time / jvm_gc_cms_count. new_gc_metrics: true instances: - host: localhost port: 9010 # user: monitorRole # если на JMX включена аутентификация # password: <пароль> name: tomcat_instanceПерезапустите агента:
systemctl restart protoobp-agent.
Если агент запускается в виде Docker контейнера
Добавьте autodiscovery-лейблы к контейнеру Tomcat. В docker-compose.yaml:
services:
tomcat:
labels:
com.protoobp.ad.check_names: '["tomcat"]'
com.protoobp.ad.init_configs: '[{"is_jmx": true, "collect_default_metrics": true, "new_gc_metrics": true}]'
com.protoobp.ad.instances: '[{"host": "%%host%%", "port": "9010", "name": "tomcat_instance"}]'
Контейнер агента
Контейнер агента должен находиться в той же docker network, что и Tomcat, а образ агента — иметь суффикс-jmx. Также агенту нужен смонтированный
/var/run/docker.sock:/var/run/docker.sock:ro для autodiscovery контейнеров.Проверка
Убедитесь, что проверка запустилась и собирает метрики:
docker exec protoobp-agent agent status | grep -A 8 "^ tomcat$"
Ожидаемый вывод — status : OK и metric_count > 0:
tomcat
instance_name : tomcat_instance
message : <no value>
metric_count : 157
service_check_count : 0
status : OK
Полный список найденных JMX-атрибутов (видны beans ThreadPool,
GlobalRequestProcessor, Servlet, JspMonitor, WebResourceRoot,
StringCache и стандартные java.lang:*):
docker exec protoobp-agent agent jmx list collected
Собираемые метрики
Все метрики собираются по JMX и имеют тип gauge — содержат мгновенное
значение на момент сбора. Метрики, имена которых заканчиваются на _count
(tomcat_request_count, tomcat_error_count, tomcat_bytes_sent,
tomcat_bytes_rcvd, tomcat_processing_time, tomcat_servlet_*_count,
tomcat_servlet_processing_time, tomcat_jsp_*, tomcat_string_cache_*_count,
tomcat_web_cache_*_count), не являются кумулятивными счётчиками: в JMX
они отдаются как монотонные счётчики, а интеграция конвертирует их в
rate в секунду на стороне агента. (Метрики JDBC-пула — обычные gauge,
без конверсии.)
Лейблы
Общие (на всех метриках)
Добавляются агентом и ProtoOBP backend’ом:
| Лейбл | Значение |
|---|---|
host | Хост, на котором работает агент |
instance | name из instances: конфига проверки (tomcat_instance и т.п.) |
jmx_domain | Домен MBean’а — Catalina (или Tomcat) для метрик Tomcat; java.lang / java.nio для метрик JVM |
service | Тег service (через com.protoobp.tags.service или POBP_TAGS) |
env | Тег env |
docker_image | Полный ref образа контейнера (например, tomcat:9.0-jdk17-temurin) |
image_name | Имя образа без тега |
image_tag | Тег образа |
short_image | Короткое имя образа |
Специфичные для конкретных beans
Извлекаются из имени MBean’а:
| Лейбл | На каких метриках | Пример |
|---|---|---|
type | ThreadPool, GlobalRequestProcessor, StringCache, WebResourceRoot, MemoryPool, BufferPool, … | ThreadPool, GlobalRequestProcessor |
name | пулы потоков и коннекторы — имя коннектора; WebResourceRoot — Cache; MemoryPool/BufferPool — имя пула; сервлеты — имя сервлета | "http-nio-8080", Cache, G1 Eden Space, default |
j2ee_type | beans сервлетов (Catalina:j2eeType=Servlet) | Servlet |
webmodule | beans сервлетов и JspMonitor — путь развёрнутого веб-модуля | //localhost/examples |
host(в имени bean’а WebResourceRoot) | tomcat_web_cache_* — виртуальный хост Tomcat | localhost |
context | tomcat_web_cache_* — контекст веб-приложения | /, /docs |
Имя коннектора Tomcat в JMX заключено в двойные кавычки (
name="http-nio-8080") — в лейблах они сохраняются.
Метрики JVM
Стандартный набор JMXFetch (collect_default_metrics: true). Несут лейблы
jmx_domain (java.lang / java.nio), type и name (для memory/buffer
пулов).
| Имя метрики | Единица | Описание |
|---|---|---|
jvm_heap_memory | byte | Использовано heap-памяти JVM |
jvm_heap_memory_committed | byte | Heap-память, зарезервированная под использование |
jvm_heap_memory_init | byte | Начально выделенная heap-память |
jvm_heap_memory_max | byte | Максимально доступная heap-память |
jvm_non_heap_memory | byte | Использовано non-heap памяти (Metaspace, CompressedClassSpace, CodeCache) |
jvm_non_heap_memory_committed | byte | Non-heap память, зарезервированная под использование |
jvm_non_heap_memory_init | byte | Начально выделенная non-heap память |
jvm_non_heap_memory_max | byte | Максимально доступная non-heap память |
jvm_gc_eden_size | byte | Занято в Eden Space |
jvm_gc_survivor_size | byte | Занято в Survivor Space |
jvm_gc_old_gen_size | byte | Занято в Old Generation |
jvm_gc_metaspace_size | byte | Занято в Metaspace |
jvm_gc_major_collection_count | collection/s | Частота major (full) GC (при new_gc_metrics: true) |
jvm_gc_minor_collection_count | collection/s | Частота minor (young) GC (при new_gc_metrics: true) |
jvm_gc_major_collection_time | ms/s | Время, проведённое в major GC (при new_gc_metrics: true) |
jvm_gc_minor_collection_time | ms/s | Время, проведённое в minor GC (при new_gc_metrics: true) |
jvm_thread_count | thread | Количество живых потоков JVM |
jvm_loaded_classes | class | Количество загруженных классов |
jvm_cpu_load_process | percent | Загрузка CPU процессом JVM |
jvm_cpu_load_system | percent | Загрузка CPU всей системы |
jvm_os_open_file_descriptors | descriptor | Количество открытых файловых дескрипторов |
jvm_buffer_pool_direct_used | byte | Используется в пуле direct-буферов NIO |
jvm_buffer_pool_direct_count | buffer | Количество direct-буферов NIO |
jvm_buffer_pool_direct_capacity | byte | Ёмкость пула direct-буферов NIO |
jvm_buffer_pool_mapped_used | byte | Используется в пуле mapped-буферов NIO |
jvm_buffer_pool_mapped_count | buffer | Количество mapped-буферов NIO |
jvm_buffer_pool_mapped_capacity | byte | Ёмкость пула mapped-буферов NIO |
Метрики коннекторов и пулов потоков
tomcat_threads_* — из bean’а ThreadPool (по одному на коннектор; лейбл
name = имя коннектора, например "http-nio-8080"). tomcat_bytes_*,
tomcat_*_count, tomcat_*_time — из bean’а GlobalRequestProcessor
(агрегат по всем процессорам запросов коннектора).
| Имя метрики | Единица | Описание |
|---|---|---|
tomcat_threads_busy | thread | Количество занятых рабочих потоков пула |
tomcat_threads_count | thread | Текущее количество потоков, которыми управляет пул |
tomcat_threads_max | thread | Максимально допустимое количество рабочих потоков |
tomcat_threads_min | thread | Минимальное количество резервных потоков (minSpareThreads) |
tomcat_request_count | request/second | Скорость обработки запросов всеми процессорами запросов коннектора |
tomcat_error_count | error/second | Скорость ошибочных ответов на всех процессорах запросов |
tomcat_bytes_sent | byte/second | Скорость отдачи данных всеми процессорами запросов |
tomcat_bytes_rcvd | byte/second | Скорость приёма данных всеми процессорами запросов |
tomcat_processing_time | millisecond/second | Суммарное время обработки запросов (в мс) в секунду — растёт быстрее при росте latency или RPS |
tomcat_max_time | millisecond | Самое долгое время обработки одного запроса |
tomcat_min_time | millisecond | Самое быстрое время обработки одного запроса |
Метрики сервлетов
Из beans Catalina:j2eeType=Servlet. Несут лейблы j2ee_type=Servlet,
webmodule (путь веб-модуля, например //localhost/examples) и name
(имя сервлета).
| Имя метрики | Единица | Описание |
|---|---|---|
tomcat_servlet_request_count | request/second | Скорость запросов к сервлету |
tomcat_servlet_error_count | error/second | Скорость ошибочных запросов к сервлету |
tomcat_servlet_processing_time | millisecond/second | Суммарное время обработки запросов сервлетом (в мс) в секунду |
tomcat_servlet_max_time | millisecond | Максимальное время обработки одного запроса сервлетом |
tomcat_servlet_min_time | millisecond | Минимальное время обработки одного запроса сервлетом |
Метрики JSP и кэшей
tomcat_jsp_* — из beans Catalina:type=JspMonitor (лейблы webmodule,
name=jsp). tomcat_string_cache_* — из глобального Catalina:type=StringCache.
tomcat_web_cache_* — из beans Catalina:type=WebResourceRoot,name=Cache
(лейблы host = виртуальный хост Tomcat, context = контекст веб-приложения,
name=Cache).
| Имя метрики | Единица | Описание |
|---|---|---|
tomcat_jsp_count | page/second | Скорость загрузки (компиляции) JSP в веб-модуле |
tomcat_jsp_reload_count | page/second | Скорость перезагрузки JSP в веб-модуле |
tomcat_string_cache_access_count | get/second | Скорость обращений к строковому кэшу |
tomcat_string_cache_hit_count | hit/second | Скорость попаданий в строковый кэш |
tomcat_string_cache_size | byte | Текущий размер строкового кэша |
tomcat_string_cache_max_size | byte | Максимальный размер строкового кэша |
tomcat_web_cache_hit_count | hit/second | Скорость попаданий в кэш веб-ресурсов контекста |
tomcat_web_cache_lookup_count | get/second | Скорость обращений к кэшу веб-ресурсов контекста |
Метрики пула JDBC-соединений
Появляются только если приложение использует Catalina:type=DataSource
(Tomcat JDBC Connection Pool). Обычные gauge.
| Имя метрики | Единица | Описание |
|---|---|---|
tomcat_jdbc_connection_pool_active | connection | Установленных соединений пула, занятых сейчас |
tomcat_jdbc_connection_pool_idle | connection | Установленных соединений пула в простое |
tomcat_jdbc_connection_pool_size | connection | Всего установленных соединений пула (занятые + простаивающие) |
tomcat_jdbc_connection_pool_max_active | connection | Максимальное число открытых соединений |
tomcat_jdbc_connection_pool_max_idle | connection | Максимальное число простаивающих соединений |
tomcat_jdbc_connection_pool_min_idle | connection | Минимальное число простаивающих соединений |
Метрик уровня HTTP-сессий (
Catalina:type=Manager) в стандартном наборе интеграции нет — если они нужны, добавьте свой блокconf.yamlс JMX-bean’омCatalina:type=Manager(атрибутыactiveSessions,sessionCounter,expiredSessions,rejectedSessions, …).
Ключевые метрики для дашбордов и алертов
Доступность
- Отсутствие свежих серий по
instance— алерт: Tomcat недоступен или JMX отвалился (агент не получает метрики). Сервис-проверкаtomcat_can_connect— индикатор того, что JMX-подключение установлено.
Насыщение пула потоков
tomcat_threads_busy / tomcat_threads_maxpername(коннектор) — основной SLI. Приближение к1→ пул исчерпан, новые запросы ждут в очереди acceptor’а. Алерт при> 0.85–0.9.- Рост
tomcat_threads_countкtomcat_threads_max— пул расширяется под нагрузкой; если упёрся вmaxиbusyтоже у потолка — пора увеличиватьmaxThreadsили масштабировать.
Поток запросов
tomcat_request_countpername— RPS коннектора.tomcat_bytes_rcvd/tomcat_bytes_sent— объём входящего/исходящего трафика; резкий ростbytes_sentбез ростаrequest_count= крупные ответы.- На уровне приложения —
tomcat_servlet_request_countperwebmodule/name.
Ошибки
tomcat_error_countpername— частота ошибочных ответов коннектора; алерт при ненулевом или превышении доли отrequest_count.tomcat_servlet_error_countperwebmodule/name— какой именно сервлет «фонит» ошибками.
Latency
tomcat_processing_time(rate, мс/с) растёт пропорционально RPS × среднему времени запроса — резкий рост при стабильномrequest_count= деградация.tomcat_max_time— пиковая длительность запроса коннектора; на уровне сервлета —tomcat_servlet_max_time/tomcat_servlet_processing_time.
JVM
jvm_heap_memory / jvm_heap_memory_maxблизко к1— приближение к OOM; смотрите вместе сjvm_gc_major_collection_count/jvm_gc_major_collection_time(частые/долгие full GC = «GC trashing»).jvm_thread_countнеконтролируемо растёт — утечка потоков.jvm_os_open_file_descriptorsу потолка ulimit — утечка дескрипторов (незакрытые соединения/файлы).
Кэши
tomcat_web_cache_hit_count / tomcat_web_cache_lookup_count— hit-ratio кэша веб-ресурсов; низкий ratio при высокомlookup_count= кэш мал (cacheMaxSize) или приложение постоянно читает новые ресурсы.
Сбор логов Tomcat
Логи Tomcat собираются ProtoOBP агентом и отправляются в бэкенд ProtoOBP.
Здесь — только специфичные для Tomcat настройки. Включение логов на стороне
агента (logs_enabled, logs_pobp_url) описано в
Получение данных логов.
Конфигурация ProtoOBP агента
Если агент запускается в виде службы на хосте
Дополните уже существующий /etc/protoobp-agent/conf.d/tomcat.d/conf.yaml
(тот же файл, в котором лежит instances: для JMX) блоком logs::
logs:
- type: file
path: <CATALINA_BASE>/logs/catalina.out
source: tomcat
service: tomcat
log_processing_rules:
- type: multi_line
name: log_start_with_date
pattern: \d{2}-\w{3}-\d{4}
# Если включён AccessLogValve (по умолчанию пишет в файл, не в stdout):
- type: file
path: <CATALINA_BASE>/logs/localhost_access_log.*.txt
source: tomcat
service: tomcat
<CATALINA_BASE> — каталог инстанса Tomcat (часто совпадает с CATALINA_HOME,
например /opt/tomcat или /usr/local/tomcat). catalina.out — это
перенаправленный stdout/stderr процесса Tomcat (то, куда ConsoleHandler JULI
печатает строки лога); access-лог появляется, только если в server.xml
сконфигурирован AccessLogValve.
Перезапустите агента: systemctl restart protoobp-agent.
Если агент запускается в виде Docker контейнера
Шаг 1 — включите сбор логов в самом агенте через переменные окружения и смонтируйте директорию JSON-логов docker-демона:
services:
protoobp-agent:
environment:
POBP_LOGS_ENABLED: "true"
POBP_LOGS_CONFIG_USE_HTTP: "true"
POBP_LOGS_CONFIG_LOGS_POBP_URL: <protoobp-backend>:<port>
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# Прямое чтение JSON-лог файлов docker-демона быстрее,
# чем тянуть их через Docker socket API.
- /var/lib/docker/containers:/var/lib/docker/containers:ro
Шаг 2 — добавьте лейбл com.protoobp.ad.logs к контейнеру Tomcat. Агент
подхватит stdout/stderr контейнера (официальный образ tomcat пишет туда
catalina.out) и пометит записи указанными source и service:
services:
tomcat:
labels:
com.protoobp.ad.logs: '[{"source": "tomcat", "service": "tomcat", "log_processing_rules": [{"type": "multi_line", "name": "log_start_with_date", "pattern": "\\d{2}-\\w{3}-\\d{4}"}]}]'
Только нужные контейнеры
Если в агенте не задана переменнаяPOBP_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true,
агент собирает логи только тех контейнеров, на которых есть лейбл
com.protoobp.ad.logs.Multi-line
Tomcat пишет лог через JULIConsoleHandler (java.util.logging.SimpleFormatter),
и каждая запись начинается с метки времени в формате dd-MMM-yyyy HH:mm:ss.SSS,
например 12-May-2026 10:00:00.123 INFO [main] … — день-месяц-год, а не
yyyy-MM-dd, как у многих других сервисов. Поэтому якорь правила multi_line
здесь — \d{2}-\w{3}-\d{4}. Правило склеивает следующие за меткой времени
строки (Java stack traces, multi-line сообщения) в одну логическую запись;
без него каждая строка трейса попадёт в ProtoOBP как отдельная запись.Проверка
В выводе agent status должен быть раздел Logs Agent с источником tomcat
и ненулевым BytesRead:
docker exec protoobp-agent agent status \
| sed -n '/^==== Logs Agent ====/,/^====/p'
docker
------
- Type: file
Path: /var/lib/docker/containers/<id>/<id>-json.log
Service: tomcat
Source: tomcat
BytesRead: 13158
(Поле Status у источника типа «JSON-файл docker-контейнера» может
отображаться как Pending даже при активном чтении — ориентируйтесь на
ненулевой BytesRead и на рост LogsProcessed в шапке раздела Logs Agent.)