[Bps-public-commit] app-aws-cloudwatch-monitor branch add-fcgi-monitoring-prototype created. cf6e7d58498e10af7612160ad1ea26e39bd38425
BPS Git Server
git at git.bestpractical.com
Tue Mar 8 16:33:43 UTC 2022
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "app-aws-cloudwatch-monitor".
The branch, add-fcgi-monitoring-prototype has been created
at cf6e7d58498e10af7612160ad1ea26e39bd38425 (commit)
- Log -----------------------------------------------------------------
commit cf6e7d58498e10af7612160ad1ea26e39bd38425
Author: Brian Conry <bconry at bestpractical.com>
Date: Thu Jan 27 16:23:07 2022 -0600
WIP commit - not even syntax checked
diff --git a/lib/App/AWS/CloudWatch/Monitor/Check/bconry.pm b/lib/App/AWS/CloudWatch/Monitor/Check/bconry.pm
new file mode 100644
index 0000000..86f636e
--- /dev/null
+++ b/lib/App/AWS/CloudWatch/Monitor/Check/bconry.pm
@@ -0,0 +1,271 @@
+# Copyright 2021 Best Practical Solutions, LLC <sales at bestpractical.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package App::AWS::CloudWatch::Monitor::Check::bconry;
+
+use strict;
+use warnings;
+
+use parent 'App::AWS::CloudWatch::Monitor::Check';
+
+use Getopt::Long qw(:config pass_through);
+
+our $VERSION = '0.01';
+
+our $PMAP_CONFIG = '/home/admin/tmp/pmaprc';
+our $TOP_CONFIG = '/home/admin/tmp/';
+
+our %UNITS_BY_CATEGORY = (
+ ps_cpu => 'Seconds',
+ ps_age => 'Seconds',
+ ps_rss => 'Kilobytes',
+ ps_size => 'Kilobytes',
+ pmap_rss => 'Kilobytes',
+ pmap_pss => 'Kilobytes',
+ pmap_rsan => 'Kilobytes',
+ pmap_killsize => 'Kilobytes',
+ top_rss => 'Kilobytes',
+ top_rsan => 'Kilobytes',
+);
+
+sub check {
+ my $self = shift;
+ my $arg = shift;
+
+ Getopt::Long::GetOptionsFromArray( $arg, \my %opt, 'user=s@' );
+
+ die "Option: user is required" unless $opt{'user'};
+
+ my $match = '^(' . join( '|', @{$opt{'user'}} ) . ')';
+ $match = qr/$match/;
+
+ my $metrics;
+
+ # use ps to get process list and some information
+ my @ps_command = ( '/bin/ps', 'axco', 'user,pid,stat,rss,size,cputime,etime,command' );
+ my ( $exit, $stdout, $stderr ) = $self->run_command( \@ps_command );
+
+ if ($exit) {
+ die "$stderr\n";
+ }
+
+ return unless $stdout;
+
+ # remove header, but make sure it's what we expect
+ # if it isn't then we're probably not going to process the data properly
+ my $header = shift @$stdout;
+ die "unexpected header" unless $header =~ /^ USER \s+ PID \s+ STAT \s+ RSS \s+ SIZE \s+ TIME \s+ ELAPSED \s+ COMMAND/x;
+
+ my %data_by_user_and_pid;
+ my %summary;
+
+ # for each pid, gather additional information
+ foreach my $line ( @{$stdout} ) {
+ next unless $line =~ $match;
+
+ my( $uname, $pid, $status, $ps_rss, $mem_size, $cpu_time, $elapsed_time, $command ) = split /\s+/, $line;
+
+ # ignore zombie processes
+ next if $status =~ /^Z/;
+
+ foreach my $time ($cpu_time, $elapsed_time) {
+ if ($time =~ /^(?:(?<days>\d+)-)?(?:(?<hours>\d+):)?(?:(?<minutes>\d+):)(?<seconds>\d+)/) {
+ $time = ((($+{days} // 0) * 24 + ($+{hours} // 0)) * 60 + ($+{minutes} // 0)) * 60 + $+{seconds};
+ }
+ else {
+ # die? warn?
+ # setting a negative value that will be ignored later
+ $time = -1;
+ }
+ }
+
+ # store what we have so far
+ my $summary_key = "$uname/$command";
+ my $summary_record = $summary{$summary_key} //= {
+ ps_rss => [],
+ ps_size => [],
+ ps_cpu => [],
+ ps_age => [],
+ pmap_rss => [],
+ pmap_pss => [],
+ pmap_rsan => [],
+ };
+
+ push @{$summary_record->{ps_rss}}, $ps_rss;
+ push @{$summary_record->{ps_size}}, $mem_size;
+ push @{$summary_record->{ps_cpu}}, $cpu_time;
+ push @{$summary_record->{ps_age}}, $elapsed_time;
+
+ # gather more data from pmap
+ my @pmap_command = ( '/usr/bin/sudo', '/usr/bin/pmap', '-C', $PMAP_CONFIG, '-p', $pid );
+ my ( $pmap_exit, $pmap_stdout, $pmap_stderr ) = $self->run_command( \@pmap_command );
+
+ if (!$pmap_exit and $pmap_stdout) {
+ # first line is the full command line
+ my $pmap_command = @$pmap_stdout;
+
+ # second line is the headers
+ my $pmap_header = shift @pmap_$sdtout;
+
+ # next are detail lines
+ if ($pmap_header eq =~ /^ \s+ Address \s+ Rss \s+ Pss \s+ Anonymous $/x) {
+ my $kill_size = 0;
+
+ while (my $detail = shift @$stdout) {
+ # then a line of lines ('=' characters)
+ last if $detail =~ /==/;
+
+ my ($addr, $pmap_rss, $pss, $pmap_rsan) = split /\s+/, $detail;
+
+ if( $pmap_rsan ) {
+ $kill_size += $pmap_rsan;
+ }
+ elsif ($pmap_rss == $pss) {
+ $kill_size += $pss;
+ }
+ }
+
+ # then a summary line
+ my ($pmap_sum_rss, $pmap_sum_pss, $pmap_sum_rsan) = split ' ', shift @$stdout;
+
+ push @{$summary_record->{pmap_rss}}, $pmap_sum_rss;
+ push @{$summary_record->{pmap_pss}}, $pmap_sum_pss;
+ push @{$summary_record->{pmap_rsan}}, $pmap_sum_rsan;
+ push @{$summary_record->{pmap_killsize}}, $pmap_killsize;
+ }
+
+ }
+
+ # gather more data from top
+ {
+ local $ENV{'XDG_CONFIG_HOME'} = $TOP_CONFIG;
+ my @top_command = ( '/usr/bin/top', '-b', '-n', '1', '-E', 'k', '-H', '-p', $pid );
+ my ( $top_exit, $top_stdout, $top_stderr ) = $self->run_command( \@top_command );
+
+ if (!$top_exit and $top_stdout) {
+ # first is a blank line (all summary lines are turned off)
+ my $top_blank = shift @$top_stdout;
+ # next is the header line
+ my $top_header = shift @$top_stdout;
+
+ if ($top_blank eq '' and $top_header =~ /^ \s+ RES \s+ RSan \s+ COMMAND$/x) {
+ # last is the line of data
+ my $data = shift @$top_stdout;
+ my ($top_rss, $top_rsan, $top_command) = split ' ', shift @$stdout;
+
+ push @{$summary_record->{top_rss}}, $top_rss;
+ push @{$summary_record->{top_rsan}}, $top_rsan;
+ }
+ }
+ }
+ }
+
+ # summarize by command
+ foreach my $summary_key (keys %summary) {
+ my $summary_record = $summary{$summary_key};
+
+ # the number of ps_cpu entries is our count
+ {
+ MetricName => $summary_key . '-Count',
+ Unit => 'Count',
+ RawValue => scalar @{$summary_record->{ps_cpu}},
+ },
+
+ foreach my $category (qw(ps_rss ps_size ps_cpu ps_age pmap_rss pmap_pss pmap_rsan pmap_killsize top_rss top_rsan)) {
+ my $entries = $summary_record->{$category};
+
+ my %values;
+
+ foreach my $value (@$entries) {
+ $values{$value}++;
+ }
+
+ my @unique_values = sort { $a <=> $b } keys %values;
+
+ my @counts = @values{@unique_values};
+
+ push @$metrics, {
+ MetricName => "$summary_key-$category",
+ Unit => $UNITS_BY_CATEGORY{$category},
+ Values => \@unique_values,
+ Counts => \@counts,
+ };
+ }
+ }
+
+ return $metrics;
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+App::AWS::CloudWatch::Monitor::Check::bconry - gather process metric data by user and process
+
+=head1 SYNOPSIS
+
+ my $plugin = App::AWS::CloudWatch::Monitor::Check::bconry->new();
+ my $metrics = $plugin->check( $args_arrayref );
+
+ aws-cloudwatch-monitor --check bconry --user www-data
+ aws-cloudwatch-monitor --check bconry --user postfix
+ aws-cloudwatch-monitor --check bconry --user postgres
+
+=head1 DESCRIPTION
+
+C<App::AWS::CloudWatch::Monitor::Check::bconry> is a L<App::AWS::CloudWatch::Monitor::Check> module which gathers process metric data.
+
+=head1 METRICS
+
+Data for this check is read from L<ps(1)>. The following metrics are returned.
+
+=over
+
+=item tbd
+
+=item tbd
+
+=item tbd
+
+=back
+
+=head1 METHODS
+
+=over
+
+=item check
+
+Gathers the metric data and returns an arrayref of hashrefs with keys C<MetricName>, C<Unit>, C<RawValue>, and C<Dimensions>.
+
+=back
+
+=head1 ARGUMENTS
+
+C<App::AWS::CloudWatch::Monitor::Check::bconry> requires the C<--user> argument through the commandline.
+
+ aws-cloudwatch-monitor --check bconry --user www-data
+
+Multiple C<--user> arguments may be defined to gather metrics for multiple users.
+
+ aws-cloudwatch-monitor --check bconry --user www-data --user postgres
+
+=head1 DEPENDENCIES
+
+C<App::AWS::CloudWatch::Monitor::Check::bconry> depends on the external program, L<ps(1)>.
+
+=cut
diff --git a/pmaprc b/pmaprc
new file mode 100644
index 0000000..4b19b26
--- /dev/null
+++ b/pmaprc
@@ -0,0 +1,36 @@
+# pmap's Config File
+
+# All the entries are case sensitive.
+# Unsupported entries are ignored!
+
+[Fields Display]
+
+# To enable a field uncomment its entry
+
+#Perm
+#Offset
+#Device
+#Inode
+#Size
+Rss
+Pss
+#Shared_Clean
+#Shared_Dirty
+#Private_Clean
+#Private_Dirty
+#Referenced
+Anonymous
+#AnonHugePages
+#Swap
+#KernelPageSize
+#MMUPageSize
+#Locked
+#VmFlags
+#Mapping
+
+
+[Mapping]
+
+# to show paths in the mapping column uncomment the following line
+#ShowPath
+
diff --git a/toprc b/toprc
new file mode 100644
index 0000000..3a30505
--- /dev/null
+++ b/toprc
@@ -0,0 +1,16 @@
+top's Config File (Linux processes with windows)
+Id:i, Mode_altscr=0, Mode_irixps=1, Delay_time=3.0, Curwin=0
+Def fieldscur=%&(34;½@DÙ\7:9Å')*+,-./012568<>?ABCFGHIJKLMNOPQRSTUVWXZ[]^_`abcdefghij
+ winflags=165296, sortindx=0, maxtasks=0, graph_cpus=0, graph_mems=0
+ summclr=1, msgsclr=1, headclr=3, taskclr=1
+Job fieldscur=¥¦¹·º(³´Ä»½@<§Å)*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+ winflags=193844, sortindx=0, maxtasks=0, graph_cpus=0, graph_mems=0
+ summclr=6, msgsclr=6, headclr=7, taskclr=6
+Mem fieldscur=¥º»<½¾¿ÀÁMBNÃD34·Å&'()*+,-./0125689FGHIJKLOPQRSTUVWXYZ[\]^_`abcdefghij
+ winflags=193844, sortindx=21, maxtasks=0, graph_cpus=0, graph_mems=0
+ summclr=5, msgsclr=5, headclr=4, taskclr=5
+Usr fieldscur=¥¦§¨ª°¹·ºÄÅ)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij
+ winflags=193844, sortindx=3, maxtasks=0, graph_cpus=0, graph_mems=0
+ summclr=3, msgsclr=3, headclr=2, taskclr=3
+Fixed_widest=0, Summ_mscale=1, Task_mscale=0, Zero_suppress=0
+
-----------------------------------------------------------------------
hooks/post-receive
--
app-aws-cloudwatch-monitor
More information about the Bps-public-commit
mailing list