[Bps-public-commit] app-aws-cloudwatch-monitor branch 0.02/split-metric-payload-upload created. b715ffa57018fb9716cdfab30a2329ca5f3073b7

BPS Git Server git at git.bestpractical.com
Wed May 11 22:03:02 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, 0.02/split-metric-payload-upload has been created
        at  b715ffa57018fb9716cdfab30a2329ca5f3073b7 (commit)

- Log -----------------------------------------------------------------
commit b715ffa57018fb9716cdfab30a2329ca5f3073b7
Author: Blaine Motsinger <blaine at bestpractical.com>
Date:   Wed May 11 17:01:01 2022 -0500

    Split metrics into sets of 20 to upload to AWS
    
    AWS CloudWatch will return a 400 response if attempting to upload
    more than 20 different metrics at once.
    
    This commit works around that limitation by uploading metrics to
    AWS in sets of 20.

diff --git a/lib/App/AWS/CloudWatch/Monitor.pm b/lib/App/AWS/CloudWatch/Monitor.pm
index 60eb77c..cdcc317 100644
--- a/lib/App/AWS/CloudWatch/Monitor.pm
+++ b/lib/App/AWS/CloudWatch/Monitor.pm
@@ -56,9 +56,7 @@ sub run {
         sleep( rand(20) );
     }
 
-    my $param = {};
-    $param->{Input}{Namespace}  = 'System/Linux';
-    $param->{Input}{MetricData} = [];
+    my @metrics_all = ();
 
     my $checks = delete $opt->{check};
 
@@ -95,11 +93,11 @@ sub run {
             push( @{ $metric->{Dimensions} }, { 'Name' => 'InstanceId', 'Value' => $instance_id } );
             $metric->{Timestamp} = App::AWS::CloudWatch::Monitor::CloudWatchClient::get_offset_time(NOW);
 
-            push( @{ $param->{Input}{MetricData} }, $metric );
+            push( @metrics_all, $metric );
         }
     }
 
-    unless ( scalar @{ $param->{Input}{MetricData} } ) {
+    unless ( scalar @metrics_all ) {
         print "\nNo metrics to upload; exiting\n\n";
         exit;
     }
@@ -109,24 +107,38 @@ sub run {
     $opt->{retries}             = 2;
     $opt->{'user-agent'}        = CLIENT_NAME . "/$VERSION";
 
-    my $response = App::AWS::CloudWatch::Monitor::CloudWatchClient::call_json( 'PutMetricData', $param, $opt );
-    my $code     = $response->code;
-    my $message  = $response->message;
+    # make a copy of metrics_all to pass into _split_metrics so the original isn't modified during the splice
+    my $metric_sets = $self->_split_metrics( [ @metrics_all ] );
+    if ( !$opt->{'from-cron'} && scalar @{$metric_sets} > 1 ) {
+        print "Splitting metrics into " . scalar @{$metric_sets} . " uploads\n";
+    }
+
+    foreach my $set ( @{$metric_sets} ) {
+        my $param = {};
+        $param->{Input}{Namespace}  = 'System/Linux';
+        $param->{Input}{MetricData} = [];
+
+        push( @{ $param->{Input}{MetricData} }, @{$set} );
+
+        my $response = App::AWS::CloudWatch::Monitor::CloudWatchClient::call_json( 'PutMetricData', $param, $opt );
+        my $code     = $response->code;
+        my $message  = $response->message;
 
-    if ( $code == 200 && !$opt->{'from-cron'} ) {
-        if ( $opt->{verify} ) {
-            print "\nVerification completed successfully. No actual metrics sent to CloudWatch.\n\n";
+        if ( $code == 200 && !$opt->{'from-cron'} ) {
+            if ( $opt->{verify} ) {
+                print "Verification completed successfully. No actual metrics sent to CloudWatch.\n";
+            }
+            else {
+                my $request_id = $response->headers->{'x-amzn-requestid'};
+                print "Successfully reported metrics to CloudWatch. Reference Id: $request_id\n";
+            }
         }
-        else {
-            my $request_id = $response->headers->{'x-amzn-requestid'};
-            print "\nSuccessfully reported metrics to CloudWatch. Reference Id: $request_id\n\n";
+        elsif ( $code < 100 ) {
+            die "error: $message\n";
+        }
+        elsif ( $code != 200 ) {
+            die "Failed to call CloudWatch: HTTP $code. Message: $message\n";
         }
-    }
-    elsif ( $code < 100 ) {
-        die "error: $message\n";
-    }
-    elsif ( $code != 200 ) {
-        die "Failed to call CloudWatch: HTTP $code. Message: $message\n";
     }
 
     return;
@@ -155,6 +167,18 @@ sub _verify_metrics {
     return 1;
 }
 
+sub _split_metrics {
+    my $self    = shift;
+    my $metrics = shift;
+
+    my $metric_sets = [];
+    while ( my @next_n = splice @{$metrics}, 0, 20 ) {
+        push @{$metric_sets}, \@next_n;
+    }
+
+    return $metric_sets;
+}
+
 1;
 
 __END__
-----------------------------------------------------------------------


hooks/post-receive
-- 
app-aws-cloudwatch-monitor


More information about the Bps-public-commit mailing list