Troubleshooting SharePoint Performance issues are probably the most challenging issues for a SharePoint Administrator to troubleshoot. Collecting Performance Monitor output can take time because not only must you understand the options available in the UI, but you also need to know which counters to add. Microsoft does have some automation available to assists in this area by using publicly available PLA interfaces. I wrote a PowerShell script that any SharePoint Administrator can save off to a Web Front-End, run, and start Performance Gathering in a quick and efficient manner. First, I’d like to give a super huge thanks to Brad Rutkowski. He tipped me off that this was possible using PowerShell by creating –com objects and leveraging the PLA interfaces. His blog documenting interacting with data collector sets is here:
http://blogs.technet.com/b/brad_rutkowski/archive/2009/02/18/interacting-with-data-collector-sets-via-powershell.aspx
The publicly available PLA interfaces and MSDN documentation was a great help as well.
http://msdn.microsoft.com/en-us/library/aa372243(v=VS.85).aspx
Also, the Windows SDK provided some slick samples of how to do this in CPP.
Reasons why I wrote this script:
In order to run this, save the below script to a text editor like notepad. Save the file with a .ps1 extension to a SharePoint server. To run the file from PowerShell, run .\yourfilename.ps1
Important: I successfully tested this script on both SharePoint 2007 and SharePoint 2010 installed on Windows 2008. This script will prompt the user to input the maximum size in MB for the performance monitor log. When the maximum size is reached, a new performance log (file) is created and used. This cycle continues until the Performance Data Collection is manually stopped. I confirmed this script can run against remote SharePoint servers which means you won’t be required to run this script on each SharePoint Server. Rather, you can run it from one SharePoint server and for each time you run the script, specify the destination SharePoint Server. I provided an option in the script to allow for automatically starting the Data Collector to immediately start collecting performance data. Below is a sample run I performed and I set opted to have the script automatically start the data collector called SharePointRocks.
What the script looks like
Data Collector set automatically started
Script is below. Enjoy!
####################### #Grab Initial Settings# ####################### $Name = Read-Host "Enter a name your Data Collector Set?" $Machine = Read-Host "Enter the SharePoint Server Name to monitor" $Sample = Read-Host "Please Enter sample interval in Seconds" $output = Read-Host "Please enter location for the output (For Example: C:\Perflogs)" Write-host "Please enter the maximum size of each output file in MB" $buffer = Read-Host "I recommend 250"
############################ #Create the Data Collector Set# ############################ $DataCollSet = new-object -ComObject pla.DataCollectorSet $DataCollSet.DisplayName = $Name
####################### #Create a Data Collector# ####################### $DataCollector = $DataCollSet.DataCollectors.CreateDataCollector(0) $DataCollector.name = "SharePoint - Collect" $filename = $Machine + ".blg" $DataCollector.FileName = $filename $DataCollector.FileNameFormat = 0x4000 $DataCollector.SampleInterval = $Sample
###################################################################### #Building up Array of counters and adding as property to the Datacollector# ###################################################################### $counters = @("\ASP.NET v2.0.50727\*","\ASP.NET Apps v2.0.50727(*)\*", "\.NET CLR Networking(*)\*", "\.NET CLR Memory(*)\*", "\.NET CLR Exception(*)\*", "\.NET CLR Loading(*)\*", "\.NET Data Provider for SqlServer(*)\*", "\Processor(*)\*", "\Process(*)\*", "\LogicalDisk(*)\*", "\Memory\*", "\Network Interface(*)\*", "\PhysicalDisk(*)\*", "\Web Service(*)\*", "\Web Service Cache\*", "\System\*", "\TCPv4\*", "\TCPV6\*", "\SharePoint Publishing Cache(*)\*") $DataCollector.PerformanceCounters = $counters
######################################################################## #Add the data collector to the data collector set and set additional properties# ########################################################################
try { $DataCollSet.DataCollectors.Add($DataCollector) $DataCollSet.Segment = "VARIANT_TRUE" $DataCollSet.SegmentMaxSize = $buffer $DataCollSet.RootPath = $output
$DataCollSet.Commit($Name, $machine, 0x0003)
Write-Host "The Data Collector set has been created Successfully." -ForegroundColor Green } catch [Exception] { Write-Host "Exception Caught: " $_.Exception -ForegroundColor Red return } Write-Host "Would you like to automatically start the data collection?" $decide = Read-Host "Press 1 or yes or 2 for no"
if($decide = 1) { try { $DataCollSet.Start($true) Write-Host "Operation Completed Successfully" -ForegroundColor Green Write-Host } catch [Exception] { Write-Host "Exception Caught: " $_.Exception -ForegroundColor Red return } }
else { Write-Host Write-Host "To access and start this Data Collector set:" Write-Host "1. Select Start, Run, and type Perfmon (press enter)" Write-Host "2. Expand Data Collector Sets\User Defined" Write-Host "3. Right click on desired data collector set to Start" }
Write-Host Write-Host "Script Completed"
Thanks!
Russ Maxwell, MSFT
Snapshots and SharePoint 2010 are a great thing in that they provide an additional level of fault tolerance for any SharePoint 2010 farm. A SharePoint Administrator can quickly restore Sites, Lists, or items from a snapshot. This out of the box solution is possible through the Central Administrators Recover Data from an unattached content database feature. This functionality exports the user selected data out of the Snapshot database and into a backup file. Finally, the backup file and be used with import-spweb to restore the data. For a walkthrough of restoring snapshots using Central Administrator, see my blog posts here.
I recently found out this functionality isn’t possible using out of the box PowerShell cmdlets. I put together a PowerShell script that will guide you through Recovering Data from an Unattached database. It’s possible to recover from a Site, Subsite, List, or Document Library. Once, the export is complete, simply run import-spweb cmdlet. I recommend running this in a test farm to get more familiar with it.
In order to run this, save the below script to a text editor like notepad. Save the file with a .ps1 extension. To run the file from PowerShell, run .\yourfilename.ps1
I assume you know the following things when running this script:
1. If the end goal is restoring a specific subsite, it’s expected that you know the partial path to your subsite.
For Example: Site Collection is: http://contoso
Let’s assume subsite1 is a subsite that resides directly under contoso and subsite2 is a subsite that resides directly under SubSite1.
The full url looks like: http://contoso/subsite1/subsite2
2. It’s expected that you know the list or document library name.
3. It’s assumed that your Central Admin site’s display name contains the words “Central Admin”, if this isn’t the case, adjust the $_.DisplayName property on the line which declares $caweb variable.
Enjoy!
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") Add-PSSnapin Microsoft.SharePoint.PowerShell
Start-SPAssignment -Global Write-Host "This PowerShell script will assists you in exporting data out of a snapshot and into a physical file which can then be restored via import-spweb." Write-Host " "
#################### # Initial Setup # ####################
#Get the CA URL $caweb = Get-SPWebapplication -IncludeCentralAdministration | where{$_.DisplayName -match "Central Admin"} $ca = $caweb.url
############################## #Manually Grab other settings# ############################## $SQLserv = Read-Host "Enter your SQL Server Name" $location = Read-Host "Enter desired backup directory (For Example: D:\backupdir)" $filename = Read-Host "Enter desired backup filename (For Example: bufile.cmp)" $includesec = Read-Host "Press y to include security or any other key to export without security"
################################################## #Choose a ContentDB and inserting into $contentDB# ################################################## $cdb = Get-SPContentDatabase $cdbname = $cdb | ForEach-Object {$_.Name} Write-Host write-host "Choose a Content Database from which the snapshot was taken" Write-Host $num = 0
Foreach ($i in $cdbname) { Write-Host $num $i $num++ }
$result = Read-Host $num = 0 Foreach($i in $cdbname) { if($num -eq $result) { $contentDB = $i } $num++ }
############################################### #Select a snapshot and inserting it in $snapdb# ############################################### $snapdbs = Get-SPContentDatabase $contentDB $snap = $snapdbs.Snapshots | ForEach-Object {$_.Name} $num = 0 Write-Host Write-Host "Select a Snapshot" Foreach ($i in $snap) { Write-Host $num $i $num++ } $num = 0
$result = Read-Host Foreach($i in $snap) { if($num -eq $result) { $snapdb = $i } $num++ }
##################### # Grab the Snapshot # ##################### $snapshot = [Microsoft.SharePoint.Administration.SPContentDatabase]::CreateUnattachedContentDatabase($SQLserv, $snapdb, $null, $null)
################ #Choose a site # ################ $snapnames = $snapshot.Sites | ForEach-Object {$_.Url} Write-Host Write-Host "Choose a site to export from" $num = 0 ForEach($i in $snapnames) { write-host $num $i $num++ } $result = Read-Host $num = 0 ForEach($i in $snapnames) { if($num -eq $result) { $URL = $i } $num++ }
Write-Host "You chose site" Write-Host $URL
############################## #Only export from a subsite? # ############################## write-host "Press y to export from a specific subsite" write-host "Press any other key to export from the site collection level" $subdec = Read-Host if(($subdec -eq "Y") -or ($subdec -eq "y")) { write-host "Please Enter the subsite name in the format of /subsitename" write-host "For Example: http://contoso/subsite1 would look like /subsite1" $subsite = Read-Host $URL2 = $URL + $subsite }
############################### #Only export a list or doclib?# ############################### Write-host "Press y to only export a list or document library" Write-Host "Press any other key to export from site level" $listit = Read-Host if(($listit -eq "y") -or ($listit -eq "Y")) { Write-Host "Please enter the list or doc library in the format of /testlist" Write-Host "For Example: http://contoso/testlist would look like: /testlist" $list = Read-Host if(($subdec -eq "Y") -or ($subdec -eq "y")) { $URL2 = $URL2 + $list } elseif(($subdec -ne "Y") -or ($subdec -ne "y")) { $URL2 = $URL + $list } }
##################################### # Inserting Site or List to export # ##################################### $exportobject = New-Object Microsoft.SharePoint.Deployment.SPExportObject
if(($listit -ne "y") -or ($listit -ne "Y")) { $exportobject.Type = [Microsoft.SharePoint.Deployment.SPDeploymentObjectType]::Web if(($subdec -eq "Y") -or ($subdec -eq "y")) { $exportobject.Url = $URL2 } else {$exportobject.Url = $URL} }
elseif(($listit -eq "y") -or ($listit -eq "Y")) { $exportobject.Type = [Microsoft.SharePoint.Deployment.SPDeploymentObjectType]::List $exportobject.Url = $URL2 }
$exportobject.IncludeDescendants = [Microsoft.SharePoint.Deployment.SPIncludeDescendants]::All
############################## # Configuring Export Settings# ############################## $exportsettings = New-Object Microsoft.SharePoint.Deployment.SPExportSettings $exportsettings.UnattachedContentDatabase = $snapshot $exportsettings.SiteURL = $URL $exportsettings.FileLocation = $location $exportsettings.LogFilePath = $location $exportsettings.BaseFileName = $filename $exportsettings.ExportObjects.Add($exportobject) $exportsettings.IncludeVersions = [Microsoft.SharePoint.Deployment.SPIncludeVersions]::All $exportsettings.LogExportObjectsTable = 1
if($includesec -eq "y" -or "Y") { $exportsettings.IncludeSecurity = [Microsoft.SharePoint.Deployment.SPIncludeSecurity]::All }
#################################### # Create Export Object and Export # #################################### $export = New-Object Microsoft.SharePoint.Deployment.SPExport($exportsettings) Write-Host Write-Host "Starting Export" $export.Run() Write-Host Write-Host "Operation Completed Successfully!"
Stop-SPAssignment –Global