프로그래밍 방식으로 SharePoint ULS에 로깅
-
02-07-2019 - |
문제
SharePoint 웹 부품에 물건을 기록하고 싶지만 ULS로 들어가기를 원합니다. 내가 찾은 대부분의 예제는 이벤트 로그 나 다른 파일에 로그인하지만 ULS에 로그인하기 위해 아직 찾을 수는 없었습니다.
성가 시게, Microsoft.sharePoint.diagnostics 클래스는 모두 내부로 표시되어 있습니다. 나는 찾았다 한 예 Microsoft는 원하는 핫픽스로 해당 클래스를 변경할 수 있기 때문에 반사를 통해 어쨌든 사용하는 방법은 정말 위험하고 불안정 해 보입니다.
SharePoint 문서는 실제로 도움이되지 않았습니다. ULS의 내용과 구성 방법에 대한 많은 관리자 정보가 있지만 실제로 내 이벤트를 실제로 기록하는 지원 코드의 예를 찾지 못했습니다.
힌트 나 팁이 있습니까?
편집하다: 이 질문의 나이부터 볼 수 있듯이 SharePoint 2007 용입니다. SharePoint 2010에서는 spdiagnosticsservice.local을 사용할 수 있습니다. 쓰기. 아래 Jürgen의 답변을 참조하십시오.
해결책
예, 가능합니다.이 MSDN 기사를 참조하십시오. http://msdn2.microsoft.com/hi-in/library/aa979595(en-us).aspx
다음은 C#의 샘플 코드입니다.
using System;
using System.Runtime.InteropServices;
using Microsoft.SharePoint.Administration;
namespace ManagedTraceProvider
{
class Program
{
static void Main(string[] args)
{
TraceProvider.RegisterTraceProvider();
TraceProvider.WriteTrace(0, TraceProvider.TraceSeverity.High, Guid.Empty, "MyExeName", "Product Name", "Category Name", "Sample Message");
TraceProvider.WriteTrace(TraceProvider.TagFromString("abcd"), TraceProvider.TraceSeverity.Monitorable, Guid.NewGuid(), "MyExeName", "Product Name", "Category Name", "Sample Message");
TraceProvider.UnregisterTraceProvider();
}
}
static class TraceProvider
{
static UInt64 hTraceLog;
static UInt64 hTraceReg;
static class NativeMethods
{
internal const int TRACE_VERSION_CURRENT = 1;
internal const int ERROR_SUCCESS = 0;
internal const int ERROR_INVALID_PARAMETER = 87;
internal const int WNODE_FLAG_TRACED_GUID = 0x00020000;
internal enum TraceFlags
{
TRACE_FLAG_START = 1,
TRACE_FLAG_END = 2,
TRACE_FLAG_MIDDLE = 3,
TRACE_FLAG_ID_AS_ASCII = 4
}
// Copied from Win32 APIs
[StructLayout(LayoutKind.Sequential)]
internal struct EVENT_TRACE_HEADER_CLASS
{
internal byte Type;
internal byte Level;
internal ushort Version;
}
// Copied from Win32 APIs
[StructLayout(LayoutKind.Sequential)]
internal struct EVENT_TRACE_HEADER
{
internal ushort Size;
internal ushort FieldTypeFlags;
internal EVENT_TRACE_HEADER_CLASS Class;
internal uint ThreadId;
internal uint ProcessId;
internal Int64 TimeStamp;
internal Guid Guid;
internal uint ClientContext;
internal uint Flags;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct ULSTraceHeader
{
internal ushort Size;
internal uint dwVersion;
internal uint Id;
internal Guid correlationID;
internal TraceFlags dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
internal string wzExeName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
internal string wzProduct;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
internal string wzCategory;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 800)]
internal string wzMessage;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ULSTrace
{
internal EVENT_TRACE_HEADER Header;
internal ULSTraceHeader ULSHeader;
}
// Copied from Win32 APIs
internal enum WMIDPREQUESTCODE
{
WMI_GET_ALL_DATA = 0,
WMI_GET_SINGLE_INSTANCE = 1,
WMI_SET_SINGLE_INSTANCE = 2,
WMI_SET_SINGLE_ITEM = 3,
WMI_ENABLE_EVENTS = 4,
WMI_DISABLE_EVENTS = 5,
WMI_ENABLE_COLLECTION = 6,
WMI_DISABLE_COLLECTION = 7,
WMI_REGINFO = 8,
WMI_EXECUTE_METHOD = 9
}
// Copied from Win32 APIs
internal unsafe delegate uint EtwProc(NativeMethods.WMIDPREQUESTCODE requestCode, IntPtr requestContext, uint* bufferSize, IntPtr buffer);
// Copied from Win32 APIs
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
internal static extern unsafe uint RegisterTraceGuids([In] EtwProc cbFunc, [In] void* context, [In] ref Guid controlGuid, [In] uint guidCount, IntPtr guidReg, [In] string mofImagePath, [In] string mofResourceName, out ulong regHandle);
// Copied from Win32 APIs
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
internal static extern uint UnregisterTraceGuids([In]ulong regHandle);
// Copied from Win32 APIs
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
internal static extern UInt64 GetTraceLoggerHandle([In]IntPtr Buffer);
// Copied from Win32 APIs
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern uint TraceEvent([In]UInt64 traceHandle, [In]ref ULSTrace evnt);
}
public enum TraceSeverity
{
Unassigned = 0,
CriticalEvent = 1,
WarningEvent = 2,
InformationEvent = 3,
Exception = 4,
Assert = 7,
Unexpected = 10,
Monitorable = 15,
High = 20,
Medium = 50,
Verbose = 100,
}
public static void WriteTrace(uint tag, TraceSeverity level, Guid correlationGuid, string exeName, string productName, string categoryName, string message)
{
const ushort sizeOfWCHAR = 2;
NativeMethods.ULSTrace ulsTrace = new NativeMethods.ULSTrace();
// Pretty standard code needed to make things work
ulsTrace.Header.Size = (ushort)Marshal.SizeOf(typeof(NativeMethods.ULSTrace));
ulsTrace.Header.Flags = NativeMethods.WNODE_FLAG_TRACED_GUID;
ulsTrace.ULSHeader.dwVersion = NativeMethods.TRACE_VERSION_CURRENT;
ulsTrace.ULSHeader.dwFlags = NativeMethods.TraceFlags.TRACE_FLAG_ID_AS_ASCII;
ulsTrace.ULSHeader.Size = (ushort)Marshal.SizeOf(typeof(NativeMethods.ULSTraceHeader));
// Variables communicated to SPTrace
ulsTrace.ULSHeader.Id = tag;
ulsTrace.Header.Class.Level = (byte)level;
ulsTrace.ULSHeader.wzExeName = exeName;
ulsTrace.ULSHeader.wzProduct = productName;
ulsTrace.ULSHeader.wzCategory = categoryName;
ulsTrace.ULSHeader.wzMessage = message;
ulsTrace.ULSHeader.correlationID = correlationGuid;
// Pptionally, to improve performance by reducing the amount of data copied around,
// the Size parameters can be reduced by the amount of unused buffer in the Message
if (message.Length < 800)
{
ushort unusedBuffer = (ushort) ((800 - (message.Length + 1)) * sizeOfWCHAR);
ulsTrace.Header.Size -= unusedBuffer;
ulsTrace.ULSHeader.Size -= unusedBuffer;
}
if (hTraceLog != 0)
NativeMethods.TraceEvent(hTraceLog, ref ulsTrace);
}
public static unsafe void RegisterTraceProvider()
{
SPFarm farm = SPFarm.Local;
Guid traceGuid = farm.TraceSessionGuid;
uint result = NativeMethods.RegisterTraceGuids(ControlCallback, null, ref traceGuid, 0, IntPtr.Zero, null, null, out hTraceReg);
System.Diagnostics.Debug.Assert(result == NativeMethods.ERROR_SUCCESS);
}
public static void UnregisterTraceProvider()
{
uint result = NativeMethods.UnregisterTraceGuids(hTraceReg);
System.Diagnostics.Debug.Assert(result == NativeMethods.ERROR_SUCCESS);
}
public static uint TagFromString(string wzTag)
{
System.Diagnostics.Debug.Assert(wzTag.Length == 4);
return (uint) (wzTag[0] << 24 | wzTag[1] << 16 | wzTag[2] << 8 | wzTag[3]);
}
static unsafe uint ControlCallback(NativeMethods.WMIDPREQUESTCODE RequestCode, IntPtr Context, uint* InOutBufferSize, IntPtr Buffer)
{
uint Status;
switch (RequestCode)
{
case NativeMethods.WMIDPREQUESTCODE.WMI_ENABLE_EVENTS:
hTraceLog = NativeMethods.GetTraceLoggerHandle(Buffer);
Status = NativeMethods.ERROR_SUCCESS;
break;
case NativeMethods.WMIDPREQUESTCODE.WMI_DISABLE_EVENTS:
hTraceLog = 0;
Status = NativeMethods.ERROR_SUCCESS;
break;
default:
Status = NativeMethods.ERROR_INVALID_PARAMETER;
break;
}
*InOutBufferSize = 0;
return Status;
}
}
}
다른 팁
크레딧은 다음과 같습니다. http://msdn.microsoft.com/en-us/library/gg512103(v=Office.14).aspx
방금 내 블로그에 게시물을 게시했지만 여기에 코드를 붙여 넣습니다.
다음 줄에 대한 코드의 솔루션 이름을 정의하십시오.
private const string PRODUCT_NAME = "My Custom Solution";
다음은 사용 방법에 대한 샘플 코드입니다.
UlsLogging.LogInformation("This is information message");
UlsLogging.LogInformation("{0}This is information message","Information:");
UlsLogging.LogWarning("This is warning message");
UlsLogging.LogWarning("{0}This is warning message", "Warning:");
UlsLogging.LogError("This is error message");
UlsLogging.LogError("{0}This is error message","Error:");
다음은 코드입니다.
using System;
using System.Collections.Generic;
using Microsoft.SharePoint.Administration;
namespace MyLoggingApp
{
public class UlsLogging : SPDiagnosticsServiceBase
{
// Product name
private const string PRODUCT_NAME = "My Custom Solution";
#region private variables
// Current instance
private static UlsLogging _current;
// area
private static SPDiagnosticsArea _area;
// category
private static SPDiagnosticsCategory _catError;
private static SPDiagnosticsCategory _catWarning;
private static SPDiagnosticsCategory _catLogging;
#endregion
private static class CategoryName
{
public const string Error = "Error";
public const string Warning = "Warning";
public const string Logging = "Logging";
}
private static UlsLogging Current
{
get
{
if (_current == null)
{
_current = new UlsLogging();
}
return _current;
}
}
// Get Area
private static SPDiagnosticsArea Area
{
get
{
if (_area == null)
{
_area = UlsLogging.Current.Areas[PRODUCT_NAME];
}
return _area;
}
}
// Get error category
private static SPDiagnosticsCategory CategoryError
{
get
{
if (_catError == null)
{
_catError = Area.Categories[CategoryName.Error];
}
return _catError;
}
}
// Get warning category
private static SPDiagnosticsCategory CategoryWarning
{
get
{
if (_catWarning == null)
{
_catWarning = Area.Categories[CategoryName.Warning];
}
return _catWarning;
}
}
// Get logging category
private static SPDiagnosticsCategory CategoryLogging
{
get
{
if (_catLogging == null)
{
_catLogging = Area.Categories[CategoryName.Logging];
}
return _catLogging;
}
}
private UlsLogging()
: base(PRODUCT_NAME, SPFarm.Local)
{
}
protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
var cat = new List<SPDiagnosticsCategory>{
new SPDiagnosticsCategory(CategoryName.Error, TraceSeverity.High,EventSeverity.Error),
new SPDiagnosticsCategory(CategoryName.Warning, TraceSeverity.Medium,EventSeverity.Warning),
new SPDiagnosticsCategory(CategoryName.Logging,TraceSeverity.Verbose,EventSeverity.Information)
};
var areas = new List<SPDiagnosticsArea>();
areas.Add(new SPDiagnosticsArea(PRODUCT_NAME, cat));
return areas;
}
// Log Error
public static void LogError(string msg)
{
UlsLogging.Current.WriteTrace(0, CategoryError, TraceSeverity.High, msg);
}
public static void LogError(string msg,params object[] args)
{
UlsLogging.Current.WriteTrace(0, CategoryError, TraceSeverity.High, msg,args);
}
// Log Warning
public static void LogWarning(string msg)
{
UlsLogging.Current.WriteTrace(0, CategoryWarning, TraceSeverity.Medium, msg);
}
public static void LogWarning(string msg, params object[] args)
{
UlsLogging.Current.WriteTrace(0, CategoryWarning, TraceSeverity.Medium, msg,args);
}
// Log Information
public static void LogInformation(string msg)
{
UlsLogging.Current.WriteTrace(0, CategoryLogging, TraceSeverity.Verbose, msg);
}
public static void LogInformation(string msg,params object[] args)
{
UlsLogging.Current.WriteTrace(0, CategoryLogging, TraceSeverity.Verbose, msg,args);
}
}
}
여기에서 SharePoint 로그인에 대한 또 다른 훌륭한 기사를 찾을 수 있습니다.http://www.parago.de/2011/01/how-to-implement-a-custom-sharepoint-2010-logging-service-for-uls-and-windows-nevent-log/
아래 코드를 시도하십시오.
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPDiagnosticsService diagSvc = SPDiagnosticsService.Local;
diagSvc.WriteTrace(123456, new SPDiagnosticsCategory("Category_Name_Here", TraceSeverity.Monitorable, EventSeverity.Error), TraceSeverity.Monitorable, "{0}:{1}", new object[] { "Method_Name", "Error_Message"});
});
}
catch (Exception ex)
{
}
이제 ULS Viewer를 열고 카테고리 이름으로 필터를 열었습니다.
이것은 나에게 효과가 없었고 내 웹 파트를 일관되게 끊었습니다. 나는 그것을 잠시 동안 일했고 그렇지 않았습니다. 그리고 트레이스 레지스터/등록/등록 성명서를 제거했을 때만 작동합니다.
그래서 저는 저에게 효과적인이 훌륭한 기사를 추천합니다.http://sharepoint.namics.com/2008/05/logging_in_webparts.html
본질적으로 사용해야합니다.
.NET 용 공통 인프라 라이브러리.
여기에서 다운로드했습니다.http://netcommon.sourceforge.net/
Gacutil (또는 Control Pane/Admin Tools/.NET Config Tool)을 사용하여 2.0/릴리스 DLL을 GAC에 추가했습니다.
내 코드에 대한 참조를 DLL에 추가했습니다 (다운로드에서). 모든 것이 편집되었습니다.
디렉토리와 빈 로그 파일을 만들어야했습니다. 첫 번째 웹 파트로드에서 작동했습니다. 나는 내 웹 부품에 대한 로깅을 위해 몇 시간과 몇 시간 동안 노력했고 이것은 훌륭하게 작동했으며 Log4J와 같은 좋은 표준입니다.