Update – 1-8-2018
I didn’t spell this out as clearly as I should’ve but this script is intended for reproducible issues. If you want to reproduce an issue with a fresh set of logs, this script is for you. If you require to pull logs from the past, other scripts have been created based on this one which facilitate that functionality. Why pull a fresh set of logs one might ask? Because the overall size of the logs are decreased dramatically especially if verbose logging is enabled. The official blog starts below:
Troubleshooting SharePoint On-Premises issues can be a very time consuming and cumbersome task depending on the issue and the complexity of that issue. When you check the obvious things and you’re still out of ideas, the next step for almost all SharePoint Administrator’s is to turn ULS logs to verbose and reproduce the issue. I personally like to run new-splogfile before reproducing the issue.
Question: Why run New-SPLogfile on every server?
Answer: Running New-SPLogfile gives you a fresh log so you get a more concise set of log files that encompass the time during reproducing the issue. Also, the size of the log will be relevant to the time it takes to reproduce the problem in addition to the logging level.
I authored a script that will automate ULS Log collection while attempting to reproduce whatever SharePoint problem exists. The script will perform the following automatically:
- You decide if you want verbose ULS Logging to Verbose All Categories or go with level currently set – Updated 9-7-17
- Run New-SPLogfile on all SharePoint Servers in the Farm
- Will give you time to reproduce the issue
- After Reproducing issue and pressing any key, it will collect the new ULS Log from each SharePoint server into a destination path of your choosing.
- The ULS Logging will be reset to default logging levels for all categories if verbose was selected. – Updated 9-7-17
- The Destination Directory will open and the ULS Logs will be present
Please Note: From Step 1, if you decide not to select verbose and go with preconfigured level, the logging level will not be reset upon completion. – Updated 9-7-17
Question: Why don’t you just run merge-splogfile?
Answer: That’s certainly an option but I like this approach for the following reasons:
A.) It’s faster and I’m not waiting on a timer job to finish which is the case with merge-splogfile
B.) I want a separate unfiltered ULS log from each server. So if I have 10 server SharePoint farm, I will have 10 ULS Logs. Merge-SPLogfile only gives me 1 file.
I worked in a SharePoint support capacity for quite some time and I’ll tell you that running thru the process of collecting verbose ULS Logs, creating a new ULS log, reproducing the issue, copying those ULS logs to a single location, and finally resetting the ULS back to default level can be very time consuming especially for large server farms. The script is below and I tested it against both SharePoint 2010, 2013 and 2016 on-premises farms. Running the script looks like the following:
My Example Scenario
- 3 Server SharePoint 2016 On-Premises Farm
- ULS Log directory: E:\ULSLogs
- Script directory and filename: c:\PS\ulslogCollect
- Designated Output directory: c:\ulsOutput
1. Launch PowerShell and navigate to c:\ps and run .\ulslogcollect.ps1
2. Specify where I want ULS logs copied (this is my output directory). I typed in: c:\ulsOutput
3. Next, select 1 to use current ULS Logging Level or select 2 to turn up Verbose Logging level for all categories
4. After hitting enter, verbose logging is cranked if it was selected, and new-splogfile is created for all servers. Left PowerShell window open while reproducing the SharePoint issue.
5. After reproducing issue, pressed 1 and enter key and the following occurs (latest ULS Log copied, reset log level back to medium, explorer opens to destination uls directory:
5. I can start reviewing those logs with awesome tools like ULS Viewer or contact Microsoft Support for help.
Important Note 1: If verbose is selected, it turns all categories to verbose which can quickly grow the size of ULS logs. The more load/activity the SharePoint Farm has, the larger these ULS Logs will become. Make sure you have adequate disk space where your ULS Log directory is located.
Important Note 2: If verbose is selected, it doesn’t save custom ULS Logging categories. That means if you have custom logging categories configured, they’ll be reset back to default setting of trace severity medium after running this script.
Instructions for running the script:
1. Copy the below script and save it in notepad
2. Save it with a anyfilename.ps1 extension
3. To run, copy the file to a SharePoint Server
4. Select Start\Microsoft SharePoint 201x Products\SharePoint 201x Management Shell
5. Browse to directory holding the copied script file
6. Run the script: .\anyfilename.ps1 (assuming anyfilename is the name of the file)
<# ==============================================================
//
// Microsoft provides programming examples for illustration only,
// without warranty either expressed or implied, including, but not
// limited to, the implied warranties of merchantability and/or
// fitness for a particular purpose.
//
// This sample assumes that you are familiar with the programming
// language being demonstrated and the tools used to create and debug
// procedures. Microsoft support professionals can help explain the
// functionality of a particular procedure, but they will not modify
// these examples to provide added functionality or construct
// procedures to meet your specific needs. If you have limited
// programming experience, you may want to contact a Microsoft
// Certified Partner or the Microsoft fee-based consulting line at
// (800) 936-5200.
//
// For more information about Microsoft Certified Partners, please
// visit the following Microsoft Web site:
// https://partner.microsoft.com/global/30000104
//
// Author: Russ Maxwell (russmax@microsoft.com)
//
// ———————————————————- #>
##Version 2.0 – Date 9-7-17##
[Void][System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue
Start-SPAssignment -Global
#############
##Variables##
#############
$global:ulsPath = (get-spdiagnosticconfig).LogLocation
$global:servs = (get-spfarm).servers | ?{$_.Role -ne “Invalid”}
$global:keepCount = 0
#################################
#Function to set custom log path#
#################################
function custLogPath()
{
$global:ulsPath = $global:ulsPath -replace “:”, “$”
$localPath = “\\” + $env:ComputerName + “\” + $global:ulsPath
$resTemp = get-childitem -path $localPath | ?{$_.Extension -eq “.log”}
return $resTemp
}
#########################################
#InnerFunction to retrieve and copy logs#
#########################################
function innerGrabULS($temsrv)
{
$partPath = “\\” + $srv.name + “\” + $global:ulsPath + “\*.*”
$srvInclude = $srv.name + “*.log”
$sortedFiles = get-childitem -path $partPath -Include $srvInclude | sort-object LastWriteTime -descending
$filePath = $sortedFiles[0].FullName
$fileName = $sortedFiles[0].Name
try
{
Copy-Item -Path $filePath -Destination $temdestPath
$fulldestPath = $temdestPath + “\” + $fileName
if(Test-Path $fulldestPath)
{$Global:keepCount++}
else
{
Write-Host “Unable to copy latest ULS file from the following Server: ” + $srv.Name -ForegroundColor Yellow
Write-Host “You will need to go retrieve the latest ULS log manually” -ForegroundColor Yellow
Write-Host
}
}
catch [Exception]
{
Write-Host “Exception Caught: ” $_.Exception -ForegroundColor Red
Write-Host “Error attempting to copy file from Server: ” + $srv.Name -ForegroundColor Red
Write-Host
}
}
#####################################
#Function to retrieve and copy logs#
#####################################
function grabULS($temdestPath)
{
#$srvCount = $temSrvs.count
if($global:servs.gettype().tostring() -eq “System.Object[]”)
{
$srvCount = $global:servs.count
foreach($srv in $global:servs)
{innerGrabULS $srv}
}
elseif($global:servs.gettype().tostring() -eq “Microsoft.SharePoint.Administration.SPServer”)
{
#We’re dealing with a single server farm#
innerGrabULS
$srvCount = 1
}
if($keepCount -eq $srvCount)
{return, 1}
else
{return, 2}
}
#########################
##Function to clear log##
#########################
function clearLog($temfinalRes)
{
if($temfinalRes -eq 1)
{
Write-Host “Latest ULS Logs have been copied” -ForegroundColor Green
Write-Host “Resetting Log Level back to Default”
Clear-SPLogLevel
}
else
{
Write-Host “Either no files or a partial of ULS log files copied” -ForegroundColor Yellow
Write-Host “Please inspect the destination directory for more details”
Write-Host “Resetting Log Level back to Default”
Clear-SPLogLevel
}
}
######################
##Script Starts Here##
######################
######################
#Get Destination Path#
######################
Write-Host “Enter a folder path where you want the ULS files copied”
$outputDir = Read-Host “(For Example: c:\logs\)”
if(test-path -Path $outputDir)
{Write-Host}
else
{
Write-Host “The path you provided could not be found” -foregroundcolor Yellow
Write-Host “Path Specified: ” $outputDir -ForegroundColor Yellow
Write-Host
$outputDir = Read-Host “Enter a folder path where you want the ULS files copied (For Example: c:\logs\)”
$checkPath = test-path $outputDir
if($checkPath -ne $true)
{
Write-Host “Path was not found – Exiting Script” -ForegroundColor Yellow
Return
}
else
{Write-Host “Path is now valid and will continue”}
}
########################################
#Get SharePoint Servers and SP Version##
########################################
$spVersion = (Get-PSSnapin Microsoft.Sharepoint.Powershell).Version.Major
if((($spVersion -ne 14) -and ($spVersion -ne 15) -and ($spVersion -ne 16)))
{
Write-Host “Supported version of SharePoint not Detected” -ForegroundColor Yellow
Write-Host “Script is supported for SharePoint 2010, 2013, or 2016” -ForegroundColor Yellow
Write-Host “Exiting Script” -ForegroundColor Yellow
Return
}
if($spVersion -eq 14)
{
$defPathTemp = “%CommonProgramFiles%\Microsoft Shared\Web Server Extensions\14\Logs\”
if($global:ulsPath -eq $defPathTemp)
{
$global:ulsPath = “\c$\” + “program files\common files\microsoft shared\web server extensions\14\logs”
$localPath = “\\” + $env:ComputerName + $global:ulsPath
$resTemp = get-childitem -path $localPath | ?{$_.Extension -eq “.log”}
}
else
{$resTemp = custLogPath}
}
elseif($spVersion -eq 15)
{
$defPathTemp = “%CommonProgramFiles%\Microsoft Shared\Web Server Extensions\15\Logs\”
if($global:ulsPath -eq $defPathTemp)
{
$global:ulsPath = “\c$\” + “program files\common files\microsoft shared\web server extensions\15\logs”
$localPath = “\\” + $env:ComputerName + $global:ulsPath
$resTemp = get-childitem -path $localPath | ?{$_.Extension -eq “.log”}
}
else
{$resTemp = custLogPath}
}
elseif($spVersion -eq 16)
{
$defPathTemp = “%CommonProgramFiles%\Microsoft Shared\Web Server Extensions\16\Logs\”
if($global:ulsPath -eq $defPathTemp)
{
$global:ulsPath = “\c$\” + “program files\common files\microsoft shared\web server extensions\16\logs”
$localPath = “\\” + $env:ComputerName + $global:ulsPath
$resTemp = get-childitem -path $localPath | ?{$_.Extension -eq “.log”}
}
else
{$resTemp = custLogPath}
}
if($resTemp -eq $null)
{
Write-Host “ULS Log directory is invalid or no log files are present. Exiting Script” -foregroundcolor Red
Return
}
######################################
#Determine Verbose or Regular Logging#
######################################
Write-Host “Press 1 to use the current ULS Logging Level”
Write-Host “Press 2 to crank up Verbose logging for all categories”
$resV = read-host
Write-Host
Write-Host
if($resV -eq 2)
{
try
{
Write-Host “Turning up Diagnostic Logging to Verbose”
set-sploglevel -TraceSeverity Verbose
Write-Host “Verbose Logging now Enabled”
}
catch [Exception]
{
Write-Host “Exception Caught: ” $_.Exception -ForegroundColor Red
Write-Host
Write-Host “Error attempting to set ULS Tracing to Verbose” -ForegroundColor Red
#Clearing Just in Case#
Clear-SPLogLevel -ErrorAction SilentlyContinue
Write-Host “Exiting Script” -ForegroundColor Red
Return
}
}
elseif($resV -ne 1)
{Write-Host “Unable to detect desired logging level. Please run script again and press 1 or 2 and Enter”;Return}
###################################
#create new ULS Log on all servers#
###################################
if($global:servs.gettype().tostring() -eq “System.Object[]”)
{
foreach($srv in $global:servs)
{
Write-Host “Creating New ULS Log on Server: ” $srv
$service = get-service -ComputerName $srv.Name -Name “SPTraceV4”
if($service){$service.ExecuteCommand(129)}
}
}
elseif($global:servs.gettype().tostring() -eq “Microsoft.SharePoint.Administration.SPServer”)
{
Write-Host “Creating New ULS Log on Server: ” $global:servs
$service = get-service -ComputerName $srv.Name -Name “SPTraceV4”
if($service){$service.ExecuteCommand(129)}
}
Write-Host “New ULS Logs Created for every SharePoint Server in the farm” -ForegroundColor Green
Write-Host
######################################
#Reproduce the Issue and Collect Logs#
######################################
Write-Host “Keep this window open and reproduce the issue!”
Write-Host “After reproducing issue press 1 and enter key!”
Write-Host
$val = Read-Host
if($val -eq 1)
{
Write-Host “Copying files into Destination Provided”
$finalRes = grabULS $outputDir
if($resV -eq 2)
{clearLog $finalRes}
Write-Host “Operation Complete – Exiting Script” -ForegroundColor Green
Invoke-Item $outputDir
}
else
{
Write-Host “You pressed a different key” -ForegroundColor Yellow
Write-Host
Write-Host “Try Again: After reproducing issue press 1 and enter key!”
Write-Host
$val = Read-Host
if($val -eq 1)
{
Write-Host “Copying files into Destination Provided”
$finalRes = grabULS $outputDir
if($resV -eq 2)
{clearLog $finalRes}
Write-Host “Operation Complete – Exiting Script” -ForegroundColor Green
Invoke-Item $outputDir
}
else
{
Write-Host “This is the second attempt and a wrong key was entered” -foregroundcolor Yellow
if($resV -eq 2)
{
Write-Host “Resetting Logging Level back to default and exiting script”-ForegroundColor Yellow
Clear-SPLogLevel
Return
}
Write-Host “Exiting script”
Return
}
}
Stop-SPAssignment –Global
Thanks!
Russ Maxwell, MSFT