Продолжаем развивать систему мониторинга и оповещений. В данной заметке рассмотрим визуализацию состояния MongoDB. Есть замечательный вариант для мониторинга от Percona использующий Prometheus и если у вас сложная распределённая система я бы рекомендовал использовать именно его. Но т.к. мне необходимо мониторить всего два сервера MongoDB, поэтому я просто использовал выходные данные утилиты mongostat при помощи следующего скрипта и collectd для передачи результата в graphite: 

vi /usr/local/script/mongo.sh

 

#!/bin/bash
host="${COLLECTD_HOSTNAME:-`hostname -f`}"
pause="${COLLECTD_INTERVAL:-10}"
while getopts "h:p:u:" c; do
       case $c in
               h)      host=$OPTARG;;
               p)      pause=$OPTARG;;
               *)      echo "Usage: $0 [-h <hostname>] [-p <seconds>]";;
       esac
done
version=`mongostat --version|grep "mongostat version"|awk -F'[^0-9.]*' '$0=$2'|tr -d '.'`
#column only for version 3.4 and higher from serverStatus fields
column='insert,query,update,delete,getmore,flushes,dirty,used,net_in,net_out,conn,uptime,globalLock.activeClients.writers,'
column2='globalLock.activeClients.readers,globalLock.activeClients.total,'
asserts='asserts.regular,asserts.warning,asserts.msg,asserts.user,asserts.rollovers,'
resource='wiredTiger.concurrentTransactions.read.out,wiredTiger.concurrentTransactions.write.out,'
resource2='wiredTiger.concurrentTransactions.read.available,wiredTiger.concurrentTransactions.write.available,'
cursors='metrics.cursor.open.total,metrics.cursor.timedOut,metrics.cursor.open.noTimeout,'
connections='connections.current,connections.available,'
mem='mem.virtual,mem.resident,extra_info.page_faults,'
sat='globalLock.currentQueue.readers,globalLock.currentQueue.writers'
column=$column$column2$asserts$resource$resource2$cursors$connections$mem$sat
#check version of mongodb
if [ $version -ge 340 ]
   then
     param='-n1 --noheaders --humanReadable=false -o'$column
   else
     param='-n1 --noheaders'
     column=`mongostat -h andromeda -n 1|head -n 1`
fi
while [ $? -eq 0 ]; do
#replace coma to space
column="${column//,/ }"
#remove dots
column="${column//./}"
       mongostat $param -h $host |sed s/*//g\
       |while IFS=' ' read $column; do
               for word in $(echo $column)
               do
                   pa=`echo ${!word}|tr -d '%|'|awk '/[0-9]$/{print $1;next};/[gG]$/{printf"%u\n", \
                   $1*(1024*1024*1024);next};/[mM]$/{printf "%u\n", $1*(1024*1024);next};/[kK]$/{printf "%u\n", $1*1024;next}'`
                echo "PUTVAL $host/mongodb/gauge-mongo_$word interval=$pause N:$pa"
               done
       done
       sleep $pause
done

chmod +x /usr/local/script/mongo.sh

Несколько замечаний. Начиная с версии 3.4 в mongostat появились очень полезные опции - "--humanReadable=false" - позволяет вывысти информацию не переводя данные в убочитаемые человеку, такие как килобайты, мегабайты и т.п., "-о" - позволяет определить список выводимых полей, используется результат запроса serverStatus. Но если используется версия ниже 3.4 результат ограничен только выводом самой утилиты. По этой причине я использовал в скрипте проверку версии mongostat

Пора передать данные в graphite. Используем collectd и плагин exec

vi /etc/collectd/collectd.conf

 

LoadPlugin write_graphite
LoadPlugin exec
<Plugin exec>
    exec nobody "/usr/local/script/mongo.sh"
</Plugin>
<Plugin write_graphite>
       <Node "mongo">
               Host "10.0.0.1"
               Port "2003"
               Protocol "tcp"
               ReconnectInterval 0
               LogSendErrors true
               Prefix "andromeda"
               Postfix "collectd"
               StoreRates true
               AlwaysAppendDS false
               EscapeCharacter "_"
               SeparateInstances false
               PreserveSeparator false
               DropDuplicateFields false
       </Node>
</Plugin>


И строим графики в grafana. В итоге получим что-то похожее на :
mongo grafana