ULS 로깅 팁
ULS 로깅 팁
2011년 2월 4일 업데이트: 이 문서에서 설명하는 내용의 업데이트된 예제는 https://blogs.msdn.com/b/sharepoint_ko/archive/2011/03/21/uls-2.aspx에서 확인하는 것이 좋습니다. 새로운 예제가 보다 효율적이며 작동성도 뛰어납니다.
최근 프로젝트에 몇 가지 ULS 로깅을 추가했는데, 이 경우 사소하지만 번거로운 부작용이 있었습니다. 즉, ULS 로그에서 Area가 “Unknown”으로 표시되었습니다. 다른 게시물에서도 여기에 대한 몇 가지 측면을 다룬 적이 있지만 이 문제를 가장 편리하게 해결할 수 있는 방법에 대한 설명을 즉시 제공하고자 이 게시물을 작성했습니다. 여기서 주목해야 할 점은 수동으로 문제를 해결하기를 원치 않는 경우 모범 사례 팀에서 CodePlex에 제공하는 Logging Framework에서 문제를 자체적으로 해결할 수 있다는 점입니다. 그러나 일반적으로는 가급적이면 직접 코드를 작성하므로, 여기서 해당 솔루션에 대해 간단하게 설명하겠습니다.
대부분의 SDK 설명서에서는 새로운 SPDiagnosticsCategory 만들기를 중심으로 작업을 설명합니다. 클래스의 새 인스턴스 생성자는 Category 이름을 제공할 수 있도록 하며, 이름을 제공하면 사용하려는 모든 사용자 지정 Category 이름이 ULS 로그의 Category 열에 표시됩니다. 고유한 사용자 지정 로깅을 수행하는 경우에는 대부분 사용자 지정 Category와 함께 사용할 사용자 지정 Area도 지정하게 됩니다. 그러나 SDK를 사용하는 경우에는 이렇게 하려면 작업이 훨씬 복잡해집니다. 단순한 생성자를 사용하여 새 Area를 만들고 사용할 수 없으며, SPDiagnosticsServiceBase에서 파생되는 클래스를 직접 작성해야 하기 때문입니다.
전체 프로세스를 구현하기 위해 제가 선택한 방법은, 로깅 클래스와 진단 서비스 기본 클래스를 모두 포함하는 CS 파일 하나를 만드는 것입니다. 먼저 진단 기본 클래스부터 작성합니다. 아래에 전체 클래스를 붙여 넣었으며, 그 중에서 확인해야 하는 부분에 대해 설명하겠습니다.
public class SteveDiagnosticService : SPDiagnosticsServiceBase
{
private const string LOG_AREA = "Steve Area";
public enum LogCategories
{
SteveCategory
}
public SteveDiagnosticService()
: base("Steve Diagnostics Service", SPFarm.Local)
{
}
public SteveDiagnosticService(string name, SPFarm parent)
: base(name, parent)
{
}
protected override bool HasAdditionalUpdateAccess()
{
return true;
}
public static SteveDiagnosticService Local
{
get
{
return SPDiagnosticsServiceBase.GetLocal<SteveDiagnosticService>();
}
}
public void LogMessage(ushort id, LogCategories LogCategory, TraceSeverity traceSeverity,
string message, params object[] data)
{
if (traceSeverity != TraceSeverity.None)
{
SPDiagnosticsCategory category
= Local.Areas[LOG_AREA].Categories[LogCategory.ToString()];
Local.WriteTrace(id, category, traceSeverity, message, data);
}
}
protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
List<SPDiagnosticsCategory> categories = new List<SPDiagnosticsCategory>();
categories.Add(new SPDiagnosticsCategory(
LogCategories.SteveCategory.ToString(),
TraceSeverity.Medium, EventSeverity.Information));
SPDiagnosticsArea area = new SPDiagnosticsArea(
LOG_AREA, 0, 0, false, categories);
List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>();
areas.Add(area);
return areas;
}
}
여기서 몇 가지 부분을 살펴보겠습니다.
private const string LOG_AREA = "Steve Area";
여기서 ULS 로그에 작성할 Area의 이름을 정의합니다.
public enum LogCategories
{
SteveCategory
}
이 범주 목록을 사용자 지정 Area에 추가합니다. 여기서는 이 Area에 사용할 범주가 하나뿐이지만 여러 범주를 사용하려는 경우에는 이 열거의 콘텐츠를 확장하면 됩니다.
public void LogMessage(ushort id, LogCategories LogCategory, TraceSeverity traceSeverity,
string message, params object[] data)
{
if (traceSeverity != TraceSeverity.None)
{
SPDiagnosticsCategory category
= Local.Areas[LOG_AREA].Categories[LogCategory.ToString()];
Local.WriteTrace(id, category, traceSeverity, message, data);
}
}
이 메서드는 구현해야 할 중요한 두 가지 메서드 중 하나로, 실제로 ULS 로그를 작성하는 위치입니다. 첫 줄에서 SPDiagnosticCategory를 가져오며, 이때 SPDiagnosticCategory가 속하는 Area를 참조합니다. 두 번째 줄에서는 ULS 로그에 기록할 로컬 SPDiagnosticsServiceBase 클래스에 있는 기본 클래스 메서드를 호출하며, 이 작업의 일부로 Area와 연결된 Category를 전달합니다.
protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
List<SPDiagnosticsCategory> theCategories = new List<SPDiagnosticsCategory>();
theCategories.Add(new SPDiagnosticsCategory(
LogCategories.SteveCategory.ToString(),
TraceSeverity.Medium, EventSeverity.Information));
SPDiagnosticsArea theArea = new SPDiagnosticsArea(
LOG_AREA, 0, 0, false, theCategories);
List<SPDiagnosticsArea> theArea = new List<SPDiagnosticsArea>();
theArea.Add(area);
return theArea;
}
이 재정의에서 모든 사용자 지정 Area를 SharePoint로 반환합니다. 이 경우에는 Area를 하나만 사용할 것이므로 해당 Area만 다시 보냅니다. 또한 앞서 설명한 것처럼 Area에도 사용자 지정 Category를 하나만 사용할 것입니다. 여러 사용자 지정 Category를 사용하려는 경우에는 1) 앞서 설명한 열거에 해당 Category를 추가한 다음 2) 이 메서드에서 정의한 theCategories 목록 인스턴스에 각 Category를 추가합니다.
이 작업은 사용자 지정 Area를 추가하고 ULS 로그의 적절한 열에 해당 Area를 표시하는 과정에서 가장 중요한 작업입니다. 로깅 클래스 구현 역시 아주 단순합니다. 해당 구현의 주요 코드 부분을 붙여 넣고 추가로 설명을 하겠습니다.
public class Log
{
private const int LOG_ID = 11100;
public static void WriteLog(string Message, TraceSeverity TraceLogSeverity)
{
try
{
//in this simple example, I’m always using the same category
//you could of course pass that in as a method parameter too
//and use it when you call SteveDiagnosticService
SteveDiagnosticService.Local.LogMessage(LOG_ID,
SteveDiagnosticService.LogCategories.SteveCategory,
TraceLogSeverity, Message, null);
}
catch (Exception writeEx)
{
//ignore
Debug.WriteLine(writeEx.Message);
}
}
}
이 코드는 해당 코드를 참조하는 메서드에서 쉽게 구현할 수 있습니다. WriteLog는 정적 메서드이므로 Log.WriteLog(“오류 메시지입니다.”, TraceSeverity.Medium);와 같이 간단한 코드를 작성하면 됩니다. 이 예제의 경우 ULS 로그의 "Steve Area"라는 Area와 "SteveCategory"라는 Category에 "오류 메시지입니다."라는 메시지가 포함된 항목이 작성됩니다.
이 문서는 현지화된 블로그 게시물입니다. 원본 문서는 Tips for ULS Logging을 참조하십시오.