0. Общие моменты
Про технологический журнал 1С Предприятия слышали многие (если не слышали, то Вам сюда), а что и как из него можно извлечь для многих остается весьма сложной "наукой". Предлагаемый ниже материал не претендует на оригинальность, а всего лишь представляет еще один взгляд на "проблему". Важно понимать, что собираемые, в результате выполнения описанных действий, данные не дают готовых ответов/решений, а носят характер вспомогательных для анализа и/или быстрого выявления имеющихся проблем.
Вместе с тем, это еще один материал, который немного про GNU/Linux, и немного про инструменты для анализа работы 1С Предприятия не от фирмы 1С.
ВАЖНО: Ответственность за любые последствия, возникшие в результате внесения изменений в работающую систему по материалам данной статьи, лежат исключительно на лице, внесшим данные изменения!
1. Настройки сервера 1С Предприятия
1.1. Поместить файлы 1c_common_module.sh и 1c_work_server.sh (см. Приложения 2,3) в каталог /etc/zabbix/scripts. Установить права на выполнение (см. man 1 chmod);
1.2. Добавить конфигурационный файл для zabbix-agent, содержащий необходимые значения параметра UserParameter
UserParameter=1c.ws.locks[*],/etc/zabbix/scripts/1c_work_server.sh locks $1 $2 $3 $4 $5 $6
UserParameter=1c.ws.calls[*],/etc/zabbix/scripts/1c_work_server.sh calls $1 $2 $3
UserParameter=1c.ws.memory[*],/etc/zabbix/scripts/1c_work_server.sh memory
UserParameter=1c.ws.ram[*],/etc/zabbix/scripts/1c_work_server.sh ram
UserParameter=1c.ws.excps[*],/etc/zabbix/scripts/1c_work_server.sh excps $1
UserParameter=1c.ws.dump_logs[*],/etc/zabbix/scripts/1c_work_server.sh dump_logs $1 $2
Текст 1. Содержимое файла /etc/zabbix/zabbix_agentd.d/userparameter_1c-ws.conf
1.3. Перезапустить сервис zabbix-agent
[fedotov@server_a ~]$ sudo systemctl restart zabbix-agent
1.4. Создать каталог /var/log/1C/zabbix/, владельцем установить пользователя:группу от имени которого выполняются процессы сервера 1С Предприятия (по умолчанию, usr1cv8:grp1cv8, см. man 1 chown). Внутри созданного каталога создать подкаталог problem_log.
1.5. Пользователя zabbix добавить в группу grp1cv8, чтобы он мог читать файлы журналов:
[fedotov@server_a ~]$ sudo usermod -a -G grp1cv8 zabbix
1.6. Создать файл logcfg.xml или добавить секции log содержимое, которого приведено в Приложении 1.
1.7. Убедиться что технологический журнал стал собираться в соответствующих подкаталогах каталога, созданного в п.1.4.
2. Настройки на Zabbix-сервере
2.1. Сделать импорт шаблона 1c_work_server.xml (см. Приложение 4).
2.2. Добавить данный шаблон серверу 1С Предприятия.
2.3. С помощью макроса {$LOG_DIR} вы можете менять каталог содержащий файлы технологического журнала (см. п.1.4.).
2.4. С помощью макроса {$TOP_CALL_LIMIT} можно задать количество строк в ТОП-отборах по серверным вызовам.
2.5. С помощью макроса {$MAX_LOCK_WAIT} можно установить пороговое количество секунд ожидания на управляемых блокировках, по превышении которого будет срабатывать триггер.
3. Что получилось?
Каждый час zabbix будет анализировать файлы технологического журнала за предыдущий час и выдавать информацию:
- По управляемым блокировкам (суммарное ожидание, количество таймаутов, количество взаимоблокировок). Триггеры срабатывают если обнаружены таймауты, или взаимоблокировки, или превышено пороговое значение суммарного ожидания на блокировках (установленное макросом {$MAX_LOCK_WAIT}). В случае если обнаружены какие-то проблемы, то файл технологического журнала копируется в каталог problem_log.
- По суммарной длительности серверного вызова, с указанием части от суммарной длительности вызовов по конкретной ИБ
- По суммарному процессорному времени с указанием указанием части от суммарного процессорного времени по конкретной ИБ
- По суммарному количеству серверных вызовов.
<config xmlns="http://v8.1c.ru/v8/tech-log">
<dump create="false"/>
<log location="/var/log/1C/zabbix/locks" history="1">
<event>
<eq property="name" value="tlock"/>
</event>
<event>
<eq property="name" value="ttimeout"/>
</event>
<event>
<eq property="name" value="tdeadlock"/>
</event>
<property name="p:processname"/>
<property name="t:connectid"/>
<property name="waitconnections"/>
<property name="deadlockconnectionintersections"/>
<property name="regions"/>
<property name="locks"/>
<property name="context"/>
</log>
<log location="/var/log/1C/zabbix/calls" history="1">
<event>
<eq property="name" value="call"/>
<ne property="context" value=""/>
</event>
<event>
<eq property="name" value="call"/>
<ne property="module" value=""/>
<ne property="method" value=""/>
</event>
<property name="p:processname"/>
<property name="context"/>
<property name="module"/>
<property name="method"/>
<property name="memorypeak"/>
<property name="cputime"/>
<property name="inbytes"/>
<property name="outbytes"/>
</log>
<log location="/var/log/1C/zabbix/excps" history="1">
<event>
<eq property="name" value="excp"/>
</event>
<property name="p:processname"/>
<property name="descr"/>
<property name="context"/>
</log>
</config>
#!/bin/bash
#
# Мониторинг 1С Предприятия 8.3 (общие переменные и функции)
#
# (c) 2019-2020, Алексей Ю. Федотов
#
# Email: fedotov@kaminsoft.ru
#
# Имя сервера, используемое в кластере 1С Предприятия
HOSTNAME=$(hostname -s)
# Добавление пути к бинарным файлам 1С Предприятия
PATH=${PATH}:$(ls -d /opt/1C/v8*/[xi]* | tail -n1)
# Модуль менеджера задач
TM_MODULE="1c_common_tm.sh"
[[ -f ${0%/*}/${TM_MODULE} ]] && source ${0%/*}/${TM_MODULE} 2>/dev/null
# Каталог для различных кешей скриптов
CACHE_DIR="/var/tmp/1C"
[[ ! -d ${CACHE_DIR} ]] && mkdir -p ${CACHE_DIR}
# Файл списка кластеров
CLSTR_CACHE="${CACHE_DIR}/1c_clusters_cache"
# Параметры взаимодействия с сервисом RAS
declare -A RAS_PARAMS=([port]=1545 [timeout]=1.5 [auth]="")
# Общие для всех скрпитов тексты ошибок
ERROR_UNKNOWN_MODE="Неизвестный режим работы скрипта!"
ERROR_UNKNOWN_PARAM="Неизвестный параметр для данного режима работы скрипта!"
# Вывести сообщение об ошибке переданное в аргументе и выйти с кодом 1
function error {
echo "ОШИБКА: ${1}" >&2
exit 1
}
# Вывести разделительную строку длинной ${1} из символов ${2}
# По-умолчанию раделительная строка - это 80 символов "-"
function put_brack_line {
[[ -n ${1} ]] && LIMIT=${1} || LIMIT=80
[[ -n ${2} ]] && CHAR=${2} || CHAR="-"
printf "%*s\n" ${LIMIT} ${CHAR} | sed "s/ /${CHAR}/g"
}
# Выполнить серию команд ${1} с параметром, являющимся элементом массива ${@}, следующим за ${1}
function execute_tasks {
TASK_CMD=${1}
shift
if [[ -z ${TM_AVAILABLE} || ${#@} -eq 1 ]]; then
for CURR_TASK in ${@}; do
${TASK_CMD} ${CURR_TASK}
done
else
TASKS_LIST=(${@})
tasks_manager ${TASK_CMD} 3
fi
}
# Проверить наличие ring license и вернуть путь до ring
function check_ring_license {
[[ ! -f /etc/1C/1CE/ring-commands.cfg ]] && error "Не установлена утилита ring!"
LIC_TOOL=$(grep license-tools /etc/1C/1CE/ring-commands.cfg | cut -d: -f2)
[[ -z ${LIC_TOOL} ]] && error "Не установлена утилита license-tools!"
ls ${LIC_TOOL%\/*\/*}/*ring*/ring
}
# Получить список имен установленных программных лицензий
# в качестве параметра ${1} указать путь до ring
function get_license_list {
${1} license list --send-statistics false | sed -re 's/^([0-9\-]+).*/\1/'
}
# Установить параметры взаимодействия с сервисом RAS
# Метод заменяет значения в массиве RAS_PARAMS значениями,
# указанными в параметрах:
# * ${1} - номер порта RAS
# * ${2} - максимальное время ожидания ответа RAS
# * ${3} - пользователь администратор кластрера
# * ${4} - пароль пользователя администратора кластера
function make_ras_params {
[[ -n ${1} ]] && RAS_PARAMS[port]=${1}
[[ -n ${2} ]] && RAS_PARAMS[timeout]=${2}
[[ -n ${3} ]] && RAS_PARAMS[auth]="--cluster-user=${3}"
[[ -n ${4} ]] && RAS_PARAMS[auth]+=" --cluster-pwd=${4}"
}
# Сохранить список кластеров во временный файл
function push_clusters_list {
# Сохранить список UUID кластеров во временный файл
function push_clusters_uuid {
CURR_CLSTR=$( timeout -s HUP ${RAS_PARAMS[timeout]} rac cluster list \
${1%%:*}:${RAS_PARAMS[port]} | grep -Pe '^(cluster|name|port)' | \
perl -pe 's/[ "]//g; s/^name:(.*)$/\1\n/; s/^cluster:(.*)/\1,/; s/^port:(.*)/\1,/; s/\n//' | \
grep -Pe ${1##*:} | perl -pe 's/(.*,)\d+,(.*)/\1\2/; s/\n/;/' )
[[ -n ${CURR_CLSTR} ]] && echo ${1%%:*}:${CURR_CLSTR} >> ${CLSTR_CACHE}
}
# Получим список менеджеров кластеров, в которых участвует данный сервер, следующего вида:
# <имя_сервера>:<номер_порта_0>[|<номер_порта_1>[|..<номер_порта_N>]]
RMNGR_LIST=( $(pgrep -ax rphost | \
sed -r 's/.*-regport ([^ ]+).*/\0|\1/; s/.*-reghost ([^ ]+).*\|/\1:/' | sort -u | \
awk -F: '{ if ( clstr_list[$1]== "" ) { clstr_list[$1]=$2 } \
else { clstr_list[$1]=clstr_list[$1]"|"$2 } } \
END { for ( i in clstr_list ) { print i":"clstr_list[i]} }' ) )
# Проверка необходимости обновления временного файла:
# - если временный файл не сущствует
# - если количество строк во временном файле отличается от количества элементов
# списка менеджеров кластеров
# - если временный файл старше 1 часа
if [[ ! -e ${CLSTR_CACHE} || ${#RMNGR_LIST[@]} -ne $(grep -c "." ${CLSTR_CACHE}) ||
$(date -r ${CLSTR_CACHE} "+%s") -lt $(date -d "last hour" "+%s") ]]; then
cat /dev/null > ${CLSTR_CACHE}
execute_tasks push_clusters_uuid ${RMNGR_LIST[@]}
fi
}
# Считать список кластеров из временного файла в массив HOSTS_LIST
# (массив должен быть инициализирован до вызова метода)
function pop_clusters_list {
push_clusters_list # Обновить список перед извлечением
while read -r CURRENT_HOST; do
HOSTS_LIST+=(${CURRENT_HOST})
done < ${CLSTR_CACHE}
}
#!/bin/bash
#
# Мониторинг 1С Предприятия 8.3 (рабочий сервер)
#
# (c) 2019-2020, Алексей Ю. Федотов
#
# Email: fedotov@kaminsoft.ru
#
source ${0%/*}/1c_common_module.sh 2>/dev/null || { echo "ОШИБКА: Не найден файл 1c_common_module.sh!" ; exit 1; }
# Коды завершения процедуры архивирования файлов технологического журнала
DUMP_CODE_0=0 # Архивированение файлов ТЖ выполнено успешно
DUMP_CODE_1=1 # Файл архива ТЖ уже существует
DUMP_CODE_2=2 # При архивировании файлов ТЖ возникли ошибки
DUMP_CODE_3=3 # Не удалось выполнить архивирование ТЖ на удаленом сервере
function check_log_dir {
[[ ! -d "${1}/zabbix/${2}" ]] && error "Неверно задан каталог технологического журнала!"
}
function get_calls_info {
MODE=${1}
[[ -n ${2} ]] && TOP_LIMIT=${2} || TOP_LIMIT=25
case ${MODE} in
count) echo "Кол-во | Длит-ть,с | СрДл-ть,мс | Контекст";;
cpu) echo "Процессор,с (%) | Длит-ть,с | Кол-во | СрДл-ть,мс | Контекст";;
duration) echo "Длительность,с (%) | Кол-во | СрДл-ть,мс | Процессор | Контекст";;
lazy) echo "Длит-ть,с | Кол-во | СрДл-ть,мс | Процессор | Контекст";;
dur_avg) echo "СрДл-ть,с | Длит-ть,с | Кол-во | Процессор | Контекст";;
memory) echo "Память,МБ | СрДл-ть,мс | СрПр-ор,мс | Кол-во | Контекст";;
iobytes) echo "Объем IO,МБ | Длит-ть,с | Процессор | Кол-во | Контекст";;
*) error "${ERROR_UNKNOWN_PARAM}" ;;
esac
put_brack_line
cat ${LOG_DIR}/rphost_*/${LOG_FILE}.log 2>/dev/null | grep -Pe "CALL,.*(Context|Module)" | \
sed -re 's/,Module=(.*),Method=/,Context=ОбщийМодуль.ФоновыйВызов : ОбщийМодуль.\1.Модуль./' | \
sed -re "s/[0-9]+:[0-9]+.[0-9]+-//; s/,Method=[^,]+//; s/,[a-zA-Z:]+=/,/g" | \
awk -F, -v mode=${MODE} '{ if ($4) {count[$4"->"$5]+=1; durations[$4"->"$5]+=$1; \
cpus[$4"->"$5]+=$9; iobytes[$4"->"$5]+=$7+$8; duration[$4]+=$1; cpu[$4]+=$9; \
if ( mempeak[$4"->"$5] < $6 ) { mempeak[$4"->"$5]=$6; } } } \
END { for ( i in count ) { \
if ( mode == "count" ) { printf "%6d | %9.2f | %10.2f | %s\n", count[i], \
durations[i]/1000000, durations[i]/count[i]/1000, i } \
else if ( mode == "cpu" ) { printf "%8.2f (%4.1f) | %9.2f | %6d | %10.2f | %s\n", \
cpus[i]/1000000, cpus[i]/cpu[substr(i,0,index(i,"->")-1)]*100, durations[i]/1000000, count[i], durations[i]/count[i]/1000, i } \
else if ( mode == "lazy" ) { printf "%f@%9.2f | %6d | %10.2f | %9.2f | %s\n", \
durations[i]/cpus[i], durations[i]/1000000, count[i], durations[i]/count[i]/1000, cpus[i]/1000000, i } \
else if ( mode == "dur_avg" ) { printf "%9.2f | %9.2f | %6d | %9.2f | %s\n", \
durations[i]/count[i]/1000000, durations[i]/1000000, count[i], cpus[i]/1000000, i } \
else if ( mode == "duration" ) { printf "%11.2f (%4.1f) | %6d | %10.2f | %9.2f | %s\n", \
durations[i]/1000000, durations[i]/duration[substr(i,0,index(i, "->")-1)]*100, count[i], durations[i]/count[i]/1000, cpus[i]/1000000, i } \
else if ( mode == "memory" ) { printf "%9.2f | %10.2f | %10.2f | %6d | %s\n", \
mempeak[i]/1024/1024, durations[i]/count[i]/1000, cpus[i]/count[i]/1000, count[i], i } \
else if ( mode == "iobytes" ) { printf "%11.2f | %9.2f | %9.2f | %6d | %s\n", \
iobytes[i]/1024/1024, durations[i]/1000000, cpus[i]/1000000, count[i], i } \
} }' | \
sort -rn | head -n ${TOP_LIMIT} | awk -v mode=${MODE} -F"@" '{ if ( mode == "lazy" ) { print $2 } else { print $0 } }'
}
function get_locks_info {
STORE_PERIOD=30 # Срок хранения архивов ТЖ, содержащих информацию о проблемах - 30 дней
WAIT_LIMIT=${1}
function save_logs {
if [[ $(echo ${1} | grep -ic ${HOSTNAME}) -ne 0 ]]; then
DUMP_RESULT=$(dump_logs ${LOG_DIR} ${LOG_FILE})
else
DUMP_RESULT=$(zabbix_get -s ${1} -k 1c.ws.dump_logs[${LOG_DIR},${LOG_FILE}] 2>/dev/null)
[[ -z ${DUMP_RESULT} || ${DUMP_RESULT} -eq ${DUMP_CODE_2} ]] && DUMP_RESULT=${DUMP_CODE_3}
fi
[[ ${DUMP_RESULT} -gt 1 ]] && DUMP_TEXT="ОШИБКА: не удалось сохранить файлы технологического журнала!" ||
DUMP_TEXT="Файлы технологического журнала сохранены (${LOG_DIR%/*}/problem_log/${LOG_DIR##*/}-${LOG_FILE}.tgz)"
[[ -n ${DUMP_RESULT} ]] && echo "[${1} (${DUMP_RESULT})] ${DUMP_TEXT}" && unset DUMP_RESULT
}
echo "lock: $(cat ${LOG_DIR}/rphost_*/${LOG_FILE}.log 2>/dev/null | grep -c ',TLOCK,')"
RESULT=($(cat ${LOG_DIR}/rphost_*/${LOG_FILE}.log 2>/dev/null | \
grep -P "(TDEADLOCK|TTIMEOUT|TLOCK.*,WaitConnections=\d+)" | \
sed -re "s/[0-9]{2}:[0-9]{2}.[0-9]{6}-//; s/,[a-zA-Z\:]+=/,/g" | \
awk -F"," -v lts=${WAIT_LIMIT} 'BEGIN {dl=0; to=0; lw=0} { if ($2 == "TDEADLOCK") {dl+=1} \
else if ($2 == "TTIMEOUT") { to+=1 } \
else { lw+=$1; lws[$4"->"$6]+=$1; } } \
END { print "timeout: "to"<nl>"; print "deadlock: "dl"<nl>"; print "wait: "lw/1000000"<nl>"; \
if ( lw > 0 ) { print "Ожидания на блокировках (установлен порог "lts" сек):<nl>"; \
for ( i in lws ) { print "> "i" - "lws[i]/1000000" сек.<nl>" } } }'))
echo ${RESULT[@]} | perl -pe 's/<nl>\s?/\n/g'
if [[ ${RESULT[1]%<*} != 0 || ${RESULT[3]%<*} != 0 || $(echo "${RESULT[5]%<*} > ${WAIT_LIMIT}" | bc) != 0 ]]; then
shift; make_ras_params ${@}
HOSTS_LIST=()
pop_clusters_list
for CURRENT_HOST in ${HOSTS_LIST}; do
CLSTR_LIST=${CURRENT_HOST#*:}
for CURR_CLSTR in ${CLSTR_LIST//;/ }; do
SRV_LIST+=( $(timeout -s HUP ${RAS_PARAMS[timeout]} rac server list --cluster=${CURR_CLSTR%,*} \
${RAS_PARAMS[auth]} ${CURRENT_HOST%:*}:${RAS_PARAMS[port]} 2>/dev/null| grep agent-host | sort -u | \
sed -r "s/.*: (.*)$/\1/; s/\"//g") )
done
done
fi
execute_tasks save_logs $(echo ${SRV_LIST[@]} | perl -pe 's/ /\n/g' | sort -u)
find ${LOG_DIR%/*}/problem_log/ -mtime +${STORE_PERIOD} -name "*.tgz" -delete 2>/dev/null
}
function get_excps_info {
for PROCESS in ${PROCESS_NAMES[@]}; do
EXCP_COUNT=$(cat ${LOG_DIR}/${PROCESS}_*/${LOG_FILE}.log 2>/dev/null | grep -c ",EXCP,")
echo ${PROCESS}: $([[ -n ${EXCP_COUNT} ]] && echo ${EXCP_COUNT} || echo 0)
done
}
function get_memory_counts {
MEMORY_PAGE_SIZE=$(getconf PAGE_SIZE)
RPHOST_PID_HASH="${CACHE_DIR}/1c_rphost_pid_hash"
for PROCESS in ${PROCESS_NAMES[@]}; do
PROCESS_MEMORY=0
PID_LIST=$(pgrep -xd, ${PROCESS})
for CURRENT_PID in ${PID_LIST//,/ }; do
(( PROCESS_MEMORY+=$(cut -f2 -d" " /proc/${CURRENT_PID}/statm)*${MEMORY_PAGE_SIZE} )) ;
done
if [[ ${PROCESS} == "rphost" ]]; then
RPHOST_OLD_HASH=$(cat ${RPHOST_PID_HASH} 2>/dev/null)
echo ${PID_LIST} | md5sum | cut -f1 -d\ > ${RPHOST_PID_HASH}
[[ ${RPHOST_OLD_HASH} == $(cat ${RPHOST_PID_HASH}) ]]
CHANGE=${?}
fi
echo ${PROCESS}: $(echo ${PID_LIST//,/ } | wc -w) ${PROCESS_MEMORY} ${CHANGE}
done
}
# Архивирование файлов ТЖ с именем ${2} из каталога ${1} в problem_log
function dump_logs {
# TODO: Проверка наличия каталога problem_log и возможности записи в него
if [[ -f ${1%/*}/problem_log/${1##*/}-${2}.tgz ]]; then
DUMP_RESULT=${DUMP_CODE_1}
else
cd ${1} 2>/dev/null && tar czf ../problem_log/${1##*/}-${2}.tgz ./rphost_*/${2}.log && \
DUMP_RESULT=${DUMP_CODE_0} || DUMP_RESULT=${DUMP_CODE_2}
fi
echo ${DUMP_RESULT}
}
case ${1} in
calls | locks | excps) check_log_dir ${2} ${1};
LOG_FILE=$(date --date="last hour" "+%y%m%d%H");
LOG_DIR="${2%/}/zabbix/${1}" ;;&
memory | excps) PROCESS_NAMES=(ragent rmngr rphost) ;;&
calls) shift 2; get_calls_info ${@} ;;
locks) shift 2; get_locks_info ${@} ;;
excps) shift 2; get_excps_info ${@} ;;
memory) get_memory_counts ;;
ram) free -b | grep -m1 "^[^ ]" | awk '{ print $2 }';;
dump_logs) shift; dump_logs ${@} ;;
*) error "${ERROR_UNKNOWN_MODE}" ;;
esac
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
<version>4.4</version>
<date>2020-05-26T08:48:55Z</date>
<groups>
<group>
<name>Templates (Kaminsoft)</name>
</group>
</groups>
<templates>
<template>
<template>Template App 1C Enterprise Work Server</template>
<name>Template App 1C Enterprise Work Server</name>
<description>Шаблон для мониторинга рабочего сервера 1С Предприятия, работающего на платформе GNU/Linux
Подробнее https://slothfk.github.io/1c_zabbix_template_ce/</description>
<groups>
<group>
<name>Templates (Kaminsoft)</name>
</group>
</groups>
<applications>
<application>
<name>[1С] Информация</name>
</application>
<application>
<name>[1С] Ошибки</name>
</application>
<application>
<name>[1С] Производительность</name>
</application>
<application>
<name>[1С] Управляемые блокировки</name>
</application>
<application>
<name>[1С] Устойчивость системы</name>
</application>
</applications>
<items>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} по суммарному количеству</name>
<key>1c.ws.calls[{$LOG_DIR},count,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} по суммарному процессорному времени</name>
<key>1c.ws.calls[{$LOG_DIR},cpu,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} по суммарной длительности</name>
<key>1c.ws.calls[{$LOG_DIR},duration,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} по средней длительности</name>
<key>1c.ws.calls[{$LOG_DIR},dur_avg,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} по суммарному вводу-выводу</name>
<key>1c.ws.calls[{$LOG_DIR},iobytes,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} "ленивых" вызовов</name>
<key>1c.ws.calls[{$LOG_DIR},lazy,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Серверные вызовы] ТОП{$TOP_LIST_SIZE} по максимальной памяти за вызов</name>
<key>1c.ws.calls[{$LOG_DIR},memory,{$TOP_LIST_SIZE}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Рабочий сервер] Ошибки процессов</name>
<type>ZABBIX_ACTIVE</type>
<key>1c.ws.excps[{$LOG_DIR}]</key>
<delay>1h</delay>
<history>0</history>
<trends>0</trends>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Информация</name>
</application>
<application>
<name>[1С] Ошибки</name>
</application>
</applications>
</item>
<item>
<name>[1С/Блокировки] Число взаимоблокировок</name>
<type>DEPENDENT</type>
<key>1c.ws.locks.deadlock</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Управляемые блокировки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>deadlock: (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.locks[{$LOG_DIR},{$MAX_LOCK_WAIT},{$RAS_PORT},{$RAS_TIMEOUT},{$RAS_USER},{$RAS_PASS}]</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}>0</expression>
<name>[1С/Блокировки] Обнаружены взаимоблокировки</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Блокировки] Число блокировок</name>
<type>DEPENDENT</type>
<key>1c.ws.locks.lock</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Управляемые блокировки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>lock: (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.locks[{$LOG_DIR},{$MAX_LOCK_WAIT},{$RAS_PORT},{$RAS_TIMEOUT},{$RAS_USER},{$RAS_PASS}]</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}=0</expression>
<name>[1С/Блокировки] Отсутствуют блокировки</name>
<priority>INFO</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Блокировки] Число таймаутов</name>
<type>DEPENDENT</type>
<key>1c.ws.locks.timeout</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Управляемые блокировки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>timeout: (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.locks[{$LOG_DIR},{$MAX_LOCK_WAIT},{$RAS_PORT},{$RAS_TIMEOUT},{$RAS_USER},{$RAS_PASS}]</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}>0</expression>
<name>[1С/Блокировки] Обнаружены таймауты</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Блокировки] Общее ожидание на блокировках</name>
<type>DEPENDENT</type>
<key>1c.ws.locks.wait</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<value_type>FLOAT</value_type>
<units>s</units>
<applications>
<application>
<name>[1С] Управляемые блокировки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>wait: (\d+.?\d*)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.locks[{$LOG_DIR},{$MAX_LOCK_WAIT},{$RAS_PORT},{$RAS_TIMEOUT},{$RAS_USER},{$RAS_PASS}]</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}>{$MAX_LOCK_WAIT}</expression>
<name>[1С/Блокировки] Превышено пороговое значение ожидания на блокировках</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Блокировки] Сводка</name>
<key>1c.ws.locks[{$LOG_DIR},{$MAX_LOCK_WAIT},{$RAS_PORT},{$RAS_TIMEOUT},{$RAS_USER},{$RAS_PASS}]</key>
<delay>1h</delay>
<history>30d</history>
<trends>0</trends>
<status>DISABLED</status>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Информация</name>
</application>
<application>
<name>[1С] Управляемые блокировки</name>
</application>
</applications>
</item>
<item>
<name>[1С/Рабочий сервер] Объем памяти процессов</name>
<type>ZABBIX_ACTIVE</type>
<key>1c.ws.memory</key>
<delay>30s</delay>
<history>0</history>
<trends>0</trends>
<value_type>TEXT</value_type>
<applications>
<application>
<name>[1С] Информация</name>
</application>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Агент сервера] Число процессов</name>
<type>DEPENDENT</type>
<key>1c.ws.ragent.count</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>ragent: (\d+) \d+
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}=0</expression>
<name>[1С/Агент сервера] Нет запущенных процессов</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Агент сервера] Количество исключений</name>
<type>DEPENDENT</type>
<key>1c.ws.ragent.excps</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Ошибки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>ragent: (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.excps[{$LOG_DIR}]</key>
</master_item>
</item>
<item>
<name>[1С/Агент сервера] Объем памяти всех процессов</name>
<type>DEPENDENT</type>
<key>1c.ws.ragent.memory</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<units>B</units>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>ragent: \d+ (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
</item>
<item>
<name>[1С/Рабочий сервер] Объем памяти сервера</name>
<type>ZABBIX_ACTIVE</type>
<key>1c.ws.ram</key>
<delay>1h</delay>
<history>30d</history>
<trends>90d</trends>
<units>B</units>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
</item>
<item>
<name>[1С/Менеджер кластера] Число процессов</name>
<type>DEPENDENT</type>
<key>1c.ws.rmngr.count</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>rmngr: (\d+) \d+
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}=0</expression>
<name>[1С/Менеджер кластера] Нет запущенных процессов</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Менеджер кластера] Количество исключений</name>
<type>DEPENDENT</type>
<key>1c.ws.rmngr.excps</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Ошибки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>rmngr: (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.excps[{$LOG_DIR}]</key>
</master_item>
</item>
<item>
<name>[1С/Менеджер кластера] Объем памяти всех процессов</name>
<type>DEPENDENT</type>
<key>1c.ws.rmngr.memory</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<units>B</units>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>rmngr: \d+ (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
</item>
<item>
<name>[1С/Рабочий процесс] Перемены в процессах</name>
<type>DEPENDENT</type>
<key>1c.ws.rphost.change</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Устойчивость системы</name>
</application>
</applications>
<valuemap>
<name>[1С/Рабочий процесс] Перемены в процессах</name>
</valuemap>
<preprocessing>
<step>
<type>REGEX</type>
<params>rphost: \d+ \d+ (\d)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
<triggers>
<trigger>
<expression>{count(5m,1)}>=3</expression>
<name>[1С/Рабочий процесс] Частые изменения в списке процессов</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Рабочий процесс] Число процессов</name>
<type>DEPENDENT</type>
<key>1c.ws.rphost.count</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>rphost: (\d+) \d+ \d
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
<triggers>
<trigger>
<expression>{last()}=0</expression>
<name>[1С/Рабочий процесс] Нет запущенных процессов</name>
<priority>HIGH</priority>
</trigger>
</triggers>
</item>
<item>
<name>[1С/Рабочий процесс] Количество исключений</name>
<type>DEPENDENT</type>
<key>1c.ws.rphost.excps</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<applications>
<application>
<name>[1С] Ошибки</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>rphost: (\d+)
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.excps[{$LOG_DIR}]</key>
</master_item>
</item>
<item>
<name>[1С/Рабочий процесс] Объем памяти всех процессов</name>
<type>DEPENDENT</type>
<key>1c.ws.rphost.memory</key>
<delay>0</delay>
<history>30d</history>
<trends>90d</trends>
<units>B</units>
<applications>
<application>
<name>[1С] Производительность</name>
</application>
</applications>
<preprocessing>
<step>
<type>REGEX</type>
<params>rphost: \d+ (\d+) \d
\1</params>
</step>
</preprocessing>
<master_item>
<key>1c.ws.memory</key>
</master_item>
</item>
</items>
<macros>
<macro>
<macro>{$EXCP_THRESHOLD}</macro>
<value>100</value>
<description>Пороговое количество исключений на процесс</description>
</macro>
<macro>
<macro>{$LOG_DIR}</macro>
<value>/var/log/1C</value>
<description>Каталог технологического журнала</description>
</macro>
<macro>
<macro>{$MAX_LOCK_WAIT}</macro>
<value>5</value>
<description>Пороговая величина времени ожидания на управляемых блокировках, сек</description>
</macro>
<macro>
<macro>{$RAS_PASS}</macro>
<description>Пароль пользователя администратора кластера</description>
</macro>
<macro>
<macro>{$RAS_PORT}</macro>
<value>1545</value>
<description>Сетевой порт службы RAS</description>
</macro>
<macro>
<macro>{$RAS_TIMEOUT}</macro>
<value>1.5</value>
<description>Таймаут ожидания ответа от службы RAS</description>
</macro>
<macro>
<macro>{$RAS_USER}</macro>
<description>Имя пользователя администратора кластера</description>
</macro>
<macro>
<macro>{$RPHOST_MAX_MEM}</macro>
<value>0.85</value>
<description>Относительная допустимая величина объема памяти процессов rphost</description>
</macro>
<macro>
<macro>{$TOP_LIST_SIZE}</macro>
<value>25</value>
<description>Количество записей в TOP-списках</description>
</macro>
</macros>
</template>
</templates>
<triggers>
<trigger>
<expression>{Template App 1C Enterprise Work Server:1c.ws.ragent.excps.last()}/{Template App 1C Enterprise Work Server:1c.ws.ragent.count.avg(3600)}>{$EXCP_THRESHOLD}</expression>
<name>[1С/Агент сервера] Количество исключений свыше {$EXCP_THRESHOLD}</name>
<priority>AVERAGE</priority>
</trigger>
<trigger>
<expression>{Template App 1C Enterprise Work Server:1c.ws.rmngr.excps.last()}/{Template App 1C Enterprise Work Server:1c.ws.rmngr.count.avg(3600)}>{$EXCP_THRESHOLD}</expression>
<name>[1С/Менеджер кластера] Количество исключений свыше {$EXCP_THRESHOLD}</name>
<priority>AVERAGE</priority>
</trigger>
<trigger>
<expression>{Template App 1C Enterprise Work Server:1c.ws.rphost.excps.last()}/{Template App 1C Enterprise Work Server:1c.ws.rphost.count.avg(3600)}>{$EXCP_THRESHOLD}</expression>
<name>[1С/Рабочий процесс] Количество исключений свыше {$EXCP_THRESHOLD}</name>
<priority>AVERAGE</priority>
</trigger>
<trigger>
<expression>{Template App 1C Enterprise Work Server:1c.ws.rphost.memory.last()}/{Template App 1C Enterprise Work Server:1c.ws.ram.last()}>{$RPHOST_MAX_MEM}</expression>
<name>[1С/Рабочий процесс] Превышено пороговое значение используемой памяти</name>
<priority>AVERAGE</priority>
</trigger>
</triggers>
<graphs>
<graph>
<name>[1С/Рабочий сервер] Объем используемой памяти</name>
<graph_items>
<graph_item>
<color>FF4000</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.ram</key>
</item>
</graph_item>
<graph_item>
<sortorder>1</sortorder>
<color>FC6EA3</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.ragent.memory</key>
</item>
</graph_item>
<graph_item>
<sortorder>2</sortorder>
<color>C7A72D</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rmngr.memory</key>
</item>
</graph_item>
<graph_item>
<sortorder>3</sortorder>
<color>199C0D</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rphost.memory</key>
</item>
</graph_item>
<graph_item>
<sortorder>4</sortorder>
<color>6C59DC</color>
<yaxisside>RIGHT</yaxisside>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.ragent.count</key>
</item>
</graph_item>
<graph_item>
<sortorder>5</sortorder>
<color>BA2A5D</color>
<yaxisside>RIGHT</yaxisside>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rmngr.count</key>
</item>
</graph_item>
<graph_item>
<sortorder>6</sortorder>
<color>0040FF</color>
<yaxisside>RIGHT</yaxisside>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rphost.count</key>
</item>
</graph_item>
<graph_item>
<sortorder>7</sortorder>
<color>F7941D</color>
<yaxisside>RIGHT</yaxisside>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rphost.change</key>
</item>
</graph_item>
</graph_items>
</graph>
<graph>
<name>[1С/Рабочий сервер] Ошибки процессов</name>
<graph_items>
<graph_item>
<color>199C0D</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.ragent.excps</key>
</item>
</graph_item>
<graph_item>
<sortorder>1</sortorder>
<color>F63100</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rmngr.excps</key>
</item>
</graph_item>
<graph_item>
<sortorder>2</sortorder>
<color>2774A4</color>
<item>
<host>Template App 1C Enterprise Work Server</host>
<key>1c.ws.rphost.excps</key>
</item>
</graph_item>
</graph_items>
</graph>
</graphs>
<value_maps>
<value_map>
<name>[1С/Рабочий процесс] Перемены в процессах</name>
<mappings>
<mapping>
<value>0</value>
<newvalue>изменений нет</newvalue>
</mapping>
<mapping>
<value>1</value>
<newvalue>произошло изменение</newvalue>
</mapping>
</mappings>
</value_map>
</value_maps>
</zabbix_export>
P.S. Если у Вас есть вопросы, предложения, замечания или Вам просто интересна тема мониторинга кластера серверов 1С Предприятия посредством Zabbix и не только, пишите, пообщаемся!
P.P.S. Теперь следить за проектом можно через GitHub