@@ -810,7 +810,7 @@ mongo_currentop_count() {
810810 fi
811811 mongo_eval "
812812 const __pt = db.getSiblingDB('admin');
813- const __doc = __pt.runCommand({currentOp: 1, active: true, idleConnections: false});
813+ const __doc = __pt.runCommand({currentOp: 1, active: true, idleConnections: false, allUsers: true });
814814 const __parts = '$field '.split('.');
815815 const __re = ${js_regex} ;
816816 let __count = 0;
@@ -836,6 +836,56 @@ mongo_currentop_count() {
836836 "
837837}
838838
839+ mongo_repl_lag_seconds () {
840+ mongo_eval "
841+ const __pt = db.getSiblingDB('admin');
842+ let __doc = {};
843+ try {
844+ __doc = __pt.runCommand({replSetGetStatus: 1});
845+ } catch (e) {
846+ print('');
847+ quit(0);
848+ }
849+ if (!__doc || !Array.isArray(__doc.members)) {
850+ print('');
851+ quit(0);
852+ }
853+
854+ let __primary = null;
855+ for (const __member of __doc.members) {
856+ if (__member.stateStr === 'PRIMARY' && __member.optimeDate) {
857+ __primary = __member;
858+ break;
859+ }
860+ }
861+ if (!__primary) {
862+ print(0);
863+ quit(0);
864+ }
865+
866+ const __primaryMs = new Date(__primary.optimeDate).getTime();
867+ let __maxLag = 0;
868+ for (const __member of __doc.members) {
869+ if (__member._id === __primary._id || !__member.optimeDate) {
870+ continue;
871+ }
872+ const __state = __member.stateStr || '';
873+ if (!/^(SECONDARY|STARTUP2|RECOVERING|ROLLBACK)$/.test(__state)) {
874+ continue;
875+ }
876+ const __memberMs = new Date(__member.optimeDate).getTime();
877+ if (isNaN(__memberMs)) {
878+ continue;
879+ }
880+ const __lag = Math.max(0, Math.floor((__primaryMs - __memberMs) / 1000));
881+ if (__lag > __maxLag) {
882+ __maxLag = __lag;
883+ }
884+ }
885+ print(__maxLag);
886+ "
887+ }
888+
839889_js_quote () {
840890 printf ' %s' " $1 " | perl -0pe ' s/\\/\\\\/g; s/' " '" ' /\\' " '" ' /g; $_="' " '" ' $_' " '" ' "'
841891}
@@ -996,7 +1046,7 @@ collect_mongodb_data_one() {
9961046collect_mongodb_data_loop () {
9971047 local d=" $1 "
9981048 (mongo_admin_json " db.runCommand({serverStatus: 1})" > " $( sample_file " $d " " serverStatus" " json" ) " ) &
999- (mongo_admin_json " db.runCommand({currentOp: 1, active: true, idleConnections: false})" > " $( sample_file " $d " " currentOp" " json" ) " ) &
1049+ (mongo_admin_json " db.runCommand({currentOp: 1, active: true, idleConnections: false, allUsers: true })" > " $( sample_file " $d " " currentOp" " json" ) " ) &
10001050}
10011051
10021052collect_mongodb_data_two () {
@@ -1091,10 +1141,28 @@ set_trg_func() {
10911141 fi
10921142
10931143 func=$( echo " $func " | tr ' [:upper:]' ' [:lower:]' )
1094- if [ " $func " = " status" ] || [ " $func " = " currentop" ]; then
1095- TRIGGER_FUNCTION=" trg_$func "
1096- return 0
1097- fi
1144+ case " $func " in
1145+ status|currentop|cpu|memory|writewait|repllag)
1146+ TRIGGER_FUNCTION=" trg_$func "
1147+ return 0
1148+ ;;
1149+ mem)
1150+ TRIGGER_FUNCTION=" trg_memory"
1151+ return 0
1152+ ;;
1153+ processcpu|process-cpu|proc_cpu|proc-cpu)
1154+ TRIGGER_FUNCTION=" trg_process_cpu"
1155+ return 0
1156+ ;;
1157+ processmemory|process-memory|proc_memory|proc-memory)
1158+ TRIGGER_FUNCTION=" trg_process_memory"
1159+ return 0
1160+ ;;
1161+ replicationlag|replciationlag|waitforreplicationlag|waitforreplciationlag)
1162+ TRIGGER_FUNCTION=" trg_repllag"
1163+ return 0
1164+ ;;
1165+ esac
10981166
10991167 return 1
11001168}
@@ -1109,6 +1177,92 @@ trg_currentop() {
11091177 mongo_currentop_count " $var "
11101178}
11111179
1180+ trg_cpu () {
1181+ local cpu user nice system idle iowait irq softirq steal guest guest_nice
1182+ local idle_all non_idle total total_delta idle_delta value
1183+ local cpu_state last_total last_idle
1184+
1185+ read -r cpu user nice system idle iowait irq softirq steal guest guest_nice < /proc/stat || return 1
1186+ iowait=${iowait:- 0}
1187+ irq=${irq:- 0}
1188+ softirq=${softirq:- 0}
1189+ steal=${steal:- 0}
1190+ idle_all=$(( idle + iowait))
1191+ non_idle=$(( user + nice + system + irq + softirq + steal))
1192+ total=$(( idle_all + non_idle))
1193+ cpu_state=" $PT_TMPDIR /cpu-trigger-state"
1194+
1195+ if [ ! -f " $cpu_state " ]; then
1196+ echo " $total $idle_all " > " $cpu_state "
1197+ echo 0
1198+ return 0
1199+ fi
1200+
1201+ read -r last_total last_idle < " $cpu_state " || {
1202+ echo " $total $idle_all " > " $cpu_state "
1203+ echo 0
1204+ return 0
1205+ }
1206+ total_delta=$(( total - last_total))
1207+ idle_delta=$(( idle_all - last_idle))
1208+ echo " $total $idle_all " > " $cpu_state "
1209+
1210+ if [ " $total_delta " -le 0 ]; then
1211+ echo 0
1212+ return 0
1213+ fi
1214+
1215+ value=$( awk -v total=" $total_delta " -v idle=" $idle_delta " ' BEGIN { printf "%.2f\n", ((total - idle) / total) * 100 }' )
1216+ echo " $value "
1217+ }
1218+
1219+ trg_memory () {
1220+ awk '
1221+ /^MemTotal:/ { total = $2 }
1222+ /^MemAvailable:/ { available = $2 }
1223+ /^MemFree:/ { free = $2 }
1224+ /^Buffers:/ { buffers = $2 }
1225+ /^Cached:/ { cached = $2 }
1226+ END {
1227+ if (available == "" && free >= 0) {
1228+ available = free + buffers + cached
1229+ }
1230+ if (total > 0 && available >= 0) {
1231+ printf "%.2f\n", ((total - available) / total) * 100
1232+ }
1233+ }
1234+ ' /proc/meminfo
1235+ }
1236+
1237+ trg_process_cpu () {
1238+ local pid value
1239+ pid=$( get_mongo_pid)
1240+ [ -n " $pid " ] || return 1
1241+ value=$( ps -p " $pid " -o %cpu= 2> /dev/null | awk ' {gsub(/,/, "."); printf "%.2f\n", $1 + 0; exit}' )
1242+ [ -n " $value " ] && echo " $value "
1243+ }
1244+
1245+ trg_process_memory () {
1246+ local pid value
1247+ pid=$( get_mongo_pid)
1248+ [ -n " $pid " ] || return 1
1249+ value=$( ps -p " $pid " -o %mem= 2> /dev/null | awk ' {gsub(/,/, "."); printf "%.2f\n", $1 + 0; exit}' )
1250+ [ -n " $value " ] && echo " $value "
1251+ }
1252+
1253+ trg_writewait () {
1254+ local value
1255+ value=$( mongo_status_value " globalLock.currentQueue.writers" )
1256+ if [ -z " $value " ]; then
1257+ value=0
1258+ fi
1259+ echo " $value "
1260+ }
1261+
1262+ trg_repllag () {
1263+ mongo_repl_lag_seconds
1264+ }
1265+
11121266oktorun () {
11131267 if [ " $OKTORUN " -eq 0 ]; then
11141268 [ -z " $EXIT_REASON " ] && EXIT_REASON=" OKTORUN is false"
@@ -1372,8 +1526,8 @@ model as C<pt-stalk>, but uses MongoDB administration commands instead of
13721526MySQL commands.
13731527
13741528The default trigger watches C<serverStatus.connections.current>. You can also
1375- watch C<currentOp> and count active operations whose field matches a regular
1376- expression .
1529+ watch C<currentOp>, host CPU usage, host memory usage, queued writers, and
1530+ replica set replication lag .
13771531
13781532=head1 OPTIONS
13791533
@@ -1435,7 +1589,8 @@ Do not collect if the disk has less than this percent free space.
14351589
14361590type: string; default: status
14371591
1438- Trigger source. Valid built-in values are C<status> and C<currentop>.
1592+ Trigger source. Valid built-in values are C<status>, C<currentop>, C<cpu>,
1593+ C<memory>, C<writewait>, and C<repllag>.
14391594
14401595With C<status>, L<"--variable"> is a dot-separated path inside
14411596C<serverStatus>. Example:
@@ -1446,7 +1601,25 @@ With C<currentop>, L<"--variable"> is a dot-separated field path inside each
14461601C<currentOp.inprog> document and L<"--match"> is a regex. The trigger value is
14471602the number of matching operations. Example:
14481603
1449- --function currentop --variable ns --match '^app\.orders$' --threshold 10
1604+ --function currentop --variable command.aggregate --match '^orders$' --threshold 10
1605+
1606+ With C<cpu>, the trigger value is host CPU busy percentage from C</proc/stat>.
1607+ With C<memory>, the trigger value is host memory used percentage from
1608+ C</proc/meminfo>. C<mem> is accepted as an alias for C<memory>. Example:
1609+
1610+ --function cpu --threshold 85
1611+ --function memory --threshold 90
1612+
1613+ With C<writewait>, the trigger value is
1614+ C<serverStatus.globalLock.currentQueue.writers>. Example:
1615+
1616+ --function writewait --threshold 5
1617+
1618+ With C<repllag>, the trigger value is the maximum replica set member lag behind
1619+ the primary, in seconds, from C<replSetGetStatus>. C<replicationlag> and
1620+ C<waitForReplicationLag> are accepted as aliases. Example:
1621+
1622+ --function repllag --threshold 30
14501623
14511624You can also specify a file that defines C<trg_plugin>.
14521625
@@ -1554,7 +1727,7 @@ collect immediately.
15541727
15551728=item --threshold
15561729
1557- type: int ; default: 100
1730+ type: float ; default: 100
15581731
15591732Collection is triggered when L<"--variable"> is greater than this value.
15601733
@@ -1592,7 +1765,8 @@ User for login.
15921765
15931766type: string; default: connections.current
15941767
1595- Variable to watch inside C<serverStatus> or C<currentOp>.
1768+ Variable to watch inside C<serverStatus> or C<currentOp>. This option is ignored
1769+ by C<cpu>, C<memory>, C<writewait>, and C<repllag>.
15961770
15971771=item --verbose
15981772
@@ -1641,7 +1815,28 @@ Run in stalking mode using currentOp matches instead of a serverStatus metric:
16411815
16421816 pt-mongodb-stalk \
16431817 --host localhost --port 30001 --user admin --password admin --authenticationDatabase admin \
1644- --function currentop --variable ns --match '^app\.orders$' --threshold 10 --cycles 2 --interval 1 --iterations 1 \
1818+ --function currentop --variable command.aggregate --match '^orders$' --threshold 10 --cycles 2 --interval 1 --iterations 1 \
1819+ --dest /tmp/pt-mongodb-stalk
1820+
1821+ Run in stalking mode when host CPU is above 85 percent:
1822+
1823+ pt-mongodb-stalk \
1824+ --host localhost --port 30001 --user admin --password admin --authenticationDatabase admin \
1825+ --function cpu --threshold 85 --cycles 3 --interval 1 --iterations 1 \
1826+ --dest /tmp/pt-mongodb-stalk
1827+
1828+ Run in stalking mode when host memory is above 90 percent:
1829+
1830+ pt-mongodb-stalk \
1831+ --host localhost --port 30001 --user admin --password admin --authenticationDatabase admin \
1832+ --function memory --threshold 90 --cycles 3 --interval 1 --iterations 1 \
1833+ --dest /tmp/pt-mongodb-stalk
1834+
1835+ Run in stalking mode when replica set lag is above 30 seconds:
1836+
1837+ pt-mongodb-stalk \
1838+ --host localhost --port 30001 --user admin --password admin --authenticationDatabase admin \
1839+ --function repllag --threshold 30 --cycles 2 --interval 1 --iterations 1 \
16451840 --dest /tmp/pt-mongodb-stalk
16461841
16471842=head1 COPYRIGHT, LICENSE, AND WARRANTY
0 commit comments