Here is an example Powershell script to extract data out of AWS CloudWatch using the AWS tool kit.
I needed to visualize this data outside of the AWS console… so I built this extractor to pull out metric data for different types of AWS objects, check out the example below.
<#
AWS CloudWatch Metric Extractor , Requires Module --> https://github.com/dfinke/ImportExcel
Collecting metric / state data from AWS CloudWatch api and output's to CSV, run the script without parameters for instructions.
Script requires Powershell v3 and above.
Run the command below to store AccessKey and SecretKey in secure credential XML for each environment
$cred = Get-Credential
$cred | Export-Clixml -Path "d:\AWS\config\us-east-1.xml"
Run the command below to store user and password which will login to the internet proxy.
$cred = Get-Credential
$cred | Export-Clixml -Path "d:\AWS\config\proxy.xml"
#>
param
(
[String]$CollectionType = 'Collection',
[String]$AWSMetricNameSpace = 'AWS/EC2',
[String]$AWSRegion = 'us-east-1',
[Array]$InstanceById = @('i-BleBlahBlue','i-BleBlahRed'),
[Array]$Metrics = @('CPUUtilization','DiskReadBytes','DiskReadOps','DiskWriteBytes','DiskWriteOps','NetworkIn','NetworkOut','NetworkPacketsIn','NetworkPacketsOut'),
[String]$rollUpType = 'Average',
[String]$intervalType = 3600,
[DateTime]$StartDate = (Get-date).addDays(-2),
[DateTime]$EndDate = (Get-date),
[String]$Format = 'XLS',
[String]$Email,
[String]$FileName, # = 'MyBoxes',
[String]$OutputLocation, # = 'd:\Watcher\WebSSO\us-east-1',
[String]$InstanceByIdLookupList # = 'd:\Watcher\Servers.csv'
)
#Params
$ScriptPath = 'D:\Wacther'
$LogFileLoc = $ScriptPath + '\Log\Logfile.log'
$RunDateTime = (Get-date)
$RunDateTime = $RunDateTime.tostring("yyyyMMddHHmmss")
$StartDateFile = $StartDate.tostring("yyyyMMdd-HHmmss")
$EndDateFile = $EndDate.tostring("yyyyMMdd-HHmmss")
$Share = '\\localhost\completed\'
$mailserver = 'mailserverbox.vMan.ch'
$mailport = 25
$ProxyCreds = 'MeProxy'
$ProxyHost = 'proxy.vMan.ch'
$ProxyPort = 8080
#Functions
#Logging Function
Function Log([String]$message, [String]$LogType, [String]$LogFile){
$date = Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
$message = $date + "`t" + $LogType + "`t" + $message
$message >> $LogFile
}
#Send Email Function
Function SS64Mail($SMTPServer, $SMTPPort, $SMTPuser, $SMTPPass, $strSubject, $strBody, $strSenderemail, $strRecipientemail, $AttachFile)
{
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true }
$MailMessage = New-Object System.Net.Mail.MailMessage
$SMTPClient = New-Object System.Net.Mail.smtpClient ($SMTPServer, $SMTPPort)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($SMTPuser, $SMTPPass)
$Recipient = New-Object System.Net.Mail.MailAddress($strRecipientemail, "Recipient")
$Sender = New-Object System.Net.Mail.MailAddress($strSenderemail, "vMan AWS Metrics")
$MailMessage.Sender = $Sender
$MailMessage.From = $Sender
$MailMessage.Subject = $strSubject
$MailMessage.To.add($Recipient)
$MailMessage.Body = $strBody
if ($AttachFile -ne $null) {$MailMessage.attachments.add($AttachFile) }
$SMTPClient.Send($MailMessage)
}
switch($CollectionType)
{
Collection {
If ($InstanceByIdLookupList -gt ''){
Log -Message "Collecting $intervalType between $StartDateFile and $EndDateFile" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Collecting $intervalType between $StartDateFile and $EndDateFile"
Log -Message "Collecting metrics: $Metrics" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Collecting metrics: $Metrics"
Log -Message "Data collection for objects listed in the file $InstanceByIdLookupList" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Data collection for objects listed in the file $InstanceByIdLookupList"
$InstanceById = ''
[Array]$InstanceById = import-csv $InstanceByIdLookupList | where ENV -eq $AWSRegion | Select Server
[Array]$InstanceById = $InstanceById.Server
Log -Message "Data collection for $InstanceById" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Data collection for $InstanceById"
}
else {
Log -Message "Collecting $intervalType between $StartDateFile and $EndDateFile" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Collecting $intervalType between $StartDateFile and $EndDateFile"
Log -Message "Collecting metrics: $Metrics" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Collecting metrics: $Metrics"
Log -Message "Data collection for object: $InstanceById" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Data collection for object: $InstanceById"
}
#Set's the AWS Region to query
if($AWSRegion-gt ""){
Set-DefaultAWSRegion -Region $AWSRegion
}
else {
echo "AWS region not specified, bye!!"
Exit
}
#Sets the credentials to access the data.
if($AWSRegion -gt ""){
$AWSCred = Import-Clixml -Path "$ScriptPath\config\$AWSRegion.xml"
$AWSUser = $AWSCred.GetNetworkCredential().Username
$AWSPassword = $AWSCred.GetNetworkCredential().Password
Set-AWSCredentials -AccessKey $AWSUser -SecretKey $AWSPassword
}
else
{
Log -Message "AWS credentials not specified, bye!!" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "AWS credentials not specified, bye!!"
Exit
}
#Check if any metrics specified
if($Metrics -eq ""){
echo "No metrics specified, bye!!"
Exit
}
#Set the Internet Proxy if you cant get out directly the to net.
if($ProxyCreds -gt ""){
$ProxyCred = Import-Clixml -Path "$ScriptPath\config\$ProxyCreds.xml"
$ProxyUser = $ProxyCred.GetNetworkCredential().Username
$ProxyPassword = $ProxyCred.GetNetworkCredential().Password
Set-AWSProxy -Hostname $ProxyHost -Port $ProxyPort -Password $ProxyPassword -Username $ProxyUser
}
else
{
Log -Message "Proxy credentials not specified so not configuring proxy" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
echo "Proxy credentials not specified so not configuring proxy"
}
if($Email -imatch '^.*@vMan\.ch
Hope this was helpful
vMAN
){
Log -Message "$email matches the vMan.ch domain" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "$email matches the vMan.ch domain"
$SMTPcred = Import-Clixml -Path "$ScriptPath\config\smtp.xml"
$SMTPUser = $SMTPcred.GetNetworkCredential().Username
$SMTPPassword = $SMTPcred.GetNetworkCredential().Password
}
else
{
Log -Message "$email is not in the vMan.ch domain, will not send mail but report generation will continue" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "$email is not in the vMan.ch domain, will not send mail but report generation will continue"
$Email = ''
}
$report = @()
ForEach ($InstanceID in $InstanceById){
echo "Running collection for instance: $InstanceID"
Log -Message "Running collection for instance: $InstanceID" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
$dimension = New-Object Amazon.CloudWatch.Model.Dimension
$dimension.set_Name('InstanceId')
$dimension.set_Value($InstanceID)
ForEach ($Metric in $Metrics){
$Data = @()
echo "Collecting Metric $Metric for $InstanceID"
Log -Message "Collecting Metric $Metric for $InstanceID" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
$Data = Get-CWMetricStatistics -Namespace $AWSMetricNameSpace -dimension $dimension -MetricName $Metric -StartTime $StartDate -EndTime $EndDate -Period $intervalType -Statistics $rollUpType
echo "Transforming Metric $Metric for $InstanceID"
Log -Message "Transforming Metric $Metric for $InstanceID" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
If ($rollUpType -eq 'Average') {$values = @($Data.DataPoints.Average)}
If ($rollUpType -eq 'Maximum') {$values = @($Data.DataPoints.Maximum)}
If ($rollUpType -eq 'Minumum') {$values = @($Data.DataPoints.Minumum)}
$Timestamps = @($Data.DataPoints.timestamp)
for ($i=0; $i -lt $Values.Count -and $i -lt $Timestamps.Count; $i++) {
$report += New-Object PSObject -Property @{
Metric = $Metric
InstanceId = $InstanceID
Timestamp = $Timestamps[$i]
value = $values[$i]
}
}
}
}
#Output merge to Excel
if ($Format -eq 'XLS'){
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
echo 'Generate XLS'
Log -Message "Generate XLS" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
If ($FileName -gt ''){
$OutputExcelFile = $OutputLocation + $FileName + '.xlsx'
$ShareExcelFile = $OutputLocation + $FileName + '.xlsx'
remove-item $OutputExcelFile -Force -ErrorAction SilentlyContinue -Recurse
}
else
{
$OutputExcelFile = $ScriptPath + '\completed\Collected_Metrics_' + $intervalType + '_' + [String]$rollUpType + '_' + [String]$StartDateFile + '_' + [String]$EndDateFile + '_' + $RunDateTime + '.xlsx'
$ShareExcelFile = $share + 'Collected_Metrics_' + $intervalType + '_' + [String]$rollUpType + '_' + [String]$StartDateFile + '_' + [String]$EndDateFile + '_' + $RunDateTime + '.xlsx'
}
$report | select Timestamp,InstanceId,Metric,value | Sort-Object { $_.Timestamp -as [datetime] } | Export-Excel $OutputExcelFile -WorkSheetname Data -ChartType Line -IncludePivotChart -IncludePivotTable -PivotRows Timestamp -PivotData value -PivotColumns InstanceId,Metric
Log -Message "Task complete, pickup your file from the share $ShareExcelFile within the next 24 hours as it will be automatically deleted" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "Task complete, pickup your file from the share $ShareExcelFile within the next 24 hours as it will be automatically deleted"
if($Email -gt "")
{
Log -Message "Email found and is vMan.ch domain, sending report to $email" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "Email found and is vMan.ch domain, sending email to $email"
SS64Mail $mailserver $mailport $SMTPUser $SMTPPassword "ENV $creds Report started at $RunDateTime complete" "Your report should be attached, if it's missing it was probably too large to send via the mail server.... Pickup it up from here $ShareExcelFile within the next 24H" 'info@vman.ch' $email $OutputExcelFile
Log -Message "Email sent to $email" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "Email sent to $email"
}
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
echo 'All done, Terminating Script'
Log -Message "All done, Terminating Script" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Remove-Variable * -Force -ErrorAction SilentlyContinue
Exit
}
#Output to CSV
if ($Format -eq 'CSV'){
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
echo 'Generate CSV'
Log -Message "Generate CSV" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
If ($FileName -gt ''){
$OutputCSVFile = $OutputLocation + $FileName + '.csv'
$ShareCSVFile = $OutputLocation + $FileName + '.csv'
}
else
{
$OutputCSVFile = $ScriptPath + '\completed\Collected_Metrics_' + $intervalType + '_' + [String]$rollUpType + '_' + [String]$StartDateFile + '_' + [String]$EndDateFile + '_' + $RunDateTime + '.csv'
$ShareCSVFile = $share + 'Collected_Metrics_' + $intervalType + '_' + [String]$rollUpType + '_' + [String]$StartDateFile + '_' + [String]$EndDateFile + '_' + $RunDateTime + '.csv'
}
$report | select Timestamp,InstanceId,Metric,value | Sort-Object { $_.Timestamp -as [datetime] } | Export-csv $OutputCSVFile -NoTypeInformation
Log -Message "Task complete, pickup your file from the share $ShareCSVFile within the next 24 hours as it will be automatically deleted" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "Task complete, pickup your file from the share $ShareCSVFile within the next 24 hours as it will be automatically deleted"
if($Email -gt "")
{
Log -Message "Email found and is vMan.ch domain, sending CSV link to $email" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "Email found and is vMan.ch domain, sending CSV link to $email"
SS64Mail $mailserver $mailport $SMTPUser $SMTPPassword "ENV $creds Report started at $RunDateTime complete" "Your report is ready, Pickup it up from here $ShareCSVFile within the next 24H" 'info@vman.ch' $email
Log -Message "Email sent to $email" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Echo "Email sent to $email"
}
Get-Date -UFormat '%m-%d-%Y %H:%M:%S'
echo 'All done, Terminating Script'
Log -Message "All done, Terminating Script" -LogType "JOB-$RunDateTime" -LogFile $LogFileLoc
Remove-Variable * -Force -ErrorAction SilentlyContinue
Exit
}
}
<#
#Debug, get list of Metrics
#$AWSCW = Get-CWMetrics
#>
default{"Usage
The script can be run by specifying all parameters otherwise it will use some default values.
.\CloudWatcher.ps1 -CollectionType 'Collection' -AWSRegion 'us-east-1' -StartDate '2016/09/16 10:00' -EndDate '2016/09/16 11:00' -Metrics 'CPUUtilization','DiskReadBytes','DiskReadOps','DiskWriteBytes','DiskWriteOps','NetworkIn','NetworkOut','NetworkPacketsIn','NetworkPacketsOut' -rollUpType 'Average' -intervalType '3600' -Format 'XLS' -FileName 'MyBoxes' -OutputLocation 'D:\Watcher\' -InstanceByIdLookupList 'D:\Watcher\Servers.csv'
"}
}
Hope this was helpful
vMAN


Recent Comments