PSCoreApplicationInsights.psm1
function New-ApplicationInsightsClient { [CmdletBinding()] param ( [Parameter(Mandatory = $true, HelpMessage = "The Application Insights Instrumentation Key that is used to send the messages to the correct Application Insights Instance.")] [ValidateNotNullOrEmpty()] [Guid] $InstrumentationKey ) $global:AIClient = [Microsoft.ApplicationInsights.TelemetryClient]::new() $global:AIClient.InstrumentationKey = $InstrumentationKey $defaultUserInformation = @{ AuthenticatedUserId = whoami UserAgent = ("PS $($psversiontable.PSEdition) $($psversiontable.PSVersion)") } $defaultDeviceInformation = @{ OperatingSystem = $psversiontable.OS } $global:AIClient = Set-ApplicationInsightsClientInformation -UserInformation $defaultUserInformation -DeviceInformation $defaultDeviceInformation -Client $global:AIClient return $global:AIClient } Export-ModuleMember -Function New-ApplicationInsightsClient function Confirm-ApplicationInsightsClient { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [Microsoft.ApplicationInsights.TelemetryClient] $Client ) if ($null -eq $client) { if ($null -eq $global:AIClient) { write-error ("No Application insight client defined. Please use 'New-ApplicationInsightsClient' to create one.") return; } else { $client = $global:AIClient } } [bool] $isValid = $true Write-Verbose ("Checking if the Application Insights Client is valid...") if ([string]::IsNullOrWhiteSpace($client.InstrumentationKey)) { Write-Verbose ("The Instrumentation Key is not set.") $isValid = $false } if ($client.Isenabled() -eq $false) { Write-Verbose ("The Application Insights Client is not enabled.") $isValid = $false } if ($isValid -eq $true) { Write-Verbose ("The Application Insights Client is valid.") } else { throw ("The Application Insights Client is not valid.") } } function Set-ApplicationInsightsClientInformation { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [Microsoft.ApplicationInsights.TelemetryClient] $Client, [Parameter(Mandatory = $false)] [hashtable] $UserInformation, [Parameter(Mandatory = $false)] [hashtable] $DeviceInformation ) begin { if (-not $null -eq $UserInformation) { Write-Verbose ("Received 'User' properties to set in the client") } if (-not $null -eq $DeviceInformation) { Write-Verbose ("Received 'Device' properties to set in the client") } } process { if (-not $null -eq $UserInformation) { foreach ($property in $Client.Context.User.psobject.Properties.name) { Write-Verbose ("Checking property '$($property)' in supplied hashtable") if (-not [string]::IsNullOrWhiteSpace($UserInformation[$property])) { Write-Verbose ("Found property '$($property)' with a value. Changing value from '$($Client.Context.User.$property)' to '$($UserInformation[$property])'") $Client.Context.User.$property = $UserInformation[$property] } } } if (-not $null -eq $DeviceInformation) { foreach ($property in $Client.Context.Device.psobject.Properties.name) { Write-Verbose ("Checking property '$($property)' in supplied hashtable") if (-not [string]::IsNullOrWhiteSpace($DeviceInformation[$property])) { Write-Verbose ("Found property '$($property)' with a value. Changing value from '$($Client.Context.Device.$property)' to '$($DeviceInformation[$property])'") $Client.Context.Device.$property = $DeviceInformation[$property] } } } } end { return $Client } } Export-ModuleMember -Function Set-ApplicationInsightsClientInformation function Write-ApplicationInsightsTrace { <# .SYNOPSIS Write a simple Trace message to the Application Insights service. .DESCRIPTION Write a simple Trace message to the Application Insights service. Supports several Seveity levels .PARAMETER Client The Application Insights client you want to use to send the message to Application Insights. .PARAMETER Message The message you want to send to Application Insights. .PARAMETER SeverityLevel The severity level of the message. Default is 'Information'. Allowed values: 'Verbose', 'Information', 'Warning', 'Error', 'Critical' .PARAMETER properties A Dictionary of properties you want to send with the message. .EXAMPLE Write-ApplicationInsightsTrace -Client $client -Message "This is a test message as Critical" -SeverityLevel "Critical" .EXAMPLE $properties = [System.Collections.Generic.Dictionary[string, string]]::new() $properties.Add("target", "azkv-powershell-001") $properties.Add("type", "Keyvault") Write-ApplicationInsightsTrace -Client $client -Message "Created new keyvault" -SeverityLevel "Information" -properties $properties #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [Microsoft.ApplicationInsights.TelemetryClient] $Client, [Parameter(Mandatory = $true)] [string] $Message, [Parameter(Mandatory = $false)] [validateSet('Information', 'Verbose', 'Warning', 'Error', 'Critical')] [string] $SeverityLevel = "information", [Parameter(Mandatory = $false, HelpMessage = "This is a dictionary<string, string> with additional information that will be added as 'customDimensions' in Application Insights")] [System.Collections.Generic.Dictionary[string, string]] $properties ) BEGIN { Write-Verbose ("Received '$($SeverityLevel)' severity level for the message '$($Message)'") if ($null -eq $client) { if ($null -eq $global:AIClient) { write-error ("No Application insight client defined. Please use 'New-ApplicationInsightsClient' to create one.") return; } else { $client = $global:AIClient } } if ($properties.Count -ge 1) { Write-Verbose ("Received '$($properties.Count)' properties to add to the message.") } Confirm-ApplicationInsightsClient $client } PROCESS { if ($properties.Count -ge 1) { $Client.TrackTrace($Message, [Microsoft.ApplicationInsights.DataContracts.SeverityLevel]::$($SeverityLevel), $properties) Write-Verbose ("Sent message '$($Message)' with '$($properties.Count)' properties to Application Insights.") } else { $Client.TrackTrace($Message, [Microsoft.ApplicationInsights.DataContracts.SeverityLevel]::$($SeverityLevel)) Write-Verbose ("Sent message '$($Message)' to Application Insights.") } } END { $Client.Flush() Write-Verbose ("Client Flushed") } } Export-ModuleMember -Function Write-ApplicationInsightsTrace function Write-ApplicationInsightsMetric { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [Microsoft.ApplicationInsights.TelemetryClient] $Client, [Parameter(Mandatory = $true)] [string] $Name, [Parameter(Mandatory = $true)] [Double] $Metric, [Parameter(Mandatory = $false, HelpMessage = "This is a dictionary<string, string> with additional information that will be added as 'customDimensions' in Application Insights")] [System.Collections.Generic.Dictionary[string, string]] $properties ) BEGIN { if ($null -eq $client) { if ($null -eq $global:AIClient) { write-error ("No Application insight client defined. Please use 'New-ApplicationInsightsClient' to create one.") return; } else { $client = $global:AIClient } } if ($properties.Count -ge 1) { Write-Verbose ("Received '$($properties.Count)' properties to add to the message.") } } PROCESS { if ($properties.Count -ge 1) { $client.TrackMetric($name, $Metric, $properties) Write-Verbose ("Sent metric '$($Name)' with '$($Metric)' value and '$($properties.Count)' properties to Application Insights.") } else { $client.TrackMetric($name, $Metric) Write-Verbose ("Sent metric '$($Name)' with '$($Metric)' value to Application Insights.") } } END { $Client.Flush() Write-Verbose ("Client Flushed") } } Export-ModuleMember -Function Write-ApplicationInsightsMetric function Write-ApplicationInsightsException { [CmdletBinding(DefaultParameterSetName = "Exception")] param ( [Parameter(Mandatory = $false)] [Microsoft.ApplicationInsights.TelemetryClient] $Client, [Parameter(Mandatory = $true, ParameterSetName = "Exception")] [System.Exception] $Exception, [Parameter(Mandatory = $true, ParameterSetName = "StringException")] [String] $ExceptionString, [Parameter(Mandatory = $false, HelpMessage = "This is a dictionary<string, double> with additional information that will be added as 'customMeasurements' in Application Insights")] [System.Collections.Generic.Dictionary[string, double]] $Metrics = [System.Collections.Generic.Dictionary[string, double]]::new(), [Parameter(Mandatory = $false, HelpMessage = "This is a dictionary<string, string> with additional information that will be added as 'customDimensions' in Application Insights")] [System.Collections.Generic.Dictionary[string, string]] $properties = [System.Collections.Generic.Dictionary[string, string]]::new() ) BEGIN { Write-Verbose ("Running in Parameterset '$($PSCmdlet.ParameterSetName)'") if ($null -eq $client) { if ($null -eq $global:AIClient) { write-error ("No Application insight client defined. Please use 'New-ApplicationInsightsClient' to create one.") return; } else { $client = $global:AIClient } } if ($PSCmdlet.ParameterSetName -eq "StringException") { $Exception = [System.Exception]::new($ExceptionString) } } PROCESS { $client.TrackException($Exception, $properties, $Metrics) Write-Verbose ("Sent exception '$($Exception)' with '$($Metrics.Count)' metrics and '$($properties.Count)' properties to Application Insights.") } END { $Client.Flush() Write-Verbose ("Client Flushed") } } Export-ModuleMember -Function Write-ApplicationInsightsException function Write-ApplicationInsightsRequest { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [Microsoft.ApplicationInsights.TelemetryClient] $Client, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.DateTimeOffset] $StartTime, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Timespan] $Duration, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $responseCode = "200", [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Bool] $success, [Parameter(Mandatory = $false, HelpMessage = "This is a dictionary<string, string> with additional information that will be added as 'customProperties' in Application Insights")] [System.Collections.Generic.Dictionary[string, string]] $properties = [System.Collections.Generic.Dictionary[string, string]]::new(), [Parameter(Mandatory = $false, HelpMessage = "This is the URL that will be added as 'url' in Application Insights")] [ValidateNotNullOrEmpty()] [string] $url ) BEGIN { Write-Verbose ("Received '$($Name)' name for the request") Write-Verbose ("Received '$($StartTime)' start time for the request") Write-Verbose ("Received '$($Duration)' duration for the request") Write-Verbose ("Received '$($responseCode)' response code for the request") Write-Verbose ("Received '$($success)' success for the request") if ($null -eq $client) { if ($null -eq $global:AIClient) { write-error ("No Application insight client defined. Please use 'New-ApplicationInsightsClient' to create one.") return; } else { $client = $global:AIClient } } } PROCESS { $requestTelemetry = [Microsoft.ApplicationInsights.DataContracts.RequestTelemetry]::new() $requestTelemetry.Duration = $Duration $requestTelemetry.Name = $Name $requestTelemetry.ResponseCode = $responseCode $requestTelemetry.Success = $success $requestTelemetry.Timestamp = $StartTime if ($properties.Count -ge 1) { Write-Verbose ("Received '$($properties.Count)' properties to add to the request.") foreach ($key in $properties.Keys) { Write-Verbose ("Received '$($key)' property to add to the request.") $requestTelemetry.Properties[$key] = $properties[$key] } } if (-not [string]::IsNullOrWhiteSpace($url)) { Write-Verbose ("Received '$($url)' url for the request") $requestTelemetry.Url = $url } $client.TrackRequest($requestTelemetry) } END { $Client.Flush() Write-Verbose ("Client Flushed") } } Export-ModuleMember -Function Write-ApplicationInsightsRequest Function Invoke-ApplicationInsightsMeasuredCommand { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [Microsoft.ApplicationInsights.TelemetryClient] $Client, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [scriptblock] $scriptblock, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $name ) BEGIN { if ($null -eq $client) { if ($null -eq $global:AIClient) { write-error ("No Application insight client defined. Please use 'New-ApplicationInsightsClient' to create one.") return; } else { $client = $global:AIClient } } Write-Verbose ("Received '$($name)' name for the command") } PROCESS { $success = $true $statusCode = "200" $startDate = [System.DateTime]::UtcNow try { $retVal = $scriptblock.Invoke() } catch [System.Exception] { Write-Verbose ("Caught exception in the scriptblock") $statusCode = $_ $success = $false throw } finally { $endDate = [System.DateTime]::UtcNow } $duration = New-TimeSpan -Start $startDate -End $endDate Write-Verbose ("Received '$($duration)' as duration for the command") Write-ApplicationInsightsRequest -Name $name -StartTime $startDate -Duration $duration -responseCode $statusCode -success $success } END { $Client.Flush() Write-Verbose ("Client Flushed") return $retVal } } Export-ModuleMember -Function Invoke-ApplicationInsightsMeasuredCommand |