Skip to content

Instantly share code, notes, and snippets.

@hkarthik7
Created February 18, 2021 16:45
Show Gist options
  • Save hkarthik7/7ef69d558a6132adf9879b2f84969b05 to your computer and use it in GitHub Desktop.
Save hkarthik7/7ef69d558a6132adf9879b2f84969b05 to your computer and use it in GitHub Desktop.
function Export-AzureWebAppLogFiles {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$AppServiceName,
[Parameter(Mandatory = $true)]
[string]
$ResourceGroupName,
[Parameter(Mandatory = $true)]
[string]
$LogFilePath,
# if you want to download the logfiles as zip
# then you have to provide the file path with .zip extension.
# e.g., C:\Temp\Logs.zip
[Parameter(Mandatory = $true)]
[string]
$ExportPath,
[Parameter(Mandatory = $false)]
[switch]
$Zip
)
begin {
$functionName = $MyInvocation.MyCommand.Name
$LogFilePath = $LogFilePath.TrimEnd("/")
$scm = "https://$($AppServiceName).scm.azurewebsites.net/api/vfs/$LogFilePath/"
Write-Verbose "[$(Get-Date -Format s)] : $functionName : Begin Function.."
}
process {
try {
Write-Verbose "[$(Get-Date -Format s)] : $functionName : Fetching web app details.."
# We need username and password to read the logs, oublishing profile can be used to get the information for it
$webApp = Get-AzWebApp -ResourceGroupName $ResourceGroupName -Name $AppServiceName
[xml]$publishingProfile = Get-AzWebAppPublishingProfile -WebApp $webApp
# connect to SCM
$username = $publishingProfile.publishData.publishProfile[0].userName
$password = $publishingProfile.publishData.publishProfile[0].userPWD
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
# this helps me to get the log files under the http/RawLogs folder then manipulate to get the information
$logFiles = Invoke-RestMethod -Uri $scm -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET
# Download only recent files
$logFiles = $logFiles | Where-Object { (Get-Date $_.crtime).Date -eq (Get-Date).Date }
if ($Zip.IsPresent) {
Write-Verbose "[$(Get-Date -Format s)] : $functionName : Downloading files from - $LogFilePath.."
Invoke-RestMethod -Uri $scm.Replace("vfs", "zip") -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET -OutFile $ExportPath -ContentType "multipart/form-data"
}
foreach ($file in $logFiles) {
if ((Get-Date $file.crtime).Date -eq (Get-Date).Date) {
Write-Verbose "[$(Get-Date -Format s)] : $functionName : Downloading - $($file.name).."
Invoke-RestMethod -Uri "$scm/$($file.name)" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET -OutFile "$ExportPath\$($file.name)" -ContentType "text/plain"
}
}
}
catch {
throw $_
}
}
end {
Write-Verbose "[$(Get-Date -Format s)] : $functionName : End Function.."
}
}
function LogParser {
# this comes in analysis section; So, need a place to store the files.
# We need a separate function to list this.
# Intended to run in pipeline
$report = @()
$files = Get-ChildItem -Path $PWD.Path -Filter "*.log"
foreach ($file in $files) {
$contents = Get-Content -Path $file.FullName | Select-Object -Skip 2
for ($i = 0; $i -lt $contents.Count; $i++) {
$value = $contents[$i].Split()
if ($value[-6] -notlike "*20*" -and $value[-6] -notlike "*30*") {
$h = [PSCustomObject]@{
"Date Time" = $value[0] + " " + $value[1]
"AppName" = $value[2]
"Method" = $value[3]
"Endpoint" = $value[4]
"IP" = $value[8]
"StatusCode" = $value[-6]
"Host" = $value[-7]
}
$report += $h
}
}
}
return $report
}
function Export-Html {
[CmdletBinding(DefaultParameterSetName='Page')]
param(
[Parameter(ValueFromPipeline=$true)]
[psobject]
${InputObject},
[Parameter(Position=0)]
[System.Object[]]
${Property},
[Parameter(ParameterSetName='Page', Position=3)]
[string[]]
${Body},
[Parameter(ParameterSetName='Page', Position=1)]
[string[]]
${Head},
[Parameter(ParameterSetName='Page', Position=2)]
[ValidateNotNullOrEmpty()]
[string]
${Title},
[ValidateNotNullOrEmpty()]
[ValidateSet('Table','List')]
[string]
${As},
[Parameter(ParameterSetName='Page')]
[Alias('cu','uri')]
[ValidateNotNullOrEmpty()]
[uri]
${CssUri},
[Parameter(ParameterSetName='Fragment')]
[ValidateNotNullOrEmpty()]
[switch]
${Fragment},
[ValidateNotNullOrEmpty()]
[string[]]
${PostContent},
[ValidateNotNullOrEmpty()]
[string[]]
${PreContent},
[ValidateNotNullOrEmpty()]
[string]
$FilePath
)
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('ConvertTo-Html', [System.Management.Automation.CommandTypes]::Cmdlet)
if($PSBoundParameters['FilePath']) {
$null = $PSBoundParameters.Remove('FilePath')
if($PSBoundParameters['CssUri']) {
$null = $PSBoundParameters.Remove('CssUri')
}
if($PSBoundParameters['Head']) {
$null = $PSBoundParameters.Remove('Head')
$header = "
<div class='shadow-sm p-3 mb-5 bg-white rounded'>
<nav class='navbar navbar-dark bg-dark'>
<a class='navbar-brand'>$($Head)</a>
</nav>
</div>
"
}
if($PSBoundParameters['PreContent']) {
$null = $PSBoundParameters.Remove('PreContent')
$Content = "
<div class='card'>
<div class='card-body'>
<h4 class='card-title'>$($PreContent)</h4>
<hr>
<div class='table-responsive'>
"
}
$ContentPost = "
</div>
</div>
</div>
<script src='https://code.jquery.com/jquery-3.4.1.slim.min.js' integrity='sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n' crossorigin='anonymous'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js' integrity='sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo' crossorigin='anonymous'></script>
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js' integrity='sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6' crossorigin='anonymous'></script>
"
$scriptCmd = { & $wrappedCmd @PSBoundParameters -CssUri "https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" `
-Head $header `
-PreContent $Content `
-PostContent $ContentPost `
| ForEach-Object {
if($_ -like "*<table>*") { $_ -replace "<table>", '<table class="table table-bordered table-hover">' }
else { $_ }
} | Out-File -FilePath $FilePath }
} else { $scriptCmd = { & $wrappedCmd @PSBoundParameters } }
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
}
LogParser | Export-Html -FilePath "$($PWD.Path)\Report.html" `
-Head "ERROR CODE DETAILS" `
-PreContent "SERVER/BROWSER ERRORs"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment