Als SharePoint Entwickler ist man es gewohnt umfangreiche Trace Logs und und das Windows Event Log durchzukämmen. Besonders die Informationen welche von SharePoint in die Trace Log Dateien im 14-Hive unter \LOGS, sind extrem umfangreich, je nach den Einstellungen in der Farm.
Auf dem eigenen virtuellen Entwicklungsserver mag das durcharbeiten der Log Dateien noch erträglich sein – besonders mit nützlichen Tools wie dem ULS Log Viewer. Wird die eigene Solution dann auf ein Test/Staging System ausgerollt und das Testen geht so richtig los, hört der Spass dann meist auf. Die Logs jedes mal via RDP öffnen oder irgendwie kopieren und durchkramen ist mühsame Arbeit.
In diesem un den folgenden Posts wollen wir uns mehrere Dinge ansehen welche uns das Logging Leben erleichtern sollen in SharePoint 2010.
- Eigene Informationen via ULS in die Trace Logs schreiben
- Die Trave Logs effizient verwalten und einfach durchsuchen
Eigene Informationen via ULS loggen
Das Einbringen von eigenen Logging Informationen ist eigentlich erfrischend einfach – man glaubt es kaum, aber in den Weiten des Internets kursieren viele Beispiele, welche Unmanaged Code und die Windows API dazu verwenden.
Im folgenden ein klassisches “Hello World” Beispiel, wie mit der SharePoint API direkt in SharePoint Server Trace Logs geschrieben werden kann.
Logging “Hello World” Beispiel
Zuerst ist eine Referenz auf die Assembly Microsoft.Office.Server erforderlich

Diese Assembly ist teil von SharePoint SERVER – also auf Systemen, welchen lediglich die Gratis “SharePoint Foundation” besitzen nicht verfügbar.
Über die statische Klasse PortalLog im Namespace Microsoft.Office.Server.Diagnostics wird direkt ins Trace Log geschrieben.
1: void LogMessage(string message)
2: {
3: Microsoft.Office.Server.Diagnostics.PortalLog.LogString(message);
4: }
Einfacher gehts kaum!
Interessant ist bei SharePoint basierten Solutions oft auch, welche Methode aufgerufen wurde im Custom Code – zum Beispiel wenn Event Receiver zum Einsatz kommen. Den Aufruf und das Verlassen einer Methode logged man wie in Beispiel 2.
1: void LogMessage(string message)
2: {
3: Microsoft.Office.Server.Diagnostics.PortalLog.EnterFunction("SPLoggingSample.WebParts.LogMessage");
4: Microsoft.Office.Server.Diagnostics.PortalLog.LogString(message);
5: Microsoft.Office.Server.Diagnostics.PortalLog.LeaveFunction("SPLoggingSample.WebParts.LogMessage");
6: }
Will man das Loggin in einem try..catch Block verwenden, sollte man immer darauf achten, nach dem entsprechenden Loging Code eine Instanz von SPException zu werfen, damit SharePoint auf den Fehler mit einer Fehlerseite für den User reagieren kann.
1:
2: void DoSomething()
3: {
4: try
5: {
6:
7: }
8: catch (Exception ex)
9: {
10: LogMessage("Error in DoSomething()" + ex.Message);
11: throw new SPException(@"Ein Fehler ist aufgetreten. Die Fehlerinformationen wurden protokolliert.
12: Kontaktieren sie ihren Administrator");
13: }
14: }
SharePoint reagiert automatisch auf eine SPException mit der bekannten weissen Fehlerseite.

Das Austauschen von eingabauten SharePoint Application Pages, wie der “Access Denied” Seite oder eben der obigen Fehlerseite, war bisher nur möglich in dem die entsprechenden ASPX Seiten im _layouts Ordner verändert wurden. Mit SharePoint 2010 gibt es die Möglichkeit Systemseiten im Code zu verändern, am besten beim Aktivieren des entsprechenden Features.
1: public override void FeatureActivated(SPFeatureReceiverProperties properties)
2: {
3: var webApp = properties.Feature.Parent as SPWebApplication;
4: if (webApp != null)
5: {
6: // Set Access Denied.
7: if (!webApp.UpdateMappedPage(SPWebApplication.SPCustomPage.AccessDenied,
8: "/_layouts/CodeForceErrorPages/AccessDenied.aspx"))
9: {
10: throw new ApplicationException("Failed setting new access denied page mapping.");
11: }
12:
13: // Set Signout.
14: if (!webApp.UpdateMappedPage(SPWebApplication.SPCustomPage.Signout,
15: "/_layouts/CodeForceErrorPages/Signout.aspx"))
16: {
17: throw new ApplicationException("Failed setting new signout page mapping.");
18: }
19:
20: // Set File Not Found.
21: webApp.FileNotFoundPage = "/_layouts/CodeForceErrorPages/FileNotFound.htm";
22:
23: webApp.Update(true);
24: }
25: }
Das Schöne hierbei ist, dass sich die Änderungen nur auf eine Anwendung beziehen!
Soweit das einfachste Logging Szenario – hilft aber bei Problemen welche in Custom Code stecken schon sehr gut weiter um Fehler nachzuvollziehen.
Im nächsten Artikel sehen wir uns die neuen Dienste welche SharePoint 2010 zum Thema Logging bietet genauer an. Danach soll ein WebPart – ein LogViewer – erstellt werden, der uns direkt in der Weboberfläche ein Betrachten und Filtern der Logeinträge ermöglicht. In Teil 3 zu guter Letzt gehe ich dann noch auf selbst entwickelte Logging Provider ein, die es zB ermöglichen Fehlermeldungen via WebService zu versenden.
Stay tuned for more Up-Front SharePoint Development!

Andreas Aschauer