You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
@@ -17,7 +17,7 @@ namespace System.Diagnostics {
|
||||
// conditions. Users should implement this interface to be used as an argument to
|
||||
// System.Diagnostics.Debugger.CustomNotification.
|
||||
//
|
||||
// @dbgtodo [....]: when this goes public, it must be replaced by a custom attribute
|
||||
// @dbgtodo dlaw: when this goes public, it must be replaced by a custom attribute
|
||||
internal interface ICustomDebuggerNotification
|
||||
{
|
||||
// Interface does not need to be marked with the serializable attribute
|
||||
|
||||
@@ -113,7 +113,6 @@ namespace System.Diagnostics.Contracts {
|
||||
System.Runtime.CompilerServices.ContractHelper.TriggerFailure(failureKind, displayMessage, userMessage, conditionText, innerException);
|
||||
}
|
||||
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
/// <summary>
|
||||
/// Allows a managed application environment such as an interactive interpreter (IronPython)
|
||||
/// to be notified of contract failures and
|
||||
@@ -143,11 +142,9 @@ namespace System.Diagnostics.Contracts {
|
||||
System.Runtime.CompilerServices.ContractHelper.InternalContractFailed -= value;
|
||||
}
|
||||
}
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
#endregion FailureBehavior
|
||||
}
|
||||
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE // Not usable on Silverlight by end users due to security, and full trust users have not yet expressed an interest.
|
||||
public sealed class ContractFailedEventArgs : EventArgs
|
||||
{
|
||||
private ContractFailureKind _failureKind;
|
||||
@@ -207,7 +204,6 @@ namespace System.Diagnostics.Contracts {
|
||||
_unwind = true;
|
||||
}
|
||||
}
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
|
||||
#if FEATURE_SERIALIZATION
|
||||
[Serializable]
|
||||
@@ -279,15 +275,13 @@ namespace System.Runtime.CompilerServices
|
||||
{
|
||||
#region Private fields
|
||||
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
private static volatile EventHandler<ContractFailedEventArgs> contractFailedEvent;
|
||||
private static readonly Object lockObject = new Object();
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
|
||||
internal const int COR_E_CODECONTRACTFAILED = unchecked((int)0x80131542);
|
||||
|
||||
#endregion
|
||||
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
/// <summary>
|
||||
/// Allows a managed application environment such as an interactive interpreter (IronPython) or a
|
||||
/// web browser host (Jolt hosting Silverlight in IE) to be notified of contract failures and
|
||||
@@ -325,7 +319,6 @@ namespace System.Runtime.CompilerServices
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
|
||||
/// <summary>
|
||||
/// Rewriter will call this method on a contract failure to allow listeners to be notified.
|
||||
@@ -352,16 +345,13 @@ namespace System.Runtime.CompilerServices
|
||||
|
||||
string returnValue;
|
||||
String displayMessage = "contract failed."; // Incomplete, but in case of OOM during resource lookup...
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
ContractFailedEventArgs eventArgs = null; // In case of OOM.
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
#if FEATURE_RELIABILITY_CONTRACTS
|
||||
System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
|
||||
#endif
|
||||
try
|
||||
{
|
||||
displayMessage = GetDisplayMessage(failureKind, userMessage, conditionText);
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
EventHandler<ContractFailedEventArgs> contractFailedEventLocal = contractFailedEvent;
|
||||
if (contractFailedEventLocal != null)
|
||||
{
|
||||
@@ -389,17 +379,14 @@ namespace System.Runtime.CompilerServices
|
||||
throw new ContractException(failureKind, displayMessage, userMessage, conditionText, innerException);
|
||||
}
|
||||
}
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
if (eventArgs != null && eventArgs.Handled)
|
||||
{
|
||||
returnValue = null; // handled
|
||||
}
|
||||
else
|
||||
#endif // !FEATURE_CORECLR || FEATURE_NETCORE
|
||||
{
|
||||
returnValue = displayMessage;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace System.Diagnostics
|
||||
[ResourceConsumption(ResourceScope.Process)]
|
||||
public static void Break()
|
||||
{
|
||||
if (!IsDebuggerAttached())
|
||||
if (!Debugger.IsAttached)
|
||||
{
|
||||
// Try and demand UnmanagedCodePermission. This is done in a try block because if this
|
||||
// fails we want to be able to silently eat the exception and just return so
|
||||
@@ -69,7 +69,7 @@ namespace System.Diagnostics
|
||||
[ResourceConsumption(ResourceScope.Process)]
|
||||
static void BreakCanThrow()
|
||||
{
|
||||
if (!IsDebuggerAttached())
|
||||
if (!Debugger.IsAttached)
|
||||
{
|
||||
#pragma warning disable 618
|
||||
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
|
||||
@@ -93,7 +93,7 @@ namespace System.Diagnostics
|
||||
[ResourceConsumption(ResourceScope.Machine)]
|
||||
public static bool Launch()
|
||||
{
|
||||
if (IsDebuggerAttached())
|
||||
if (Debugger.IsAttached)
|
||||
return (true);
|
||||
|
||||
// Try and demand UnmanagedCodePermission. This is done in a try block because if this
|
||||
@@ -130,6 +130,14 @@ namespace System.Diagnostics
|
||||
}
|
||||
}
|
||||
|
||||
// Do not inline the slow path
|
||||
[MethodImplAttribute(MethodImplOptions.NoInlining)]
|
||||
private static void NotifyOfCrossThreadDependencySlow()
|
||||
{
|
||||
CrossThreadDependencyNotification notification = new CrossThreadDependencyNotification();
|
||||
CustomNotification(notification);
|
||||
}
|
||||
|
||||
// Sends a notification to the debugger to indicate that execution is about to enter a path
|
||||
// involving a cross thread dependency. A debugger that has opted into this type of notification
|
||||
// can take appropriate action on receipt. For example, performing a funceval normally requires
|
||||
@@ -145,12 +153,10 @@ namespace System.Diagnostics
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
CrossThreadDependencyNotification notification = new CrossThreadDependencyNotification();
|
||||
CustomNotification(notification);
|
||||
NotifyOfCrossThreadDependencySlow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
@@ -158,18 +164,15 @@ namespace System.Diagnostics
|
||||
|
||||
// Returns whether or not a debugger is attached to the process.
|
||||
//
|
||||
public static bool IsAttached
|
||||
public static extern bool IsAttached
|
||||
{
|
||||
[ResourceExposure(ResourceScope.Process)]
|
||||
[ResourceConsumption(ResourceScope.Process)]
|
||||
get { return IsDebuggerAttached(); }
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
get;
|
||||
}
|
||||
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.Process)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
private static extern bool IsDebuggerAttached();
|
||||
|
||||
// Constants representing the importance level of messages to be logged.
|
||||
//
|
||||
// An attached debugger can enable or disable which messages will
|
||||
|
||||
350
external/referencesource/mscorlib/system/diagnostics/eventing/StubEnvironment.cs
vendored
Normal file
350
external/referencesource/mscorlib/system/diagnostics/eventing/StubEnvironment.cs
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing.Internal
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing.Internal
|
||||
#endif
|
||||
{
|
||||
#if ES_BUILD_AGAINST_DOTNET_V35
|
||||
using Microsoft.Internal;
|
||||
#endif
|
||||
using Microsoft.Reflection;
|
||||
using System.Reflection;
|
||||
|
||||
internal static class Environment
|
||||
{
|
||||
public static readonly string NewLine = System.Environment.NewLine;
|
||||
|
||||
public static int TickCount
|
||||
{ get { return System.Environment.TickCount; } }
|
||||
|
||||
public static string GetResourceString(string key, params object[] args)
|
||||
{
|
||||
string fmt = rm.GetString(key);
|
||||
if (fmt != null)
|
||||
return string.Format(fmt, args);
|
||||
|
||||
string sargs = String.Empty;
|
||||
foreach(var arg in args)
|
||||
{
|
||||
if (sargs != String.Empty)
|
||||
sargs += ", ";
|
||||
sargs += arg.ToString();
|
||||
}
|
||||
|
||||
return key + " (" + sargs + ")";
|
||||
}
|
||||
|
||||
public static string GetRuntimeResourceString(string key, params object[] args)
|
||||
{
|
||||
return GetResourceString(key, args);
|
||||
}
|
||||
|
||||
private static System.Resources.ResourceManager rm = new System.Resources.ResourceManager("Microsoft.Diagnostics.Tracing.Messages", typeof(Environment).Assembly());
|
||||
}
|
||||
}
|
||||
|
||||
#if ES_BUILD_AGAINST_DOTNET_V35
|
||||
|
||||
namespace Microsoft.Diagnostics.Contracts.Internal
|
||||
{
|
||||
internal class Contract
|
||||
{
|
||||
public static void Assert(bool invariant)
|
||||
{
|
||||
Assert(invariant, string.Empty);
|
||||
}
|
||||
public static void Assert(bool invariant, string message)
|
||||
{
|
||||
if (!invariant)
|
||||
{
|
||||
if (System.Diagnostics.Debugger.IsAttached)
|
||||
System.Diagnostics.Debugger.Break();
|
||||
throw new Exception("Assertion failed: " + message);
|
||||
}
|
||||
}
|
||||
public static void EndContractBlock()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Microsoft.Internal
|
||||
{
|
||||
using System.Text;
|
||||
|
||||
internal static class Tuple
|
||||
{
|
||||
public static Tuple<T1> Create<T1>(T1 item1)
|
||||
{
|
||||
return new Tuple<T1>(item1);
|
||||
}
|
||||
|
||||
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
|
||||
{
|
||||
return new Tuple<T1, T2>(item1, item2);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class Tuple<T1>
|
||||
{
|
||||
private readonly T1 m_Item1;
|
||||
|
||||
public T1 Item1 { get { return m_Item1; } }
|
||||
|
||||
public Tuple(T1 item1)
|
||||
{
|
||||
m_Item1 = item1;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("(");
|
||||
sb.Append(m_Item1);
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Tuple<T1, T2>
|
||||
{
|
||||
private readonly T1 m_Item1;
|
||||
private readonly T2 m_Item2;
|
||||
|
||||
public T1 Item1 { get { return m_Item1; } }
|
||||
public T2 Item2 { get { return m_Item2; } }
|
||||
|
||||
public Tuple(T1 item1, T2 item2)
|
||||
{
|
||||
m_Item1 = item1;
|
||||
m_Item2 = item2;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("(");
|
||||
sb.Append(m_Item1);
|
||||
sb.Append(", ");
|
||||
sb.Append(m_Item2);
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Reflection
|
||||
{
|
||||
using System.Reflection;
|
||||
|
||||
#if ES_BUILD_PCL
|
||||
[Flags]
|
||||
public enum BindingFlags
|
||||
{
|
||||
DeclaredOnly = 0x02, // Only look at the members declared on the Type
|
||||
Instance = 0x04, // Include Instance members in search
|
||||
Static = 0x08, // Include Static members in search
|
||||
Public = 0x10, // Include Public members in search
|
||||
NonPublic = 0x20, // Include Non-Public members in search
|
||||
}
|
||||
|
||||
public enum TypeCode {
|
||||
Empty = 0, // Null reference
|
||||
Object = 1, // Instance that isn't a value
|
||||
DBNull = 2, // Database null value
|
||||
Boolean = 3, // Boolean
|
||||
Char = 4, // Unicode character
|
||||
SByte = 5, // Signed 8-bit integer
|
||||
Byte = 6, // Unsigned 8-bit integer
|
||||
Int16 = 7, // Signed 16-bit integer
|
||||
UInt16 = 8, // Unsigned 16-bit integer
|
||||
Int32 = 9, // Signed 32-bit integer
|
||||
UInt32 = 10, // Unsigned 32-bit integer
|
||||
Int64 = 11, // Signed 64-bit integer
|
||||
UInt64 = 12, // Unsigned 64-bit integer
|
||||
Single = 13, // IEEE 32-bit float
|
||||
Double = 14, // IEEE 64-bit double
|
||||
Decimal = 15, // Decimal
|
||||
DateTime = 16, // DateTime
|
||||
String = 18, // Unicode character string
|
||||
}
|
||||
#endif
|
||||
static class ReflectionExtensions
|
||||
{
|
||||
#if !ES_BUILD_PCL
|
||||
|
||||
//
|
||||
// Type extension methods
|
||||
//
|
||||
public static bool IsEnum(this Type type) { return type.IsEnum; }
|
||||
public static bool IsAbstract(this Type type) { return type.IsAbstract; }
|
||||
public static bool IsSealed(this Type type) { return type.IsSealed; }
|
||||
public static Type BaseType(this Type type) { return type.BaseType; }
|
||||
public static Assembly Assembly(this Type type) { return type.Assembly; }
|
||||
public static TypeCode GetTypeCode(this Type type) { return Type.GetTypeCode(type); }
|
||||
|
||||
public static bool ReflectionOnly(this Assembly assm) { return assm.ReflectionOnly; }
|
||||
|
||||
#else // ES_BUILD_PCL
|
||||
|
||||
//
|
||||
// Type extension methods
|
||||
//
|
||||
public static bool IsEnum(this Type type) { return type.GetTypeInfo().IsEnum; }
|
||||
public static bool IsAbstract(this Type type) { return type.GetTypeInfo().IsAbstract; }
|
||||
public static bool IsSealed(this Type type) { return type.GetTypeInfo().IsSealed; }
|
||||
public static Type BaseType(this Type type) { return type.GetTypeInfo().BaseType; }
|
||||
public static Assembly Assembly(this Type type) { return type.GetTypeInfo().Assembly; }
|
||||
|
||||
public static MethodInfo[] GetMethods(this Type type, BindingFlags flags)
|
||||
{
|
||||
// Minimal implementation to cover only the cases we need
|
||||
System.Diagnostics.Debug.Assert((flags & BindingFlags.DeclaredOnly) != 0);
|
||||
System.Diagnostics.Debug.Assert((flags & ~(BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic)) == 0);
|
||||
Func<MethodInfo, bool> visFilter;
|
||||
Func<MethodInfo, bool> instFilter;
|
||||
switch (flags & (BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
case 0: visFilter = mi => false; break;
|
||||
case BindingFlags.Public: visFilter = mi => mi.IsPublic; break;
|
||||
case BindingFlags.NonPublic: visFilter = mi => !mi.IsPublic; break;
|
||||
default: visFilter = mi => true; break;
|
||||
}
|
||||
switch (flags & (BindingFlags.Instance | BindingFlags.Static))
|
||||
{
|
||||
case 0: instFilter = mi => false; break;
|
||||
case BindingFlags.Instance: instFilter = mi => !mi.IsStatic; break;
|
||||
case BindingFlags.Static: instFilter = mi => mi.IsStatic; break;
|
||||
default: instFilter = mi => true; break;
|
||||
}
|
||||
List<MethodInfo> methodInfos = new List<MethodInfo>();
|
||||
foreach (var declaredMethod in type.GetTypeInfo().DeclaredMethods)
|
||||
{
|
||||
if (visFilter(declaredMethod) && instFilter(declaredMethod))
|
||||
methodInfos.Add(declaredMethod);
|
||||
}
|
||||
return methodInfos.ToArray();
|
||||
}
|
||||
public static FieldInfo[] GetFields(this Type type, BindingFlags flags)
|
||||
{
|
||||
// Minimal implementation to cover only the cases we need
|
||||
System.Diagnostics.Debug.Assert((flags & BindingFlags.DeclaredOnly) != 0);
|
||||
System.Diagnostics.Debug.Assert((flags & ~(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) == 0);
|
||||
Func<FieldInfo, bool> visFilter;
|
||||
Func<FieldInfo, bool> instFilter;
|
||||
switch (flags & (BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
case 0: visFilter = fi => false; break;
|
||||
case BindingFlags.Public: visFilter = fi => fi.IsPublic; break;
|
||||
case BindingFlags.NonPublic: visFilter = fi => !fi.IsPublic; break;
|
||||
default: visFilter = fi => true; break;
|
||||
}
|
||||
switch (flags & (BindingFlags.Instance | BindingFlags.Static))
|
||||
{
|
||||
case 0: instFilter = fi => false; break;
|
||||
case BindingFlags.Instance: instFilter = fi => !fi.IsStatic; break;
|
||||
case BindingFlags.Static: instFilter = fi => fi.IsStatic; break;
|
||||
default: instFilter = fi => true; break;
|
||||
}
|
||||
List<FieldInfo> fieldInfos = new List<FieldInfo>();
|
||||
foreach (var declaredField in type.GetTypeInfo().DeclaredFields)
|
||||
{
|
||||
if (visFilter(declaredField) && instFilter(declaredField))
|
||||
fieldInfos.Add(declaredField);
|
||||
}
|
||||
return fieldInfos.ToArray();
|
||||
}
|
||||
public static Type GetNestedType(this Type type, string nestedTypeName)
|
||||
{
|
||||
TypeInfo ti = null;
|
||||
foreach(var nt in type.GetTypeInfo().DeclaredNestedTypes)
|
||||
{
|
||||
if (nt.Name == nestedTypeName)
|
||||
{
|
||||
ti = nt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ti == null ? null : ti.AsType();
|
||||
}
|
||||
public static TypeCode GetTypeCode(this Type type)
|
||||
{
|
||||
if (type == typeof(bool)) return TypeCode.Boolean;
|
||||
else if (type == typeof(byte)) return TypeCode.Byte;
|
||||
else if (type == typeof(char)) return TypeCode.Char;
|
||||
else if (type == typeof(ushort)) return TypeCode.UInt16;
|
||||
else if (type == typeof(uint)) return TypeCode.UInt32;
|
||||
else if (type == typeof(ulong)) return TypeCode.UInt64;
|
||||
else if (type == typeof(sbyte)) return TypeCode.SByte;
|
||||
else if (type == typeof(short)) return TypeCode.Int16;
|
||||
else if (type == typeof(int)) return TypeCode.Int32;
|
||||
else if (type == typeof(long)) return TypeCode.Int64;
|
||||
else if (type == typeof(string)) return TypeCode.String;
|
||||
else if (type == typeof(float)) return TypeCode.Single;
|
||||
else if (type == typeof(double)) return TypeCode.Double;
|
||||
else if (type == typeof(DateTime)) return TypeCode.DateTime;
|
||||
else if (type == (typeof(Decimal))) return TypeCode.Decimal;
|
||||
else return TypeCode.Object;
|
||||
}
|
||||
|
||||
//
|
||||
// FieldInfo extension methods
|
||||
//
|
||||
public static object GetRawConstantValue(this FieldInfo fi)
|
||||
{ return fi.GetValue(null); }
|
||||
|
||||
//
|
||||
// Assembly extension methods
|
||||
//
|
||||
public static bool ReflectionOnly(this Assembly assm)
|
||||
{
|
||||
// In PCL we can't load in reflection-only context
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Defining some no-ops in PCL builds
|
||||
#if ES_BUILD_PCL
|
||||
namespace System.Security
|
||||
{
|
||||
class SuppressUnmanagedCodeSecurityAttribute : Attribute { }
|
||||
|
||||
enum SecurityAction { Demand }
|
||||
}
|
||||
namespace System.Security.Permissions
|
||||
{
|
||||
class HostProtectionAttribute : Attribute { public bool MayLeakOnAbort { get; set; } }
|
||||
class PermissionSetAttribute : Attribute
|
||||
{
|
||||
public PermissionSetAttribute(System.Security.SecurityAction action) { }
|
||||
public bool Unrestricted { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
60
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ArrayTypeInfo.cs
vendored
Normal file
60
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ArrayTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
internal sealed class ArrayTypeInfo<ElementType>
|
||||
: TraceLoggingTypeInfo<ElementType[]>
|
||||
{
|
||||
private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
|
||||
|
||||
public ArrayTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
|
||||
{
|
||||
this.elementInfo = elementInfo;
|
||||
}
|
||||
|
||||
public override void WriteMetadata(
|
||||
TraceLoggingMetadataCollector collector,
|
||||
string name,
|
||||
EventFieldFormat format)
|
||||
{
|
||||
collector.BeginBufferedArray();
|
||||
this.elementInfo.WriteMetadata(collector, name, format);
|
||||
collector.EndBufferedArray();
|
||||
}
|
||||
|
||||
public override void WriteData(
|
||||
TraceLoggingDataCollector collector,
|
||||
ref ElementType[] value)
|
||||
{
|
||||
var bookmark = collector.BeginBufferedArray();
|
||||
|
||||
var count = 0;
|
||||
if (value != null)
|
||||
{
|
||||
count = value.Length;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
this.elementInfo.WriteData(collector, ref value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
collector.EndBufferedArray(bookmark, count);
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
var array = (ElementType[])value;
|
||||
var serializedArray = new object[array.Length];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
serializedArray[i] = this.elementInfo.GetData(array[i]);
|
||||
}
|
||||
return serializedArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSet.cs
vendored
Normal file
123
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSet.cs
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using Interlocked = System.Threading.Interlocked;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: A very simple lock-free add-only dictionary.
|
||||
/// Warning: this is a copy-by-value type. Copying performs a snapshot.
|
||||
/// Accessing a readonly field always makes a copy of the field, so the
|
||||
/// GetOrAdd method will not work as expected if called on a readonly field.
|
||||
/// </summary>
|
||||
/// <typeparam name="KeyType">
|
||||
/// The type of the key, used for TryGet.
|
||||
/// </typeparam>
|
||||
/// <typeparam name="ItemType">
|
||||
/// The type of the item, used for GetOrAdd.
|
||||
/// </typeparam>
|
||||
internal struct ConcurrentSet<KeyType, ItemType>
|
||||
where ItemType : ConcurrentSetItem<KeyType, ItemType>
|
||||
{
|
||||
private ItemType[] items;
|
||||
|
||||
public ItemType TryGet(KeyType key)
|
||||
{
|
||||
ItemType item;
|
||||
var oldItems = this.items;
|
||||
|
||||
if (oldItems != null)
|
||||
{
|
||||
var lo = 0;
|
||||
var hi = oldItems.Length;
|
||||
do
|
||||
{
|
||||
int i = (lo + hi) / 2;
|
||||
item = oldItems[i];
|
||||
|
||||
int cmp = item.Compare(key);
|
||||
if (cmp == 0)
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{
|
||||
lo = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = i;
|
||||
}
|
||||
}
|
||||
while (lo != hi);
|
||||
}
|
||||
|
||||
item = null;
|
||||
|
||||
Done:
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public ItemType GetOrAdd(ItemType newItem)
|
||||
{
|
||||
ItemType item;
|
||||
var oldItems = this.items;
|
||||
ItemType[] newItems;
|
||||
|
||||
Retry:
|
||||
|
||||
if (oldItems == null)
|
||||
{
|
||||
newItems = new ItemType[] { newItem };
|
||||
}
|
||||
else
|
||||
{
|
||||
var lo = 0;
|
||||
var hi = oldItems.Length;
|
||||
do
|
||||
{
|
||||
int i = (lo + hi) / 2;
|
||||
item = oldItems[i];
|
||||
|
||||
int cmp = item.Compare(newItem);
|
||||
if (cmp == 0)
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{
|
||||
lo = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = i;
|
||||
}
|
||||
}
|
||||
while (lo != hi);
|
||||
|
||||
int oldLength = oldItems.Length;
|
||||
newItems = new ItemType[oldLength + 1];
|
||||
Array.Copy(oldItems, 0, newItems, 0, lo);
|
||||
newItems[lo] = newItem;
|
||||
Array.Copy(oldItems, lo, newItems, lo + 1, oldLength - lo);
|
||||
}
|
||||
|
||||
newItems = Interlocked.CompareExchange(ref this.items, newItems, oldItems);
|
||||
if (oldItems != newItems)
|
||||
{
|
||||
oldItems = newItems;
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
item = newItem;
|
||||
|
||||
Done:
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSetItem.cs
vendored
Normal file
21
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSetItem.cs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: Abstract base class that must be inherited by items in a
|
||||
/// ConcurrentSet.
|
||||
/// </summary>
|
||||
/// <typeparam name="KeyType">Type of the set's key.</typeparam>
|
||||
/// <typeparam name="ItemType">Type of the derived class.</typeparam>
|
||||
internal abstract class ConcurrentSetItem<KeyType, ItemType>
|
||||
where ItemType : ConcurrentSetItem<KeyType, ItemType>
|
||||
{
|
||||
public abstract int Compare(ItemType other);
|
||||
public abstract int Compare(KeyType key);
|
||||
}
|
||||
}
|
||||
315
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/DataCollector.cs
vendored
Normal file
315
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/DataCollector.cs
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: This is the implementation of the DataCollector
|
||||
/// functionality. To enable safe access to the DataCollector from
|
||||
/// untrusted code, there is one thread-local instance of this structure
|
||||
/// per thread. The instance must be Enabled before any data is written to
|
||||
/// it. The instance must be Finished before the data is passed to
|
||||
/// EventWrite. The instance must be Disabled before the arrays referenced
|
||||
/// by the pointers are freed or unpinned.
|
||||
/// </summary>
|
||||
[SecurityCritical]
|
||||
internal unsafe struct DataCollector
|
||||
{
|
||||
[ThreadStatic]
|
||||
internal static DataCollector ThreadInstance;
|
||||
|
||||
private byte* scratchEnd;
|
||||
private EventSource.EventData* datasEnd;
|
||||
private GCHandle* pinsEnd;
|
||||
private EventSource.EventData* datasStart;
|
||||
private byte* scratch;
|
||||
private EventSource.EventData* datas;
|
||||
private GCHandle* pins;
|
||||
private byte[] buffer;
|
||||
private int bufferPos;
|
||||
private int bufferNesting; // We may merge many fields int a single blob. If we are doing this we increment this.
|
||||
private bool writingScalars;
|
||||
|
||||
internal void Enable(
|
||||
byte* scratch,
|
||||
int scratchSize,
|
||||
EventSource.EventData* datas,
|
||||
int dataCount,
|
||||
GCHandle* pins,
|
||||
int pinCount)
|
||||
{
|
||||
this.datasStart = datas;
|
||||
this.scratchEnd = scratch + scratchSize;
|
||||
this.datasEnd = datas + dataCount;
|
||||
this.pinsEnd = pins + pinCount;
|
||||
this.scratch = scratch;
|
||||
this.datas = datas;
|
||||
this.pins = pins;
|
||||
this.writingScalars = false;
|
||||
}
|
||||
|
||||
internal void Disable()
|
||||
{
|
||||
this = new DataCollector();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completes the list of scalars. Finish must be called before the data
|
||||
/// descriptor array is passed to EventWrite.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A pointer to the next unused data descriptor, or datasEnd if they were
|
||||
/// all used. (Descriptors may be unused if a string or array was null.)
|
||||
/// </returns>
|
||||
internal EventSource.EventData* Finish()
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
return this.datas;
|
||||
}
|
||||
|
||||
internal void AddScalar(void* value, int size)
|
||||
{
|
||||
var pb = (byte*)value;
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
var scratchOld = this.scratch;
|
||||
var scratchNew = scratchOld + size;
|
||||
if (this.scratchEnd < scratchNew)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_AddScalarOutOfRange"));
|
||||
}
|
||||
|
||||
this.ScalarsBegin();
|
||||
this.scratch = scratchNew;
|
||||
|
||||
for (int i = 0; i != size; i++)
|
||||
{
|
||||
scratchOld[i] = pb[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldPos = this.bufferPos;
|
||||
this.bufferPos = checked(this.bufferPos + size);
|
||||
this.EnsureBuffer();
|
||||
for (int i = 0; i != size; i++, oldPos++)
|
||||
{
|
||||
this.buffer[oldPos] = pb[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddBinary(string value, int size)
|
||||
{
|
||||
if (size > ushort.MaxValue)
|
||||
{
|
||||
size = ushort.MaxValue - 1;
|
||||
}
|
||||
|
||||
if (this.bufferNesting != 0)
|
||||
{
|
||||
this.EnsureBuffer(size + 2);
|
||||
}
|
||||
|
||||
this.AddScalar(&size, 2);
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
this.PinArray(value, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldPos = this.bufferPos;
|
||||
this.bufferPos = checked(this.bufferPos + size);
|
||||
this.EnsureBuffer();
|
||||
fixed (void* p = value)
|
||||
{
|
||||
Marshal.Copy((IntPtr)p, this.buffer, oldPos, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddBinary(Array value, int size)
|
||||
{
|
||||
this.AddArray(value, size, 1);
|
||||
}
|
||||
|
||||
internal void AddArray(Array value, int length, int itemSize)
|
||||
{
|
||||
if (length > ushort.MaxValue)
|
||||
{
|
||||
length = ushort.MaxValue;
|
||||
}
|
||||
|
||||
var size = length * itemSize;
|
||||
if (this.bufferNesting != 0)
|
||||
{
|
||||
this.EnsureBuffer(size + 2);
|
||||
}
|
||||
|
||||
this.AddScalar(&length, 2);
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
this.PinArray(value, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldPos = this.bufferPos;
|
||||
this.bufferPos = checked(this.bufferPos + size);
|
||||
this.EnsureBuffer();
|
||||
Buffer.BlockCopy(value, 0, this.buffer, oldPos, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the start of a non-blittable array or enumerable.
|
||||
/// </summary>
|
||||
/// <returns>Bookmark to be passed to EndBufferedArray.</returns>
|
||||
internal int BeginBufferedArray()
|
||||
{
|
||||
this.BeginBuffered();
|
||||
this.bufferPos += 2; // Reserve space for the array length (filled in by EndEnumerable)
|
||||
return this.bufferPos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the end of a non-blittable array or enumerable.
|
||||
/// </summary>
|
||||
/// <param name="bookmark">The value returned by BeginBufferedArray.</param>
|
||||
/// <param name="count">The number of items in the array.</param>
|
||||
internal void EndBufferedArray(int bookmark, int count)
|
||||
{
|
||||
this.EnsureBuffer();
|
||||
this.buffer[bookmark - 2] = unchecked((byte)count);
|
||||
this.buffer[bookmark - 1] = unchecked((byte)(count >> 8));
|
||||
this.EndBuffered();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the start of dynamically-buffered data.
|
||||
/// </summary>
|
||||
internal void BeginBuffered()
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
this.bufferNesting += 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the end of dynamically-buffered data.
|
||||
/// </summary>
|
||||
internal void EndBuffered()
|
||||
{
|
||||
this.bufferNesting -= 1;
|
||||
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
/*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
this.EnsureBuffer();
|
||||
this.PinArray(this.buffer, this.bufferPos);
|
||||
this.buffer = null;
|
||||
this.bufferPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureBuffer()
|
||||
{
|
||||
var required = this.bufferPos;
|
||||
if (this.buffer == null || this.buffer.Length < required)
|
||||
{
|
||||
this.GrowBuffer(required);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureBuffer(int additionalSize)
|
||||
{
|
||||
var required = this.bufferPos + additionalSize;
|
||||
if (this.buffer == null || this.buffer.Length < required)
|
||||
{
|
||||
this.GrowBuffer(required);
|
||||
}
|
||||
}
|
||||
|
||||
private void GrowBuffer(int required)
|
||||
{
|
||||
var newSize = this.buffer == null ? 64 : this.buffer.Length;
|
||||
|
||||
do
|
||||
{
|
||||
newSize *= 2;
|
||||
}
|
||||
while (newSize < required);
|
||||
|
||||
Array.Resize(ref this.buffer, newSize);
|
||||
}
|
||||
|
||||
private void PinArray(object value, int size)
|
||||
{
|
||||
var pinsTemp = this.pins;
|
||||
if (this.pinsEnd <= pinsTemp)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_PinArrayOutOfRange"));
|
||||
}
|
||||
|
||||
var datasTemp = this.datas;
|
||||
if (this.datasEnd <= datasTemp)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
|
||||
}
|
||||
|
||||
this.pins = pinsTemp + 1;
|
||||
this.datas = datasTemp + 1;
|
||||
|
||||
*pinsTemp = GCHandle.Alloc(value, GCHandleType.Pinned);
|
||||
datasTemp->m_Ptr = (long)(ulong)(UIntPtr)(void*)pinsTemp->AddrOfPinnedObject();
|
||||
datasTemp->m_Size = size;
|
||||
}
|
||||
|
||||
private void ScalarsBegin()
|
||||
{
|
||||
if (!this.writingScalars)
|
||||
{
|
||||
var datasTemp = this.datas;
|
||||
if (this.datasEnd <= datasTemp)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
|
||||
}
|
||||
|
||||
datasTemp->m_Ptr = (long)(ulong)(UIntPtr)this.scratch;
|
||||
this.writingScalars = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ScalarsEnd()
|
||||
{
|
||||
if (this.writingScalars)
|
||||
{
|
||||
var datasTemp = this.datas;
|
||||
datasTemp->m_Size = checked((int)(this.scratch - (byte*)datasTemp->m_Ptr));
|
||||
this.datas = datasTemp + 1;
|
||||
this.writingScalars = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EmptyStruct.cs
vendored
Normal file
13
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EmptyStruct.cs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: Empty struct indicating no payload data.
|
||||
/// </summary>
|
||||
internal struct EmptyStruct
|
||||
{
|
||||
}
|
||||
}
|
||||
42
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumHelper.cs
vendored
Normal file
42
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumHelper.cs
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides support for casting enums to their underlying type
|
||||
/// from within generic context.
|
||||
/// </summary>
|
||||
/// <typeparam name="UnderlyingType">
|
||||
/// The underlying type of the enum.
|
||||
/// </typeparam>
|
||||
internal static class EnumHelper<UnderlyingType>
|
||||
{
|
||||
private delegate UnderlyingType Transformer<ValueType>(ValueType value);
|
||||
|
||||
private static readonly MethodInfo IdentityInfo =
|
||||
Statics.GetDeclaredStaticMethod(typeof(EnumHelper<UnderlyingType>), "Identity");
|
||||
|
||||
public static UnderlyingType Cast<ValueType>(ValueType value)
|
||||
{
|
||||
return Caster<ValueType>.Instance(value);
|
||||
}
|
||||
|
||||
internal static UnderlyingType Identity(UnderlyingType value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
private static class Caster<ValueType>
|
||||
{
|
||||
public static readonly Transformer<ValueType> Instance =
|
||||
(Transformer<ValueType>)Statics.CreateDelegate(
|
||||
typeof(Transformer<ValueType>),
|
||||
IdentityInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumerableTypeInfo.cs
vendored
Normal file
62
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumerableTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
internal sealed class EnumerableTypeInfo<IterableType, ElementType>
|
||||
: TraceLoggingTypeInfo<IterableType>
|
||||
where IterableType : IEnumerable<ElementType>
|
||||
{
|
||||
private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
|
||||
|
||||
public EnumerableTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
|
||||
{
|
||||
this.elementInfo = elementInfo;
|
||||
}
|
||||
|
||||
public override void WriteMetadata(
|
||||
TraceLoggingMetadataCollector collector,
|
||||
string name,
|
||||
EventFieldFormat format)
|
||||
{
|
||||
collector.BeginBufferedArray();
|
||||
this.elementInfo.WriteMetadata(collector, name, format);
|
||||
collector.EndBufferedArray();
|
||||
}
|
||||
|
||||
public override void WriteData(
|
||||
TraceLoggingDataCollector collector,
|
||||
ref IterableType value)
|
||||
{
|
||||
var bookmark = collector.BeginBufferedArray();
|
||||
|
||||
var count = 0;
|
||||
if (value != null)
|
||||
{
|
||||
foreach (var element in value)
|
||||
{
|
||||
var el = element;
|
||||
this.elementInfo.WriteData(collector, ref el);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
collector.EndBufferedArray(bookmark, count);
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
var iterType = (IterableType)value;
|
||||
List<object> serializedEnumerable = new List<object>();
|
||||
foreach (var element in iterType)
|
||||
{
|
||||
serializedEnumerable.Add(elementInfo.GetData(element));
|
||||
}
|
||||
return serializedEnumerable.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
142
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventDataAttribute.cs
vendored
Normal file
142
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventDataAttribute.cs
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when authoring types that will be passed to EventSource.Write.
|
||||
/// EventSource.Write<T> only works when T is either an anonymous type
|
||||
/// or a type with an [EventData] attribute. In addition, the properties
|
||||
/// of T must be supported property types. Supported property types include
|
||||
/// simple built-in types (int, string, Guid, DateTime, DateTimeOffset,
|
||||
/// KeyValuePair, etc.), anonymous types that only contain supported types,
|
||||
/// types with an [EventData] attribute, arrays of the above, and IEnumerable
|
||||
/// of the above.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
|
||||
public class EventDataAttribute
|
||||
: Attribute
|
||||
{
|
||||
private EventLevel level = (EventLevel)(-1);
|
||||
private EventOpcode opcode = (EventOpcode)(-1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name to use if this type is used for an
|
||||
/// implicitly-named event or an implicitly-named property.
|
||||
///
|
||||
/// Example 1:
|
||||
///
|
||||
/// EventSource.Write(null, new T()); // implicitly-named event
|
||||
///
|
||||
/// The name of the event will be determined as follows:
|
||||
///
|
||||
/// if (T has an EventData attribute and attribute.Name != null)
|
||||
/// eventName = attribute.Name;
|
||||
/// else
|
||||
/// eventName = typeof(T).Name;
|
||||
///
|
||||
/// Example 2:
|
||||
///
|
||||
/// EventSource.Write(name, new { _1 = new T() }); // implicitly-named field
|
||||
///
|
||||
/// The name of the field will be determined as follows:
|
||||
///
|
||||
/// if (T has an EventData attribute and attribute.Name != null)
|
||||
/// fieldName = attribute.Name;
|
||||
/// else
|
||||
/// fieldName = typeof(T).Name;
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level to use for the event.
|
||||
/// Invalid levels (outside the range 0..255) are treated as unset.
|
||||
/// Note that the Level attribute can bubble-up, i.e. if a type contains
|
||||
/// a sub-object (a field or property), and the sub-object's type has a
|
||||
/// TraceLoggingEvent attribute, the Level from the sub-object's attribute
|
||||
/// can affect the event's level.
|
||||
///
|
||||
/// Example: for EventSource.Write(name, options, data), the level of the
|
||||
/// event will be determined as follows:
|
||||
///
|
||||
/// if (options.Level has been set)
|
||||
/// eventLevel = options.Level;
|
||||
/// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Level has been set)
|
||||
/// eventLevel = attribute.Level;
|
||||
/// else if (a field/property contained in data has a TraceLoggingEvent attribute and attribute.Level has been set)
|
||||
/// eventLevel = attribute.Level;
|
||||
/// else
|
||||
/// eventLevel = EventLevel.LogAlways;
|
||||
/// </summary>
|
||||
internal EventLevel Level
|
||||
{
|
||||
get { return this.level; }
|
||||
set { this.level = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the opcode to use for the event.
|
||||
/// Invalid opcodes (outside the range 0..255) are treated as unset.
|
||||
/// Note that the Opcode attribute can bubble-up, i.e. if a type contains
|
||||
/// a sub-object (a field or property), and the sub-object's type has a
|
||||
/// TraceLoggingEvent attribute, the Opcode from the sub-object's attribute
|
||||
/// can affect the event's opcode.
|
||||
///
|
||||
/// Example: for EventSource.Write(name, options, data), the opcode of the
|
||||
/// event will be determined as follows:
|
||||
///
|
||||
/// if (options.Opcode has been set)
|
||||
/// eventOpcode = options.Opcode;
|
||||
/// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Opcode has been set)
|
||||
/// eventOpcode = attribute.Opcode;
|
||||
/// else if (a field/property contained in data has a TraceLoggingEvent attribute and attribute.Opcode has been set)
|
||||
/// eventOpcode = attribute.Opcode;
|
||||
/// else
|
||||
/// eventOpcode = EventOpcode.Info;
|
||||
/// </summary>
|
||||
internal EventOpcode Opcode
|
||||
{
|
||||
get { return this.opcode; }
|
||||
set { this.opcode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the keywords to use for the event.
|
||||
/// Note that the Keywords attribute can bubble-up, i.e. if a type contains
|
||||
/// a sub-object (a field or property), and the sub-object's type has a
|
||||
/// TraceLoggingEvent attribute, the Keywords from the sub-object's attribute
|
||||
/// can affect the event's keywords.
|
||||
///
|
||||
/// Example: for EventSource.Write(name, options, data), the keywords of the
|
||||
/// event will be determined as follows:
|
||||
///
|
||||
/// eventKeywords = options.Keywords;
|
||||
/// if (data.GetType() has a TraceLoggingEvent attribute)
|
||||
/// eventKeywords |= attribute.Keywords;
|
||||
/// if (a field/property contained in data has a TraceLoggingEvent attribute)
|
||||
/// eventKeywords |= attribute.Keywords;
|
||||
/// </summary>
|
||||
internal EventKeywords Keywords
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flags for an event. These flags are ignored by ETW,
|
||||
/// but can have meaning to the event consumer.
|
||||
/// </summary>
|
||||
internal EventTags Tags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Tags are flags that are not interpreted by EventSource but are passed along
|
||||
/// to the EventListener. The EventListener determines the semantics of the flags.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum EventFieldTags
|
||||
{
|
||||
/// <summary>
|
||||
/// No special traits are added to the field.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/* Bits below 0x10000 are available for any use by the provider. */
|
||||
/* Bits at or above 0x10000 are reserved for definition by Microsoft. */
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TraceLogging: used when authoring types that will be passed to EventSource.Write.
|
||||
/// Controls how a field or property is handled when it is written as a
|
||||
/// field in a TraceLogging event. Apply this attribute to a field or
|
||||
/// property if the default handling is not correct. (Apply the
|
||||
/// TraceLoggingIgnore attribute if the property should not be
|
||||
/// included as a field in the event.)
|
||||
/// The default for Name is null, which means that the name of the
|
||||
/// underlying field or property will be used as the event field's name.
|
||||
/// The default for PiiTag is 0, which means that the event field does not
|
||||
/// contain personally-identifiable information.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EventFieldAttribute
|
||||
: Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// User defined options for the field. These are not interpreted by the EventSource
|
||||
/// but are available to the Listener. See EventFieldSettings for details
|
||||
/// </summary>
|
||||
public EventFieldTags Tags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name to use for the field. This defaults to null.
|
||||
/// If null, the name of the corresponding property will be used
|
||||
/// as the event field's name.
|
||||
///
|
||||
|
||||
internal string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a field formatting hint.
|
||||
/// </summary>
|
||||
public EventFieldFormat Format
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventFieldFormat.cs
vendored
Normal file
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventFieldFormat.cs
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a hint that may be used by an event listener when formatting
|
||||
/// an event field for display. Note that the event listener may ignore the
|
||||
/// hint if it does not recognize a particular combination of type and format.
|
||||
/// Similar to TDH_OUTTYPE.
|
||||
/// </summary>
|
||||
public enum EventFieldFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Field receives default formatting based on the field's underlying type.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should not be displayed.
|
||||
/// </summary>
|
||||
NoPrint = 1,
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Field should be formatted as character or string data.
|
||||
/// Typically applied to 8-bit or 16-bit integers.
|
||||
/// This is the default format for String and Char types.
|
||||
/// </summary>
|
||||
String = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as boolean data. Typically applied to 8-bit
|
||||
/// or 32-bit integers. This is the default format for the Boolean type.
|
||||
/// </summary>
|
||||
Boolean = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as hexadecimal data. Typically applied to
|
||||
/// integer types.
|
||||
/// </summary>
|
||||
Hexadecimal = 4,
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should be formatted as a process identifier. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
ProcessId = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as a thread identifier. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
ThreadId = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as an Internet port. Typically applied to 16-bit integer
|
||||
/// types.
|
||||
/// </summary>
|
||||
Port = 7,
|
||||
/// <summary>
|
||||
/// Field should be formatted as an Internet Protocol v4 address. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
Ipv4Address = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as an Internet Protocol v6 address. Typically applied to
|
||||
/// byte[] types.
|
||||
/// </summary>
|
||||
Ipv6Address = 9,
|
||||
/// <summary>
|
||||
/// Field should be formatted as a SOCKADDR. Typically applied to byte[] types.
|
||||
/// </summary>
|
||||
SocketAddress = 10,
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Field should be formatted as XML string data. Typically applied to
|
||||
/// strings or arrays of 8-bit or 16-bit integers.
|
||||
/// </summary>
|
||||
Xml = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as JSON string data. Typically applied to
|
||||
/// strings or arrays of 8-bit or 16-bit integers.
|
||||
/// </summary>
|
||||
Json = 12,
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should be formatted as a Win32 error code. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
Win32Error = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as an NTSTATUS code. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
NTStatus = 14,
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Field should be formatted as an HRESULT code. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
HResult = 15,
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should be formatted as a FILETIME. Typically applied to 64-bit
|
||||
/// integer types. This is the default format for DateTime types.
|
||||
/// </summary>
|
||||
FileTime = 16,
|
||||
/// <summary>
|
||||
/// When applied to a numeric type, indicates that the type should be formatted
|
||||
/// as a signed integer. This is the default format for signed integer types.
|
||||
/// </summary>
|
||||
Signed = 17,
|
||||
|
||||
/// <summary>
|
||||
/// When applied to a numeric type, indicates that the type should be formatted
|
||||
/// as an unsigned integer. This is the default format for unsigned integer types.
|
||||
/// </summary>
|
||||
Unsigned = 18,
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when authoring types that will be passed to EventSource.Write.
|
||||
/// By default, EventSource.Write will write all of an object's public
|
||||
/// properties to the event payload. Apply [EventIgnore] to a public
|
||||
/// property to prevent EventSource.Write from including the property in
|
||||
/// the event.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EventIgnoreAttribute
|
||||
: Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
147
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventPayload.cs
vendored
Normal file
147
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventPayload.cs
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
#if !ES_BUILD_AGAINST_DOTNET_V35
|
||||
using Contract = System.Diagnostics.Contracts.Contract;
|
||||
#else
|
||||
using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
|
||||
#endif
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// EventPayload class holds the list of parameters and their corresponding values for user defined types passed to
|
||||
/// EventSource APIs.
|
||||
/// Preserving the order of the elements as they were found inside user defined types is the most important characteristic of this class.
|
||||
/// </summary>
|
||||
internal class EventPayload : IDictionary<string, object>
|
||||
{
|
||||
internal EventPayload(List<string> payloadNames, List<object> payloadValues)
|
||||
{
|
||||
Contract.Assert(payloadNames.Count == payloadValues.Count);
|
||||
|
||||
m_names = payloadNames;
|
||||
m_values = payloadValues;
|
||||
}
|
||||
|
||||
public ICollection<string> Keys { get { return m_names; } }
|
||||
public ICollection<object> Values { get { return m_values; } }
|
||||
|
||||
public object this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (key == null)
|
||||
throw new System.ArgumentNullException("key");
|
||||
|
||||
int position = 0;
|
||||
foreach(var name in m_names)
|
||||
{
|
||||
if (name == key)
|
||||
{
|
||||
return m_values[position];
|
||||
}
|
||||
position++;
|
||||
}
|
||||
|
||||
throw new System.Collections.Generic.KeyNotFoundException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string key, object value)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, object> payloadEntry)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, object> entry)
|
||||
{
|
||||
return ContainsKey(entry.Key);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
if (key == null)
|
||||
throw new System.ArgumentNullException("key");
|
||||
|
||||
foreach (var item in m_names)
|
||||
{
|
||||
if (item == key)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int Count { get { return m_names.Count; } }
|
||||
|
||||
public bool IsReadOnly { get { return true; } }
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
var instance = this as IEnumerable<KeyValuePair<string, object>>;
|
||||
return instance.GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, object>[] payloadEntries, int count)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, object> entry)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out object value)
|
||||
{
|
||||
if (key == null)
|
||||
throw new System.ArgumentNullException("key");
|
||||
|
||||
int position = 0;
|
||||
foreach (var name in m_names)
|
||||
{
|
||||
if (name == key)
|
||||
{
|
||||
value = m_values[position];
|
||||
return true;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
|
||||
value = default(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
#region private
|
||||
private List<string> m_names;
|
||||
private List<object> m_values;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
317
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceActivity.cs
vendored
Normal file
317
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceActivity.cs
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
using System;
|
||||
|
||||
#if !ES_BUILD_AGAINST_DOTNET_V35
|
||||
using Contract = System.Diagnostics.Contracts.Contract;
|
||||
#else
|
||||
using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
|
||||
#endif
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides support for EventSource activities by marking the start and
|
||||
/// end of a particular operation.
|
||||
/// </summary>
|
||||
internal sealed class EventSourceActivity
|
||||
: IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EventSourceActivity class that
|
||||
/// is attached to the specified event source. The new activity will
|
||||
/// not be attached to any related (parent) activity.
|
||||
/// The activity is created in the Initialized state.
|
||||
/// </summary>
|
||||
/// <param name="eventSource">
|
||||
/// The event source to which the activity information is written.
|
||||
/// </param>
|
||||
public EventSourceActivity(EventSource eventSource)
|
||||
{
|
||||
if (eventSource == null)
|
||||
throw new ArgumentNullException("eventSource");
|
||||
Contract.EndContractBlock();
|
||||
|
||||
this.eventSource = eventSource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// You can make an activity out of just an EventSource.
|
||||
/// </summary>
|
||||
public static implicit operator EventSourceActivity(EventSource eventSource) { return new EventSourceActivity(eventSource); }
|
||||
|
||||
/* Properties */
|
||||
/// <summary>
|
||||
/// Gets the event source to which this activity writes events.
|
||||
/// </summary>
|
||||
public EventSource EventSource
|
||||
{
|
||||
get { return this.eventSource; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this activity's unique identifier, or the default Guid if the
|
||||
/// event source was disabled when the activity was initialized.
|
||||
/// </summary>
|
||||
public Guid Id
|
||||
{
|
||||
get { return this.activityId; }
|
||||
}
|
||||
|
||||
#if false // don't expose RelatedActivityId unless there is a need.
|
||||
/// <summary>
|
||||
/// Gets the unique identifier of this activity's related (parent)
|
||||
/// activity.
|
||||
/// </summary>
|
||||
public Guid RelatedId
|
||||
{
|
||||
get { return this.relatedActivityId; }
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Start event with the specified name and data. If the start event is not active (because the provider
|
||||
/// is not on or keyword-level indiates the event is off, then the returned activity is simply the 'this' poitner
|
||||
/// and it is effectively like the Start d
|
||||
///
|
||||
/// A new activityID GUID is generated and the returned
|
||||
/// EventSourceActivity remembers this activity and will mark every event (including the start stop and any writes)
|
||||
/// with this activityID. In addition the Start activity will log a 'relatedActivityID' that was the activity
|
||||
/// ID before the start event. This way event processors can form a linked list of all the activities that
|
||||
/// caused this one (directly or indirectly).
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. It is strongly suggested that this name end in 'Start' (e.g. DownloadStart).
|
||||
/// If you do this, then the Stop() method will automatically replace the 'Start' suffix with a 'Stop' suffix.
|
||||
/// </param>
|
||||
/// <param name="options">Allow options (keywords, level) to be set for the write associated with this start
|
||||
/// These will also be used for the stop event.</param>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public EventSourceActivity Start<T>(string eventName, EventSourceOptions options, T data)
|
||||
{
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
|
||||
/// and level==Info) Data payload is empty.
|
||||
/// </summary>
|
||||
public EventSourceActivity Start(string eventName)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
var data = new EmptyStruct();
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Shortcut version see Start(string eventName, EventSourceOptions options, T data). Data payload is empty.
|
||||
/// </summary>
|
||||
public EventSourceActivity Start(string eventName, EventSourceOptions options)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
|
||||
/// and level==Info)
|
||||
/// </summary>
|
||||
public EventSourceActivity Start<T>(string eventName, T data)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Stop event with the specified data, and sets the activity
|
||||
/// to the Stopped state. The name is determined by the eventName used in Start.
|
||||
/// If that Start event name is suffixed with 'Start' that is removed, and regardless
|
||||
/// 'Stop' is appended to the result to form the Stop event name.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public void Stop<T>(T data)
|
||||
{
|
||||
this.Stop(null, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
|
||||
/// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
|
||||
/// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
|
||||
/// </summary>
|
||||
public void Stop<T>(string eventName)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
this.Stop(eventName, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
|
||||
/// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
|
||||
/// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
|
||||
/// </summary>
|
||||
public void Stop<T>(string eventName, T data)
|
||||
{
|
||||
this.Stop(eventName, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an event associated with this activity to the eventSource associted with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. If null, the name is determined from
|
||||
/// data's type.
|
||||
/// </param>
|
||||
/// <param name="options">
|
||||
/// The options to use for the event.
|
||||
/// </param>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public void Write<T>(string eventName, EventSourceOptions options, T data)
|
||||
{
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes an event associated with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. If null, the name is determined from
|
||||
/// data's type.
|
||||
/// </param>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public void Write<T>(string eventName, T data)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes a trivial event associated with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. Must not be null.
|
||||
/// </param>
|
||||
/// <param name="options">
|
||||
/// The options to use for the event.
|
||||
/// </param>
|
||||
public void Write(string eventName, EventSourceOptions options)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes a trivial event associated with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. Must not be null.
|
||||
/// </param>
|
||||
public void Write(string eventName)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
var data = new EmptyStruct();
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes an event to a arbitrary eventSource stamped with the activity ID of this activity.
|
||||
/// </summary>
|
||||
public void Write<T>(EventSource source, string eventName, EventSourceOptions options, T data)
|
||||
{
|
||||
this.Write(source, eventName, ref options, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases any unmanaged resources associated with this object.
|
||||
/// If the activity is in the Started state, calls Stop().
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.state == State.Started)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
this.Stop(null, ref data);
|
||||
}
|
||||
}
|
||||
|
||||
#region private
|
||||
private EventSourceActivity Start<T>(string eventName, ref EventSourceOptions options, ref T data)
|
||||
{
|
||||
if (this.state != State.Started)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
// If the source is not on at all, then we don't need to do anything and we can simply return ourselves.
|
||||
if (!this.eventSource.IsEnabled())
|
||||
return this;
|
||||
|
||||
var newActivity = new EventSourceActivity(eventSource);
|
||||
if (!this.eventSource.IsEnabled(options.Level, options.Keywords))
|
||||
{
|
||||
// newActivity.relatedActivityId = this.Id;
|
||||
Guid relatedActivityId = this.Id;
|
||||
newActivity.activityId = Guid.NewGuid();
|
||||
newActivity.startStopOptions = options;
|
||||
newActivity.eventName = eventName;
|
||||
newActivity.startStopOptions.Opcode = EventOpcode.Start;
|
||||
this.eventSource.Write(eventName, ref newActivity.startStopOptions, ref newActivity.activityId, ref relatedActivityId, ref data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are not active, we don't set the eventName, which basically also turns off the Stop event as well.
|
||||
newActivity.activityId = this.Id;
|
||||
}
|
||||
|
||||
return newActivity;
|
||||
}
|
||||
|
||||
private void Write<T>(EventSource eventSource, string eventName, ref EventSourceOptions options, ref T data)
|
||||
{
|
||||
if (this.state != State.Started)
|
||||
throw new InvalidOperationException(); // Write after stop.
|
||||
if (eventName == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
eventSource.Write(eventName, ref options, ref this.activityId, ref s_empty, ref data);
|
||||
}
|
||||
|
||||
private void Stop<T>(string eventName, ref T data)
|
||||
{
|
||||
if (this.state != State.Started)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
// If start was not fired, then stop isn't as well.
|
||||
if (!StartEventWasFired)
|
||||
return;
|
||||
|
||||
this.state = State.Stopped;
|
||||
if (eventName == null)
|
||||
{
|
||||
eventName = this.eventName;
|
||||
if (eventName.EndsWith("Start"))
|
||||
eventName = eventName.Substring(0, eventName.Length - 5);
|
||||
eventName = eventName + "Stop";
|
||||
}
|
||||
this.startStopOptions.Opcode = EventOpcode.Stop;
|
||||
this.eventSource.Write(eventName, ref this.startStopOptions, ref this.activityId, ref s_empty, ref data);
|
||||
}
|
||||
|
||||
private enum State
|
||||
{
|
||||
Started,
|
||||
Stopped
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If eventName is non-null then we logged a start event
|
||||
/// </summary>
|
||||
private bool StartEventWasFired { get { return eventName != null; }}
|
||||
|
||||
private readonly EventSource eventSource;
|
||||
private EventSourceOptions startStopOptions;
|
||||
internal Guid activityId;
|
||||
// internal Guid relatedActivityId;
|
||||
private State state;
|
||||
private string eventName;
|
||||
|
||||
static internal Guid s_empty;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceOptions.cs
vendored
Normal file
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceOptions.cs
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when calling EventSource.Write.
|
||||
/// Optional overrides for event settings such as Level, Keywords, or Opcode.
|
||||
/// If overrides are not provided for a setting, default values will be used.
|
||||
/// </summary>
|
||||
public struct EventSourceOptions
|
||||
{
|
||||
internal EventKeywords keywords;
|
||||
internal EventTags tags;
|
||||
internal EventActivityOptions activityOptions;
|
||||
internal byte level;
|
||||
internal byte opcode;
|
||||
internal byte valuesSet;
|
||||
|
||||
internal const byte keywordsSet = 0x1;
|
||||
internal const byte tagsSet = 0x2;
|
||||
internal const byte levelSet = 0x4;
|
||||
internal const byte opcodeSet = 0x8;
|
||||
internal const byte activityOptionsSet = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level to use for the specified event. If this property
|
||||
/// is unset, the event's level will be 5 (Verbose).
|
||||
/// </summary>
|
||||
public EventLevel Level
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EventLevel)this.level;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.level = checked((byte)value);
|
||||
this.valuesSet |= levelSet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the opcode to use for the specified event. If this property
|
||||
/// is unset, the event's opcode will 0 (Info).
|
||||
/// </summary>
|
||||
public EventOpcode Opcode
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EventOpcode)this.opcode;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.opcode = checked((byte)value);
|
||||
this.valuesSet |= opcodeSet;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsOpcodeSet
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.valuesSet & opcodeSet) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the keywords to use for the specified event. If this
|
||||
/// property is unset, the event's keywords will be 0.
|
||||
/// </summary>
|
||||
public EventKeywords Keywords
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.keywords;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.keywords = value;
|
||||
this.valuesSet |= keywordsSet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags to use for the specified event. If this property is
|
||||
/// unset, the event's tags will be 0.
|
||||
/// </summary>
|
||||
public EventTags Tags
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.tags;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.tags = value;
|
||||
this.valuesSet |= tagsSet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the activity options for this specified events. If this property is
|
||||
/// unset, the event's activity options will be 0.
|
||||
/// </summary>
|
||||
public EventActivityOptions ActivityOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.activityOptions;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.activityOptions = value;
|
||||
this.valuesSet |= activityOptionsSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
227
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/FieldMetadata.cs
vendored
Normal file
227
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/FieldMetadata.cs
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using Encoding = System.Text.Encoding;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: Contains the information needed to generate tracelogging
|
||||
/// metadata for an event field.
|
||||
/// </summary>
|
||||
internal class FieldMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the field
|
||||
/// </summary>
|
||||
private readonly string name;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes in the UTF8 Encoding of 'name' INCLUDING a null terminator.
|
||||
/// </summary>
|
||||
private readonly int nameSize;
|
||||
private readonly EventFieldTags tags;
|
||||
private readonly byte[] custom;
|
||||
|
||||
/// <summary>
|
||||
/// ETW supports fixed sized arrays. If inType has the InTypeFixedCountFlag then this is the
|
||||
/// statically known count for the array. It is also used to encode the number of bytes of
|
||||
/// custom meta-data if InTypeCustomCountFlag set.
|
||||
/// </summary>
|
||||
private readonly ushort fixedCount;
|
||||
|
||||
private byte inType;
|
||||
private byte outType;
|
||||
|
||||
/// <summary>
|
||||
/// Scalar or variable-length array.
|
||||
/// </summary>
|
||||
public FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType type,
|
||||
EventFieldTags tags,
|
||||
bool variableCount)
|
||||
: this(
|
||||
name,
|
||||
type,
|
||||
tags,
|
||||
variableCount ? Statics.InTypeVariableCountFlag : (byte)0,
|
||||
0,
|
||||
null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fixed-length array.
|
||||
/// </summary>
|
||||
public FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType type,
|
||||
EventFieldTags tags,
|
||||
ushort fixedCount)
|
||||
: this(
|
||||
name,
|
||||
type,
|
||||
tags,
|
||||
Statics.InTypeFixedCountFlag,
|
||||
fixedCount,
|
||||
null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom serializer
|
||||
/// </summary>
|
||||
public FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType type,
|
||||
EventFieldTags tags,
|
||||
byte[] custom)
|
||||
: this(
|
||||
name,
|
||||
type,
|
||||
tags,
|
||||
Statics.InTypeCustomCountFlag,
|
||||
checked((ushort)(custom == null ? 0 : custom.Length)),
|
||||
custom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType dataType,
|
||||
EventFieldTags tags,
|
||||
byte countFlags,
|
||||
ushort fixedCount = 0,
|
||||
byte[] custom = null)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException(
|
||||
"name",
|
||||
"This usually means that the object passed to Write is of a type that"
|
||||
+ " does not support being used as the top-level object in an event,"
|
||||
+ " e.g. a primitive or built-in type.");
|
||||
}
|
||||
|
||||
Statics.CheckName(name);
|
||||
var coreType = (int)dataType & Statics.InTypeMask;
|
||||
this.name = name;
|
||||
this.nameSize = Encoding.UTF8.GetByteCount(this.name) + 1;
|
||||
this.inType = (byte)(coreType | countFlags);
|
||||
this.outType = (byte)(((int)dataType >> 8) & Statics.OutTypeMask);
|
||||
this.tags = tags;
|
||||
this.fixedCount = fixedCount;
|
||||
this.custom = custom;
|
||||
|
||||
if (countFlags != 0)
|
||||
{
|
||||
if (coreType == (int)TraceLoggingDataType.Nil)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNil"));
|
||||
}
|
||||
if (coreType == (int)TraceLoggingDataType.Binary)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
|
||||
}
|
||||
#if !BROKEN_UNTIL_M3
|
||||
if (coreType == (int)TraceLoggingDataType.Utf16String ||
|
||||
coreType == (int)TraceLoggingDataType.MbcsString)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (((int)this.tags & 0xfffffff) != 0)
|
||||
{
|
||||
this.outType |= Statics.OutTypeChainFlag;
|
||||
}
|
||||
|
||||
if (this.outType != 0)
|
||||
{
|
||||
this.inType |= Statics.InTypeChainFlag;
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementStructFieldCount()
|
||||
{
|
||||
this.inType |= Statics.InTypeChainFlag;
|
||||
this.outType++;
|
||||
if ((this.outType & Statics.OutTypeMask) == 0)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_TooManyFields"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the main routine for FieldMetaData. Basically it will serialize the data in
|
||||
/// this structure as TraceLogging style meta-data into the array 'metaArray' starting at
|
||||
/// 'pos' (pos is updated to reflect the bytes written).
|
||||
///
|
||||
/// Note that 'metaData' can be null, in which case it only updates 'pos'. This is useful
|
||||
/// for a 'two pass' approach where you figure out how big to make the array, and then you
|
||||
/// fill it in.
|
||||
/// </summary>
|
||||
public void Encode(ref int pos, byte[] metadata)
|
||||
{
|
||||
// Write out the null terminated UTF8 encoded name
|
||||
if (metadata != null)
|
||||
{
|
||||
Encoding.UTF8.GetBytes(this.name, 0, this.name.Length, metadata, pos);
|
||||
}
|
||||
pos += this.nameSize;
|
||||
|
||||
// Write 1 byte for inType
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata[pos] = this.inType;
|
||||
}
|
||||
pos += 1;
|
||||
|
||||
// If InTypeChainFlag set, then write out the outType
|
||||
if (0 != (this.inType & Statics.InTypeChainFlag))
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata[pos] = this.outType;
|
||||
}
|
||||
pos += 1;
|
||||
|
||||
// If OutTypeChainFlag set, then write out tags
|
||||
if (0 != (this.outType & Statics.OutTypeChainFlag))
|
||||
{
|
||||
Statics.EncodeTags((int)this.tags, ref pos, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
// If InTypeFixedCountFlag set, write out the fixedCount (2 bytes little endian)
|
||||
if (0 != (this.inType & Statics.InTypeFixedCountFlag))
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata[pos + 0] = unchecked((byte)this.fixedCount);
|
||||
metadata[pos + 1] = (byte)(this.fixedCount >> 8);
|
||||
}
|
||||
pos += 2;
|
||||
|
||||
// If InTypeCustomCountFlag set, write out the blob of custom meta-data.
|
||||
if (Statics.InTypeCustomCountFlag == (this.inType & Statics.InTypeCountMask) &&
|
||||
this.fixedCount != 0)
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
Buffer.BlockCopy(this.custom, 0, metadata, pos, this.fixedCount);
|
||||
}
|
||||
pos += this.fixedCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/InvokeTypeInfo.cs
vendored
Normal file
114
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/InvokeTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: An implementation of TraceLoggingTypeInfo that works
|
||||
/// for arbitrary types. It writes all public instance properties of
|
||||
/// the type. Implemented using Delegate.CreateDelegate(property.Getter).
|
||||
/// </summary>
|
||||
/// <typeparam name="ContainerType">
|
||||
/// Type from which to read values.
|
||||
/// </typeparam>
|
||||
internal sealed class InvokeTypeInfo<ContainerType>
|
||||
: TraceLoggingTypeInfo<ContainerType>
|
||||
{
|
||||
private readonly PropertyAnalysis[] properties;
|
||||
private readonly PropertyAccessor<ContainerType>[] accessors;
|
||||
|
||||
public InvokeTypeInfo(
|
||||
TypeAnalysis typeAnalysis)
|
||||
: base(
|
||||
typeAnalysis.name,
|
||||
typeAnalysis.level,
|
||||
typeAnalysis.opcode,
|
||||
typeAnalysis.keywords,
|
||||
typeAnalysis.tags)
|
||||
{
|
||||
if (typeAnalysis.properties.Length != 0)
|
||||
{
|
||||
this.properties = typeAnalysis.properties;
|
||||
this.accessors = new PropertyAccessor<ContainerType>[this.properties.Length];
|
||||
for (int i = 0; i < this.accessors.Length; i++)
|
||||
{
|
||||
this.accessors[i] = PropertyAccessor<ContainerType>.Create(this.properties[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteMetadata(
|
||||
TraceLoggingMetadataCollector collector,
|
||||
string name,
|
||||
EventFieldFormat format)
|
||||
{
|
||||
var groupCollector = collector.AddGroup(name);
|
||||
if (this.properties != null)
|
||||
{
|
||||
foreach (var property in this.properties)
|
||||
{
|
||||
var propertyFormat = EventFieldFormat.Default;
|
||||
var propertyAttribute = property.fieldAttribute;
|
||||
if (propertyAttribute != null)
|
||||
{
|
||||
groupCollector.Tags = propertyAttribute.Tags;
|
||||
propertyFormat = propertyAttribute.Format;
|
||||
}
|
||||
|
||||
property.typeInfo.WriteMetadata(
|
||||
groupCollector,
|
||||
property.name,
|
||||
propertyFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteData(
|
||||
TraceLoggingDataCollector collector,
|
||||
ref ContainerType value)
|
||||
{
|
||||
if (this.accessors != null)
|
||||
{
|
||||
foreach (var accessor in this.accessors)
|
||||
{
|
||||
accessor.Write(collector, ref value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
if (this.properties != null)
|
||||
{
|
||||
var membersNames = new List<string>();
|
||||
var memebersValues = new List<object>();
|
||||
for (int i = 0; i < this.properties.Length; i++)
|
||||
{
|
||||
var propertyValue = accessors[i].GetData((ContainerType)value);
|
||||
membersNames.Add(properties[i].name);
|
||||
memebersValues.Add(properties[i].typeInfo.GetData(propertyValue));
|
||||
}
|
||||
return new EventPayload(membersNames, memebersValues);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void WriteObjectData(
|
||||
TraceLoggingDataCollector collector,
|
||||
object valueObj)
|
||||
{
|
||||
if (this.accessors != null)
|
||||
{
|
||||
var value = valueObj == null
|
||||
? default(ContainerType)
|
||||
: (ContainerType)valueObj;
|
||||
this.WriteData(collector, ref value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user