#v1.9 Updating new media server modules so they work with the new infrastructure #v1.8 Alright settle down. We've heard the news about the media servers. It's Thu 13/8/15 and we lose access to the media servers as it stands tomorrow. OK, so... PANIIIIC! - disabling write by default. Next release will be to get it working on the new media servers-. Freddie Sackur #v1.7 Ok def fixed this logging error now, i missed reimporting the module would mess it up again #v1.6 Hopefully found the root cause of all the logging path issues #v1.5 Further fixes to logging path #v1.4 Logging fixes #v1.3 Media server functions #v1.2 Added help #v1.1 Added extra variables #v1.0 release #https://one.rackspace.com/display/IAW/Logging+Module $loggingversion = "1.9.10" #$VerbosePreference = "Continue" Write-Verbose "logging module $loggingversion" #This fixes an issue where the filesystem provider is lost when using stuff like SQLPS If ($Global:RootPath -like "Microsoft.PowerShell.Core\FileSystem::*") { #Already added new path, so no need to add it again } ELSE { $Global:RootPath = "Microsoft.PowerShell.Core\FileSystem::$Global:RootPath" } ####Logging functions Function New-LogFile { <# .Synopsis Creates new log file for logging on the relative path .DESCRIPTION Create a logging file and adds the header the script will use to run $Global:RootPath - should contain the full local path to whre the script is executing (check function called Get-CurrentRootPath to set this) When log file is created, it sets $Global:LogCreated to true and puts the log path in $Global:LogPath. It also adds the log name to $Global:LogsToUpload for SFTP uploading .EXAMPLE New-LogFile -ScriptName "$scriptname" -Path "$Global:RootPath\"} .OUTPUTS Variables set: $Global:LogPath = Path to log file $Global:LogCreated = sets this to $true $Global:LogsToUpload = adds path to log file to create Creates new log file #> Param ( [Parameter()][string]$ScriptName, [Parameter()][switch]$CustomLog, [Parameter()]$Path, [Parameter()][switch]$MediaServersAvailable # v.1.8 - TEMPORARY - handling media server changeover ) write-verbose "New-LogFile" write-verbose "LogCreated: $Global:LogCreated" write-verbose "RootPath: $Global:RootPath" write-verbose "loggingversion: $loggingversion" write-verbose "LogPath: $Global:LogPath" if ($MediaServersAvailable) { #Check log file exists, if it doesnt, create it If($Global:LogCreated) { $logfilepath = $Global:LogPath #Get the date as a string $DateTime = get-date -uFormat "%d/%m/%Y %H:%M:%S" #update prexisting log file Update-LogFile "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -NoConsole Update-LogFile "Log file already exists. Module reimported at $DateTime" -NoConsole Add-content $logfilepath -value "$strDateTime` : Running as user: $env:username" Add-content $logfilepath -value "$strDateTime` : Running on: $ENV:ComputerName" Add-content $logfilepath -value "$strDateTime` : RootPath: $Global:RootPath" Add-content $logfilepath -value "$strDateTime` : Logging version: $loggingversion" } ELSE { #check the sub folder of the script name exists IF (-NOT (Test-Path "$Global:RootPath\LOGS\$ScriptName")) { #If it doesnt, make a new folder mkdir "$Global:RootPath\LOGS\$ScriptName" | Out-Null } #get date $strDateTime = get-date -uFormat "%d_%m_%Y_%H_%M_%S" #if the global dev variable is set, add DEV to the name, if not use normal name If($Global:Dev) { $logfilepath = "$Global:RootPath\Logs\$ScriptName\DEV_$ScriptName`_$env:username`_$strDateTime.log" } ELSE { $logfilepath = "$Global:RootPath\Logs\$ScriptName\$ScriptName`_$env:username`_$strDateTime.log" } #create the log file New-Item $logfilepath -Type File | Out-Null #update new log file with our header information Add-content $logfilepath -value "#################################################" Add-content $logfilepath -value "# $ScriptName log file #" Add-content $logfilepath -value "#################################################" Add-content $logfilepath -value "-------------------------------" Add-content $logfilepath -value "$strDateTime` : New log file created" Add-content $logfilepath -value "$strDateTime` : Running as user: $env:username" Add-content $logfilepath -value "$strDateTime` : Running on: $ENV:ComputerName" Add-content $logfilepath -value "$strDateTime` : RootPath: $Global:RootPath" Add-content $logfilepath -value "$strDateTime` : Logging version: $loggingversion" #set the global variables $Global:LogPath = $logfilepath $Global:LogCreated = $True $Global:LogsToUpload = "$Global:LogsToUpload#$logfilepath" } } } Function Update-LogFile{ <# .SYNOPSIS Writes message to log file and screen .DESCRIPTION Pass a message to log file You can control if you want to write to the log and screen and the colour of the message on the screen .PARAMETER Message The content of your log entry. It is required and should be first .PARAMETER NoConsole Switch, do not write to screen .PARAMETER Type Select text colour Error = red, Warn = yellow, Info = grey (Default) .EXAMPLE Default behaviour, this message will write to the log and screen in grey and add the date. Write-Log "This is a standard message" .EXAMPLE Using the type parameter will change text colour Update-LogFile "this text will be red!" -Type Error .EXAMPLE This will not appear on screen Update-LogFile "This is a variable = $var" -NoConsole .NOTES Author : Martin Howlett - martin.howlett@rackspace.co.uk Requires : PowerShell V1 .LINK None #> Param ( [Parameter()][string]$Message, [Parameter()][Switch]$NoConsole, [Parameter()][Switch]$NoLogFile, [Parameter()][string]$logfilepath = $Global:LogPath, [Parameter()][ValidateSet(“Error”, “Warn”, “Info”,"Success")][string] $Type = “Info”, [Parameter()][switch]$MediaServersAvailable # v.1.8 - TEMPORARY - handling media server changeover ) #Get the date $strDateTime = get-date -uFormat "%d-%m-%Y %H:%M:%S" #The type of message, it will control the text colour switch ($Type) { "Error" {$ConsoleTextColour = 'Red'} "Warn" {$ConsoleTextColour = 'Yellow'} "Info" {$ConsoleTextColour = 'Gray'} "Success" {$ConsoleTextColour = 'Green'} } $Colour = "-ForegroundColor $ConsoleTextColour" #If outputting to the console it will do both the event log and write-host If($NoLogFile){ write-host "$strDateTime : $Message" -ForegroundColor $ConsoleTextColour return } #Only write to the screen, not the log file if($NoConsole) { #Add-content $logfilepath -value "$strDateTime : $Message" }ELSE{ #Default will write to both screen and log file #Add-content $logfilepath -value "$strDateTime : $Message" write-host "$strDateTime : $Message" -ForegroundColor $ConsoleTextColour } } Function New-AppStatsFile { <# .Synopsis Function to create an XML file AppStats will import from the file share .DESCRIPTION Function to create an XML file AppStats will import from the file share Will need access to the media shares, scripts run from Nucleus menu or toolinator will already have this covered .EXAMPLE New-AppStatsFile -scriptname "MyScript" -version $version -Device $ENV:Computername -Account 113548 .OUTPUTS XML file on the media share #> Param ( [Parameter(Mandatory=$true)]$scriptname, [Parameter(Mandatory=$true)]$version, [Parameter()]$functionname, [Parameter()]$device, [Parameter()]$account, [Parameter()]$os = "Windows", [Parameter()]$source = $Global:Source, [Parameter()]$status, [Parameter()]$notes, [Parameter()]$nolog = $Global:NoLog, #Disables Logging [Parameter()][switch]$NewMediaServers ) #Added to stopping logging to audit trail. If ($nolog){ Write-Host "Logging - Disabled." Break } #Get the date and time $date = get-date -uFormat "%d/%m/%Y" $time = get-date -uFormat "%H:%M:%S" #Get the username $username = [Environment]::UserName #Set the proper variable names $functionid = $functionname $appid = $scriptname #if not defined set it as so If ($Source.Length -eq 0){ $Source = "Not defined" } #if device not defined set it If ($Source.device -eq 0){ $device = $ENV:ComputerName } $VarObject = New-Object PSObject -Property @{ appid = $appid bizunit = $bizunit date = $date device = $device functionid = $functionid ip = $ip notes = $notes os = $os source = $source status = $status time = $time username = $username version = $version UseCurrentDate = $true } write-verbose "RootPath: $Global:RootPath" #Get the date used in the file name $strDateTime = get-date -uFormat "%d_%m_%Y_%H_%M_%S" $XMLName = "LOG_$ScriptName`_$env:username`_$device`_$strDateTime.xml" $logfilepath = "$LogPath\LOG_$ScriptName`_$env:username`_$device`_$strDateTime.xml" If ($NewMediaServers){ $XMLPath = "$env:TEMP\$XMLName" Copy-MediaServerFile -DC LON -LocalPath $XMLPath -URLPath "Powershell/AppStats/$XMLName" }else{ #Make sure all our subfolder structure exists IF (-NOT (Test-Path "$Global:RootPath\Logs")){ New-Item -Path "$Global:RootPath\Logs" -ItemType Directory | Out-Null } IF (-NOT (Test-Path "$Global:RootPath\Logs\AppStats")){ New-Item -Path "$Global:RootPath\Logs\AppStats" -ItemType Directory | Out-Null } IF (-NOT (Test-Path "$Global:RootPath\Logs\AppStats\ToLog")){ New-Item -Path "$Global:RootPath\Logs\AppStats\ToLog" -ItemType Directory | Out-Null } #Set file name and paths $LogPath = "$Global:RootPath\Logs\AppStats\ToLog" $logfilepath = "$LogPath\$XMLName" #Make sure the folder path is available and move forward if (Test-Path $LogPath){ $VarObject | Export-Clixml $logfilepath }else{ #There is a weird bug in SQL where you import the provider and it breaks UNC path access as the provder changes $VarObject | Export-Clixml "$logfilepath" } } } Function Update-AppStatAPI { <# .Synopsis log script use to the AppStat API .DESCRIPTION Calls the appstat API directly to update the sceipt usage .EXAMPLE Update-AppStatAPI -appid ScriptName -UseCurrentDate -username Bob -device 123465 .OUTPUTS Returns if the API call wass successful #> Param ( [Parameter(mandatory=$true)][alias("Scriptname")]$appid, [Parameter()]$bizunit, [Parameter()]$device, [Parameter()]$functionid, [Parameter()]$ip, [Parameter()]$notes, [Parameter()]$os="Windows", [Parameter()]$source, [Parameter()]$status, [Parameter()]$version, [Parameter()]$datey, [Parameter()]$datem, [Parameter()]$dated, [Parameter()]$dateh, [Parameter()]$datemin, [Parameter()]$dates, [Parameter()]$username, [Parameter()]$Account, [Parameter()][switch]$UseCurrentDate, [Parameter()][switch]$DEVURL ) #get ps version $psVersion = $PSVersionTable.PSVersion.Major #Use dev or prod URL IF ($DEVURL) { $URL = "http://10.21.229.29/appstats/event/" } ELSE { $URL = "https://appstats.rackspace.com/appstats/event/" } #If username is blank, just grab the current one If ($Username.length -eq 0) { $username = [Environment]::UserName } #Make sure we are running at least PoSh 3 If ($psVersion -ge 3) { #Get the current date and split it up If ($UseCurrentDate) { $date = get-date $datey = $date.Year $datem = $date.Month $dated = $date.Day $dateh = $date.Hour $datemin = $date.Minute $dates = $date.Second } #API fields: appid,bizunit,date,device,functionid,ip,notes,os,source,status,time,username,version #Build a PSoject of our data $Functiondetails = New-Object -TypeName psobject -Property @{ "appid" = $appid; "bizunit" = "$bizunit"; "datey" = "$datey"; "datem" = "$datem"; "dated" = "$dated"; "device" = "$device"; "functionid" = "$functionid"; "ip" = "$IP"; "OS" = "$OS"; "source" = "$source"; "status" = "$status"; "dateh" = "$dateh"; "datemin" = "$datemin"; "dates" = "$dates" "username" = "$username"; "version" = "$version"; } #Convert our object to JSON $JSON = $Functiondetails | ConvertTo-Json Try { #Try to post to API $APIOutput = Invoke-RestMethod -Uri "$URL" -Body "$JSON" -ContentType "application\json" -Method "Post" Write-Verbose $APIOutput #Check the API response If ($APIOutput -eq "OK") { Return $true Write-Verbose "API success" } ELSE { Return $false Write-Verbose "API failed" } } CATCH { #unknown error Write-Verbose "Unknown error in API call" Return $false } } ELSE { #no posh 3 so failed to write to API Write-Verbose "no posh 3" Return $false } } Function Copy-LogFile { <# .Synopsis Upload all our log files to the media share .DESCRIPTION All log files we create we log to $Global:LogsToUpload This function will go over them all and upload them .EXAMPLE Upload-LogFile .OUTPUTS None #> #Split the log file paths from our string in the global varialbe $Logs = $Global:LogsToUpload.Split("#") ForEach ($log in $logs) { #If XML it will be an appstat log so we can upload it to that folder If ($Log -like "*.xml") { Upload-MediaServerFile -DC $DC -Credentials $Credentials -LocalPath $Log -URLPath "LOGS/AppStats/ToLog/$(Split-Path -Leaf $Log)" -Desktop } ELSE { #if not app stat going to be normal folder Upload-MediaServerFile -DC $DC -Credentials $Credentials -LocalPath $Log -URLPath "LOGS/$ScriptName/$(Split-Path -Leaf $Log)" -Desktop } } } Function New-AppStatsLogFile { <# .Synopsis Function to create an XML file AppStats and upload it to the media server .DESCRIPTION Will need to import the meda server function module .EXAMPLE New-AppStatsMediaServerFile -scriptname "MyScript" -version $version -Device $ENV:Computername -Account 113548 .OUTPUTS XML file on the media share #> Param ( [Parameter(Mandatory=$true)]$scriptname, [Parameter(Mandatory=$true)]$version, [Parameter()]$functionname, [Parameter()]$device, [Parameter()]$account, [Parameter()]$os = "Windows", [Parameter()]$source = $Global:Source, [Parameter()]$status, [Parameter()]$notes, [Parameter()]$nolog = $Global:NoLog, #Disables Logging [Parameter()][switch]$NewMediaServers, [Parameter()][switch]$RunLocal ) #Added to stopping logging to audit trail. If ($nolog){ Write-Host "Logging - Disabled." Break } #Get the date and time $date = get-date -uFormat "%d/%m/%Y" $time = get-date -uFormat "%H:%M:%S" #Get the username $username = [Environment]::UserName #Set the proper variable names $functionid = $functionname $appid = $scriptname #if not defined set it as so If ($Source.Length -eq 0){ $Source = "Not defined" } #if device not defined set it If ($Source.device -eq 0){ $device = $ENV:ComputerName } $VarObject = New-Object PSObject -Property @{ appid = $appid bizunit = $bizunit date = $date device = $device functionid = $functionid ip = $ip notes = $notes os = $os source = $source status = $status time = $time username = $username version = $version UseCurrentDate = $true } #Get the date used in the file name $strDateTime = get-date -uFormat "%d_%m_%Y_%H_%M_%S" $XMLName = "LOG_$ScriptName`_$env:username`_$device`_$strDateTime.xml" $XMLPath = "$env:TEMP\$XMLName" $VarObject | Export-Clixml $XMLPath -Force write-verbose "XMLPath $XMLPath" write-verbose "XMLName $XMLName" if($RunLocal){ write-host "Please copy $env:TEMP\$XMLName to K:\Interdepartmental\PowershellTools\Logs\AppStats\ToLog" -ForegroundColor Yellow Invoke-Item $env:TEMP }else{ Upload-MediaServerFile -LocalPath $XMLPath -URLPath "Media/ScriptRepository/Powershell/Logs/AppStats/$XMLName" -Credentials $Global:Credentials } } #### #################################################################### #Legacy function - please do not use. Please use New-AppStatsFile which replaces this one Function Write-MasterLogFile { <# .Synopsis Legacy function - please do not use. Please use Log-AppStatsFile which replaces this one #> Param ( [Parameter()]$scriptname, [Parameter()]$functionname, [Parameter()]$appid, [Parameter()]$bizunit, [Parameter()]$device, [Parameter()]$functionid, [Parameter()]$ip, [Parameter()]$notes, [Parameter()]$os = "Windows", [Parameter()]$source = $Global:Source, [Parameter()]$status, [Parameter()]$version, [Parameter()]$path, [Parameter()]$account, [Parameter()][switch]$MediaServersAvailable # v.1.8 - TEMPORARY - handling media server changeover ) #Added to stopping logging to audit trail. If ($nolog) { Write-Host "Logging - Disabled." Break } $date = get-date -uFormat "%d/%m/%Y" $time = get-date -uFormat "%H:%M:%S" $username = [Environment]::UserName $functionid = $functionname $appid = $scriptname If ($Source.Length -eq 0) { $Source = "Not defined" } $Path = $Global:RootPath #Write to the master log file #$VarObject = New-Object PSObject -Property @{appid = $appid ; bizunit = $bizunit ; date = $date; device = $device ; functionid = $functionid ; ip = $ip ; notes = $notes ; os = $os ; source = $source ; status = $status ; time = $time ; username = $username ; version = $version ; UseCurrentDate = $true} #$VarObject | select appid,bizunit,date,device,functionid,ip,notes,os,source,status,time,username,version | export-csv "$path\Logs\One_Log_To_Rule_Them_All.csv" -noType -Append -ErrorAction Stop #Add-content $Path\Logs\One_Log_To_Rule_Them_All.log -value "`r$appid,$bizunit,$date,$device,$functionid,$ip,$notes,$os,$source,$status,$time,$username,$version" If ($account -ne "1103359") { $VarObject = New-Object PSObject -Property @{ appid = $appid bizunit = $bizunit date = $date device = $device functionid = $functionid ip = $ip notes = $notes os = $os source = $source status = $status time = $time username = $username version = $version UseCurrentDate = $true } $strDateTime = get-date -uFormat "%d_%m_%Y_%H_%M_%S" #Make sure all our subfolders exist $LogPath = "$Global:RootPath\Logs\AppStats\ToLog" $logfilepath = "$LogPath\LOG_$ScriptName`_$env:username`_$strDateTime.xml" IF (-NOT (Test-Path $LogPath)) { New-Item -Path $LogPath -ItemType Directory | Out-Null } If (Test-Path $LogPath) { $VarObject | Export-Clixml $logfilepath } ELSE { #There is a weird bug in SQL where you import the provider and it breaks UNC path access $VarObject | Export-Clixml "$logfilepath" } $Global:LogsToUpload = "$Global:LogsToUpload#$logfilepath" } }