github.com/mweagle/Sparta@v1.15.0/aws/cloudwatch/metrics_awsbinary.go (about) 1 // +build lambdabinary 2 3 package cloudwatch 4 5 import ( 6 "os" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws" 10 awsCloudWatch "github.com/aws/aws-sdk-go/service/cloudwatch" 11 sparta "github.com/mweagle/Sparta" 12 spartaAWS "github.com/mweagle/Sparta/aws" 13 gopsutilCPU "github.com/shirou/gopsutil/cpu" 14 gopsutilDisk "github.com/shirou/gopsutil/disk" 15 gopsutilHost "github.com/shirou/gopsutil/host" 16 gopsutilLoad "github.com/shirou/gopsutil/load" 17 gopsutilNet "github.com/shirou/gopsutil/net" 18 "github.com/sirupsen/logrus" 19 ) 20 21 // publishMetrics is the actual metric publishing logic. T 22 func publishMetrics(customDimensionMap map[string]string) { 23 currentTime := time.Now() 24 25 // https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html 26 functionName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") 27 cpuMetrics, cpuMetricsErr := gopsutilCPU.Percent(0, false) 28 // https://docs.aws.amazon.com/lambda/latest/dg/limits.html 29 diskMetrics, diskMetricsErr := gopsutilDisk.Usage("/tmp") 30 uptime, uptimeErr := gopsutilHost.Uptime() 31 loadMetrics, loadMetricsErr := gopsutilLoad.Avg() 32 netMetrics, netMetricsErr := gopsutilNet.IOCounters(false) 33 34 // For now, just log everything... 35 logger, _ := sparta.NewLogger("info") 36 logger.WithFields(logrus.Fields{ 37 "functionName": functionName, 38 "cpuMetrics": cpuMetrics, 39 "cpuMetricsErr": cpuMetricsErr, 40 "diskMetrics": diskMetrics, 41 "diskMetricsErr": diskMetricsErr, 42 "uptime": uptime, 43 "uptimeErr": uptimeErr, 44 "loadMetrics": loadMetrics, 45 "loadMetricsErr": loadMetricsErr, 46 "netMetrics": netMetrics, 47 "netMetricsErr": netMetricsErr, 48 }).Info("Metric info") 49 50 // Return the array of metricDatum for the item 51 metricDatum := func(name string, value float64, unit MetricUnit) []*awsCloudWatch.MetricDatum { 52 defaultDatum := []*awsCloudWatch.MetricDatum{{ 53 MetricName: aws.String(name), 54 Dimensions: []*awsCloudWatch.Dimension{{ 55 Name: aws.String("Name"), 56 Value: aws.String(sparta.StampedServiceName), 57 }}, 58 Value: aws.Float64(value), 59 Timestamp: ¤tTime, 60 Unit: aws.String(string(unit)), 61 }, 62 } 63 if len(customDimensionMap) != 0 { 64 metricDimension := []*awsCloudWatch.Dimension{{ 65 Name: aws.String("Name"), 66 Value: aws.String(sparta.StampedServiceName), 67 }} 68 for eachKey, eachValue := range customDimensionMap { 69 metricDimension = append(metricDimension, &awsCloudWatch.Dimension{ 70 Name: aws.String(eachKey), 71 Value: aws.String(eachValue), 72 }) 73 } 74 defaultDatum = append(defaultDatum, &awsCloudWatch.MetricDatum{ 75 MetricName: aws.String(name), 76 Dimensions: metricDimension, 77 Value: aws.Float64(value), 78 Timestamp: ¤tTime, 79 Unit: aws.String(string(unit)), 80 }) 81 } 82 return defaultDatum 83 } 84 // Publish all the metrics... 85 // https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html 86 metricData := []*awsCloudWatch.MetricDatum{} 87 // CPU? 88 if len(cpuMetrics) == 1 { 89 metricData = append(metricData, metricDatum("CPUPercent", cpuMetrics[0], UnitPercent)...) 90 } 91 if diskMetricsErr == nil { 92 metricData = append(metricData, metricDatum("DiskUsedPercent", diskMetrics.UsedPercent, UnitPercent)...) 93 } 94 if uptimeErr == nil { 95 metricData = append(metricData, metricDatum("Uptime", float64(uptime), UnitMilliseconds)...) 96 } 97 if loadMetricsErr == nil { 98 metricData = append(metricData, metricDatum("Load1", loadMetrics.Load1, UnitNone)...) 99 metricData = append(metricData, metricDatum("Load5", loadMetrics.Load5, UnitNone)...) 100 metricData = append(metricData, metricDatum("Load15", loadMetrics.Load15, UnitNone)...) 101 } 102 if netMetricsErr == nil && len(netMetrics) == 1 { 103 metricData = append(metricData, metricDatum("NetBytesSent", float64(netMetrics[0].BytesSent), UnitBytes)...) 104 metricData = append(metricData, metricDatum("NetBytesRecv", float64(netMetrics[0].BytesRecv), UnitBytes)...) 105 metricData = append(metricData, metricDatum("NetErrin", float64(netMetrics[0].Errin), UnitCount)...) 106 metricData = append(metricData, metricDatum("NetErrout", float64(netMetrics[0].Errout), UnitCount)...) 107 } 108 putMetricInput := &awsCloudWatch.PutMetricDataInput{ 109 MetricData: metricData, 110 Namespace: aws.String(sparta.ProperName), 111 } 112 session := spartaAWS.NewSession(logger) 113 awsCloudWatchSvc := awsCloudWatch.New(session) 114 putMetricResponse, putMetricResponseErr := awsCloudWatchSvc.PutMetricData(putMetricInput) 115 if putMetricResponseErr != nil { 116 logger.WithField("Error", putMetricResponseErr).Error("Failed to submit CloudWatch Metric data") 117 } else { 118 logger.WithField("Response", putMetricResponse).Info("CloudWatch Metric response") 119 } 120 } 121 122 // RegisterLambdaUtilizationMetricPublisher installs a periodic task 123 // to publish the current system metrics to CloudWatch Metrics. See 124 // https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html 125 // for more information. 126 func RegisterLambdaUtilizationMetricPublisher(customDimensionMap map[string]string) { 127 128 // Publish when we start 129 publishMetrics(customDimensionMap) 130 131 ticker := time.NewTicker(1 * time.Minute) 132 quit := make(chan struct{}) 133 go func() { 134 for { 135 select { 136 case <-ticker.C: 137 publishMetrics(customDimensionMap) 138 case <-quit: 139 ticker.Stop() 140 return 141 } 142 } 143 }() 144 }