{"id":1862,"date":"2013-04-24T05:21:05","date_gmt":"2013-04-24T05:21:05","guid":{"rendered":"https:\/\/poiseddevelopers.com\/reality-tech\/?p=1862"},"modified":"2024-04-26T13:00:15","modified_gmt":"2024-04-26T13:00:15","slug":"scripting-sharepoint-logging-to-uls-and-event-log","status":"publish","type":"post","link":"https:\/\/poiseddevelopers.com\/reality-tech\/scripting-sharepoint-logging-to-uls-and-event-log\/","title":{"rendered":"Scripting SharePoint logging to ULS and Event Log"},"content":{"rendered":"<p>It\u2019s easy to dump output to a text file in a script, but for enterprise-class logging, the two standards are the Event Log and ULS (Unified Logging System). First ULS.<\/p>\n<p>Below in PowerShell I grab a reference to the SPDiagnosticsService, define a SPDiagnosticsCategory, then call the writeTrace() method:<\/p>\n<pre lang=\"php\">\r\n$diagSrc = [Microsoft.SharePoint.Administration.SPDiagnosticsService]::Local\r\n$diacategory = new-object Microsoft.SharePoint.Administration.SPDiagnosticsCategory(\"MyTestCategory\",[Microsoft.SharePoint.Administration.TraceSeverity]::Monitorable, [Microsoft.SharePoint.Administration.EventSeverity]::ErrorCritical)\r\n$diagSrc.WriteTrace(98765, $diacategory, [Microsoft.SharePoint.Administration.TraceSeverity]::Monitorable, \"Write your log description here\" )\r\n<\/pre>\n<p>ULS is a good standard central way to go, but let\u2019s move onto writing into the Event Log, which is extra useful given we are first going to create a custom application log:<\/p>\n<pre lang=\"php\">\r\nNew-EventLog -LogName MyCustomScripts -Source scripts\r\n<\/pre>\n<p>First challenge is if the logfile exists, then it will throw an error, even if you try encapsulating in a try\/catch. the trick is to leverage the Get-EventLog CmdLet.<\/p>\n<p>First, to see what exists, format as a list:<\/p>\n<pre lang=\"php\">\r\nGet-EventLog -list\r\n<\/pre>\n<p>You now have your very own Event Log, and can write into it with your own event IDs, and messages, and severity levels. Here\u2019s two worknig examples:<\/p>\n<pre lang=\"php\">\r\nWrite-EventLog -LogName MyCustomScripts -Source Scripts -Message \"trying 4142 it works ... COOL!\" -EventId 4142 -EntryType information\r\nWrite-EventLog -LogName MyCustomScripts  -Source Scripts -Message \"trying 4942 as an error\" -EventId 4942 -EntryType error\r\n<\/pre>\n<p>Now let\u2019s simplify for re-use and consistency. Let\u2019s declare some basics at the top of all scripts:<\/p>\n<pre lang=\"php\">\r\n$Eventing = $true;  #determine if any events are written to the event log\r\n$LogName = \"JoelScripts\"\r\n$SourceName = \"Scripts\"\r\n$ScriptID = 3; # unique number per script\r\n<\/pre>\n<p>Here\u2019s a one-line function to make life simpler for our scripts:<\/p>\n<pre lang=\"php\">\r\nfunction Write-MyLog([int] $EventID, [string] $Description, [system.Diagnostics.EventLogEntryType] $Severity)\r\n{\r\n    if ($Eventing)\r\n    {\r\n    Write-EventLog -LogName $LogName -Source $SourceName -Message $Description -EventId $EventID -EntryType $Severity\r\n    }\r\n}\r\n<\/pre>\n<p>Now let\u2019s add a line at the start and end of the scripts to trigger an information event on what\u2019s running. Note that references to $MyInvocation contain information about the currently running script:<\/p>\n<pre lang=\"php\">\r\nWrite-MyLog -Description \"Start of $($MyInvocation.MyCommand.Path)\" -EventId $ScriptID -Severity information\r\nWrite-MyLog -Description \"End of $($MyInvocation.MyCommand.Path)\" -EventId $ScriptID -Severity information\r\n<\/pre>\n<p>Lastly, here\u2019s a sample normal message evented for warning, and next for error:<\/p>\n<pre lang=\"php\">\r\nWrite-MyLog -Description $RunStatus -EventId $ScriptID -Severity Warning\r\nWrite-MyLog -Description $RunStatus -EventId $ScriptID -Severity Error\r\n<\/pre>\n<p>A nice way to write events is to use the \u201cSource\u201d to map back to the script name or some other useful value for filtering. However sources need to be pre-defined. Here\u2019s how to define a source:<\/p>\n<pre lang=\"php\">\r\nNew-EventLog -LogName $LogName -Source \"X\"\r\n<\/pre>\n<p>The challenge is when to create this source. I find it\u2019s best to declare the source only if it does not exist:<\/p>\n<pre lang=\"php\">\r\ntry\r\n{\r\n$Sources = Get-EventLog -LogName $logname | Select-Object Source -Unique\r\n$found = $false;\r\nforeach ($OneSource in $Sources)\r\n    {\r\n        if ($OneSource.source -eq $Source)\r\n        {\r\n            $found=$true;\r\n        }\r\n    }   \r\n}\r\ncatch\r\n{\r\n    Write-Host \"cannot find logfile, so we are in deep trouble\"\r\n}\r\n \r\nif (!$found)\r\n{\r\n    New-EventLog -LogName $LogName -Source $Source\r\n    Write-Host \"Created new Source $($Source) in log name $($LogName)\"\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>It\u2019s easy to dump output to a text file in a script, but for enterprise-class logging, the two standards are the Event Log and ULS (Unified Logging System). First ULS. Below in PowerShell I grab a reference to the SPDiagnosticsService, define a SPDiagnosticsCategory, then call the writeTrace() method: $diagSrc = [Microsoft.SharePoint.Administration.SPDiagnosticsService]::Local $diacategory = new-object Microsoft.SharePoint.Administration.SPDiagnosticsCategory(&#8220;MyTestCategory&#8221;,[Microsoft.SharePoint.Administration.TraceSeverity]::Monitorable, [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":1864,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[31],"tags":[],"class_list":["post-1862","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-alerts"],"acf":[],"_links":{"self":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/1862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/comments?post=1862"}],"version-history":[{"count":1,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/1862\/revisions"}],"predecessor-version":[{"id":1869,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/posts\/1862\/revisions\/1869"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/media\/1864"}],"wp:attachment":[{"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/media?parent=1862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/categories?post=1862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/poiseddevelopers.com\/reality-tech\/wp-json\/wp\/v2\/tags?post=1862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}